Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ name: Release
# Builds and publishes the Docker image to GitHub Container Registry.
# - push to main -> ghcr.io/<owner>/study-helper:main + :edge
# - push a v* git tag -> :1.2.3, :1.2, :1, :latest (semver)
#
# workflow_dispatch exists so version-bump.yml can trigger this explicitly:
# GITHUB_TOKEN-authored pushes (which is how version-bump.yml pushes its
# release commit + tag) do not fire push-triggered workflow runs — GitHub
# suppresses that to prevent recursion — but an explicit workflow_dispatch
# call is exempt from that restriction.
on:
push:
branches: [main]
tags: ["v*"]
workflow_dispatch:

env:
REGISTRY: ghcr.io
Expand Down
19 changes: 16 additions & 3 deletions .github/workflows/version-bump.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Version Bump

# Bumps the app version and tags the release the moment a PR is merged into
# main, so release.yml (which listens for pushes to main and v* tags)
# builds and publishes a new Docker image automatically. No manual release
# step is needed for normal PRs — see docs/releasing.md.
# main, then explicitly triggers release.yml to build and publish the
# Docker image. No manual release step is needed for normal PRs — see
# docs/releasing.md.
#
# Bump type is derived from the PR title (Conventional Commits):
# - a "!" after the type, e.g. "feat!: ..." or "fix!: ..." -> major
Expand All @@ -12,6 +12,12 @@ name: Version Bump
#
# Add the "skip-release" label to a PR to opt it out entirely (e.g. a
# docs-only or CI-only change that shouldn't ship a new image).
#
# Note: the commit + tag below are pushed using the default GITHUB_TOKEN.
# GitHub does not let GITHUB_TOKEN-authored pushes trigger other workflows'
# push events (anti-recursion protection), so release.yml would otherwise
# never run for these pushes — that's why the last step dispatches it
# explicitly via `gh workflow run`, which IS allowed from a GITHUB_TOKEN.

on:
pull_request:
Expand All @@ -20,6 +26,7 @@ on:

permissions:
contents: write
actions: write

concurrency:
group: version-bump
Expand Down Expand Up @@ -85,3 +92,9 @@ jobs:
gh release create "v${VERSION}" \
--title "v${VERSION}" \
--notes "${TITLE} (#${PR_NUMBER})"

- name: Trigger Docker image build
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: gh workflow run release.yml --ref "v${VERSION}"
20 changes: 12 additions & 8 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ GitHub Actions. In the normal case there is nothing to do manually.
Release is created.
- Add the **`skip-release`** label to a PR to opt it out entirely (e.g. a
docs-only or CI-only change that shouldn't ship a new image).
- The commit + tag are pushed with the default `GITHUB_TOKEN`, and GitHub
does not let `GITHUB_TOKEN`-authored pushes trigger other workflows'
`push` events (anti-recursion protection). So the last step explicitly
runs `gh workflow run release.yml --ref vX.Y.Z` to kick off the image
build — `workflow_dispatch` calls are exempt from that restriction.

2. **On the resulting push to `main` and the `vX.Y.Z` tag**
([`.github/workflows/release.yml`](../.github/workflows/release.yml)):
2. **`release.yml`** builds and publishes the image:

| Git event | Published image tags |
| Trigger | Published image tags |
| --- | --- |
| Push to `main` | `ghcr.io/veniplex/study-helper:main`, `:edge` |
| Push a tag `vX.Y.Z` | `:X.Y.Z`, `:X.Y`, `:X`, `:latest` |
| Push to `main` (a normal PR merge) | `ghcr.io/veniplex/study-helper:main`, `:edge` |
| `workflow_dispatch` on tag `vX.Y.Z` (from step 1) or a manual `v*` tag push | `:X.Y.Z`, `:X.Y`, `:X`, `:latest` |

So merging a PR produces both events back to back — `:main`/`:edge`
update immediately, and the versioned tags (including `:latest`) follow
right after once the tag is pushed.
So merging a PR produces both back to back — `:main`/`:edge` update from
the merge itself, and the versioned tags (including `:latest`) follow
once `version-bump.yml` tags and dispatches the release build.

3. **Update the deployment** (e.g. Portainer):
- If the stack uses `:latest` (default), re-pull the image and
Expand Down
Loading