Skip to content

Commit dbf912e

Browse files
committed
Refactor GitHub Actions workflows for cleaner versioning and releases
Publish workflow: - Add version checking to skip publishing when unchanged - Use PAT_TOKEN to enable cascading workflow triggers - Create clean semver tags (v0.5.1) without magg/ prefix - Create movable 2-digit tags (v0.5) for minor version tracking - Rename magg/latest to latest-publish for clarity - Only publish to PyPI when version changes Docker workflow: - Trigger on main/beta pushes and v*.*.* semver tags - Fix metadata tags to handle 3-digit versions properly - Support both versioned and branch-based image tags - Remove 4-digit version pattern that wasn't semver compliant Manual publish workflow: - Restrict to pre/post/dev releases only (no regular versions) - Add validation script using JSON output and importlib.metadata - Auto-create GitHub releases for post-releases by default - Update latest-publish tag for post-releases of current version - Include proper changelog in GitHub releases - Make PyPI publish the final step after all validations Add packaging dependency for version validation in manual releases. This creates a cleaner separation between automatic releases (regular versions on main) and manual releases (pre/post/dev versions), while maintaining proper version tracking and Docker image tagging. Signed-off-by: Phillip Sitbon <[email protected]>
1 parent d116235 commit dbf912e

File tree

7 files changed

+415
-111
lines changed

7 files changed

+415
-111
lines changed

.github/workflows/docker-publish.yml

Lines changed: 138 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ name: Docker
22

33
on:
44
push:
5-
branches: [ beta ]
6-
tags: [ 'magg/v*' ]
5+
branches: [ main, beta ]
6+
tags: [ 'v*.*.*' ]
77
pull_request:
88
branches: [ main, beta ]
99
workflow_dispatch:
@@ -13,88 +13,167 @@ env:
1313
IMAGE_NAME: ${{ github.repository }}
1414

1515
jobs:
16-
test-dev-container:
16+
build-dev-image:
17+
name: Build Dev Image
1718
runs-on: ubuntu-latest
19+
1820
permissions:
1921
contents: read
20-
packages: write
21-
22+
2223
strategy:
2324
matrix:
24-
python-version: ['3.12', '3.13']
25+
python-version: [ '3.12', '3.13' ]
2526
fail-fast: false
26-
27+
2728
steps:
2829
- name: Checkout
2930
uses: actions/checkout@v4
30-
31+
3132
- name: Set up Docker Buildx
3233
uses: docker/setup-buildx-action@v3
33-
34+
3435
- name: Log in to Container Registry
3536
uses: docker/login-action@v3
3637
with:
3738
registry: ${{ env.REGISTRY }}
3839
username: ${{ github.actor }}
3940
password: ${{ secrets.GITHUB_TOKEN }}
40-
41-
- name: Extract metadata
42-
id: meta
43-
uses: docker/metadata-action@v5
44-
with:
45-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
46-
tags: |
47-
type=ref,event=branch,suffix=-dev-py${{ matrix.python-version }}
48-
type=ref,event=pr,suffix=-dev-py${{ matrix.python-version }}
49-
type=semver,pattern=v{{major}}.{{minor}}.{{patch}}.{{build}},prefix=,suffix=-dev-py${{ matrix.python-version }}
50-
type=raw,value=${{ github.ref_name == 'main' && 'dev' || format('{0}-dev', github.ref_name) }},enable=${{ matrix.python-version == '3.13' && startsWith(github.ref, 'refs/heads/') }}
51-
52-
- name: Build dev image
41+
42+
- name: Build Dev Image
5343
uses: docker/build-push-action@v6
5444
with:
5545
context: .
5646
file: ./dockerfile
5747
target: dev
5848
push: false
59-
tags: ${{ steps.meta.outputs.tags }}
49+
tags: dev-image:${{ matrix.python-version }}
50+
# tags: ${{ steps.meta.outputs.tags }}
6051
# labels: ${{ steps.meta.outputs.labels }}
6152
build-args: |
6253
PYTHON_VERSION=${{ matrix.python-version }}
6354
cache-from: type=gha
6455
cache-to: type=gha,mode=max
65-
load: true
6656
provenance: false
6757
sbom: false
68-
69-
- name: Run tests in container
58+
59+
- name: Save image as tar
7060
run: |
71-
# Use the first tag only (multiple tags break the docker run command)
72-
FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n1)
73-
docker run --rm \
74-
-e MAGG_LOG_LEVEL= \
75-
${FIRST_TAG} \
76-
pytest -v
77-
78-
- name: Push dev image
79-
if: github.event_name != 'pull_request'
80-
uses: docker/build-push-action@v6
61+
docker save dev-image:${{ matrix.python-version }} -o dev-image-${{ matrix.python-version }}.tar
62+
63+
- name: Upload image artifact
64+
uses: actions/upload-artifact@v4
8165
with:
82-
context: .
83-
file: ./dockerfile
84-
target: dev
85-
push: true
86-
tags: ${{ steps.meta.outputs.tags }}
87-
# labels: ${{ steps.meta.outputs.labels }}
88-
build-args: |
89-
PYTHON_VERSION=${{ matrix.python-version }}
90-
cache-from: type=gha
91-
cache-to: type=gha,mode=max
92-
provenance: false
93-
sbom: false
66+
name: dev-image-${{ matrix.python-version }}
67+
path: dev-image-${{ matrix.python-version }}.tar
68+
69+
test-dev-image:
70+
name: Test Dev Container
71+
runs-on: ubuntu-latest
72+
73+
needs: build-dev-image
74+
if: ${{ !startsWith(github.ref, 'refs/tags/') }} # Only run on branches or PRs, not tags
75+
76+
permissions:
77+
contents: read
78+
79+
strategy:
80+
matrix:
81+
python-version: ['3.12', '3.13']
82+
fail-fast: false
83+
84+
steps:
85+
- name: Download image artifact
86+
uses: actions/download-artifact@v4
87+
with:
88+
name: dev-image-${{ matrix.python-version }}
89+
90+
- name: Load image
91+
run: |
92+
docker load -i dev-image-${{ matrix.python-version }}.tar
9493
95-
build-and-push:
96-
needs: test-dev-container
94+
- name: Run Container Tests
95+
run: |
96+
docker run --rm -e MAGG_LOG_LEVEL= dev-image:${{ matrix.python-version }} pytest -v
97+
98+
push-dev-image:
99+
name: Push Dev Images
97100
runs-on: ubuntu-latest
101+
102+
needs: [build-dev-image, test-dev-image]
103+
104+
permissions:
105+
contents: read
106+
packages: write
107+
108+
strategy:
109+
matrix:
110+
python-version: ['3.12', '3.13']
111+
fail-fast: false
112+
113+
steps:
114+
- name: Download image artifact
115+
uses: actions/download-artifact@v4
116+
with:
117+
name: dev-image-${{ matrix.python-version }}
118+
119+
- name: Load image
120+
run: |
121+
docker load -i dev-image-${{ matrix.python-version }}.tar
122+
123+
- name: Log in to registry
124+
uses: docker/login-action@v3
125+
with:
126+
registry: ${{ env.REGISTRY }}
127+
username: ${{ github.actor }}
128+
password: ${{ secrets.GITHUB_TOKEN }}
129+
130+
- name: Extract Metadata
131+
id: meta
132+
uses: docker/metadata-action@v5
133+
with:
134+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
135+
tags: |
136+
# pr-NN-dev-py3.XX or pr-NN-dev for 3.13
137+
type=ref,event=pr,suffix=-dev-py${{ matrix.python-version }}
138+
type=ref,event=pr,suffix=-dev,enable=${{ matrix.python-version == '3.13' }}
139+
140+
# branch-dev-py3.XX
141+
type=ref,event=branch,suffix=-dev-py${{ matrix.python-version }}
142+
143+
# dev for main branch, only for 3.13
144+
type=raw,value=dev,enable=${{ matrix.python-version == '3.13' && github.ref_name == 'main' }}
145+
146+
# branch-dev for other branches, only for 3.13
147+
type=raw,value=${{ github.ref_name }}-dev,enable=${{ matrix.python-version == '3.13' && github.ref_name != 'main' && startsWith(github.ref, 'refs/heads/') }}
148+
149+
# This matches v1.2.3 and outputs 1.2.3-dev-py3.XX or 1.2.3-dev for 3.13
150+
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},pattern={{major}}.{{minor}}.{{patch}},suffix=-dev-py${{ matrix.python-version }}
151+
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},pattern={{major}}.{{minor}}.{{patch}},suffix=-dev,enable=${{ matrix.python-version == '3.13' }}
152+
153+
# This matches v1.2 and outputs 1.2-dev-py3.XX or 1.2-dev for 3.13
154+
type=semver,pattern=v{{major}}.{{minor}},pattern={{major}}.{{minor}},suffix=-dev-py${{ matrix.python-version }}
155+
type=semver,pattern=v{{major}}.{{minor}},pattern={{major}}.{{minor}},suffix=-dev,enable=${{ matrix.python-version == '3.13' }}
156+
157+
- name: Tag image with all tags
158+
run: |
159+
for TAG in ${{ steps.meta.outputs.tags }}; do
160+
docker tag dev-image:${{ matrix.python-version }} $TAG
161+
done
162+
shell: bash
163+
164+
- name: Push all tags
165+
run: |
166+
for TAG in ${{ steps.meta.outputs.tags }}; do
167+
docker push $TAG
168+
done
169+
shell: bash
170+
171+
build-and-push-image:
172+
name: Build and Push Image
173+
runs-on: ubuntu-latest
174+
175+
needs: [build-dev-image, test-dev-image]
176+
98177
permissions:
99178
contents: read
100179
packages: write
@@ -121,15 +200,16 @@ jobs:
121200
username: ${{ github.actor }}
122201
password: ${{ secrets.GITHUB_TOKEN }}
123202

124-
- name: Extract metadata
203+
- name: Extract Metadata
125204
id: meta
126205
uses: docker/metadata-action@v5
127206
with:
128207
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
129208
tags: |
130209
type=ref,event=branch,suffix=${{ matrix.suffix }}
131210
type=ref,event=pr,suffix=${{ matrix.suffix }}
132-
type=semver,pattern=v{{major}}.{{minor}}.{{patch}}.{{build}},prefix=,suffix=${{ matrix.suffix }}
211+
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},pattern={{major}}.{{minor}}.{{patch}},suffix=${{ matrix.suffix }}
212+
type=semver,pattern=v{{major}}.{{minor}}.{{patch}},pattern={{major}}.{{minor}},suffix=${{ matrix.suffix }}
133213
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && matrix.target == 'pro' }}
134214
135215
- name: Build and push Docker image
@@ -147,11 +227,15 @@ jobs:
147227
sbom: false
148228

149229
cleanup-untagged:
150-
needs: [test-dev-container, build-and-push]
230+
name: Cleanup Untagged Images
151231
runs-on: ubuntu-latest
152-
if: github.event_name != 'pull_request'
232+
233+
needs: [test-dev-image, build-and-push-image]
234+
if: ${{ github.event_name != 'pull_request' }}
235+
153236
permissions:
154237
packages: write
238+
155239
steps:
156240
- name: Delete untagged images
157241
uses: actions/delete-package-versions@v5

0 commit comments

Comments
 (0)