Skip to content

Commit d88e435

Browse files
authored
re-use binary of build stage in docker image (#27)
1 parent 51383b0 commit d88e435

File tree

9 files changed

+170
-92
lines changed

9 files changed

+170
-92
lines changed

.github/workflows/test.yml

+28-30
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,57 @@ on:
66
branches:
77
- master
88

9-
env:
10-
GO_VERSION: "1.23.0"
11-
GO_LANG_CI_LINT_VERSION: "v1.60.1"
12-
139
name: run tests
1410
jobs:
1511
lint:
1612
runs-on: ubuntu-latest
1713
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
1819
- name: Install Go
1920
uses: actions/setup-go@v5
2021
with:
21-
go-version: ${{ env.GO_VERSION }}
22-
- name: Checkout code
23-
uses: actions/checkout@v4
22+
go-version-file: go.mod
23+
2424
- name: Run linters
2525
uses: golangci/golangci-lint-action@v6
2626
with:
27-
version: ${{ env.GO_LANG_CI_LINT_VERSION }}
27+
version: v1.64.7
28+
problem-matchers: true
29+
args: --issues-exit-code=0 --out-format=sarif > linter-results.sarif # we expect some findings, but for this demo just continue
30+
31+
- name: Upload SARIF to Code Scanning
32+
uses: github/codeql-action/upload-sarif@v3
33+
with:
34+
sarif_file: ./linter-results.sarif
2835

2936
test:
30-
strategy:
31-
matrix:
32-
go-version: [ "1.23.0", "1.22.5" ]
33-
platform: [ubuntu-latest, macos-latest, windows-latest]
34-
runs-on: ${{ matrix.platform }}
37+
runs-on: ubuntu-latest
3538
steps:
36-
- name: Install Go
37-
if: success()
38-
uses: actions/setup-go@v5
39-
with:
40-
go-version: ${{ matrix.go-version }}
4139
- name: Checkout code
4240
uses: actions/checkout@v4
43-
- name: Run tests
44-
run: go test -v -covermode=count
41+
with:
42+
fetch-depth: 0
4543

46-
coverage:
47-
runs-on: ubuntu-latest
48-
steps:
4944
- name: Install Go
50-
if: success()
5145
uses: actions/setup-go@v5
5246
with:
53-
go-version: ${{ env.GO_VERSION }}
54-
- name: Checkout code
55-
uses: actions/checkout@v4
56-
- name: Calc coverage
47+
go-version-file: go.mod
48+
49+
- name: Verify go version
5750
run: |
58-
go test -v -covermode=count -coverprofile=coverage.out
51+
echo "GOVERSION=$(go version)" >> $GITHUB_ENV
52+
go version
53+
54+
- name: Run tests
55+
run: go test -v -covermode=count -coverprofile=coverage.out
56+
5957
- name: Coveralls
6058
uses: coverallsapp/github-action@cfd0633edbd2411b532b808ba7a8b5e04f76d2c8 #2.3.4
6159
with:
6260
github-token: ${{ secrets.github_token }}
6361
file: coverage.out
64-
format: golang
62+
format: golang

.github/workflows/upload_assets.yml

+71-16
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,26 @@ on:
44
- 'v*'
55

66
env:
7-
GO_VERSION: "1.23.0"
7+
# name of the resulting binary and the docker-image. must match name
8+
# in .goreleaser.yml
9+
BINARY: my-app
810

911
name: Upload release assets after tagging
1012
jobs:
1113
build:
1214
name: create assets
1315
runs-on: ubuntu-latest
1416
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
1522
- name: Install Go
1623
uses: actions/setup-go@v5
1724
with:
18-
go-version: ${{ env.GO_VERSION }}
19-
- name: Checkout code
20-
uses: actions/checkout@v4
25+
go-version-file: go.mod
26+
2127
- name: Run GoReleaser
2228
uses: goreleaser/goreleaser-action@90a3faa9d0182683851fbfa97ca1a2cb983bfca3 #v6
2329
with:
@@ -26,31 +32,80 @@ jobs:
2632
env:
2733
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2834

35+
- name: Upload binary artifact
36+
uses: actions/upload-artifact@v4
37+
with:
38+
name: binary
39+
path: dist/go-ci-demo_linux_amd64_v1/${{ env.BINARY }}
40+
retention-days: 1
41+
2942
docker-image:
43+
needs: build
3044
env:
3145
REGISTRY: ghcr.io
3246
IMAGE_NAME: ${{ github.repository }}
47+
3348
name: create docker image
3449
runs-on: ubuntu-latest
3550
steps:
3651
- name: Checkout code
3752
uses: actions/checkout@v4
53+
with:
54+
fetch-depth: 0
55+
56+
- name: Set up Docker Buildx
57+
uses: docker/setup-buildx-action@v3
58+
with:
59+
driver-opts: image=moby/buildkit:latest
60+
#buildkitd-flags: --debug
61+
3862
- name: Log in to the Container registry
39-
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
63+
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
4064
with:
4165
registry: ${{ env.REGISTRY }}
4266
username: ${{ github.actor }}
4367
password: ${{ secrets.GITHUB_TOKEN }}
44-
- name: build Docker image
68+
69+
# Download the binary artifact from the build job
70+
- name: Download binary artifact
71+
uses: actions/download-artifact@v4
72+
with:
73+
name: binary
74+
path: ./docker-build
75+
76+
- name: Prepare docker build
4577
run: |
46-
VERSION=$(git describe --tags)
47-
docker build --build-arg "version=$VERSION" --tag ${IMAGE_NAME} .
48-
- name: push Docker image
78+
cp Dockerfile ./docker-build
79+
chmod 755 ./docker-build/${{ env.BINARY }}
80+
81+
- name: Get tag info for image label
82+
id: tag
4983
run: |
50-
TAG=$(git describe --tags)
51-
docker tag ${IMAGE_NAME} ${REGISTRY}/${IMAGE_NAME}:${GITHUB_SHA}
52-
docker tag ${IMAGE_NAME} ${REGISTRY}/${IMAGE_NAME}:${TAG}
53-
docker tag ${IMAGE_NAME} ${REGISTRY}/${IMAGE_NAME}:latest
54-
docker push ${REGISTRY}/${IMAGE_NAME}:${GITHUB_SHA}
55-
docker push ${REGISTRY}/${IMAGE_NAME}:${TAG}
56-
docker push ${REGISTRY}/${IMAGE_NAME}:latest
84+
TAG=$(git describe --tags)
85+
echo "tag=$TAG" >> $GITHUB_OUTPUT
86+
87+
- name: Build and push Docker image
88+
uses: docker/build-push-action@v5
89+
with:
90+
context: ./docker-build
91+
build-args: |
92+
binary=${{ env.BINARY }}
93+
push: true
94+
tags: |
95+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
96+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}
97+
cache-from: type=gha
98+
cache-to: type=gha,mode=max
99+
100+
- name: Tag and push latest
101+
if: steps.tag.outputs.tag != 'v99.9.9'
102+
uses: docker/build-push-action@v5
103+
with:
104+
context: ./docker-build
105+
build-args: |
106+
binary=${{ env.BINARY }}
107+
push: true
108+
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
109+
cache-from: type=gha
110+
no-cache: false
111+
pull: false

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
golang-ci-template-github-actions
33
*zip
44
*.out
5-
5+
dist/

.goreleaser.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
version: 2
44
before:
55
hooks:
6-
# You may remove this if you don't use go modules.
76
- go mod tidy
7+
project_name: go-ci-demo
88
builds:
9-
- env:
9+
- binary: my-app
10+
env:
1011
- CGO_ENABLED=0
1112
dir: .
13+
ldflags:
14+
- -s -w
15+
- -X "main.BuildVersion={{.Tag}}"
1216
goos:
1317
- linux
1418
- darwin
@@ -34,4 +38,4 @@ changelog:
3438
filters:
3539
exclude:
3640
- '^docs:'
37-
- '^test:'
41+
- '^test:'

Dockerfile

+4-15
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
# example docker image for
2-
# https://github.com/jandelgado/golang-ci-template-github-actions/
3-
4-
FROM golang:1.23-alpine as builder
5-
ARG version
6-
7-
WORKDIR /go/src/app
8-
ADD . /go/src/app
9-
10-
RUN CGO_ENABLED=0 \
11-
go build -ldflags "-s -w" -o app
12-
13-
FROM gcr.io/distroless/base-debian10
1+
FROM gcr.io/distroless/static-debian12
2+
ARG binary
143
LABEL maintainer="Jan Delgado <jdelgado@gmx.net>"
154

16-
COPY --from=builder /go/src/app/app /
17-
ENTRYPOINT ["/app"]
5+
COPY ./$binary /app
6+
ENTRYPOINT ["/app"]

README.md

+45-23
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,55 @@
11
# golang ci template using github actions
22

3-
[![Build Status](https://github.com/jandelgado/golang-ci-template-github-actions/workflows/test%20and%20build/badge.svg)](https://github.com/jandelgado/golang-ci-template-github-actions/actions?workflow=test%20and%20build)
3+
[![Build Status](https://github.com/jandelgado/golang-ci-template-github-actions/workflows/run%20tests/badge.svg)](https://github.com/jandelgado/golang-ci-template-github-actions/actions?workflow=run%20tests)
44
[![Coverage Status](https://coveralls.io/repos/github/jandelgado/golang-ci-template-github-actions/badge.svg?branch=master)](https://coveralls.io/github/jandelgado/golang-ci-template-github-actions?branch=master)
5-
[![Go Report Card](https://goreportcard.com/badge/github.com/jandelgado/golang-ci-template-github-actions)](https://goreportcard.com/report/github.com/jandelgado/golang-ci-template-github-actions)
5+
[![Go Report Card](https://goreportcard.com/badge/github.com/jandelgado/golang-ci-template-github-actions)](https://goreportcard.com/report/github.com/jandelgado/golang-ci-template-github-actions)
66

77
<!-- vim-markdown-toc GFM -->
88

99
* [Info](#info)
10+
* [Go-Version](#go-version)
1011
* [Dependabot](#dependabot)
1112
* [Creating a release](#creating-a-release)
12-
* [Test coverage (coveralls)](#test-coverage-coveralls)
13+
* [Linting & Test](#linting--test)
14+
* [Linter](#linter)
15+
* [Test](#test)
1316
* [Author](#author)
1417

1518
<!-- vim-markdown-toc -->
1619

17-
## Info
20+
## Info
1821

1922
This repository serves as a template for github-actions integrated go projects.
2023
It consists of a `hello, world!` like example in source file [main.go](main.go)
21-
which gets compiled into the binary `golang-ci-template-github-actions`. The CI
22-
runs some [linters](https://github.com/golangci/golangci-lint-action) on the
23-
code, before the unit tests are executed. Test coverage is uploaded to
24-
coveralls.io.
24+
which gets compiled into the binary `my-app` using goreleaser. The CI is
25+
configured to run
26+
[golangci-linter](https://github.com/golangci/golangci-lint-action) on the code,
27+
before the unit tests are executed. Test coverage is uploaded to coveralls.io.
2528

2629
[goreleaser](https://github.com/goreleaser/goreleaser) is used to create the
27-
final multi-plattform assets, which are automatically uploaded to the
30+
final multi-plattform assets, which are automatically uploaded to the
2831
[release](https://github.com/jandelgado/golang-ci-template-github-actions/releases/latest).
2932
The [release-process](#creating-a-release) is triggered by pushing a git tag to
3033
the repository.
3134

3235
Finally, a docker image is built, which gets published to
33-
[ghcr.io](https://github.com/jandelgado/golang-ci-template-github-actions/pkgs/container/golang-ci-template-github-actions).
36+
[ghcr.io](https://github.com/jandelgado/golang-ci-template-github-actions/pkgs/container/my-app).
3437
Run it with
3538

3639
```console
37-
$ docker run --rm ghcr.io/jandelgado/golang-ci-template-github-actions:latest
40+
$ docker run --rm ghcr.io/jandelgado/my-app:latest
3841
hello, world!
3942
```
4043

44+
## Go-Version
45+
46+
The go version to use is configured in `go.mod` with the `toolchain` directive.
47+
When building locally, set `GOTOOLCHAIN` to `auto` to automatically install
48+
the configured toolchain (introduced with go 1.21).
49+
4150
## Dependabot
4251

43-
We use [dependabot](https://docs.github.com/en/code-security/dependabot) to
52+
We use [dependabot](https://docs.github.com/en/code-security/dependabot) to
4453
both keep the go dependencies as well as the used github action up-to-date.
4554
The configuration can be found [here](.github/dependabot.yml).
4655

@@ -53,28 +62,41 @@ $ git tag -a "v1.2.3" -m "this is release v1.2.3"
5362
$ git push origin v1.2.3
5463
```
5564

56-
The push of the new tag triggers the CI, which uses goreleaser to:
57-
* build multiplatform release artifacts
58-
* create a new release
59-
* upload the artifacts, which are then available on the [releases page](/jandelgado/golang-ci-template-github-actions/releases).
65+
The push of the new tag triggers the CI, which uses goreleaser with
66+
[this configuration](.goreleaser.yml) to
6067

61-
Finally, a docker image is built, which gets published to
68+
* build multi-platform release artifacts
69+
* create a new release
70+
* upload the artifacts, which are then available on the [releases page](/jandelgado/golang-ci-template-github-actions/releases).
71+
72+
Finally, a docker image is built using the previously built artefacts. The image
73+
is published to
6274
[ghcr.io](https://github.com/jandelgado/golang-ci-template-github-actions/pkgs/container/golang-ci-template-github-actions).
6375

64-
## Test coverage (coveralls)
76+
To run goreleaser locally, start the tool with `gorelaser build --snapshot --clean`.
77+
78+
## Linting & Test
79+
80+
### Linter
81+
82+
[golangci-linter](https://github.com/golangci/golangci-lint-action) is
83+
configured for code-linting. The report is uploaded so that linting results
84+
are visible in the MR:
85+
86+
![pr screenshot](images/linter.png)
87+
88+
### Test
6589

6690
We use the
6791
[coveralls-github-action](https://github.com/coverallsapp/github-action) to
6892
upload the golang coverage to coveralls.
6993

70-
Don't forget to enable `Leave comments (x) ` in coveralls, under `repo
71-
settings` > `pull request alerts`, so that the coveralls-action posts a comment
94+
Don't forget to enable `Leave comments (x)` in coveralls, under
95+
`repo settings` > `pull request alerts`, so that the coveralls-action posts a comment
7296
with the test coverage to affected pull requests:
7397

7498
![pr screenshot](images/pr.png)
7599

76100
## Author
77101

78-
(c) copyright 2021 by Jan Delgado, License MIT
79-
80-
102+
(c) copyright 2021-2025 by Jan Delgado, License MIT

0 commit comments

Comments
 (0)