Skip to content

Commit c941408

Browse files
Updates the build/release workflows
1 parent d9bbfd2 commit c941408

File tree

4 files changed

+236
-68
lines changed

4 files changed

+236
-68
lines changed

.github/workflows/build.yml

Lines changed: 163 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,30 @@ on:
66
- '**'
77
workflow_dispatch:
88

9+
env:
10+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
11+
912
jobs:
1013
build:
11-
runs-on: ubuntu-latest
14+
runs-on: ${{ matrix.runner }}
1215
outputs:
13-
build-image: ${{ steps.build-meta.outputs.tags }}
16+
image-app-arm64: ${{ steps.gen-output.outputs.image-app-arm64 }}
17+
image-app-x64: ${{ steps.gen-output.outputs.image-app-x64 }}
18+
image-dev-arm64: ${{ steps.gen-output.outputs.image-development-arm64 }}
19+
image-dev-x64: ${{ steps.gen-output.outputs.image-development-x64 }}
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
runner:
24+
- ubuntu-24.04
25+
- ubuntu-24.04-arm
26+
target:
27+
- app
28+
- development
1429
steps:
1530
- name: Checkout code
1631
uses: actions/checkout@v4
1732

18-
- name: Set up QEMU
19-
uses: docker/setup-qemu-action@v3
20-
2133
- name: Set up Docker Buildx
2234
uses: docker/setup-buildx-action@v3
2335

@@ -28,48 +40,58 @@ jobs:
2840
username: ${{ github.actor }}
2941
password: ${{ secrets.GITHUB_TOKEN }}
3042

31-
- name: Produce the build image tag
32-
id: build-meta
43+
- name: Docker meta
44+
id: meta
3345
uses: docker/metadata-action@v5
3446
with:
3547
images: ghcr.io/${{ github.repository }}
36-
tags: type=sha,suffix=-build-${{ github.run_id }}_${{ github.run_attempt }}
48+
# note Specifies a single tag to ensure the default doesn't add more than one.
49+
# The actual tag is not used, this is just used to sanitize the registry name
50+
# and produce labels.
51+
tags: type=sha
52+
53+
- name: Sanitize registry repository name
54+
id: get-reg
55+
run: |
56+
echo "registry=$(echo '${{ steps.meta.outputs.tags }}' | cut -f1 -d:)" | tee -a "$GITHUB_OUTPUT"
3757
38-
- name: Build and push the untested image
58+
- name: Build/push the arch-specific image
59+
id: build
3960
uses: docker/build-push-action@v6
4061
with:
41-
push: true
42-
labels: ${{ steps.build-meta.outputs.labels }}
43-
tags: ${{ steps.build-meta.outputs.tags }}
44-
provenance: true
45-
sbom: true
46-
target: development
62+
# @todo GHA caching needs tuning, these tend not to hit. Perhaps switch to type=registry?
4763
cache-from: type=gha
48-
cache-to: type=gha
64+
cache-to: type=gha,mode=max
65+
labels: ${{ steps.meta.outputs.labels }}
66+
provenance: mode=max
67+
sbom: true
68+
tags: ${{ steps.get-reg.outputs.registry }}
69+
outputs: type=image,push-by-digest=true,push=true
70+
target: ${{ matrix.target }}
71+
72+
- name: Write arch-specific image digest to outputs
73+
id: gen-output
74+
run: |
75+
echo "image-${{ matrix.target }}-${RUNNER_ARCH,,}=${{ steps.get-reg.outputs.registry }}@${{ steps.build.outputs.digest }}" | tee -a "$GITHUB_OUTPUT"
4976
50-
test:
51-
runs-on: ubuntu-latest
77+
merge:
78+
runs-on: ubuntu-24.04
5279
needs:
5380
- build
54-
strategy:
55-
fail-fast: false
56-
matrix:
57-
test:
58-
- mypy .
59-
- pydoclint .
60-
# pylint returns error codes if the checks fail
61-
# https://pylint.readthedocs.io/en/latest/user_guide/usage/run.html#exit-codes
62-
- pylint -v .
63-
- python -m unittest -v
6481
env:
65-
COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml
66-
DOCKER_APP_IMAGE: ${{ needs.build.outputs.build-image }}
82+
DOCKER_APP_IMAGE_ARM64: ${{ needs.build.outputs.image-app-arm64 }}
83+
DOCKER_APP_IMAGE_X64: ${{ needs.build.outputs.image-app-x64 }}
84+
DOCKER_DEV_IMAGE_ARM64: ${{ needs.build.outputs.image-dev-arm64 }}
85+
DOCKER_DEV_IMAGE_X64: ${{ needs.build.outputs.image-dev-x64 }}
86+
outputs:
87+
app-image: ${{ steps.app-meta.outputs.tags }}
88+
dev-image: ${{ steps.dev-meta.outputs.tags }}
6789
steps:
6890
- name: Checkout code
6991
uses: actions/checkout@v4
7092

71-
- name: Set up Docker Compose
72-
uses: docker/setup-compose-action@v1
93+
- name: Set up Docker Buildx
94+
uses: docker/setup-buildx-action@v3
7395

7496
- name: Login to GitHub Container Registry
7597
uses: docker/login-action@v3
@@ -78,35 +100,120 @@ jobs:
78100
username: ${{ github.actor }}
79101
password: ${{ secrets.GITHUB_TOKEN }}
80102

81-
- name: Copy environment file
82-
run: cp env.example .env
83-
84-
- name: Set ARTIFACTS_DIR
85-
run: echo "ARTIFACTS_DIR=${RUNNER_TEMP}/artifacts" >> $GITHUB_ENV
103+
- name: Generate tag for the dev image
104+
id: dev-meta
105+
uses: docker/metadata-action@v5
106+
with:
107+
images: ghcr.io/${{ github.repository }}
108+
tags: |
109+
type=sha,suffix=-build-${{ github.run_id }}_${{ github.run_attempt }}-dev
86110
87-
- name: Create the artifacts directory
88-
run: mkdir -p "$ARTIFACTS_DIR"
111+
- name: Push the multi-platform dev image
112+
run: |
113+
docker buildx imagetools create \
114+
--tag "$DOCKER_METADATA_OUTPUT_TAGS" \
115+
"$DOCKER_DEV_IMAGE_ARM64" "$DOCKER_DEV_IMAGE_X64"
89116
90-
- name: Record start time
91-
run: TEST_START=`date +%s` >> $GITHUB_ENV
117+
- name: Generate tag for the app image
118+
id: app-meta
119+
uses: docker/metadata-action@v5
120+
with:
121+
images: ghcr.io/${{ github.repository }}
122+
tags: |
123+
type=sha,suffix=-build-${{ github.run_id }}_${{ github.run_attempt }}
92124
93-
- name: Run the test command
125+
- name: Push the multi-platform app image
126+
run: |
127+
docker buildx imagetools create \
128+
--tag "$DOCKER_METADATA_OUTPUT_TAGS" \
129+
"$DOCKER_APP_IMAGE_ARM64" "$DOCKER_APP_IMAGE_X64"
130+
131+
test-mypy:
132+
runs-on: ubuntu-24.04
133+
needs: merge
134+
container:
135+
image: ${{ needs.merge.outputs.dev-image }}
136+
defaults:
137+
run:
138+
working-directory: /app
139+
steps:
140+
- name: Run mypy
141+
run: mypy .
142+
143+
test-pydoclint:
144+
runs-on: ubuntu-24.04
145+
needs: merge
146+
container:
147+
image: ${{ needs.merge.outputs.dev-image }}
148+
defaults:
149+
run:
150+
working-directory: /app
151+
steps:
152+
- name: Run pydoclint
153+
run: pydoclint .
154+
155+
# pylint returns error codes if the checks fail
156+
# @see https://pylint.readthedocs.io/en/latest/user_guide/usage/run.html#exit-codes
157+
test-pylint:
158+
runs-on: ubuntu-24.04
159+
needs: merge
160+
container:
161+
image: ${{ needs.merge.outputs.dev-image }}
162+
defaults:
163+
run:
164+
working-directory: /app
165+
steps:
166+
- name: Run pylint
167+
run: pylint -v .
168+
169+
test-unittest:
170+
runs-on: ubuntu-24.04
171+
needs: merge
172+
container:
173+
image: ${{ needs.merge.outputs.dev-image }}
174+
defaults:
175+
run:
176+
working-directory: /app
177+
steps:
178+
- name: Run unit tests
94179
run: |
95-
docker compose run --no-deps --rm app ${{ matrix.test }}
180+
python -m unittest .
181+
182+
test-startup:
183+
runs-on: ubuntu-24.04
184+
needs: merge
185+
env:
186+
COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml
187+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.app-image }}
188+
steps:
189+
- name: Checkout code
190+
uses: actions/checkout@v4
191+
192+
- name: Set up Docker Compose
193+
uses: docker/setup-compose-action@v1
96194

97-
- name: Upload test report
98-
if: ${{ always() }}
99-
uses: actions/upload-artifact@v4
195+
- name: Login to GitHub Container Registry
196+
uses: docker/login-action@v3
100197
with:
101-
name: Test Report - ${{ matrix.test }} (${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }})
102-
path: ${{ env.ARTIFACTS_DIR }}
103-
if-no-files-found: warn
198+
registry: ghcr.io
199+
username: ${{ github.actor }}
200+
password: ${{ secrets.GITHUB_TOKEN }}
201+
202+
- name: Run the test script
203+
run: |
204+
docker compose up --detach --wait
104205
105206
push:
106-
runs-on: ubuntu-latest
207+
runs-on: ubuntu-24.04
107208
needs:
108-
- build
109-
- test
209+
- merge
210+
- test-mypy
211+
- test-pydoclint
212+
- test-pylint
213+
- test-startup
214+
- test-unittest
215+
env:
216+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.app-image }}
110217
steps:
111218
- name: Checkout code
112219
uses: actions/checkout@v4
@@ -129,10 +236,7 @@ jobs:
129236
type=raw,value=latest,enable={{is_default_branch}}
130237
131238
- name: Retag and push the image
132-
uses: docker/build-push-action@v6
133-
with:
134-
push: true
135-
labels: ${{ steps.branch-meta.outputs.labels }}
136-
tags: ${{ steps.branch-meta.outputs.tags }}
137-
cache-from: type=registry,ref=${{ needs.build.outputs.build-image }}
138-
target: app
239+
run: |
240+
docker pull "$DOCKER_APP_IMAGE"
241+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$DOCKER_APP_IMAGE"
242+
docker push --all-tags "$(echo "$DOCKER_APP_IMAGE" | cut -f1 -d:)"

.github/workflows/release.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Push Release Tags
2+
3+
on:
4+
push:
5+
tags:
6+
- '**'
7+
workflow_dispatch:
8+
9+
env:
10+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
11+
12+
jobs:
13+
retag:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up QEMU
20+
uses: docker/setup-qemu-action@v3
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
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 }}
31+
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
38+
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"
44+
45+
- name: Produce release tags
46+
id: tag-meta
47+
uses: docker/metadata-action@v5
48+
with:
49+
images: ghcr.io/${{ github.repository }}
50+
flavor: latest=false
51+
tags: |
52+
type=ref,event=tag
53+
type=semver,pattern={{major}}
54+
type=semver,pattern={{major}}.{{minor}}
55+
type=semver,pattern={{version}}
56+
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:)"

docker-compose.ci.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
services:
2-
db: !reset
2+
db:
3+
volumes: !reset
4+
35
app:
46
build: !reset
57
depends_on: !reset
68
ports: !reset
7-
environment:
8-
CHAT_BACKEND: ollama
9-
DEFAULT_STORAGE_DIR: /tmp
10-
EMBED_BACKEND: ollama
9+
env_file: !override env.example
1110
volumes: !reset
11+
1212
ollama: !reset
13+
1314
prisma: !reset
15+
1416
localstack: !reset

docker-compose.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ services:
44
restart: always
55
environment: &dbconfig
66
POSTGRES_DB: ${POSTGRES_DB:-willa}
7-
POSTGRES_USER: ${POSTGRES_USER:-root}
8-
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-root}
9-
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}}
7+
POSTGRES_USER: ${POSTGRES_USER:-postgres}
8+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
9+
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db/${POSTGRES_DB:-willa}}
1010
ports:
1111
- 5432:5432
1212
volumes:
1313
- ./.data/postgres:/var/lib/postgresql/data
1414
healthcheck:
15-
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
15+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-willa}"]
1616
interval: 10s
1717
timeout: 5s
1818
retries: 5

0 commit comments

Comments
 (0)