Files
directus/.gitea/workflows/build.yml
T
julian 64f34e35f8
Build directus image / build-and-publish (push) Successful in 1m47s
Trigger workflow on dev branch; tag images :dev (and :sha)
2026-05-03 15:49:13 +00:00

145 lines
6.7 KiB
YAML

name: Build directus image
on:
push:
branches: [dev]
paths:
- 'snapshots/**'
- 'db-init/**'
- 'db-init-post/**'
- 'extensions/**'
- 'scripts/**'
- 'entrypoint.sh'
- 'Dockerfile'
- '.gitea/workflows/build.yml'
workflow_dispatch:
jobs:
build-and-publish:
runs-on: ubuntu-22.04
# ---------------------------------------------------------------------------
# Throwaway Postgres for the dry-run boot step.
#
# Image: pinned to the same concrete tag used in compose.dev.yaml — NOT the
# floating :pg16-latest alias (which does NOT exist on Docker Hub).
#
# PGDATA: the timescaledb-ha image initialises at /home/postgres/pgdata/data;
# the healthcheck uses pg_isready, which doesn't depend on the PGDATA path.
#
# Port mapping: 15432:5432 — host port 15432 is the conventional
# Postgres-second-instance port. We deliberately do NOT use 5432 on the
# runner because the runner host typically has another Postgres on 5432
# (dev stack, stage instance) which would cause a port-allocation collision.
# The dry-run docker run uses --network host so DB_HOST=localhost reaches
# the service on the runner's loopback at port 15432.
# ---------------------------------------------------------------------------
services:
postgres:
image: timescale/timescaledb-ha:pg16.6-ts2.17.2-all
env:
POSTGRES_USER: directus
POSTGRES_PASSWORD: directus
POSTGRES_DB: directus
ports:
- '15432:5432'
options: >-
--health-cmd "pg_isready -U directus -d directus"
--health-interval 5s
--health-timeout 5s
--health-retries 20
steps:
- name: Checkout
uses: actions/checkout@v4
# -------------------------------------------------------------------------
# Build the image locally (trm-directus:ci).
#
# We use a plain `docker build` rather than docker/build-push-action because
# we need the image available in the *local Docker daemon* for the subsequent
# `docker run` dry-run step. docker/build-push-action with the
# docker-container Buildx driver exports into a separate buildkitd cache not
# accessible to `docker run`.
# -------------------------------------------------------------------------
- name: Build image
run: docker build -t trm-directus:ci .
# -------------------------------------------------------------------------
# Dry-run boot — the gate that protects the registry from broken images.
#
# Runs the entrypoint's first FOUR steps against the throwaway Postgres:
# pre-schema db-init → bootstrap → schema-apply → post-schema db-init
#
# Bootstrap is required: schema-apply fails on a fresh DB with
# "Directus isn't installed on this database" if bootstrap hasn't created
# Directus's system tables first. The `directus schema apply` CLI prints
# an ERROR but exits 0 in that case, so an earlier "skip bootstrap for
# speed" version of this dry-run silently masked snapshot apply failures.
#
# Step 5 (`pm2-runtime start`) is intentionally skipped — that would
# require waiting for the HTTP server to come up, which adds minutes and
# tests nothing new beyond what the prior steps already validated.
#
# --network host: the service container is mapped on 127.0.0.1:5432; the
# docker run container sees it as localhost:5432 only when host networking
# is used. Without --network host, the container would be in a separate
# bridge network and could not reach the service by name or IP.
#
# --entrypoint bash: overrides /directus/entrypoint.sh so we execute only
# the script chain, not the full pm2-runtime boot.
#
# Required Directus env vars: DB_CLIENT + connection params are mandatory
# for `node cli.js schema apply`. KEY + SECRET are required by Directus's
# env initialisation even when only the schema subcommand is invoked.
# ADMIN_EMAIL + ADMIN_PASSWORD are included defensively (some Directus
# versions assert on them during CLI init). PUBLIC_URL silences the
# missing-public-url warning.
#
# If this step exits non-zero the workflow halts and the registry login /
# push steps are never reached — the broken image is never published.
# -------------------------------------------------------------------------
- name: Dry-run boot against throwaway Postgres
run: |
docker run --rm \
--network host \
--entrypoint bash \
-e DB_CLIENT=pg \
-e DB_HOST=localhost \
-e DB_PORT=15432 \
-e DB_USER=directus \
-e DB_PASSWORD=directus \
-e DB_DATABASE=directus \
-e KEY=ci-key-placeholder-not-secret \
-e SECRET=ci-secret-placeholder-not-secret \
-e ADMIN_EMAIL=ci@example.com \
-e ADMIN_PASSWORD=ci-password-not-secret \
-e PUBLIC_URL=http://localhost:8055 \
trm-directus:ci \
-c '/directus/scripts/apply-db-init.sh && node /directus/cli.js bootstrap && /directus/scripts/schema-apply.sh && DB_INIT_DIR=/directus/db-init-post /directus/scripts/apply-db-init.sh && echo "dry-run ok"'
# -------------------------------------------------------------------------
# Registry login — runs only if the dry-run succeeded (default: workflow
# halts on non-zero exit, so reaching this step implies dry-run passed).
# -------------------------------------------------------------------------
- name: Login to Gitea registry
uses: docker/login-action@v3
with:
registry: git.dev.trmtracking.org
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
# -------------------------------------------------------------------------
# Tag and push two tags:
# :dev — mutable; always points at the latest commit on dev.
# :<sha> — immutable; pinned to this specific commit.
# The deploy stack can reference either; :dev for rolling updates,
# :<sha> for pinned deployments that need explicit rollback control.
# -------------------------------------------------------------------------
- name: Tag and push
run: |
docker tag trm-directus:ci git.dev.trmtracking.org/trm/directus:dev
docker tag trm-directus:ci git.dev.trmtracking.org/trm/directus:${{ github.sha }}
docker push git.dev.trmtracking.org/trm/directus:dev
docker push git.dev.trmtracking.org/trm/directus:${{ github.sha }}