name: Build and publish container on: # On merge to main, only build/release when image-affecting files change; # CI-config, Renovate-config and docs changes do not produce a new image. push: branches: [main] paths: - 'Dockerfile' - 'default.conf' - 'index.html' - 'styles.css' - 'script.js' - 'messages.js' - '.dockerignore' # Pull requests always run (the build is a required check); no path filter. pull_request: branches: [main] workflow_dispatch: # A newer run cancels an older in-flight run in the same group (keyed by ref), # so a fresh merge to main supersedes the previous build and only the latest # release is produced, avoiding tags that would be immediately replaced. Each # pull request likewise supersedes only its own earlier runs. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true defaults: run: shell: bash jobs: build: runs-on: ubuntu-latest permissions: contents: write packages: write steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: # Full history and tags are required to derive the next version # from the conventional-commit messages since the last release. fetch-depth: 0 - name: Determine registry host run: echo "REGISTRY=${GITHUB_SERVER_URL#*://}" >> "$GITHUB_ENV" # Derive the release version from conventional commits since the last # v* tag: feat -> minor, fix/perf -> patch, ! or BREAKING CHANGE -> major. # Anything else (chore, ci, docs, build) produces no release; those builds # are published under a sha- tag only. - name: Compute version and image tags id: version run: | set -euo pipefail image="${REGISTRY}/${GITHUB_REPOSITORY,,}" last_tag="$(git tag --list 'v*' --sort=-v:refname | head -n1 || true)" if [ -n "$last_tag" ]; then range="${last_tag}..HEAD" base="${last_tag#v}" else range="" base="0.0.0" fi subjects="$(git log ${range} --format='%s')" bodies="$(git log ${range} --format='%B')" bump="none" if printf '%s\n' "$bodies" | grep -qiE 'BREAKING[ -]CHANGE' \ || printf '%s\n' "$subjects" | grep -qE '^[a-z]+([(][^)]*[)])?!:'; then bump="major" elif printf '%s\n' "$subjects" | grep -qE '^feat([(][^)]*[)])?:'; then bump="minor" elif printf '%s\n' "$subjects" | grep -qE '^(fix|perf)([(][^)]*[)])?:'; then bump="patch" fi major="${base%%.*}" rest="${base#*.}" minor="${rest%%.*}" patch="${rest##*.}" release="false" if [ "${GITHUB_EVENT_NAME}" = "push" ] && [ "$bump" != "none" ]; then release="true" case "$bump" in major) major=$((major + 1)); minor=0; patch=0 ;; minor) minor=$((minor + 1)); patch=0 ;; patch) patch=$((patch + 1)) ;; esac version="${major}.${minor}.${patch}" { echo "tags<<__EOT__" echo "${image}:${version}" echo "${image}:${major}.${minor}" echo "${image}:${major}" echo "${image}:latest" echo "__EOT__" } >> "$GITHUB_OUTPUT" echo "version=${version}" >> "$GITHUB_OUTPUT" else short="$(git rev-parse --short HEAD)" { echo "tags<<__EOT__" echo "${image}:sha-${short}" echo "__EOT__" } >> "$GITHUB_OUTPUT" fi echo "release=${release}" >> "$GITHUB_OUTPUT" echo "Computed bump=${bump}, release=${release}, base=${base}" - name: Set up QEMU uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4 - name: Set up Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - name: Log in to the Gitea container registry if: github.event_name != 'pull_request' uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4 with: registry: ${{ env.REGISTRY }} username: ${{ github.repository_owner }} password: ${{ secrets.PACKAGES_TOKEN }} - name: Build and push uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7 with: context: . platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.version.outputs.tags }} labels: | org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} # Record the release as an annotated git tag so the next run computes the # following version from it. This push does not re-trigger the workflow, # which only listens on the main branch and pull requests. - name: Tag the release if: steps.version.outputs.release == 'true' run: | set -euo pipefail v="v${{ steps.version.outputs.version }}" git config user.name "${{ github.actor }}" git config user.email "${{ github.actor }}@users.noreply.${REGISTRY}" git tag -a "$v" -m "$v" git push origin "$v"