# Cut a release and build container images. # # Triggered manually via ``workflow_dispatch`` (Actions tab → Run # workflow) when you're ready to ship. Not on every PR merge. # # Flow: # 1. ``ietf-tools/semver-action`` derives the next version from # conventional commit messages since the last tag (feat → minor, # fix → patch, breaking → major). # 2. ``requarks/changelog-action`` generates release notes from the # commit diff between the new and previous tags. # 3. ``ncipollo/release-action`` creates the GitHub Release. # 4. ``requarks/changelog-action`` writes CHANGELOG.md and # ``stefanzweifel/git-auto-commit-action`` commits it back to # master with ``[skip ci]``. # 5. All three container images are built and pushed to GHCR, # tagged with the semver version + ``latest``. name: Release on: workflow_dispatch: jobs: # ── Version + Release + Changelog ──────────────────────────────── version: runs-on: ubuntu-latest permissions: contents: write outputs: new: ${{ steps.semver.outputs.next }} newStrict: ${{ steps.semver.outputs.nextStrict }} steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Get next version id: semver uses: ietf-tools/semver-action@v1 with: token: ${{ github.token }} branch: master - name: Generate release notes id: changelog uses: requarks/changelog-action@v1 with: token: ${{ github.token }} fromTag: master toTag: ${{ steps.semver.outputs.current }} writeToFile: false - name: Create release uses: ncipollo/release-action@v1.12.0 with: allowUpdates: true draft: false makeLatest: true tag: ${{ steps.semver.outputs.next }} body: ${{ steps.changelog.outputs.changes }} token: ${{ github.token }} - name: Write CHANGELOG.md uses: requarks/changelog-action@v1 with: token: ${{ github.token }} fromTag: ${{ steps.semver.outputs.next }} toTag: ${{ steps.semver.outputs.current }} writeToFile: true - name: Commit CHANGELOG.md uses: stefanzweifel/git-auto-commit-action@v4 with: branch: master commit_message: "docs: update CHANGELOG.md for ${{ steps.semver.outputs.next }} [skip ci]" file_pattern: CHANGELOG.md # ── Build and push container images ────────────────────────────── build-api: name: API image needs: version runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-action@v5 id: meta with: images: ghcr.io/consentos/consentos-api tags: | type=semver,pattern={{version}},value=${{ needs.version.outputs.newStrict }} type=semver,pattern={{major}}.{{minor}},value=${{ needs.version.outputs.newStrict }} type=raw,value=latest - uses: docker/build-push-action@v6 with: context: apps/api file: apps/api/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-scanner: name: Scanner image needs: version runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-action@v5 id: meta with: images: ghcr.io/consentos/consentos-scanner tags: | type=semver,pattern={{version}},value=${{ needs.version.outputs.newStrict }} type=semver,pattern={{major}}.{{minor}},value=${{ needs.version.outputs.newStrict }} type=raw,value=latest - uses: docker/build-push-action@v6 with: context: apps/scanner file: apps/scanner/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-admin-ui: name: Admin UI image needs: version runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-action@v5 id: meta with: images: ghcr.io/consentos/consentos-admin-ui tags: | type=semver,pattern={{version}},value=${{ needs.version.outputs.newStrict }} type=semver,pattern={{major}}.{{minor}},value=${{ needs.version.outputs.newStrict }} type=raw,value=latest # Context is the repo root — the admin-ui Dockerfile pulls in # apps/banner/ alongside apps/admin-ui/ and bundles the banner # output at the nginx root. - uses: docker/build-push-action@v6 with: context: . file: apps/admin-ui/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}