release.yml pushes the release commit and its tag in a single `git push`, so Gitea created two build.yml runs for the same commit. Only the tag run matters: it emits the X.Y.Z and X.Y image tags, and since it is the same commit it publishes `latest` and `sha-<short>` as well. The master run was pure duplicate work that had to be waited out or cancelled by hand. Guard the build job with an `if` that skips a branch push whose head commit message starts with `chore(release):`. Ordinary pushes to master are unaffected, and tag pushes and manual dispatches always build. The skipped master run keeps the release commit's sha, which would have let release.yml's "Verify build.yml started" check go green on it alone even if the tag run were never created — the exact failure that check exists to catch. It now also requires the run's ref to be the tag, falling back to the sha match only when the API reports no ref. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
102 lines
3.5 KiB
YAML
102 lines
3.5 KiB
YAML
# Build + push the API and web container images to the git.mancinas.io registry.
|
|
#
|
|
# Two images from this one repo:
|
|
# git.mancinas.io/rmancinas/jorgecuadros-api
|
|
# git.mancinas.io/rmancinas/jorgecuadros-web
|
|
#
|
|
# Comprehensive versioning (docker/metadata-action). Every build pushes a set
|
|
# of tags so an image is addressable at several granularities:
|
|
# - vX.Y.Z / vX.Y when the trigger is a git tag vX.Y.Z (releases)
|
|
# - <branch> the branch that was pushed (e.g. master, feat-foo)
|
|
# - sha-<short> immutable per-commit id, always present
|
|
# - latest only on the default branch (master)
|
|
# The same version string + commit + build date are baked into the image as
|
|
# ARG/ENV (APP_VERSION / GIT_SHA / BUILD_DATE) and as OCI labels, so a running
|
|
# container can report exactly what is deployed.
|
|
#
|
|
# Release flow: git tag v1.2.0 && git push origin v1.2.0 -> versioned images.
|
|
|
|
name: Build and Push Images
|
|
|
|
on:
|
|
push:
|
|
branches: [master]
|
|
tags: ["v*"]
|
|
paths:
|
|
- "apps/**"
|
|
- "packages/**"
|
|
- "docker/**"
|
|
- "package.json"
|
|
- "pnpm-lock.yaml"
|
|
- ".gitea/workflows/build.yml"
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
REGISTRY: git.mancinas.io
|
|
|
|
jobs:
|
|
build:
|
|
name: Build ${{ matrix.image }}
|
|
# release.yml pushes the release commit and its tag in a single `git push`,
|
|
# so Gitea creates two runs for the same commit: one for master, one for the
|
|
# tag. Only the tag run matters — it is the one that emits the X.Y.Z / X.Y
|
|
# image tags, and it publishes `latest` and `sha-<short>` too, since it is
|
|
# the same commit. Skip the branch run rather than racing or cancelling it.
|
|
# Ordinary pushes to master (any message but `chore(release):`) still build.
|
|
if: >-
|
|
github.event_name != 'push' ||
|
|
startsWith(github.ref, 'refs/tags/') ||
|
|
!startsWith(github.event.head_commit.message, 'chore(release):')
|
|
runs-on: docker
|
|
container:
|
|
image: docker:27-dind
|
|
options: --privileged
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- image: jorgecuadros-api
|
|
dockerfile: docker/api.Dockerfile
|
|
- image: jorgecuadros-web
|
|
dockerfile: docker/web.Dockerfile
|
|
steps:
|
|
- name: Install Node.js for actions
|
|
run: apk add --no-cache nodejs npm
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: docker/setup-buildx-action@v3
|
|
|
|
- uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
|
|
- id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.image }}
|
|
tags: |
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
type=ref,event=branch
|
|
type=sha,format=short,prefix=sha-
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
|
|
- uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
file: ${{ matrix.dockerfile }}
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
platforms: linux/amd64
|
|
build-args: |
|
|
APP_VERSION=${{ steps.meta.outputs.version }}
|
|
GIT_SHA=${{ github.sha }}
|
|
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
|