Files
jorgecuadros-platform/.gitea/workflows/build.yml
T
rmancinas caacaac3f5
Build and Push Images / Build jorgecuadros-api (push) Successful in 3m30s
Build and Push Images / Build jorgecuadros-web (push) Successful in 2m6s
ci: cache Docker layers between image builds (#1)
2026-10-22 00:21:16 -07:00

113 lines
4.2 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
# -> deploy-on-tag.yml waits for this run to go green and then
# dispatches deploy-galactus.yml.
#
# This workflow BUILDS ONLY — it never deploys. The deploy chain used to be a
# job here, gated to tag refs, but Gitea draws every job of a workflow into the
# run graph before it evaluates the job's `if`: a routine master build showed a
# pending "Deploy to galactus" and looked like prod was about to be redeployed
# off an unreleased commit. Keeping the deploy in a `on: push: tags` workflow of
# its own makes that structurally impossible.
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
cache-from: type=gha,scope=${{ matrix.image }}
cache-to: type=gha,mode=max,scope=${{ matrix.image }}
build-args: |
APP_VERSION=${{ steps.meta.outputs.version }}
GIT_SHA=${{ github.sha }}
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}