11name : Release
22
3- # Cutting a release is a single action: push a SemVer tag (e.g. `v0.1.0`). This builds and
4- # publishes the API and Web container images to the GitHub Container Registry (populating the
5- # repo's Packages section), then creates the GitHub Release with auto-generated notes.
3+ # Two ways to cut a release:
4+ # • push a SemVer tag (e.g. `v0.1.0`), or
5+ # • run this workflow manually (Actions ▸ Release ▸ Run workflow) and pass the tag —
6+ # the release job then creates that tag from the current branch for you.
7+ #
8+ # Either way it builds & pushes the API and Web container images to the GitHub Container
9+ # Registry (linked to this repo via OCI source labels, so they appear under Packages),
10+ # then publishes the GitHub Release with auto-generated notes.
611
712on :
813 push :
914 tags : ['v*']
15+ workflow_dispatch :
16+ inputs :
17+ tag :
18+ description : Release tag (SemVer, e.g. v0.1.0)
19+ required : true
20+ default : v0.1.0
1021
1122permissions :
12- contents : write # create the GitHub Release
23+ contents : write # create the tag + GitHub Release
1324 packages : write # push images to ghcr.io
1425
1526jobs :
27+ prep :
28+ runs-on : ubuntu-latest
29+ outputs :
30+ version : ${{ steps.ver.outputs.version }}
31+ steps :
32+ - id : ver
33+ run : |
34+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
35+ v="${{ inputs.tag }}"
36+ else
37+ v="${{ github.ref_name }}"
38+ fi
39+ echo "version=$v" >> "$GITHUB_OUTPUT"
40+
1641 images :
1742 name : Publish ${{ matrix.name }} image
43+ needs : prep
1844 runs-on : ubuntu-latest
1945 strategy :
2046 matrix :
@@ -40,31 +66,26 @@ jobs:
4066 username : ${{ github.actor }}
4167 password : ${{ secrets.GITHUB_TOKEN }}
4268
43- - name : Derive image tags
44- id : meta
45- uses : docker/metadata-action@v5
46- with :
47- images : ${{ matrix.image }}
48- tags : |
49- type=semver,pattern={{version}}
50- type=semver,pattern={{major}}.{{minor}}
51- type=raw,value=latest
52-
5369 - name : Build & push
5470 uses : docker/build-push-action@v6
5571 with :
5672 context : .
5773 file : ${{ matrix.dockerfile }}
5874 push : true
59- tags : ${{ steps.meta.outputs.tags }}
60- labels : ${{ steps.meta.outputs.labels }}
75+ tags : |
76+ ${{ matrix.image }}:${{ needs.prep.outputs.version }}
77+ ${{ matrix.image }}:latest
78+ labels : |
79+ org.opencontainers.image.source=https://github.com/softpython2884/OpenCoperLock
80+ org.opencontainers.image.version=${{ needs.prep.outputs.version }}
81+ org.opencontainers.image.licenses=AGPL-3.0-or-later
6182 build-args : ${{ matrix.build_args }}
6283 cache-from : type=gha
6384 cache-to : type=gha,mode=max
6485
6586 release :
6687 name : GitHub Release
67- needs : images
88+ needs : [prep, images]
6889 runs-on : ubuntu-latest
6990 steps :
7091 - uses : actions/checkout@v4
@@ -74,18 +95,20 @@ jobs:
7495 - name : Create release
7596 uses : softprops/action-gh-release@v2
7697 with :
98+ tag_name : ${{ needs.prep.outputs.version }}
99+ name : OpenCoperLock ${{ needs.prep.outputs.version }}
77100 generate_release_notes : true
78101 body : |
79- ## OpenCoperLock ${{ github.ref_name }}
102+ ## OpenCoperLock ${{ needs.prep.outputs.version }}
80103
81104 Self-hostable private cloud — a classic Drive plus advanced acquisition & security tooling.
82105
83106 ### Container images
84- Pull the published images from the GitHub Container Registry:
107+ Published to the GitHub Container Registry:
85108
86109 ```bash
87- docker pull ghcr.io/softpython2884/opencoperlock-api:${{ github.ref_name }}
88- docker pull ghcr.io/softpython2884/opencoperlock-web:${{ github.ref_name }}
110+ docker pull ghcr.io/softpython2884/opencoperlock-api:${{ needs.prep.outputs.version }}
111+ docker pull ghcr.io/softpython2884/opencoperlock-web:${{ needs.prep.outputs.version }}
89112 ```
90113
91114 See `infra/docker-compose.yml` and `docs/DEPLOYMENT.md` to deploy.
0 commit comments