MartinHeinz/go-github-app

View on GitHub
Makefile

Summary

Maintainability
Test Coverage
# This is adapted from https://github.com/thockin/go-build-template

# The binary to build (just the basename).
BIN := app

# Where to push the docker image.
REGISTRY ?= ghcr.io/martinheinz/go-github-app

# This version-strategy uses git tags to set the version string
VERSION := $(shell git describe --tags --always --dirty)

# This version-strategy uses a manual value to set the version string
#VERSION := 1.2.3

###
### These variables should not need tweaking.
###

SRC_DIRS := cmd pkg # directories which hold app source (not vendored)

ALL_PLATFORMS := linux/amd64

# Used internally.  Users should pass GOOS and/or GOARCH.
OS := $(if $(GOOS),$(GOOS),$(shell go env GOOS))
ARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH))

BASEIMAGE ?= gcr.io/distroless/static

IMAGE := $(REGISTRY)/$(BIN)
TAG := $(VERSION)__$(OS)_$(ARCH)

BUILD_IMAGE ?= golang:1.17-alpine
# Tweaked image used for test runs (see `test.Dockerfile`)
TEST_IMAGE ?= martinheinz/golang:1.17-alpine-test

# If you want to build all binaries, see the 'all-build' rule.
# If you want to build all containers, see the 'all-container' rule.
all: build

# For the following OS/ARCH expansions, we transform OS/ARCH into OS_ARCH
# because make pattern rules don't match with embedded '/' characters.

build-%:
    @$(MAKE) build                        \
        --no-print-directory              \
        GOOS=$(firstword $(subst _, ,$*)) \
        GOARCH=$(lastword $(subst _, ,$*))

container-%:
    @$(MAKE) container                    \
        --no-print-directory              \
        GOOS=$(firstword $(subst _, ,$*)) \
        GOARCH=$(lastword $(subst _, ,$*))

push-%:
    @$(MAKE) push                         \
        --no-print-directory              \
        GOOS=$(firstword $(subst _, ,$*)) \
        GOARCH=$(lastword $(subst _, ,$*))

all-build: $(addprefix build-, $(subst /,_, $(ALL_PLATFORMS)))

all-container: $(addprefix container-, $(subst /,_, $(ALL_PLATFORMS)))

build: bin/$(OS)_$(ARCH)/$(BIN)

# Directories that we need created to build/test.
BUILD_DIRS := bin/$(OS)_$(ARCH)     \
              .go/bin/$(OS)_$(ARCH) \
              .go/cache

# The following structure defeats Go's (intentional) behavior to always touch
# result files, even if they have not changed.  This will still run `go` but
# will not trigger further work if nothing has actually changed.
OUTBIN = bin/$(OS)_$(ARCH)/$(BIN)
$(OUTBIN): .go/$(OUTBIN).stamp
    @true

# This will build the binary under ./.go and update the real binary if needed.
.PHONY: .go/$(OUTBIN).stamp
.go/$(OUTBIN).stamp: $(BUILD_DIRS)
    @echo "making $(OUTBIN)"
    @docker run                                                 \
        -i                                                      \
        --rm                                                    \
        -u $$(id -u):$$(id -g)                                  \
        -v $$(pwd):/src                                         \
        -w /src                                                 \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin                \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH)  \
        -v $$(pwd)/.go/cache:/.cache                            \
        --env HTTP_PROXY=$(HTTP_PROXY)                          \
        --env HTTPS_PROXY=$(HTTPS_PROXY)                        \
        $(BUILD_IMAGE)                                          \
        /bin/sh -c "                                            \
            ARCH=$(ARCH)                                        \
            OS=$(OS)                                            \
            VERSION=$(VERSION)                                  \
            ./build/build.sh                                    \
        "
    @if ! cmp -s .go/$(OUTBIN) $(OUTBIN); then \
        mv .go/$(OUTBIN) $(OUTBIN);            \
        date >$@;                              \
    fi

# Example: make shell CMD="-c 'date > datefile'"
shell: $(BUILD_DIRS)
    @echo "launching a shell in the containerized build environment"
    @docker run                                                 \
        -ti                                                     \
        --rm                                                    \
        -u $$(id -u):$$(id -g)                                  \
        -v $$(pwd):/src                                         \
        -w /src                                                 \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin                \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH)  \
        -v $$(pwd)/.go/cache:/.cache                            \
        --env HTTP_PROXY=$(HTTP_PROXY)                          \
        --env HTTPS_PROXY=$(HTTPS_PROXY)                        \
        $(BUILD_IMAGE)                                          \
        /bin/sh $(CMD)

# Used to track state in hidden files.
DOTFILE_IMAGE = $(subst /,_,$(IMAGE))-$(TAG)

container: .container-$(DOTFILE_IMAGE) say_container_name
.container-$(DOTFILE_IMAGE): bin/$(OS)_$(ARCH)/$(BIN) in.Dockerfile
    @sed                                 \
        -e 's|{ARG_BIN}|$(BIN)|g'        \
        -e 's|{ARG_ARCH}|$(ARCH)|g'      \
        -e 's|{ARG_OS}|$(OS)|g'          \
        -e 's|{ARG_FROM}|$(BASEIMAGE)|g' \
        in.Dockerfile > .dockerfile-$(OS)_$(ARCH)
    @docker build -t $(IMAGE):$(TAG) -t $(IMAGE):latest -f .dockerfile-$(OS)_$(ARCH) .
    @docker images -q $(IMAGE):$(TAG) > $@

say_container_name:
    @echo "container: $(IMAGE):$(TAG)"

push: .push-$(DOTFILE_IMAGE) say_push_name
.push-$(DOTFILE_IMAGE): .container-$(DOTFILE_IMAGE)
    @docker push $(IMAGE):$(TAG)

push-latest: .push-$(DOTFILE_IMAGE) say_push_name_latest
    @docker push $(IMAGE):latest

say_push_name:
    @echo "pushed: $(IMAGE):$(TAG)"

say_push_name_latest:
    @echo "pushed: $(IMAGE):$(TAG)"

version:
    @echo $(VERSION)

test: $(BUILD_DIRS)
    @docker run                                                 \
        -i                                                      \
        --rm                                                    \
        -u $$(id -u):$$(id -g)                                  \
        -v $$(pwd):/src                                         \
        -w /src                                                 \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin                \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH)  \
        -v $$(pwd)/.go/cache:/.cache                            \
        -v $$(pwd)/config:/config                               \
        -v $$(pwd)/cmd/app/test_data:/test_data                 \
        --env HTTP_PROXY=$(HTTP_PROXY)                          \
        --env HTTPS_PROXY=$(HTTPS_PROXY)                        \
        $(TEST_IMAGE)                                           \
        /bin/sh -c "                                            \
            ARCH=$(ARCH)                                        \
            OS=$(OS)                                            \
            VERSION=$(VERSION)                                  \
            ./build/test.sh $(SRC_DIRS)                         \
        "

ci: $(BUILD_DIRS)
    @docker run                                                 \
        -i                                                      \
        --rm                                                    \
        -u $$(id -u):$$(id -g)                                  \
        -v $$(pwd):/src                                         \
        -w /src                                                 \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin                \
        -v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH)  \
        -v $$(pwd)/.go/cache:/.cache                            \
        -v $$(pwd)/reports:/reports                             \
        -v $$(pwd)/config:/config                               \
        -v $$(pwd)/cmd/app/test_data:/test_data                 \
        --env HTTP_PROXY=$(HTTP_PROXY)                          \
        --env HTTPS_PROXY=$(HTTPS_PROXY)                        \
        $(TEST_IMAGE)                                           \
        /bin/sh -c "                                            \
            ARCH=$(ARCH)                                        \
            OS=$(OS)                                            \
            VERSION=$(VERSION)                                  \
            ./build/test_ci.sh $(SRC_DIRS)                      \
        "

$(BUILD_DIRS):
    @mkdir -p $@

run:
    @docker run                                                 \
        --rm                                                    \
        --name go-github-app                                    \
        -v $$(pwd)/config:/config                               \
        -p 8080:8080                                            \
        $(IMAGE):$(TAG)

clean: container-clean bin-clean

container-clean:
    rm -rf .container-* .dockerfile-* .push-*

bin-clean:
    rm -rf .go bin