James is your butler and helps you to create, build, debug, test and run your Go projects

go-james

Go Report Card Documentation License GitHub Version GitHub issues GitHub Last Commit

James is your butler and helps you to create, build, debug, test and run your Go projects.

When you often create new apps using Go, it quickly becomes annoying when you realize all the steps it takes to configure the basics. You need to manually create the source files, version info requires more steps to be injected into the executable, using Visual Studio Code requires you to manually setup the tasks you want to run…

Using the go-james tool, you can automate and streamline this process. The tool will take care of initializing your project, running your project, debugging it, building it and running the tests.

You should be using go-james if:

  • you're tired of setting up your projects manually
  • you don't want to have to specify the main package every time you want build or run your project
  • you keep on forgetting how to setup debugging Visual Studio Code
  • you don't want to setup your tasks file manually in Visual Studio Code
  • you want to have the Git revision, branch name and version number automatically in your project
  • you're tired of manually writing Makefiles to build, test and run your project
  • you want a better way to do tasks before and after the build than writing non-portable shell scripts
  • you want an easy way to cross-compile for all common GOOS/GOARCH combinations
  • you want a way to build, run and test your project in a cross-platform manner


Requirements

Installation

Using go get

You can run the following command to install go-james:

go get -u github.com/pieterclaerhout/go-james/cmd/go-james

This will create the go-james command in your $GOPATH/bin folder.

The tool is self-contained and doesn't have any external dependencies.

Homebrew

To install via homebrew, run the following commands:

$ brew tap pieterclaerhout/go-james
==> Tapping pieterclaerhout/go-james
Cloning into '/usr/local/Homebrew/Library/Taps/pieterclaerhout/homebrew-go-james'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
Tapped 1 formula (27 files, 26.5KB).

$ brew install go-james
==> Installing go-james from pieterclaerhout/go-james
==> Downloading https://github.com/pieterclaerhout/go-james/releases/download/v1.6.0/go-james_darwin_amd64.tar.gz
######################################################################## 100.0%
🍺  /usr/local/Cellar/go-james/1.6.0: 4 files, 11.5MB, built in 3 seconds

Manually

To install it manually, download the go-james executable from the releases and place it in $GOPATH/bin.

Starting a new project

To start a new project, you can use the new subcommand as follows:

go-james new --path=<target path> \
             --package=<package> \
             --name=<name of your project> \
             --description=<description of your project> \
             --copyright=<copyright of your project> \
             [--with-git] \
             [--with-docker] \
             [--with-github-action] \
             [--overwrite]

When you run it, you'll get the following output:

➜ go-james new --path go-example --package github.com/pieterclaerhout/go-example
Creating package: github.com/pieterclaerhout/go-example
Project path: /Users/pclaerhout/Desktop/go-example
Writing: go-example
Writing: go-example/go-james.json
Writing: go-example/.vscode
Writing: go-example/.vscode/tasks.json
Writing: go-example/.vscode/settings.json
Writing: go-example/.vscode/launch.json
Writing: go-example/LICENSE
Writing: go-example/.gitignore
Writing: go-example/.dockerignore
Writing: go-example/Dockerfile
Writing: go-example/README.md
Writing: go-example/scripts/post_build
Writing: go-example/scripts/post_build/post_build.example.go
Writing: go-example/library.go
Writing: go-example/library_test.go
Writing: go-example/cmd/go-example
Writing: go-example/cmd/go-example/main.go
Writing: go-example/versioninfo
Writing: go-example/versioninfo/versioninfo.go
Writing: go-example/scripts/pre_build
Writing: go-example/scripts/pre_build/pre_build.example.go
Writing: go-example/go.mod

It will automatically create the following folder and file structure:

go-example
.
├── Dockerfile
├── Downloads
├── DropBox
├── Twixl\ Publisher
└── go-example
    ├── Dockerfile
    ├── LICENSE
    ├── README.md
    ├── cmd
    │   └── go-example
    │       └── main.go
    ├── go-james.json
    ├── go.mod
    ├── library.go
    ├── library_test.go
    ├── scripts
    │   ├── post_build
    │   │   └── post_build.example.go
    │   └── pre_build
    │       └── pre_build.example.go
    └── versioninfo
        └── versioninfo.go

An important file which is generated and can be used to further customize the project and it's settings is the go-james.json file which sits next to the go.mod file.

You can specify the following options:

  • --path: the path where the new project should be created, e.g. /home/username/go-example (if not specified, it will create a directory with the name of the prject in the current path)
  • --package: the main package for the new project, e.g. github.com/pieterclaerhout/go-example (defaults to the project name if specified)
  • --name: the name of the project, if not specified, the last part of the path is used
  • --description: the description of the project, used for the readme
  • --copyright: the copyright of the project, used for the readme
  • --with-git: if specified, a local Git repository will be created for the project and the source files will automatically be committed.
  • --with-docker: if specified, a sample Dockerfile and .dockerignore file will be created.
  • --with-github-action: if specified, a sample Github Actions file will be created.
  • --overwrite: if the destination path already exists, overwrite it (be careful, the original folder will be replaced)

Initializing an existing project

When you already have an existing folder structure, you can run the init command to add the missing pieces.

go-james init

This command is supposed to run from the project's directory and doesn't take any arguments.

Building a project

From within the project root, run the build command to build the executable:

go-james build [-v] [--output=<path>] [--goos=<os>] [--goarch=<arch>]

By default, the output is put in the build subdirectory but can be customized in the configuration file.

You can specify the following options:

  • -v: the packages which are built will be listed.
  • --output: you can override the default output path as specified in the configuration file.
  • --goos: you can override the GOOS environment variable which indicates for which OS you are compiling.
  • --goarch: you can override the GOARCH environment variable which indicates for which architecture you are compiling.

You can read more about the GOOS and GOARCH environment variables here.

As part of the build process, the versioninfo package will be filled with the following details:

With every build, these variables are automatically updated.

Pre-build and post-build hooks

Just before the build, if a file called <project_root>/scripts/pre_build/pre_build.go is present, it will be executed and will get a lot of info about the build injected. It's a plain Go file, so use whatever trick or tool you know. A sample pre-build script looks as follows:

package main

import (
	"github.com/pieterclaerhout/go-james"
	"github.com/pieterclaerhout/go-log"
)

func main() {

	args, err := james.ParseBuildArgs()
	log.CheckError(err)

	log.InfoDump(args, "pre_build arguments")

}

You can also execute a script after the build. To do so, create a file <project_root>/scripts/post_build/post_build.go with contents similar to:

package main

import (
	"github.com/pieterclaerhout/go-james"
	"github.com/pieterclaerhout/go-log"
)

func main() {

	args, err := james.ParseBuildArgs()
	log.CheckError(err)

	log.InfoDump(args, "post_build arguments")

}

Parsing arguments in pre/post build scripts.

To parse the arguments, you can use james.ParseBuildArgs().

The parameters it gets are are struct of the type james.BuildArgs:

james.BuildArgs{
  ProjectPath: "/home/user/go-james",
  OutputPath: "/home/user/go-james/build/go-james",
  GOOS: "darwin",
  GOARCH: "amd64",
  ProjectName: "go-james",
  ProjectDescription: "James is your butler and helps you to create, build, test and run your Go projects",
  ProjectCopyright: "© 2019-2020 Copyright Pieter Claerhout",
  Version: "0.7.0",
  Revision: "2065b13",
  Branch: "master",
  RawBuildCommand: []string{
    "go",
    "build",
    "-o",
    "build/go-james",
    "-ldflags",
    "-s -w -X github.com/pieterclaerhout/go-james/versioninfo.ProjectName=go-james -X 'github.com/pieterclaerhout/go-james/versioninfo.ProjectDescription=James is your butler and helps you to create, build, test and run your Go projects' -X 'github.com/pieterclaerhout/go-james/versioninfo.ProjectCopyright=© 2019 Copyright Pieter Claerhout' -X github.com/pieterclaerhout/go-james/versioninfo.Version=0.7.0 -X github.com/pieterclaerhout/go-james/versioninfo.Revision=2065b13 -X github.com/pieterclaerhout/go-james/versioninfo.Branch=master",
    "-trimpath",
    "github.com/pieterclaerhout/go-james/cmd/go-james",
  },
}

The same information is also available in the following environment variables:

GO_JAMES_BRANCH="master"
GO_JAMES_GOARCH="amd64"
GO_JAMES_GOOS="darwin"
GO_JAMES_OUTPUT_PATH="/home/user/go-james/build/go-james"
GO_JAMES_PROJECT_COPYRIGHT="© 2019-2020 Copyright Pieter Claerhout"
GO_JAMES_PROJECT_DESCRIPTION="James is your butler and helps you to create, build, test and run your Go projects"
GO_JAMES_PROJECT_NAME="go-james"
GO_JAMES_PROJECT_PATH="/home/user/go-james"
GO_JAMES_REVISION="2065b13"
GO_JAMES_VERSION="0.7.0"

Using Bash scripts for pre/post build actions.

If you prefer to use a bash script instead for the pre/post build actions, you can create a file called:

<project_root>/scripts/post_build/pre_build.sh

or

<project_root>/scripts/post_build/post_build.sh

It should be marked as executable.

Using Batch files for pre/post build actions.

If you prefer to use a batch file on Windows instead for the pre/post build actions, you can create a file called:

<project_root>/scripts/post_build/pre_build.bat

or

<project_root>/scripts/post_build/post_build.bat

How go-james defines which pre/post build script to run

go-james will search for pre/post build scripts in the following order:

  • pre_build.go / post_build.go
  • pre_build.sh / post_build.sh
  • pre_build.bat / post_build.bat

Packaging a project

From within the project root, run the package command to build the executable for windows / darwin / linux in the 386 and amd64 variants and compresses the result as a .zip (windows) or .tgz (linux / mac):

go-james package [-v] [--concurrency=4]

By default, the output is put in the build subdirectory but can be customized in the configuration file.

The filenames which are constructed use the following convention:

build/<project.name>_<goos>-<goarch>_v<project.version>.[zip,tgz]

The executable will be compressed and, if present in the project, the project's README.md file as well.

You can specify the following options:

  • -v: the packages which are built will be listed.
  • --concurrency: how many package processes should run in parallel, defaults to the number of CPUs.

As part of the build process, the versioninfo package will be filled with the following details:

  • versioninfo.ProjectName: the name of the project from the configuration file
  • versioninfo.ProjectDescription: the description of the project from the configuration file
  • versioninfo.Version: the version of the project from the configuration file
  • versioninfo.Revision: the current Git commit hash
  • versioninfo.Branch: the current Git branch name

With every build, these variables are automatically updated.

Debugging a project

From within the project root, run:

go-james debug

This will build the project and run it's main target through the Delve debugger. If the dlv command is not yet present in your $GOPATH/bin folder, it will automaticall be installed the first time you run it.

When creating a new project or performing init on an existing project, it also configures debugging from within Visual Studio Code. It's a simple as setting one or more breakpoints and choose "Start" > "Debug" from the menu. It creates a launch configuration called Debug.

Running a project

From within the project root, run:

go-james run <args>

This will build the project and run it's main target passing the <args> to the command.

Testing a project

From within the project root, run:

go-james test

This will run all the tests defined in the package.

Installing the executable

To install the main executable of your project in $GOPATH/bin, simply run the install command.

This will build the project and install it in the $GOPATH/bin folder. The name of the executable is the basename of build output path (as specified in the configuration file.

go-james uninstall

Uninstalling the executable

Similar to the install command, there is also an uninstall command which removes the executable from $GOPATH/bin.

go-james uninstall

Running a static analysis

You can use the staticcheck command to run the staticcheck static analyzer. The binary required to run staticcheck is automatically installed if needed.

go-james staticcheck

Building a Docker image

You can use the docker-image command to build a Docker image using the Dockerfile in the project folder. When you create a new project, a starter Dockerfile will be created automatically.

go-james docker-container

The config file go-james.json

When you create a new project or init an existing one, a go-james.json file will be created in the root of your project. This file can be used to configure the project. The full config file is as follows:

{
    "project": {
        "name": "go-example",
        "version": "1.0.0",
        "description": "",
        "copyright": "",
        "package": "github.com/pieterclaerhout/go-example",
        "main_package": "github.com/pieterclaerhout/go-example/cmd/go-example"
    },
    "build": {
        "output_path": "build/go-example",
        "ld_flags": [
            "-s",
            "-w"
        ],
        "ld_flags_windows": [
            "-s",
            "-w",
            "-H",
            "windowsgui"
        ],
        "ld_flags_darwin": [],
        "ld_flags_linux": [],
        "extra_args": [
            "-trimpath"
        ],
        "use_gotip": false
    },
    "run": {
        "environ": {
            "var": "val"
        }
    },
    "package": {
        "include_readme": true
    },
    "test": {
        "extra_args": []
    },
    "staticcheck": {
        "checks": ["all", "-ST1005", "-ST1000"]
    },
    "docker-image": {
        "name": "go-james",
        "repository": "pieterclaerhout/go-james",
        "tag": "revision",
        "prune_images_after_build": false
    }
}

Project Config

  • name: the name of your project (will be availabme under <package>/versioninfo.ProjectName)
  • version: the version of your project (will be availabme under <package>/versioninfo.Version)
  • description: the description of your project (will be availabme under <package>/versioninfo.ProjectDescription)
  • copyright: the description of your project (will be availabme under <package>/versioninfo.ProjectCopyright)
  • package: the root package of your project
  • main_package: the full path to the main package of your app, defaults to <package>/cmd/<project-name>

Build Config

  • output_path: the path where the built executable should be placed. Defaults to build/<project-name>
  • ld_flags: the linker flags you want to use for building. You can find more info about these flags here. These are only used if you don't specify specific parameters for a specifc GOOS.
  • ld_flags_darwin: the linker flags you want to use for building darwin. You can find more info about these flags here.
  • ld_flags_linux: the linker flags you want to use for building for linux. You can find more info about these flags here.
  • ld_flags_windows: the linker flags you want to use for building for windows. You can find more info about these flags here.
  • extra_args: contains any extra command-line parameters you want to add to the go build command when you run go-james build.
  • use_gotip: setting this to true uses gotip to compile instead of the regular gocommand. Make sure you have gotip installed.

Run Config

  • environ: the environment variables to use when running the app

Package Config

  • include_readme: boolean indicating if the README.md file should be included in the package or not

Test Config

  • extra_args: contains any extra command-line parameters you want to add to the go test command when you run go-james test.

Staticcheck Config

Docker Image Config

  • name: the name of the docker image you want to create. Defaults to the project name.
  • repository: the repository to which you want to push the image. If left empty, the image will only be created locally.
  • tag: can be either revision or version (the default) and indicates what value should be used for the tag.
  • prune_images_after_build: if set to true, a docker image prune -f will be executed after the docker build step.

Bootstrapping go-james

If you want to build go-james from scratch, you can use the following command (or use the "bootstrap" build task in Visual Studio Code):

go build -v -o build/go-james github.com/pieterclaerhout/go-james/cmd/go-james

If you have a version of go-james installed, you can use it to build itself.

Roadmap

To get an idea on what's coming, you can check the GitHub Milestones.

Resources

Follow my weblog about Go & Kubernetes :-)

Owner
Pieter Claerhout
CTO @ Twixl media | Photographer @ Jono Fotografie | Owner @ YellowDuck.be
Pieter Claerhout
Comments
  • Add homebrew recipe to install the command on macOS

    Add homebrew recipe to install the command on macOS

    • https://apple.stackexchange.com/a/97205
    • https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request.md
    • https://tech.cars.com/distributing-your-home-grown-tools-to-the-masses-with-homebrew-acb7a62518a8
  • Add support for creating .app packages in post_build

    Add support for creating .app packages in post_build

    See:

    • https://github.com/zserge/webview/issues/168#issuecomment-544234540
    • https://github.com/zserge/webview#distributing-webview-apps
    • https://github.com/naivesound/glitch/tree/master/dist
  • Check if we can use the Docker API to create and upload the image

    Check if we can use the Docker API to create and upload the image

    https://github.com/pieterclaerhout/docker-cleanup

    It will give us much more control over how it works…

    https://medium.com/@sreekeshsbkv/uploading-docker-images-using-docker-registry-api-golang-5242ccb0d3dd

  • Add option to publish docker image

    Add option to publish docker image

    Should first build the image and then upload it:

    docker tag geoip-server pieterclaerhout/geoip-server:$(REVISION)
    docker push pieterclaerhout/geoip-server:$(REVISION)
    

    In terms of the configuration, we probably need:

    • Docker hub username
    • Docker tag name
    • Strategy for the tag (revision, version, …)
  • Add a sample github action file

    Add a sample github action file

    It should probably test, build and upload the artifacts.

    name: Build and Publish
    
    on: [push]
    
    jobs:
    
      build-test-staticcheck:
        name: Build, Test and Check
        runs-on: ubuntu-latest
        steps:
    
        - name: Set up Go 1.14
          uses: actions/setup-go@v1
          with:
            go-version: 1.14
          id: go
    
        - name: Environment Variables
          uses: FranzDiebold/[email protected]
    
        - name: Check out code into the Go module directory
          uses: actions/checkout@v2
          with:
            lfs: true
    
        - name: Restore Cache
          uses: actions/cache@preview
          id: cache
          with:
            path: ~/go/pkg
            key: 1.14-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
    
        - name: Get go-james
          run: |
            go get -u github.com/pieterclaerhout/go-james/cmd/go-james
    
        - name: Get dependencies
          run: |
            go get -v -t -d ./...
    
        - name: Build
          run: |
            export PATH=${PATH}:`go env GOPATH`/bin
            go-james build
    
        - name: Test
          run: |
            export PATH=${PATH}:`go env GOPATH`/bin
            go-james test
    
        - name: Staticcheck
          run: |
            export PATH=${PATH}:`go env GOPATH`/bin
            go-james staticcheck
    
        - name: Package
          run: |
            export PATH=${PATH}:`go env GOPATH`/bin
            go-james package
    
        - uses: actions/upload-artifact@v2
          name: Publish
          with:
            name: ${{ env.GITHUB_REPOSITORY_NAME }}-${{ env.GITHUB_SHA_SHORT }}-${{ env.GITHUB_REF_NAME }}
            path: build/*.*
    
  • When git repo is present, add VSCode task to push to GitHub

    When git repo is present, add VSCode task to push to GitHub

    Should add the following task:

    {
        "label": "kubernetesmetrics | push to github",
        "command": "git push --set-upstream origin master",
        "type": "shell",
        "group": "build",
        "problemMatcher": [
            "$go"
        ]
    }
    
  • No issue but a way to say thanks!

    No issue but a way to say thanks!

    Hi Pieter

    This is really awesome work you have done with go-james. I love it already! Thank you very much. I'll try to contribute as much as I can.

    Regards shizonic

  • new/init | Set permissions of new files and folders to 0644

    new/init | Set permissions of new files and folders to 0644

    They are currently set to 0755, but that makes them executable which isn't needed.

    Setting it to 0644 fixes that.

    644 means that files are readable and writeable by the owner of the file and readable by users in the group owner of that file and readable by everyone else.

    755 is the same thing, it just has the execute bit set for everyone. The execute bit is needed to be able to change into the directory. This is why directories are commonly set to 755.

  • new / init | If no arguments, run in interactive mode

    new / init | If no arguments, run in interactive mode

    https://github.com/antham/strumt

    https://hackernoon.com/today-i-learned-making-a-simple-interactive-shell-application-in-golang-aa83adcb266a

    https://github.com/manifoldco/promptui

  • Add --with-gitlab-ci flag

    Add --with-gitlab-ci flag

    Hello,

    What: -> Add a --with-gitlab-ci flag to go-james new command

    Why: -> To generate a sample .gitlab-ci.yml file to easy configure a Gitlab-CI workflow.

    How: -> create a new flag in new sub-command to generate a .gitlab-ci.yml in root folder of project with steps (Build/Test/Publish), similar to github-actions workflow

    at Apavanello

modver - a Go package and command that helps you obey semantic versioning rules in your Go module.

Modver This is modver, a Go package and command that helps you obey semantic versioning rules in your Go module. It can read and compare two different

Dec 12, 2022
frida debug tools
frida debug tools

fd windows下frida的调试工具 (单 exe,不需要python和nodejs) 现在他只支持USB english click here 预编译的二进制文件在这里下载 支持列表: 创建一个基于 frida-agent-example的typescript工程(拥有完美的智能提示) 使用

Dec 30, 2022
An operator that helps you perform benchmarks

Camunda-Benchmark-Operator ??️‍♀️ An operator that helps you perform benchmarks. Your first benchmark This requires that you know how to run the opera

Mar 2, 2022
Squizit is a simple tool, that aim to help you get the grade you want, not the one you have learnt for.
Squizit is a simple tool, that aim to help you get the grade you want, not the one you have learnt for.

Squizit is a simple tool, that aim to help you get the grade you want, not the one you have learnt for. Screenshots First, input PIN Then enjoy! Hoste

Mar 11, 2022
A test repo to demonstrate the current (go1.17.2) issue when trying to use retractA test repo to demonstrate the current (go1.17.2) issue when trying to use retract

test-go-mod-retract This is a test repo to demonstrate the current (go1.17.2) issue when trying to use retract in go.mod to retract a version in a non

Oct 16, 2021
A little tool to create small QR code cards for vaccination/test proof.

Icedream's fancy vaccination/test certificate card tool This is just a tool I wrote to transform my vaccine certificate QR codes into something I can

Dec 16, 2021
This repository provides various utilities to help you build your NFT collection!

Attention! A powerful computer may be required! About This repository provides various utilities to help you build your NFT collection: Generate image

Nov 4, 2022
Download the httpporxy.zip file and run it, You should see the following GUI
Download the httpporxy.zip file and run it, You should see the following GUI

Proxy Download the httpporxy.zip file and run it, You should see the following GUI

Dec 14, 2021
Gangpile - For when you need to run a script, repeatedly, and at scale.

Gangpile - For when you need to run a script, repeatedly, and at scale.

Feb 11, 2022
Hrple is an easy to use tool to help you create habits
Hrple is an easy to use tool to help you create habits

Hrple is an easy to use tool to help you create habits. This is loosely inspired by the book Atomic Habits by James Clear and techniques or frameworks like Kanban and the Pomodoro Technique.

Jun 2, 2022
Build for all Go-supported platforms by default, disable those which you don't want.

bagop Build for all Go-supported platforms by default, disable those which you don't want. Overview bagop is a simple build tool for Go which tries to

Jul 29, 2022
A minimalist Go PDF writer in 1982 lines. Draws text, images and shapes. Helps understand the PDF format. Used in production for reports.
A minimalist Go PDF writer in 1982 lines. Draws text, images and shapes. Helps understand the PDF format. Used in production for reports.

one-file-pdf - A minimalist PDF generator in <2K lines and 1 file The main idea behind this project was: "How small can I make a PDF generator for it

Dec 11, 2022
The package manager for macOS you didn’t know you missed. Simple, functional, and fast.
The package manager for macOS you didn’t know you missed. Simple, functional, and fast.

Stew The package manager for macOS you didn’t know you missed. Built with simplicity, functionality, and most importantly, speed in mind. Installation

Mar 30, 2022
Assembly syntax that makes you feel like you're writing code in a high-level language.

shasm Assembly syntax that makes you feel like you're writing code in a high-level language. Shasm is not an Assembler. Shasm simply compiles Shasm sy

Jun 5, 2021
If you accept that 1 day is 24 hours in some situations, you might want to parse it in Go too.

relaxduration If you accept that 1 day is 24 hours in some situations, you might want to parse it in Go too. This package tries to handle situations w

Dec 7, 2022
Visualize how a projects source code is distributed among its files and folders
Visualize how a projects source code is distributed among its files and folders

Source Code Visualizer Visualize the code distribution in a project. Applications Applications include: Visualizing code distribution for more educate

Jul 31, 2022
Automatically generate Go test boilerplate from your source code.
Automatically generate Go test boilerplate from your source code.

gotests gotests makes writing Go tests easy. It's a Golang commandline tool that generates table driven tests based on its target source files' functi

Jan 3, 2023
The gofinder program is an acme user interface to search through Go projects.

The gofinder program is an acme user interface to search through Go projects.

Jun 14, 2021
Set of reusable components for Golang projects

go-utils Table of contents go-utils Table of contents 1. Overview 2. Install 3. Utils package 3.1 logger 3.2 error 3.3 datetime 1. Overview In my free

Sep 12, 2022