Generates a Makefile and optionally also GitHub workflows and a Dockerfile for your Go application:
- Makefile follows established Unix conventions for installing and packaging, and includes targets for vendoring, running tests and checking code quality.
- GitHub Workflows use GitHub Actions to lint, build, and test your code. Additionally, you can enable workflows for checking your codebase for security issues (e.g. CodeQL code scanning), spelling errors, and missing license headers.
The easiest way to get go-makefile-maker
is: go install github.com/sapcc/go-makefile-maker@latest
.
We also support the usual Makefile invocations: make
, make check
, and make install
. The latter understands the conventional environment variables for choosing install locations: DESTDIR
and PREFIX
.
You usually want something like make && sudo make install PREFIX=/usr/local
.
Put a Makefile.maker.yaml
file in your Git repository's root directory, then run the following to generate Makefile and GitHub workflows:
$ go-makefile-maker
go-makefile-maker
also generates a help
target for usage info:
$ make help
In addition to the Makefile
, you should also commit the Makefile.maker.yaml
file so that your users don't need to have go-makefile-maker
installed.
go-makefile-maker
requires a config file (Makefile.maker.yaml
) in the YAML format.
Take a look at go-makefile-maker
's own config file for an example of what a config could like.
The config file has the following sections:
- metadata
- makefile
- binaries
- testPackages
- coverageTest
- dockerfile
- variables
- golang
- golangciLint
- Goreleaser
- spellCheck
- renovate
- verbatim
- githubWorkflow
metadata:
url: https://github.com/foo/bar
metadata
contains information about the project which cannot be guessed consistently:
url
is the repository's remote URL.
makefile:
enabled: false
makefile
contains settings related to the higher level Makefile
generation.
enabled
is an optional setting to disable the Makefile
generation completely.
If not specified, the setting is treated as being set to true to maintain backwards compatibility with older configs.
binaries:
- name: example
fromPackage: ./cmd/example
installTo: bin/
- name: test-helper
fromPackage: ./cmd/test-helper
For each binary specified here, a target will be generated that builds it with go build
and puts it in build/$NAME
.
The fromPackage
is a Go module path relative to the directory containing the Makefile.
If installTo
is set for at least one binary, the install
target is added to the Makefile, and all binaries with installTo
are installed by it.
In this case, example
would be installed as /usr/bin/example
by default, and test-helper
would not be installed.
testPackages:
only: '/internal'
except: '/test/util|/test/mock'
By default, all packages inside the repository are subject to testing, but this section can be used to restrict this.
The values in only
and except
are regexes for grep -E
.
Since only entire packages (not single source files) can be selected for testing, the regexes have to match package names, not on file names.
coverageTest:
only: '/internal'
except: '/test/util|/test/mock'
When make check
runs go test
, it produces a test coverage report.
By default, all packages inside the repository are subject to coverage testing, but this section can be used to restrict this.
The values in only
and except
are regexes for grep -E
.
Since only entire packages (not single source files) can be selected for coverage testing, the regexes have to match package names, not on file names.
dockerfile:
enabled: true
entrypoint: [ "/bin/bash", "--", "--arg" ]
extraDirectives:
- 'LABEL mylabel=myvalu'
extraIgnores:
- tmp
- files
extraPackages:
- curl
- openssl
user: root
withLinkerdAwait: true
When enabled
, go-makefile-maker will generate a Dockerfile
and a .dockerignore
file.
The Dockerfile uses the Golang base image to run make install
, then copies all installed files into a fresh Alpine base image.
The image is provisioned with a dedicated user account (name appuser
, UID 4200, home directory /home/appuser
) and user group (name appgroup
, GID 4200) with stable names and IDs.
This user account is intended for use with all payloads that do not require a root user.
entrypoint
allows overwriting the final entrypoint.extraDirectives
appends additional directives near the end of the Dockerfile.extraIgnores
appends entries in.dockerignore
to the default ones.extraPackages
installs extra Alpine packages in the final Docker layer.ca-certificates
is always installed.runAsRoot
skips the privilege drop in the Dockerfile, i.e. theUSER appuser:appgroup
command is not added.withLinkerdAwait
wether to download the binary and prepend linkerd-await to the entrypoint. For more details see https://github.com/linkerd/linkerd-await.
variables:
GO_BUILDFLAGS: '-mod vendor'
GO_LDFLAGS: ''
GO_TESTENV: ''
Allows to override the default values of Makefile variables used by the autogenerated recipes.
This mechanism cannot be used to define new variables to use in your own rules; use verbatim
for that.
By default, all accepted variables are empty.
The only exception is that GO_BUILDFLAGS
defaults to -mod vendor
when vendoring is enabled (see below).
A typical usage of GO_LDFLAGS
is to give compile-time values to the Go compiler with the -X
linker flag:
variables:
GO_LDFLAGS: '-X github.com/foo/bar.Version = $(shell git describe --abbrev=7)'
However, for this specific usecase, we suggest that your application use github.com/sapcc/go-api-declarations/bininfo
instead. When the respective module is present as a direct dependency in the go.mod
file, go-makefile-maker will
auto-generate suitable linker flags to fill the global variables in the bininfo
package.
GO_TESTENV
can contain environment variables to pass to go test
:
variables:
GO_TESTENV: 'POSTGRES_HOST=localhost POSTGRES_DATABASE=unittestdb'
golang:
enableVendoring: true
setGoModVersion: true
Set golang.enableVendoring
to true
if you vendor all dependencies in your repository. With vendoring enabled:
- The default for
GO_BUILDFLAGS
is set to-mod vendor
, so that build targets default to using vendored dependencies. This means that building binaries does not require a network connection. - The
make tidy-deps
target is replaced by amake vendor
target that runsgo mod tidy && go mod verify
just likemake tidy-deps
, but also runsgo mod vendor
. This target can be used to get the vendor directory up-to-date before commits.
If golang.setGoModVersion
is set to true
then go.mod
will be automatically updated to the latest version.
golangciLint:
createConfig: false
errcheckExcludes:
- io/ioutil.ReadFile
- io.Copy(*bytes.Buffer)
- io.Copy(os.Stdout)
- (*net/http.Client).Do
skipDirs:
- easypg/migrate/*
The make check
and make static-check
targets use golangci-lint
to lint your code.
If createConfig
is set to true
then go-makefile-maker
will create a
config file (.golangci.yaml
) for golangci-lint
and keep it up-to-date (in case of new
changes). This config file enables extra linters in addition to the default ones and
configures various settings that can improve code quality.
Additionally, if createConfig
is true
, you can specify a list of files skipped entirely by golangci-lint in skipDirs
and a list of functions to be excluded from errcheck
linter in errcheckExcludes
field.
Refer to errcheck
's README for info on the format
for function signatures that errcheck
accepts.
Take a look at go-makefile-maker
's own golangci-lint
config file for an up-to-date example of what the generated config would look like.
goreleaser:
enabled: true
If goreleaser.enabled
is set to true a config file for goreleaser will be generated based on the metadata of the repository.
spellCheck:
ignoreWords:
- example
- exampleTwo
golangci-lint
(if golangciLint.createConfig
is true
) and the spell check GitHub workflow (githubWorkflow.spellCheck
) use misspell
to check for spelling errors.
If spellCheck.ignoreWords
is defined then both golangci-lint
and spell check workflow will give this word list to misspell
so that they can be ignored during its checks.
renovate:
enabled: true
assignees:
- devnull
- urandom
goVersion: 1.18
packageRules:
- matchPackageNames: []
matchPackagePrefixes: []
matchUpdateTypes: []
matchDepTypes: []
matchFiles: []
allowedVersions: ""
autoMerge: false
enabled: false
Generate RenovateBot config to automatically create pull requests weekly on Fridays with dependency updates.
To assign people to the PRs created by renovate, add their GitHub handle to the assignees
list.
Optionally overwrite go version with goVersion
, by default the Go version from go.mod
file will be used.
Additionally, you can also define packageRules
. Note that only the fields mentioned above are accepted when defining a packageRule
. The following package rules are defined by default:
packageRules:
- matchPackagePatterns: [".*"]
groupName: "all" # group all PRs together
- matchPackageNames: ["golang"]
allowedVersions: $goVersion.x
- matchDepTypes: ["action"]
enabled: false # because github-actions will be updated by go-makefile-maker itself, see githubWorkflow config section below.
- matchDepTypes: ["dockerfile"]
enabled: false # because dockerfile will be updated by go-makefile-maker itself, see docker config section above.
# This package rule will be added if go.mod file has a `k8s.io/*` dependency.
- matchPackagePrefixes: ["k8s.io/"]
allowedVersions: 0.25.x
# This package rule will be added along with the required matchPackagePrefixes if go.mod file has the respective dependencies.
- matchPackagePrefixes:
- github.com/sapcc/go-api-declarations
- github.com/sapcc/gophercloud-sapcc
- github.com/sapcc/go-bits
autoMerge: true
verbatim: |
run-example: build/example
./build/example example-config.txt
This field can be used to add your own definitions and rules to the Makefile. The text in this field is copied into the Makefile mostly verbatim, with one exception: Since YAML does not like tabs for indentation, we allow rule recipes to be indented with spaces. This indentation will be replaced with tabs before writing it into the actual Makefile.
The githubWorkflow
section holds configuration options that define the behavior of various GitHub workflows.
Hint: You can prevent the workflows from running by including [ci skip]
in your commit message
(more info).
This section defines global settings that apply to all workflows. If the same setting is supported by a specific workflow and is defined then that will take override its global value.
global:
defaultBranch: dev
goVersion: 1.18
defaultBranch
specifies the Git branch on which push
actions will trigger the
workflows. This does not affect pull requests, they will automatically trigger all
workflows regardless of which branch they are working against. go-makefile-maker
will
automatically run git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
and use its value by default.
goVersion
specifies the Go version that is used for jobs that require Go.
go-makefile-maker
will automatically retrieve the Go version from go.mod
file and use
that by default.
This workflow:
- checks your code using
golangci-lint
- ensures that your code compiles successfully
- runs tests and generates test coverage report
- uploads the test coverage report to Coveralls
ci:
enabled: true
runOn:
- macos-latest
- ubuntu-latest
- windows-latest
coveralls: true
postgres:
enabled: true
version: 12
kubernetesEnvtest:
enabled: true
version: 1.25.x!
ignorePaths: []
runOn
specifies a list of machine(s) to run the build
and test
jobs on (more
info). You can use this to ensure that your build compilation and tests are
successful on multiple operating systems. Default value for this is ubuntu-latest
.
If coveralls
is true
then your test coverage report will be uploaded to Coveralls. Make sure that you have enabled Coveralls for your GitHub repo beforehand.
If postgres.enabled
is true
then a PostgreSQL service container will be added for the
test
job. You can connect to this PostgreSQL service at localhost:54321
with
postgres
as username and password (More info).
postgres.version
specifies the Docker Hub image tag for the postgres
image that is used for this container. By default 12
is used as
image tag.
If kubernetesEnvtest.enabled
is true
then
Envtest binaries will be downloaded
using
setup-envtest
for the test
job. The version for binaries can be specified using the
kubernetesEnvtest.version
field. By default 1.25.x!
is used as the version.
ignorePaths
specifies a list of filename patterns. Workflows will not trigger if a path
name matches a pattern in this list. More info and filter pattern cheat
sheet. This option is not defined by default.
If enabled
is set to true, the generated Dockerfile
is build and pushed to repository path under ghcr.io
.
pushContainerToGhcr:
enabled: true
If release
is enabled a workflow is generated which creates a new GitHub release using goreleaser when a git tag is pushed.
goreleaser.enabled
must be enabled when using this workflow.
If securityChecks
is enabled then it will generate the following workflows:
-
CodeQL workflow will run CodeQL, GitHub's industry-leading semantic code analysis engine, on your source code to find security vulnerabilities. You can see the security report generated by CodeQL under your repo's Security tab.
In addition to running the workflow when new code is pushed, this workflow will also run on a weekly basis (every Monday at 07:00 AM) so that existing code can be checked for new vulnerabilities.
-
dependency-review workflow will scan your pull requests for dependency changes and will raise an error if any new dependencies have existing vulnerabilities. It uses the GitHub Advisory Database as a source.
-
govulncheck workflow will scan your dependencies for vulnerarbilites and will raise an error if any dependency has an existing vulnerability and the code path is in use. It uses the Go Vulnerability Database as a source.
securityChecks:
enabled: true
This workflow ensures that all your source code files have a license header. It
uses addlicense
for this.
license:
enabled: true
patterns:
- "**/*.go"
ignorePatterns:
- "vendor/**"
patterns
specifies a list of file patterns to check. For convenience, the globstar
option is enabled for the workflow's shell session therefore you can use **
in your file
patterns. Additionally, addlicense
will scan directory patterns recursively. See
addlicense
's README for more info. Default value for this is **/*.go
,
i.e. check all Go files.
ignorePatterns
specifies a list of file patterns to check. You can use any pattern
supported by doublestar. See addlicense
's README for
more info. Default value for this is vendor/**
, i.e. exclude everything under vendor
directory.
Hint: you can also use addlicense
to add license headers to all Go files excluding
vendor
directory by running make license-headers
.
This workflow uses misspell
to check your repo for spelling errors. Unlike
golangci-lint
that only runs misspell
on .go
files, this workflow will run
misspell
on your entire repo.
spellCheck:
enabled: true