Adding a Makefile for Multi-git
See how a Makefile for multi-git can tie all these capabilities together and provide a one-stop shop for managing your program. We will also discuss the relationship between Makefiles and CI/CD pipelines as well as alternatives to Makefiles.
We'll cover the following
Creating a Makefile for multi-git
Letβs start with the most basic target: build
. The comment with the double hashtags will become a nice help message later. Note the tabbed indentation, which is an infamous gotcha of Makefiles. Another important issue is escaping the Dollar sign by doubling it. This is necessary because a single Dollar sign is used by Makefile variables. The command itself is using the -ldflags
to inject the git tag and timestamp to the program and writes the executable to the current directory while adding the OS and architecture.
### Build multi-git and inject the git tag and build time to variables in main
build:
go build -ldflags "-X 'main.gitTag=$$(git describe --tags)' \
-X 'main.buildTimestamp=$$(date -u)'" \
-o multi-git_$$(go env GOOS)_$$(go env GOARCH)
On my amd64 Mac the final executable is called multi-git_darwin_amd4
(Darwin is the original name of the macOS).
The install target depends on the build target as in install: build
. This means that
when you run make install
, it will first run the build
target and then execute the commands of the install target
.
### Install multi-git into /usr/local/bin (avoid standard go install)
install: build
mv multi-git_$$(go env GOOS)_$$(go env GOARCH) \
/usr/local/bin/multi-git_$$(go env GOOS)_$$(go env GOARCH)
rm /usr/local/bin/multi-git
ln -s /usr/local/bin/multi-git_$$(go env GOOS)_$$(go env GOARCH) \
/usr/local/bin/multi-git
Here are a few test targets. We can use the go test
command to run just the unit tests, just the end-to-end tests, or all the tests. In addition, there is a Ginkgo-test target that runs the tests using Ginkgo:
### Run only the unit tests
unit-tests: build
go test ./pkg/... -v
### Run only the end to end tests
e2e-tests: install
go test ./e2e_tests/... -v
### Run all the tests
test: unit-tests e2e-tests
### Run all the tests with ginkgo
ginkgo-test: build
ginkgo -r -v
Here is what it looks like to run the unit tests:
(π)/multi-git/
$ make unit-tests
? github.com/the-gigi/multi-git/pkg/helpers [no test files]
=== RUN TestRepoManager
Running Suite: RepoManager Suite
================================
Random Seed: 1594152750
Will run 7 of 7 specs
β’β’β’β’β’β’β’
Ran 7 of 7 Specs in 0.233 seconds
SUCCESS! -- 7 Passed | 0 Failed | 0 Pending | 0 Skipped
--- PASS: TestRepoManager (0.23s)
PASS
ok github.com/the-gigi/multi-git/pkg/repo_manager (cached)
Note that the unit-tests
targets only depend on the build
target. However, the e2e-tests
target depends on the install
target, which depends on the build target
because the end-to-end tests expect multi-git to be available on the path, which the install
takes care of.
We have a couple of Docker targets, too. The docker-build
builds a Docker image and tags it with multi-git:latest
. The docker-push
target logs in to DockerHub and pushes the image.
### Dockerize multi-git
docker-build:
docker build --build-arg -t g1g1/multi-git:latest .
### Push multi-git to DockerHub (requires DockerHub account)
docker-push: docker-build
docker login -u g1g1
docker push g1g1/multi-git:latest
Since, the same multi-git:latest
tag is used by all images the last image always overwrites the previous one. If you want to go back to a previous image, then another tag is needed (e.g. the git tag).
Last, but not least I skipped the first command in the Makefile, which executes if you just type make
:
## This Makefile saves some typing and groups some common commands
## # The fancy help is from here:
## https://gist.github.com/rcmachado/af3db315e31383502660#file-makefile
#
.SILENT:
.PHONY: help
### This help screen
help:
printf "Available targets:\n\n"
awk '/^[a-zA-Z\-\_0-9]+:/ { \
helpMessage = match(lastLine, /^## (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")-1); \
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
printf "%-15s %s\n", helpCommand, helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST)
I will not attempt to explain it, as I borrowed it from the above-mentioned gist and just modified it slightly. The end result is a very nice help screen that lists all the targets in the Makefile with the double-hashtag comments as the description.
(π)/multi-git/
$ make
Available targets:
help This help screen
build Build multi-git and inject the git tag and build time to variables in main
install Install multi-git into /usr/local/bin (avoid standard go install)
unit-tests Run only the unit tests
e2e-tests Run only the end to end tests
test Run all the tests
ginkgo-test Run all the tests with ginkgo
docker-build Dockerize multi-git
docker-push Push multi-git to DockerHub (requires DockerHub account)
Get hands-on with 1400+ tech skills courses.