Skip to content

Commit 703f717

Browse files
Updates build/release workflows (#18)
* Updates build/release workflows * Get old test job working
1 parent d9e9196 commit 703f717

File tree

2 files changed

+156
-134
lines changed

2 files changed

+156
-134
lines changed

.github/workflows/build.yml

Lines changed: 114 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,125 @@
1-
name: Build
2-
on: [ push, pull_request, workflow_dispatch ]
1+
name: Build / Test / Push
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
workflow_dispatch:
8+
39
env:
4-
REGISTRY: ghcr.io
10+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
511

612
jobs:
7-
# TODO: DRY w/release.yml
8-
setup:
9-
runs-on: ubuntu-latest
10-
13+
build:
14+
runs-on: ${{ matrix.runner }}
15+
outputs:
16+
build-image-arm: ${{ steps.gen-output.outputs.image-arm64 }}
17+
build-image-x64: ${{ steps.gen-output.outputs.image-x64 }}
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
runner:
22+
- ubuntu-24.04
23+
- ubuntu-24.04-arm
1124
steps:
12-
# See https://github.com/docker/build-push-action/blob/v2.10.0/TROUBLESHOOTING.md#repository-name-must-be-lowercase
13-
- name: Sanitize image name
14-
uses: actions/github-script@v6
15-
id: image-name
25+
- name: Checkout code
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Docker Buildx
29+
uses: docker/setup-buildx-action@v3
30+
31+
- name: Login to GitHub Container Registry
32+
uses: docker/login-action@v3
1633
with:
17-
result-encoding: string
18-
script: return '${{ env.REGISTRY }}/${{ github.repository }}'.toLowerCase()
34+
registry: ghcr.io
35+
username: ${{ github.actor }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
1937

20-
- name: Get short SHA
38+
- name: Docker meta
39+
id: meta
40+
uses: docker/metadata-action@v5
41+
with:
42+
images: ghcr.io/${{ github.repository }}
43+
# note Specifies a single tag to ensure the default doesn't add more than one.
44+
# The actual tag is not used, this is just used to sanitize the registry name
45+
# and produce labels.
46+
tags: type=sha
47+
48+
- name: Sanitize registry repository name
49+
id: get-reg
2150
run: |
22-
echo SHORT_SHA="${GITHUB_SHA:0:7}" >> $GITHUB_ENV
51+
echo "registry=$(echo '${{ steps.meta.outputs.tags }}' | cut -f1 -d:)" | tee -a "$GITHUB_OUTPUT"
2352
24-
outputs:
25-
base_image_name: ${{ steps.image-name.outputs.result }}
26-
build_image: ${{ steps.image-name.outputs.result }}:${{ env.SHORT_SHA }}
53+
- name: Build/push the arch-specific image
54+
id: build
55+
uses: docker/build-push-action@v6
56+
with:
57+
# @todo GHA caching needs tuning, these tend not to hit. Perhaps switch to type=registry?
58+
cache-from: type=gha
59+
cache-to: type=gha,mode=max
60+
labels: ${{ steps.meta.outputs.labels }}
61+
provenance: mode=max
62+
sbom: true
63+
tags: ${{ steps.get-reg.outputs.registry }}
64+
outputs: type=image,push-by-digest=true,push=true
65+
66+
- name: Write arch-specific image digest to outputs
67+
id: gen-output
68+
run: |
69+
echo "image-${RUNNER_ARCH,,}=${{ steps.get-reg.outputs.registry }}@${{ steps.build.outputs.digest }}" | tee -a "$GITHUB_OUTPUT"
2770
28-
build:
29-
if: github.event_name != 'release'
30-
needs: setup
71+
merge:
72+
runs-on: ubuntu-24.04
73+
needs:
74+
- build
3175
env:
32-
BUILD_IMAGE: ${{ needs.setup.outputs.build_image }}
33-
34-
runs-on: ubuntu-latest
35-
36-
permissions:
37-
packages: write
38-
76+
DOCKER_APP_IMAGE_ARM64: ${{ needs.build.outputs.build-image-arm }}
77+
DOCKER_APP_IMAGE_X64: ${{ needs.build.outputs.build-image-x64 }}
78+
outputs:
79+
build-image: ${{ steps.meta.outputs.tags }}
3980
steps:
40-
- name: Checkout repository
41-
uses: actions/checkout@v3
81+
- name: Checkout code
82+
uses: actions/checkout@v4
83+
84+
- name: Set up Docker Buildx
85+
uses: docker/setup-buildx-action@v3
4286

43-
- name: Log in to the Container registry
44-
uses: docker/login-action@v2
87+
- name: Login to GitHub Container Registry
88+
uses: docker/login-action@v3
4589
with:
46-
registry: ${{ env.REGISTRY }}
90+
registry: ghcr.io
4791
username: ${{ github.actor }}
4892
password: ${{ secrets.GITHUB_TOKEN }}
4993

50-
- name: Get build start time
51-
run: |
52-
echo BUILD_TIMESTAMP="$(date --utc --iso-8601=seconds)" >> $GITHUB_ENV
53-
54-
- name: Build and push Docker image
55-
uses: docker/build-push-action@v3
94+
- name: Docker meta
95+
id: meta
96+
uses: docker/metadata-action@v5
5697
with:
57-
context: .
58-
push: true
59-
tags: ${{ env.BUILD_IMAGE }}
60-
build-args: |
61-
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
62-
BUILD_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
63-
DOCKER_TAG=${{ env.BUILD_IMAGE }}
64-
GIT_BRANCH=${{ github.ref_name }}
65-
GIT_COMMIT=${{ github.sha }}
66-
GIT_URL=${{ github.repositoryUrl }}
98+
images: ghcr.io/${{ github.repository }}
99+
tags: |
100+
type=sha,suffix=-build-${{ github.run_id }}_${{ github.run_attempt }}
67101
68-
outputs:
69-
build_image: ${{ env.BUILD_IMAGE }}
102+
- name: Push the multi-platform image
103+
run: |
104+
docker buildx imagetools create \
105+
--tag "$DOCKER_METADATA_OUTPUT_TAGS" \
106+
"$DOCKER_APP_IMAGE_ARM64" "$DOCKER_APP_IMAGE_X64"
70107
71108
test:
72-
if: github.event_name != 'release'
73-
needs: build
74-
75109
runs-on: ubuntu-latest
76-
110+
needs:
111+
- merge
77112
container:
78-
image: ${{ needs.build.outputs.build_image }}
79-
113+
image: ${{ needs.merge.outputs.build-image }}
80114
defaults:
81115
run:
82116
working-directory: /opt/app
83-
84117
services:
85118
db:
86119
image: postgres
87120
env:
88121
POSTGRES_USER: root
89122
POSTGRES_PASSWORD: root
90-
91123
steps:
92124
- name: Run tests
93125
env:
@@ -110,38 +142,36 @@ jobs:
110142
name: artifacts
111143
path: artifacts/**
112144

113-
# TODO: DRY w/release.yml
114145
push:
115-
if: github.event_name != 'release'
116-
117-
needs: [ setup, build, test ]
146+
runs-on: ubuntu-24.04
147+
needs:
148+
- merge
149+
- test
118150
env:
119-
BASE_IMAGE_NAME: ${{ needs.setup.outputs.base_image_name }}
120-
BUILD_IMAGE: ${{ needs.build.outputs.build_image }}
121-
122-
runs-on: ubuntu-latest
123-
124-
permissions:
125-
packages: write
126-
151+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.build-image }}
127152
steps:
128-
- name: Extract metadata (tags, labels) for Docker
129-
id: meta
130-
uses: docker/metadata-action@v4
131-
with:
132-
images: ${{ env.BASE_IMAGE_NAME }}
153+
- name: Checkout code
154+
uses: actions/checkout@v4
133155

134-
- name: Log in to the Container registry
135-
uses: docker/login-action@v2
156+
- name: Login to GitHub Container Registry
157+
uses: docker/login-action@v3
136158
with:
137-
registry: ${{ env.REGISTRY }}
159+
registry: ghcr.io
138160
username: ${{ github.actor }}
139161
password: ${{ secrets.GITHUB_TOKEN }}
140162

141-
- name: Tag and push image
142-
uses: akhilerm/tag-push-action@v2.1.0
163+
- name: Produce permanent image tags
164+
id: branch-meta
165+
uses: docker/metadata-action@v5
143166
with:
144-
src: ${{ env.BUILD_IMAGE }}
145-
dst: |
146-
${{ steps.meta.outputs.tags }}
167+
images: ghcr.io/${{ github.repository }}
168+
tags: |
169+
type=sha
170+
type=ref,event=branch
171+
type=raw,value=latest,enable={{is_default_branch}}
147172
173+
- name: Retag and push the image
174+
run: |
175+
docker pull "$DOCKER_APP_IMAGE"
176+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$DOCKER_APP_IMAGE"
177+
docker push --all-tags "$(echo "$DOCKER_APP_IMAGE" | cut -f1 -d:)"

.github/workflows/release.yml

Lines changed: 42 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,62 @@
1-
name: Release
1+
name: Push Release Tags
22

33
on:
4-
release:
5-
types:
6-
- published
4+
push:
5+
tags:
6+
- '**'
77
workflow_dispatch:
88

99
env:
10-
REGISTRY: ghcr.io
10+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
1111

1212
jobs:
13-
# TODO: DRY w/build.yml
14-
setup:
13+
retag:
1514
runs-on: ubuntu-latest
16-
1715
steps:
18-
# See https://github.com/docker/build-push-action/blob/v2.10.0/TROUBLESHOOTING.md#repository-name-must-be-lowercase
19-
- name: Sanitize image name
20-
uses: actions/github-script@v6
21-
id: image-name
22-
with:
23-
result-encoding: string
24-
script: return '${{ env.REGISTRY }}/${{ github.repository }}'.toLowerCase()
16+
- name: Checkout code
17+
uses: actions/checkout@v4
2518

26-
- name: Get short SHA
27-
run: |
28-
echo SHORT_SHA="${GITHUB_SHA:0:7}" >> $GITHUB_ENV
19+
- name: Set up QEMU
20+
uses: docker/setup-qemu-action@v3
2921

30-
outputs:
31-
base_image_name: ${{ steps.image-name.outputs.result }}
32-
build_image: ${{ steps.image-name.outputs.result }}:${{ env.SHORT_SHA }}
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
3324

34-
# TODO: DRY w/build.yml
35-
push-release:
36-
needs: setup
37-
env:
38-
BASE_IMAGE_NAME: ${{ needs.setup.outputs.base_image_name }}
39-
BUILD_IMAGE: ${{ needs.setup.outputs.build_image }}
25+
- name: Login to GitHub Container Registry
26+
uses: docker/login-action@v3
27+
with:
28+
registry: ghcr.io
29+
username: ${{ github.actor }}
30+
password: ${{ secrets.GITHUB_TOKEN }}
4031

41-
runs-on: ubuntu-latest
32+
- name: Determine the sha-based image tag to retag
33+
id: get-base-image
34+
uses: docker/metadata-action@v5
35+
with:
36+
images: ghcr.io/${{ github.repository }}
37+
tags: type=sha
4238

43-
permissions:
44-
packages: write
39+
- name: Verify that the image was previously built
40+
env:
41+
BASE_IMAGE: ${{ steps.get-base-image.outputs.tags }}
42+
run: |
43+
docker pull "$BASE_IMAGE"
4544
46-
steps:
47-
# TODO: Make this fail if tag is a bad semver (see https://github.com/docker/metadata-action/issues/200)
48-
- name: Extract metadata (tags, labels) for Docker
49-
id: meta
50-
uses: docker/metadata-action@v4
45+
- name: Produce release tags
46+
id: tag-meta
47+
uses: docker/metadata-action@v5
5148
with:
52-
images: ${{ env.BASE_IMAGE_NAME }}
53-
tags:
49+
images: ghcr.io/${{ github.repository }}
50+
flavor: latest=false
51+
tags: |
52+
type=ref,event=tag
5453
type=semver,pattern={{major}}
5554
type=semver,pattern={{major}}.{{minor}}
5655
type=semver,pattern={{version}}
5756
58-
- name: Log in to the Container registry
59-
uses: docker/login-action@v2
60-
with:
61-
registry: ${{ env.REGISTRY }}
62-
username: ${{ github.actor }}
63-
password: ${{ secrets.GITHUB_TOKEN }}
64-
65-
- name: Tag and push image
66-
uses: akhilerm/tag-push-action@v2.1.0
67-
with:
68-
src: ${{ env.BUILD_IMAGE }}
69-
dst: |
70-
${{ steps.meta.outputs.tags }}
57+
- name: Retag the pulled image
58+
env:
59+
BASE_IMAGE: ${{ steps.get-base-image.outputs.tags }}
60+
run: |
61+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$BASE_IMAGE"
62+
docker push --all-tags "$(echo "$BASE_IMAGE" | cut -f1 -d:)"

0 commit comments

Comments
 (0)