Skip to content

Commit 28e8059

Browse files
Updates build/release workflows
1 parent 21e6c55 commit 28e8059

File tree

3 files changed

+190
-96
lines changed

3 files changed

+190
-96
lines changed

.github/workflows/build.yml

Lines changed: 144 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,167 @@
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+
BUILD_SUFFIX: -build-${{ github.run_id }}_${{ github.run_attempt }}
11+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
512

613
jobs:
7-
# TODO: DRY w/release.yml
8-
setup:
9-
runs-on: ubuntu-latest
10-
14+
build:
15+
runs-on: ${{ matrix.runner }}
16+
outputs:
17+
image-arm64: ${{ steps.gen-output.outputs.image-arm64 }}
18+
image-x64: ${{ steps.gen-output.outputs.image-x64 }}
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
runner:
23+
- ubuntu-24.04
24+
- ubuntu-24.04-arm
1125
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
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Docker Buildx
30+
uses: docker/setup-buildx-action@v3
31+
32+
- name: Login to GitHub Container Registry
33+
uses: docker/login-action@v3
34+
with:
35+
registry: ghcr.io
36+
username: ${{ github.actor }}
37+
password: ${{ secrets.GITHUB_TOKEN }}
38+
39+
- id: build-meta
40+
name: Docker meta
41+
uses: docker/metadata-action@v5
42+
with:
43+
images: ghcr.io/${{ github.repository }}
44+
tags: type=sha,suffix=${{ env.BUILD_SUFFIX }}
45+
46+
# Build cache is shared among all builds of the same architecture
47+
- id: cache-meta
48+
name: Docker meta
49+
uses: docker/metadata-action@v5
1650
with:
17-
result-encoding: string
18-
script: return '${{ env.REGISTRY }}/${{ github.repository }}'.toLowerCase()
51+
images: ghcr.io/${{ github.repository }}
52+
tags: type=raw,value=buildcache-${{ runner.arch }}
1953

20-
- name: Get short SHA
54+
- id: get-registry
55+
name: Get the sanitized registry name
2156
run: |
22-
echo SHORT_SHA="${GITHUB_SHA:0:7}" >> $GITHUB_ENV
57+
echo "registry=$(echo '${{ steps.build-meta.outputs.tags }}' | cut -f1 -d:)" | tee -a "$GITHUB_OUTPUT"
58+
59+
- id: build
60+
name: Build/push the arch-specific image
61+
uses: docker/build-push-action@v6
62+
with:
63+
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
64+
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
65+
labels: ${{ steps.build-meta.outputs.labels }}
66+
provenance: mode=max
67+
sbom: true
68+
tags: ${{ steps.get-registry.outputs.registry }}
69+
outputs: type=image,push-by-digest=true,push=true
2370

24-
- name: Get build start time
71+
- id: gen-output
72+
name: Write arch-specific image digest to outputs
2573
run: |
26-
echo BUILD_TIMESTAMP="$(date --utc --iso-8601=seconds)" >> $GITHUB_ENV
74+
echo "image-${RUNNER_ARCH,,}=${{ steps.get-registry.outputs.registry }}@${{ steps.build.outputs.digest }}" | tee -a "$GITHUB_OUTPUT"
2775
76+
merge:
77+
runs-on: ubuntu-24.04
78+
needs: build
79+
env:
80+
DOCKER_APP_IMAGE_ARM64: ${{ needs.build.outputs.image-arm64 }}
81+
DOCKER_APP_IMAGE_X64: ${{ needs.build.outputs.image-x64 }}
2882
outputs:
29-
base_image_name: ${{ steps.image-name.outputs.result }}
30-
build_image: ${{ steps.image-name.outputs.result }}:${{ env.SHORT_SHA }}
83+
image: ${{ steps.meta.outputs.tags }}
84+
steps:
85+
- name: Checkout code
86+
uses: actions/checkout@v4
87+
88+
- name: Set up Docker Buildx
89+
uses: docker/setup-buildx-action@v3
90+
91+
- name: Login to GitHub Container Registry
92+
uses: docker/login-action@v3
93+
with:
94+
registry: ghcr.io
95+
username: ${{ github.actor }}
96+
password: ${{ secrets.GITHUB_TOKEN }}
97+
98+
- id: meta
99+
name: Generate tag for the app image
100+
uses: docker/metadata-action@v5
101+
with:
102+
images: ghcr.io/${{ github.repository }}
103+
tags: type=sha,suffix=${{ env.BUILD_SUFFIX }}
104+
105+
- name: Push the multi-platform app image
106+
run: |
107+
docker buildx imagetools create \
108+
--tag "$DOCKER_METADATA_OUTPUT_TAGS" \
109+
"$DOCKER_APP_IMAGE_ARM64" "$DOCKER_APP_IMAGE_X64"
31110
32111
test:
33-
if: github.event_name != 'release'
34-
needs: [ setup ]
35-
runs-on: ubuntu-latest
36-
permissions:
37-
packages: write
112+
runs-on: ubuntu-24.04
113+
needs: merge
38114
env:
39-
BUILD_IMAGE: ${{ needs.setup.outputs.build_image }}
115+
COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml
116+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.image }}
40117
steps:
41-
- name: Checkout repository
42-
uses: actions/checkout@v3
118+
- name: Checkout code
119+
uses: actions/checkout@v4
120+
121+
- name: Set up Docker Compose
122+
uses: docker/setup-compose-action@v1
123+
124+
- name: Login to GitHub Container Registry
125+
uses: docker/login-action@v3
126+
with:
127+
registry: ghcr.io
128+
username: ${{ github.actor }}
129+
password: ${{ secrets.GITHUB_TOKEN }}
43130

44-
- name: Run tests
45-
run: ./test/run_tests.sh
131+
- name: Run the test script
132+
run: |
133+
docker compose pull --quiet
134+
./test/run_tests.sh
46135
47-
- name: Log in to the Container registry
48-
uses: docker/login-action@v2
136+
push:
137+
runs-on: ubuntu-24.04
138+
needs:
139+
- merge
140+
- test
141+
env:
142+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.image }}
143+
steps:
144+
- name: Checkout code
145+
uses: actions/checkout@v4
146+
147+
- name: Login to GitHub Container Registry
148+
uses: docker/login-action@v3
49149
with:
50-
registry: ${{ env.REGISTRY }}
150+
registry: ghcr.io
51151
username: ${{ github.actor }}
52152
password: ${{ secrets.GITHUB_TOKEN }}
53153

54-
- name: Build and push Docker image
55-
uses: docker/build-push-action@v3
154+
- name: Produce permanent image tags
155+
uses: docker/metadata-action@v5
56156
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 }}
157+
images: ghcr.io/${{ github.repository }}
158+
tags: |
159+
type=sha
160+
type=ref,event=branch
161+
type=raw,value=latest,enable={{is_default_branch}}
67162
68-
outputs:
69-
build_image: ${{ env.BUILD_IMAGE }}
163+
- name: Retag and push the image
164+
run: |
165+
docker pull --quiet "$DOCKER_APP_IMAGE"
166+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$DOCKER_APP_IMAGE"
167+
docker push --all-tags "$(echo "$DOCKER_APP_IMAGE" | cut -f1 -d:)"

.github/workflows/release.yml

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,59 @@
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:
8-
workflow_run:
9-
workflows: ["Build"]
10-
types: ["completed"]
11-
branches:
12-
- main
138

149
env:
15-
REGISTRY: ghcr.io
10+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
1611

1712
jobs:
18-
setup:
13+
retag:
1914
runs-on: ubuntu-latest
2015
steps:
21-
- name: Sanitize image name
22-
uses: actions/github-script@v6
23-
id: image-name
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Docker Buildx
20+
uses: docker/setup-buildx-action@v3
21+
22+
- name: Login to GitHub Container Registry
23+
uses: docker/login-action@v3
2424
with:
25-
result-encoding: string
26-
script: return '${{ env.REGISTRY }}/${{ github.repository }}'.toLowerCase()
25+
registry: ghcr.io
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
2728

28-
- name: Get short SHA
29-
run: |
30-
echo SHORT_SHA="${GITHUB_SHA:0:7}" >> $GITHUB_ENV
29+
- name: Determine the sha-based image tag to retag
30+
id: get-base-image
31+
uses: docker/metadata-action@v5
32+
with:
33+
images: ghcr.io/${{ github.repository }}
34+
tags: type=sha
3135

32-
outputs:
33-
base_image_name: ${{ steps.image-name.outputs.result }}
34-
build_image: ${{ steps.image-name.outputs.result }}:${{ env.SHORT_SHA }}
36+
- name: Verify that the image was previously built
37+
env:
38+
BASE_IMAGE: ${{ steps.get-base-image.outputs.tags }}
39+
run: |
40+
docker pull "$BASE_IMAGE"
3541
36-
push:
37-
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
38-
runs-on: ubuntu-latest
39-
needs: setup
40-
permissions:
41-
packages: write
42-
env:
43-
BASE_IMAGE_NAME: ${{ needs.setup.outputs.base_image_name }}
44-
BUILD_IMAGE: ${{ needs.setup.outputs.build_image }}
45-
steps:
46-
- name: Extract metadata (tags, labels) for Docker
47-
id: meta
48-
uses: docker/metadata-action@v4
42+
- name: Produce release tags
43+
id: tag-meta
44+
uses: docker/metadata-action@v5
4945
with:
50-
images: ${{ env.BASE_IMAGE_NAME }}
46+
images: ghcr.io/${{ github.repository }}
47+
flavor: latest=false
5148
tags: |
52-
type=raw,value=latest,enable={{is_default_branch}}
49+
type=ref,event=tag
5350
type=semver,pattern={{major}}
5451
type=semver,pattern={{major}}.{{minor}}
5552
type=semver,pattern={{version}}
5653
57-
- name: Log in to the Container registry
58-
uses: docker/login-action@v2
59-
with:
60-
registry: ${{ env.REGISTRY }}
61-
username: ${{ github.actor }}
62-
password: ${{ secrets.GITHUB_TOKEN }}
63-
64-
- name: Tag and push image
65-
uses: akhilerm/[email protected]
66-
with:
67-
src: ${{ env.BUILD_IMAGE }}
68-
dst: |
69-
${{ steps.meta.outputs.tags }}
54+
- name: Retag the pulled image
55+
env:
56+
BASE_IMAGE: ${{ steps.get-base-image.outputs.tags }}
57+
run: |
58+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$BASE_IMAGE"
59+
docker push --all-tags "$(echo "$BASE_IMAGE" | cut -f1 -d:)"

docker-compose.ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
3+
services:
4+
app:
5+
build: !reset
6+
image: ${DOCKER_APP_IMAGE}

0 commit comments

Comments
 (0)