Skip to content

Instantly share code, notes, and snippets.

@lesovsky
Created February 15, 2021 05:40
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save lesovsky/fbfac22471a13425a1110ff311dfe43f to your computer and use it in GitHub Desktop.
Save lesovsky/fbfac22471a13425a1110ff311dfe43f to your computer and use it in GitHub Desktop.
Publicating Golang application on GitHub.

Publicating Golang application on GitHub.

  • Makefile
  • Dockerfile
  • Github Actions
  • Goreleaser

Makefile

  • requires Git tags
  • application must work with imported Git tags
DOCKER_ACCOUNT = lesovsky
PROGRAM_NAME = pgcenter

COMMIT=$(shell git rev-parse --short HEAD)
BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
TAG=$(shell git describe --tags |cut -d- -f1)

LDFLAGS = -ldflags "-X main.gitTag=${TAG} -X main.gitCommit=${COMMIT} -X main.gitBranch=${BRANCH}"

.PHONY: help clean dep build install uninstall

.DEFAULT_GOAL := help

help: ## Display this help screen.
	@echo "Makefile available targets:"
	@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "  * \033[36m%-15s\033[0m %s\n", $$1, $$2}'

clean: ## Clean build directory.
	rm -f ./bin/${PROGRAM_NAME}
	rmdir ./bin

dep: ## Download the dependencies.
	go mod download

lint: dep ## Lint the source files
	golangci-lint run --timeout 5m -E golint -e '(struct field|type|method|func) [a-zA-Z`]+ should be [a-zA-Z`]+'
	gosec -quiet ./...

test: dep ## Run tests
	go test -race -p 1 -timeout 300s -coverprofile=.test_coverage.txt ./... && \
    	go tool cover -func=.test_coverage.txt | tail -n1 | awk '{print "Total test coverage: " $$3}'
	@rm .test_coverage.txt

build: dep ## Build pgcenter executable.
	mkdir -p ./bin
	CGO_ENABLED=0 GOOS=linux GOARCH=${GOARCH} go build ${LDFLAGS} -o bin/${PROGRAM_NAME} ./cmd

install: ## Install pgcenter executable into /usr/bin directory.
	install -pm 755 bin/${PROGRAM_NAME} /usr/bin/${PROGRAM_NAME}

uninstall: ## Uninstall pgcenter executable from /usr/bin directory.
	rm -f /usr/bin/${PROGRAM_NAME}

docker-build: ## Build docker image
	docker build -t ${DOCKER_ACCOUNT}/${PROGRAM_NAME}:${TAG} .
	docker image prune --force --filter label=stage=intermediate

docker-push: ## Push docker image to registry
	docker push ${DOCKER_ACCOUNT}/${PROGRAM_NAME}:${TAG}

Dockerfile

# stage 1: build
FROM golang:1.15 as build
LABEL stage=intermediate
WORKDIR /app
COPY . .
RUN make build

# stage 2: scratch
FROM scratch as scratch
COPY --from=build /app/bin/pgcenter /bin/pgcenter
CMD ["pgcenter"]

Github Actions

requires:

  • secrets defined in Settings/Secrets (except GITHUB_TOKEN, it is created automatically)
  • DockerHub repo (will created automatically at first push)
  • release branch

Default workflow (.github/workflows/default.yml)

---
name: Default

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  test:
    runs-on: ubuntu-latest
    container: lesovsky/pgcenter-testing:v0.0.1

    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Prepare test environment
        run: prepare-test-environment.sh
      - name: Run lint
        run: make lint
      - name: Run test
        run: make test

Release workflow (.github/workflows/release.yml)

---
name: Release

on:
  push:
    branches: [ release ]

jobs:
  test:
    runs-on: ubuntu-latest
    container: lesovsky/pgcenter-testing:v0.0.1

    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Prepare test environment
        run: prepare-test-environment.sh
      - name: Run lint
        run: make lint
      - name: Run test
        run: make test

  build:
    runs-on: ubuntu-latest
    needs: test
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Build image
        run: make docker-build
      - name: Log in to Docker Hub
        run: docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
      - name: Push image to Docker Hub
        run: make docker-push

  goreleaser:
    runs-on: ubuntu-latest
    needs: [ test, build ]
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - uses: actions/setup-go@v2
        with:
          go-version: 1.15
      - uses: goreleaser/goreleaser-action@v2
        with:
          version: latest
          args: release --rm-dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Goreleaser

Defined in .goreleaser.yml

before:
  hooks:
  - make dep

builds:
  - binary: pgcenter
    main: ./cmd
    goarch:
      - amd64
    goos:
      - linux
    env:
      - CGO_ENABLED=0
    ldflags:
      - -a -installsuffix cgo
      - -X main.gitTag={{.Tag}} -X main.gitCommit={{.Commit}} -X main.gitBranch={{.Branch}}

archives:
  - builds: [pgcenter]

changelog:
  sort: asc

nfpms:
  - vendor: pgcenter
    homepage: https://github.com/lesovsky/pgcenter
    maintainer: Alexey Lesovsky
    description: Command-line admin tool for observing and troubleshooting Postgres.
    license: BSD-3
    formats: [ deb, rpm ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment