Skip to content

Commit 972916e

Browse files
Updates build/release workflows
1 parent d9e9196 commit 972916e

File tree

2 files changed

+175
-163
lines changed

2 files changed

+175
-163
lines changed

.github/workflows/build.yml

Lines changed: 133 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,147 +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+
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
4283

43-
- name: Log in to the Container registry
44-
uses: docker/login-action@v2
84+
- name: Set up Docker Buildx
85+
uses: docker/setup-buildx-action@v3
86+
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-
75-
runs-on: ubuntu-latest
76-
77-
container:
78-
image: ${{ needs.build.outputs.build_image }}
79-
80-
defaults:
81-
run:
82-
working-directory: /opt/app
109+
runs-on: ubuntu-24.04
110+
needs:
111+
- merge
112+
env:
113+
COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml
114+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.build-image }}
115+
steps:
116+
- name: Checkout code
117+
uses: actions/checkout@v4
83118

84-
services:
85-
db:
86-
image: postgres
87-
env:
88-
POSTGRES_USER: root
89-
POSTGRES_PASSWORD: root
119+
- name: Set up Docker Compose
120+
uses: docker/setup-compose-action@v1
90121

91-
steps:
92-
- name: Run tests
93-
env:
94-
RAILS_ENV: test
95-
run: bundle exec rake check -t
96-
97-
- name: Run style checks
98-
run: bundle exec rubocop
99-
100-
- name: Validate database migrations
101-
env:
102-
RAILS_ENV: production
103-
DISABLE_DATABASE_ENVIRONMENT_CHECK: 1
104-
run: rails --trace db:drop db:create db:migrate
105-
106-
- name: Upload artifacts
107-
if: ${{ always() }}
108-
uses: actions/upload-artifact@v4
122+
- name: Login to GitHub Container Registry
123+
uses: docker/login-action@v3
109124
with:
110-
name: artifacts
111-
path: artifacts/**
125+
registry: ghcr.io
126+
username: ${{ github.actor }}
127+
password: ${{ secrets.GITHUB_TOKEN }}
112128

113-
# TODO: DRY w/release.yml
114-
push:
115-
if: github.event_name != 'release'
129+
- name: Run the test script
130+
run: |
131+
docker compose run --rm --user root app chown -R avplayer:avplayer artifacts
132+
docker compose up --detach --wait
133+
docker compose exec app bin/test
116134
117-
needs: [ setup, build, test ]
135+
push:
136+
runs-on: ubuntu-24.04
137+
needs:
138+
- merge
139+
- test
118140
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-
141+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.build-image }}
127142
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 }}
143+
- name: Checkout code
144+
uses: actions/checkout@v4
133145

134-
- name: Log in to the Container registry
135-
uses: docker/login-action@v2
146+
- name: Login to GitHub Container Registry
147+
uses: docker/login-action@v3
136148
with:
137-
registry: ${{ env.REGISTRY }}
149+
registry: ghcr.io
138150
username: ${{ github.actor }}
139151
password: ${{ secrets.GITHUB_TOKEN }}
140152

141-
- name: Tag and push image
142-
uses: akhilerm/[email protected]
153+
- name: Produce permanent image tags
154+
id: branch-meta
155+
uses: docker/metadata-action@v5
143156
with:
144-
src: ${{ env.BUILD_IMAGE }}
145-
dst: |
146-
${{ steps.meta.outputs.tags }}
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}}
147162
163+
- name: Retag and push the image
164+
run: |
165+
docker pull "$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: 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/[email protected]
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)