From 699831be420736e948ee35bff2b2a9f91f4160ec Mon Sep 17 00:00:00 2001 From: Akis Maziotis Date: Mon, 13 Nov 2023 10:05:31 +0200 Subject: [PATCH] [feat] Alligning makefile to the standardized template (#109) We are alligning the makefile to the standardized template, along with the changes required for this project. We are also refactoring CI to compensate for these changes. Now building and packaging for most architectures and operating systems. Signed-off-by: Akis Maziotis --- .github/workflows/build.yml | 38 -- .github/workflows/ci.yml | 49 +++ .github/workflows/golangci-lint.yml | 25 -- .github/workflows/test.yml | 37 -- Makefile | 524 +++++++++++++++++++--------- docker/Dockerfile | 1 + 6 files changed, 409 insertions(+), 265 deletions(-) delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/golangci-lint.yml delete mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 8ecf356..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Build - -on: - push: - branches: - - master - pull_request: - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: 1.20.7 - - - name: check dependencies - run: make check-deps - - - name: Run build - run: make package - - - name: Archive production artifacts - uses: actions/upload-artifact@v2 - with: - name: push-proxy-binaries - retention-days: 5 - path: | - ./dist/*.tar.gz - ./dist/checksums.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..001c049 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: Build and Test + +on: + push: + branches: + - master + pull_request: +permissions: + contents: read + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - name: Lint + run: make lint + test: + name: Test + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - name: Test + run: make test + build: + name: Build + runs-on: ubuntu-latest + needs: [lint,test] + steps: + - name: Checkout code + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - name: Build + run: make build + - name: Cleanup + run: make clean + package: + name: Package + runs-on: ubuntu-latest + needs: [build] + steps: + - name: Checkout code + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - name: Package + run: make package + - name: Cleanup + run: make clean diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml deleted file mode 100644 index 583a607..0000000 --- a/.github/workflows/golangci-lint.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: golangci-lint - -on: - push: - branches: - - master - pull_request: - -permissions: - contents: read - -jobs: - golangci: - name: lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: 1.20.7 - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: v1.52.2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 3c52cf3..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Test - -on: - push: - branches: - - master - pull_request: - -permissions: - contents: read - checks: write - pull-requests: write - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: 1.20.7 - - - name: Run tests - run: | - go install gotest.tools/gotestsum@latest - mkdir -p test-reports - gotestsum --junitfile test-reports/unit-tests.xml - - - name: Publish Unit Test Results - uses: EnricoMi/publish-unit-test-result-action@v1 - if: always() - with: - files: test-reports/unit-tests.xml diff --git a/Makefile b/Makefile index c7e6b34..2b224c5 100644 --- a/Makefile +++ b/Makefile @@ -1,172 +1,366 @@ -.PHONY: all dist build build-release build-local package test clean run update-dependencies golangci-lint - -GOFLAGS ?= $(GOFLAGS:) -LDFLAGS ?= $(LDFLAGS:) - -export GOBIN = $(PWD)/bin -GO=go - -# Set version variables for LDFLAGS +# ==================================================================================== +# Variables + +## General Variables + +# Branch Variables +PROTECTED_BRANCH := master +CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD) +# Use repository name as application name +APP_NAME := $(shell basename -s .git `git config --get remote.origin.url`) +# Get current commit +APP_COMMIT := $(shell git log --pretty=format:'%h' -n 1) +# Check if we are in protected branch, if yes use `protected_branch_name-sha` as app version. +# Else check if we are in a release tag, if yes use the tag as app version, else use `dev-sha` as app version. +APP_VERSION ?= $(shell if [ $(PROTECTED_BRANCH) = $(CURRENT_BRANCH) ]; then echo $(PROTECTED_BRANCH); else (git describe --abbrev=0 --exact-match --tags 2>/dev/null || echo dev-$(APP_COMMIT)) ; fi) GIT_VERSION ?= $(shell git describe --tags --always --dirty) -GIT_HASH ?= $(shell git rev-parse HEAD) -DATE_FMT = +'%Y-%m-%dT%H:%M:%SZ' -SOURCE_DATE_EPOCH ?= $(shell git log -1 --pretty=%ct) -ifdef SOURCE_DATE_EPOCH - BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u "$(DATE_FMT)") -else - BUILD_DATE ?= $(shell date "$(DATE_FMT)") -endif -GIT_TREESTATE = "clean" +GIT_TREESTATE = clean DIFF = $(shell git diff --quiet >/dev/null 2>&1; if [ $$? -eq 1 ]; then echo "1"; fi) ifeq ($(DIFF), 1) - GIT_TREESTATE = "dirty" + GIT_TREESTATE = dirty endif -PP_PKG=github.com/mattermost/mattermost-push-proxy/internal/version -LDFLAGS="-X $(PP_PKG).gitVersion=$(GIT_VERSION) -X $(PP_PKG).gitCommit=$(GIT_HASH) -X $(PP_PKG).gitTreeState=$(GIT_TREESTATE) -X $(PP_PKG).buildDate=$(BUILD_DATE)" - -DIST_ROOT=dist -DIST_PATH=$(DIST_ROOT)/mattermost-push-proxy - -all: dist - -dist: | build-release test package - -update-dependencies: - $(GO) get -u ./... - $(GO) mod tidy - -check-deps: - $(GO) mod tidy -v - @if [ -n "$$(command git --no-pager diff --exit-code go.mod go.sum)" ]; then \ - echo "There are unused dependencies that should be removed. Please execute `go mod tidy` to fix it."; \ - exit 1; \ - fi - -build-release: - @echo Building proxy push server - env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -o $(GOBIN)/mattermost-push-proxy-linux-amd64 -trimpath -ldflags $(LDFLAGS) $(GOFLAGS) - env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $(GO) build -o $(GOBIN)/mattermost-push-proxy-linux-arm64 -trimpath -ldflags $(LDFLAGS) $(GOFLAGS) - -build-local: # build push proxy for the current arch - @echo Building proxy push server - env CGO_ENABLED=0 $(GO) build -o $(GOBIN) -trimpath -ldflags $(LDFLAGS) $(GOFLAGS) - -golangci-lint: ## Run golangci-lint on codebase -# https://stackoverflow.com/a/677212/1027058 (check if a command exists or not) - @if ! [ -x "$$(command -v golangci-lint)" ]; then \ - echo "golangci-lint is not installed. Please see https://github.com/golangci/golangci-lint#install for installation instructions."; \ - exit 1; \ - fi; \ - - @echo Running golangci-lint - golangci-lint run ./... - -package-linux-amd64: - @ echo Packaging push proxy for linux amd64 - - mkdir -p $(DIST_PATH)/bin - cp $(GOBIN)/mattermost-push-proxy-linux-amd64 $(DIST_PATH)/bin/mattermost-push-proxy - - cp -RL config $(DIST_PATH)/config - touch $(DIST_PATH)/config/build.txt - echo $(BUILD_NUMBER) | tee -a $(DIST_PATH)/config/build.txt - - mkdir -p $(DIST_PATH)/logs - - cp LICENSE.txt $(DIST_PATH) - cp NOTICE.txt $(DIST_PATH) - cp README.md $(DIST_PATH) - - tar -C dist -czf $(DIST_PATH)-linux-amd64.tar.gz mattermost-push-proxy - rm -rf $(DIST_PATH) - -package-linux-arm64: - @ echo Packaging push proxy for linux arm64 - - mkdir -p $(DIST_PATH)/bin - cp $(GOBIN)/mattermost-push-proxy-linux-arm64 $(DIST_PATH)/bin/mattermost-push-proxy - - cp -RL config $(DIST_PATH)/config - touch $(DIST_PATH)/config/build.txt - echo $(BUILD_NUMBER) | tee -a $(DIST_PATH)/config/build.txt - - mkdir -p $(DIST_PATH)/logs - - cp LICENSE.txt $(DIST_PATH) - cp NOTICE.txt $(DIST_PATH) - cp README.md $(DIST_PATH) - - tar -C dist -czf $(DIST_PATH)-linux-arm64.tar.gz mattermost-push-proxy - -package: build-release package-linux-arm64 package-linux-amd64 - cd dist \ - sha256sum mattermost-push-proxy-linux-amd64.tar.gz >> checksums.txt \ - && sha256sum mattermost-push-proxy-linux-arm64.tar.gz >> checksums.txt - -package-image: build-release - mkdir -p $(DIST_PATH)/bin - - cp -RL config $(DIST_PATH)/config - touch $(DIST_PATH)/config/build.txt - echo $(BUILD_NUMBER) | tee -a $(DIST_PATH)/config/build.txt - - mkdir -p $(DIST_PATH)/logs - - cp LICENSE.txt $(DIST_PATH) - cp NOTICE.txt $(DIST_PATH) - cp README.md $(DIST_PATH) - -PLATFORMS ?= linux/amd64 linux/arm64 -ARCHS = $(patsubst linux/%,%,$(PLATFORMS)) -IMAGE ?= mattermost/mattermost-push-proxy -TAG ?= $(shell git describe --tags --always --dirty) - -# build with buildx -.PHONY: container -container: package-image - @for platform in $(PLATFORMS); do \ - echo "Starting build for $${platform} platform"; \ - docker buildx build \ - --load \ - --progress plain \ - --platform $${platform} \ - --build-arg=ARCH=$${platform##*/} \ - --tag $(IMAGE)-$${platform##*/}:$(TAG) \ - --file docker/Dockerfile \ - .; \ - done - -.PHONY: push -push: container - echo "Pushing $(IMGNAME) tags" - @for platform in $(PLATFORMS); do \ - echo "Pushing tags for $${platform} platform"; \ - docker push $(IMAGE)-$${platform##*/}:$(TAG); \ +# Get current date and format like: 2022-04-27 11:32 +BUILD_DATE := $(shell date +%Y-%m-%d\ %H:%M) + +## General Configuration Variables +# We don't need make's built-in rules. +MAKEFLAGS += --no-builtin-rules +# Be pedantic about undefined variables. +MAKEFLAGS += --warn-undefined-variables +# Set help as default target +.DEFAULT_GOAL := help + +# App Code location +CONFIG_APP_CODE += ./ + +## Docker Variables +# Docker executable +DOCKER := $(shell which docker) +# Dockerfile's location +DOCKER_FILE ?= ./docker/Dockerfile +# Docker options to inherit for all docker run commands +DOCKER_OPTS += --rm --platform "linux/amd64" +# Registry to upload images +DOCKER_REGISTRY ?= docker.io +DOCKER_REGISTRY_REPO ?= mattermost/${APP_NAME}-daily +# Registry credentials +DOCKER_USER ?= user +DOCKER_PASSWORD ?= password +## Docker Images +DOCKER_IMAGE_GO ?= "golang:${GO_VERSION}@sha256:dd9ad81920b63c7f9f18823d888d5fdcc7e7516086fd16654d07bc437f0e2427" +DOCKER_IMAGE_GOLINT ?= "golangci/golangci-lint:v1.52.2@sha256:5fa6a92ab28ca3421c88d2b6cd794c9759d05a999aceca73053d014aad41b9d3" +DOCKER_IMAGE_DOCKERLINT ?= "hadolint/hadolint:v2.9.2@sha256:d355bd7df747a0f124f3b5e7b21e9dafd0cb19732a276f901f0fdee243ec1f3b" +DOCKER_IMAGE_COSIGN ?= "bitnami/cosign:1.8.0@sha256:8c2c61c546258fffff18b47bb82a65af6142007306b737129a7bd5429d53629a" +DOCKER_IMAGE_GH_CLI ?= "ghcr.io/supportpal/github-gh-cli:2.31.0@sha256:71371e36e62bd24ddd42d9e4c720a7e9954cb599475e24d1407af7190e2a5685" + +## Cosign Variables +# The public key +COSIGN_PUBLIC_KEY ?= akey +# The private key +COSIGN_KEY ?= akey +# The passphrase used to decrypt the private key +COSIGN_PASSWORD ?= password + +## Go Variables +# Go executable +GO := $(shell which go) +# Extract GO version from go.mod file +GO_VERSION ?= $(shell grep -E '^go' go.mod | awk {'print $$2'}) +# LDFLAGS +GO_LDFLAGS += -X "github.com/mattermost/${APP_NAME}/internal/version.gitVersion=$(GIT_VERSION)" +GO_LDFLAGS += -X "github.com/mattermost/${APP_NAME}/internal/version.gitCommit=$(APP_COMMIT)" +GO_LDFLAGS += -X "github.com/mattermost/${APP_NAME}/internal/version.gitTreeState=$(GIT_TREESTATE)" +GO_LDFLAGS += -X "github.com/mattermost/${APP_NAME}/internal/version.buildDate=$(BUILD_DATE)" + + +# Architectures to build for +GO_BUILD_PLATFORMS ?= linux-amd64 linux-arm64 darwin-amd64 darwin-arm64 freebsd-amd64 +GO_BUILD_PLATFORMS_ARTIFACTS = $(foreach cmd,$(addprefix go-build/,${APP_NAME}),$(addprefix $(cmd)-,$(GO_BUILD_PLATFORMS))) + +# Build options +GO_BUILD_OPTS += -trimpath +GO_TEST_OPTS += -v -timeout=180s +# Temporary folder to output compiled binaries artifacts +GO_OUT_BIN_DIR := ./dist + +## Github Variables +# A github access token that provides access to upload artifacts under releases +GITHUB_TOKEN ?= a_token +# Github organization +GITHUB_ORG := mattermost +# Most probably the name of the repo +GITHUB_REPO := ${APP_NAME} + +# ==================================================================================== +# Colors + +BLUE := $(shell printf "\033[34m") +YELLOW := $(shell printf "\033[33m") +RED := $(shell printf "\033[31m") +GREEN := $(shell printf "\033[32m") +CYAN := $(shell printf "\033[36m") +CNone := $(shell printf "\033[0m") + +# ==================================================================================== +# Logger + +TIME_LONG = `date +%Y-%m-%d' '%H:%M:%S` +TIME_SHORT = `date +%H:%M:%S` +TIME = $(TIME_SHORT) + +INFO = echo ${TIME} ${BLUE}[ .. ]${CNone} +WARN = echo ${TIME} ${YELLOW}[WARN]${CNone} +ERR = echo ${TIME} ${RED}[FAIL]${CNone} +OK = echo ${TIME} ${GREEN}[ OK ]${CNone} +FAIL = (echo ${TIME} ${RED}[FAIL]${CNone} && false) + +# ==================================================================================== +# Verbosity control hack + +VERBOSE ?= 0 +AT_0 := @ +AT_1 := +AT = $(AT_$(VERBOSE)) + +# ==================================================================================== +# Targets + +help: ## to get help + @echo "Usage:" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ + awk 'BEGIN {FS = ":.*?## "}; {printf "make ${CYAN}%-30s${CNone} %s\n", $$1, $$2}' + +.PHONY: build +build: go-build-docker ## to build + +.PHONY: release +release: build github-release ## to build and release artifacts + +.PHONY: package +package: go-build package-software ## to build, package + +.PHONY: sign +sign: docker-sign docker-verify ## to sign the artifact and perform verification + +.PHONY: lint +lint: go-lint docker-lint ## to lint + +.PHONY: test +test: go-test ## to test + +package-software: ## to package the binary + @$(INFO) Packaging + $(AT) for file in $(GO_OUT_BIN_DIR)/mattermost-push-proxy-*; do \ + target=$$(basename $$file); \ + mkdir -p $(GO_OUT_BIN_DIR)/$${target}_temp/bin; \ + cp -RL config $(GO_OUT_BIN_DIR)/$${target}_temp/config; \ + echo $(APP_VERSION) > $(GO_OUT_BIN_DIR)/$${target}_temp/config/build.txt; \ + cp LICENSE.txt NOTICE.txt README.md $(GO_OUT_BIN_DIR)/$${target}_temp; \ + mv $$file $(GO_OUT_BIN_DIR)/$${target}_temp/bin/mattermost-push-proxy; \ + mv $(GO_OUT_BIN_DIR)/$${target}_temp $(GO_OUT_BIN_DIR)/$${target}; \ + tar -czf $(GO_OUT_BIN_DIR)/$${target}.tar.gz -C $(GO_OUT_BIN_DIR) $${target}; \ + rm -r $(GO_OUT_BIN_DIR)/$${target}; \ done + @$(OK) Packaging + +.PHONY: docker-build +docker-build: ## to build the docker image + @$(INFO) Performing Docker build ${APP_NAME}:${APP_VERSION} + $(AT)$(DOCKER) build \ + --build-arg GO_IMAGE=${DOCKER_IMAGE_GO} \ + --build-arg=ARCH=amd64 \ + -f ${DOCKER_FILE} . \ + -t ${APP_NAME}:${APP_VERSION} || ${FAIL} + @$(OK) Performing Docker build ${APP_NAME}:${APP_VERSION} + +.PHONY: docker-push +docker-push: ## to push the docker image + @$(INFO) Pushing to registry... + $(AT)$(DOCKER) tag ${APP_NAME}:${APP_VERSION} $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION} || ${FAIL} + $(AT)$(DOCKER) push $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION} || ${FAIL} +# if we are on a latest semver APP_VERSION tag, also push latest +ifneq ($(shell echo $(APP_VERSION) | egrep '^v([0-9]+\.){0,2}(\*|[0-9]+)'),) + ifeq ($(shell git tag -l --sort=v:refname | tail -n1),$(APP_VERSION)) + $(AT)$(DOCKER) tag ${APP_NAME}:${APP_VERSION} $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:latest || ${FAIL} + $(AT)$(DOCKER) push $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:latest || ${FAIL} + endif +endif + @$(OK) Pushing to registry $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION} + +.PHONY: docker-sign +docker-sign: ## to sign the docker image + @$(INFO) Signing the docker image... + $(AT)echo "$${COSIGN_KEY}" > cosign.key && \ + $(DOCKER) run ${DOCKER_OPTS} \ + --entrypoint '/bin/sh' \ + -v $(PWD):/app -w /app \ + -e COSIGN_PASSWORD=${COSIGN_PASSWORD} \ + -e HOME="/tmp" \ + ${DOCKER_IMAGE_COSIGN} \ + -c \ + "echo Signing... && \ + cosign login $(DOCKER_REGISTRY) -u ${DOCKER_USER} -p ${DOCKER_PASSWORD} && \ + cosign sign --key cosign.key $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION}" || ${FAIL} +# if we are on a latest semver APP_VERSION tag, also sign latest tag +ifneq ($(shell echo $(APP_VERSION) | egrep '^v([0-9]+\.){0,2}(\*|[0-9]+)'),) + ifeq ($(shell git tag -l --sort=v:refname | tail -n1),$(APP_VERSION)) + $(DOCKER) run ${DOCKER_OPTS} \ + --entrypoint '/bin/sh' \ + -v $(PWD):/app -w /app \ + -e COSIGN_PASSWORD=${COSIGN_PASSWORD} \ + -e HOME="/tmp" \ + ${DOCKER_IMAGE_COSIGN} \ + -c \ + "echo Signing... && \ + cosign login $(DOCKER_REGISTRY) -u ${DOCKER_USER} -p ${DOCKER_PASSWORD} && \ + cosign sign --key cosign.key $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:latest" || ${FAIL} + endif +endif + $(AT)rm -f cosign.key || ${FAIL} + @$(OK) Signing the docker image: $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION} + +.PHONY: docker-verify +docker-verify: ## to verify the docker image + @$(INFO) Verifying the published docker image... + $(AT)echo "$${COSIGN_PUBLIC_KEY}" > cosign_public.key && \ + $(DOCKER) run ${DOCKER_OPTS} \ + --entrypoint '/bin/sh' \ + -v $(PWD):/app -w /app \ + ${DOCKER_IMAGE_COSIGN} \ + -c \ + "echo Verifying... && \ + cosign verify --key cosign_public.key $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION}" || ${FAIL} +# if we are on a latest semver APP_VERSION tag, also verify latest tag +ifneq ($(shell echo $(APP_VERSION) | egrep '^v([0-9]+\.){0,2}(\*|[0-9]+)'),) + ifeq ($(shell git tag -l --sort=v:refname | tail -n1),$(APP_VERSION)) + $(DOCKER) run ${DOCKER_OPTS} \ + --entrypoint '/bin/sh' \ + -v $(PWD):/app -w /app \ + ${DOCKER_IMAGE_COSIGN} \ + -c \ + "echo Verifying... && \ + cosign verify --key cosign_public.key $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:latest" || ${FAIL} + endif +endif + $(AT)rm -f cosign_public.key || ${FAIL} + @$(OK) Verifying the published docker image: $(DOCKER_REGISTRY)/${DOCKER_REGISTRY_REPO}:${APP_VERSION} + +.PHONY: docker-sbom +docker-sbom: ## to print a sbom report + @$(INFO) Performing Docker sbom report... + $(AT)$(DOCKER) sbom ${APP_NAME}:${APP_VERSION} || ${FAIL} + @$(OK) Performing Docker sbom report + +.PHONY: docker-scan +docker-scan: ## to print a vulnerability report + @$(INFO) Performing Docker scan report... + $(AT)$(DOCKER) scan ${APP_NAME}:${APP_VERSION} || ${FAIL} + @$(OK) Performing Docker scan report + +.PHONY: docker-lint +docker-lint: ## to lint the Dockerfile + @$(INFO) Dockerfile linting... + $(AT)$(DOCKER) run -i ${DOCKER_OPTS} \ + ${DOCKER_IMAGE_DOCKERLINT} \ + < ${DOCKER_FILE} || ${FAIL} + @$(OK) Dockerfile linting + +.PHONY: docker-login +docker-login: ## to login to a container registry + @$(INFO) Dockerd login to container registry ${DOCKER_REGISTRY}... + $(AT) echo "${DOCKER_PASSWORD}" | $(DOCKER) login --password-stdin -u ${DOCKER_USER} $(DOCKER_REGISTRY) || ${FAIL} + @$(OK) Dockerd login to container registry ${DOCKER_REGISTRY}... + +go-build: $(GO_BUILD_PLATFORMS_ARTIFACTS) ## to build binaries + +.PHONY: go-build +go-build/%: + @$(INFO) go build $*... + $(AT)target="$*"; \ + command="${APP_NAME}"; \ + platform_ext="$${target#$$command-*}"; \ + platform="$${platform_ext%.*}"; \ + export GOOS="$${platform%%-*}"; \ + export GOARCH="$${platform#*-}"; \ + echo export GOOS=$${GOOS}; \ + echo export GOARCH=$${GOARCH}; \ + CGO_ENABLED=0 \ + $(GO) build ${GO_BUILD_OPTS} \ + -ldflags '${GO_LDFLAGS}' \ + -o ${GO_OUT_BIN_DIR}/$* \ + ${CONFIG_APP_CODE} || ${FAIL} + @$(OK) go build $* + +.PHONY: go-build-docker +go-build-docker: # to build binaries under a controlled docker dedicated go container using DOCKER_IMAGE_GO + @$(INFO) go build docker + $(AT)$(DOCKER) run \ + -v $(PWD):/app -w /app \ + $(DOCKER_IMAGE_GO) \ + /bin/sh -c \ + "cd /app && \ + make go-build" || ${FAIL} + @$(OK) go build docker + +.PHONY: go-run +go-run: ## to run locally for development + @$(INFO) running locally... + $(AT)$(GO) run ${GO_BUILD_OPTS} ${CONFIG_APP_CODE} || ${FAIL} + @$(OK) running locally + +.PHONY: go-test +go-test: ## to run tests + @$(INFO) testing... + $(AT)$(DOCKER) run ${DOCKER_OPTS} \ + -v $(PWD):/app -w /app \ + $(DOCKER_IMAGE_GO) \ + /bin/sh -c \ + "cd /app && \ + go test ${GO_TEST_OPTS} ./... " || ${FAIL} + @$(OK) testing + +.PHONY: go-mod-check +go-mod-check: ## to check go mod files consistency + @$(INFO) Checking go mod files consistency... + $(AT)$(GO) mod tidy + $(AT)git --no-pager diff --exit-code go.mod go.sum || \ + (${WARN} Please run "go mod tidy" and commit the changes in go.mod and go.sum. && ${FAIL} ; exit 128 ) + @$(OK) Checking go mod files consistency + +.PHONY: go-lint +go-lint: ## to lint go code + @$(INFO) App linting... + $(AT)$(DOCKER) run ${DOCKER_OPTS} \ + -v $(PWD):/app -w /app \ + ${DOCKER_IMAGE_GOLINT} \ + golangci-lint run ./... || ${FAIL} + @$(OK) App linting + +.PHONY: go-doc +go-doc: ## to generate documentation + @$(INFO) Generating Documentation... + $(AT)$(GO) run ./scripts/env_config.go ./docs/env_config.md || ${FAIL} + @$(OK) Generating Documentation + +.PHONY: github-release +github-release: ## to publish a release and relevant artifacts to GitHub + @$(INFO) Generating github-release http://github.com/$(GITHUB_ORG)/$(GITHUB_REPO)/releases/tag/$(APP_VERSION) ... +ifeq ($(shell echo $(APP_VERSION) | egrep '^v([0-9]+\.){0,2}(\*|[0-9]+)'),) + $(error "We only support releases from semver tags") +else + $(AT)$(DOCKER) run \ + -v $(PWD):/app -w /app \ + -e GITHUB_TOKEN=${GITHUB_TOKEN} \ + $(DOCKER_IMAGE_GH_CLI) \ + /bin/sh -c \ + "git config --global --add safe.directory /app && cd /app && \ + gh release create $(APP_VERSION) --generate-notes $(GO_OUT_BIN_DIR)/*" || ${FAIL} +endif + @$(OK) Generating github-release http://github.com/$(GITHUB_ORG)/$(GITHUB_REPO)/releases/tag/$(APP_VERSION) ... -.PHONY: manifest -manifest: push - docker manifest create --amend $(IMAGE):$(TAG) $(shell echo $(ARCHS) | sed -e "s~[^ ]*~$(IMAGE)\-&:$(TAG)~g") - @for platform in $(ARCHS); do docker manifest annotate --arch "$${platform}" ${IMAGE}:${TAG} ${IMAGE}-$${platform}:${TAG}; done - docker manifest push --purge $(IMAGE):$(TAG) - -test: - $(GO) test $(GOFLAGS) -v -timeout=180s ./... - -clean: - @echo Cleaning - rm -Rf $(DIST_ROOT) - go clean $(GOFLAGS) -i ./... - -run: - @echo Starting go web server - $(GO) run $(GOFLAGS) -ldflags '$(LDFLAGS)' main.go - -build-swagger: - npm run validate - npm run build - -serve-swagger: - npm run validate - npm run serve +.PHONY: clean +clean: ## to clean-up + @$(INFO) cleaning /${GO_OUT_BIN_DIR} folder... + $(AT)rm -rf ${GO_OUT_BIN_DIR} || ${FAIL} + @$(OK) cleaning /${GO_OUT_BIN_DIR} folder diff --git a/docker/Dockerfile b/docker/Dockerfile index 144cc75..73d8060 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,6 +10,7 @@ COPY bin/mattermost-push-proxy-linux-$ARCH bin/mattermost-push-proxy FROM alpine:3.15 +# hadolint ignore=DL3018 RUN apk add --no-cache \ ca-certificates \ libc6-compat \