`actions/checkout@v4` already runs with `fetch-depth: 0`, which pulls
every branch and tag — origin/<base_ref> is therefore present locally
and the explicit fetch is redundant. The flag value `--depth=0` is
itself invalid (git requires a positive integer), so the step failed
with `fatal: depth 0 is not a positive number` on every PR run.
Three follow-up fixes uncovered by the first end-to-end CI run on the
self-hosted act_runner image:
- Replace `nrwl/nx-set-shas@v4` with a manual shell step. The action
queries the GitHub API to discover the last successful workflow run
and returns 404 on Gitea. The replacement derives NX_BASE/NX_HEAD
from local git history (merge-base with the target branch on
pull_request, HEAD~1 on push to main).
- Pin the `perf` job to `catthehacker/ubuntu:full-22.04` so Lighthouse
CI finds a real Chrome. The default act image (act-22.04) is the
minimal variant and ships without browsers.
- Declare `pnpm.onlyBuiltDependencies` to silence the "Ignored build
scripts" warning and approve only the packages whose post-install
hooks we actually rely on (Nx, Prisma, esbuild, swc, native
watchers/resolvers).
Formalise the PR-flow conventions while we install the PR-flow itself.
.gitea/pull_request_template.md auto-populates the PR body in Gitea
with five sections: Summary / Motivation / Implementation notes /
Verification (with CI-gate checkboxes + ADR/diagram update flags) /
Related. Sections can be left blank when irrelevant; the template
guides without adding ceremony. Header HTML comment reminds the
contributor of the PR title format and links to the full convention.
docs/development.md §5 (Conventional commit cycle) gains a 'PR
conventions' subsection that:
- explains why the PR title format matters (squash-merge subject on
main, validated by commitlint in the CI 'commits' job)
- separates feature-branch commit hygiene (exploratory OK) from PR
title hygiene (must conform)
- documents the type vocabulary (feat/fix/docs/style/refactor/perf/
test/build/ci/chore/revert)
- proposes an optional scope vocabulary (apps, libs, cross-cutting
domains like decisions/docs/ci/deps)
- describes the body template
No new ADR. The PR title format is derived from ADR-0007 (Conventional
Commits at the commit-msg layer) plus ADR-0015 (squash-merge means PR
title becomes the commit subject on main). The body template is
tactical guidance, not architectural.
Wire the CI/CD pipeline scaffolding. Implements the level-2 (Gitea
Actions) part of ADR-0015 with the thin-YAML pattern, plus the perf
gate from ADR-0017. The level-1 decisions (gates list, branch model,
secrets policy) are unchanged.
Files:
- .nvmrc pins Node 24 (latest LTS major) for actions/setup-node.
- package.json gains four ci:* scripts that the workflows call:
- ci:check - 'nx affected -t format:check lint test build'
- ci:audit - 'pnpm audit --audit-level=moderate'
- ci:commits- 'commitlint --from $COMMIT_LINT_FROM --to HEAD'
- ci:perf - 'nx build portal-shell --configuration=production
&& lhci autorun --config=./lighthouserc.js'
All four runnable locally; CI workflows are thin wrappers.
- @lhci/cli added as a dev dependency for ci:perf.
- lighthouserc.js encodes the Core Web Vitals thresholds from
ADR-0017 (LCP <= 2500ms, CLS <= 0.1, TBT <= 200ms, server
response <= 800ms, Performance >= 0.9). v1 measures only the
static-served portal-shell bundle (Nx Welcome placeholder); the
critical-routes list expands as real screens land.
- .gitea/workflows/ci.yml runs five jobs on PR + push to main:
check, scan (audit + Trivy + gitleaks), commits (PR-only), perf,
a11y. The a11y job is a placeholder that no-ops with a clear
message; it wires up for real with the first Playwright e2e suite
(ADR-0016). All gates are blocking - branch protection on main
will require all five jobs green.
- .gitea/workflows/security-scheduled.yml runs weekly (Mon 04:00
UTC) for full-tree Trivy + gitleaks (no severity filter, no
skip-dirs - broader than per-PR) plus a Lighthouse run against
the prod URL when vars.LHCI_PROD_URL is set.
Slight deviation from ADR-0015 §'Level 2': Trivy and gitleaks are
binaries (Go) and don't have clean npm wrappers, so they are
invoked through their official Gitea-Actions-compatible actions
inside the YAML rather than via 'pnpm ci:scan'. The high-level
decision (gates: audit + secret-scan + dep-scan) is unchanged; the
script/action boundary is shifted by one tool. Documented here for
traceability; no ADR amendment needed.
Operational TODOs (not blocking the scaffold):
- pnpm audit currently reports 6 moderate transitive vulnerabilities
(ajv, brace-expansion, yaml, @hono/node-server, follow-redirects,
uuid) in deep deps of Nx/Angular plugins. CI will fail on this
gate until upstream updates land or Renovate bumps; expected and
documented.
- act_runner self-hosted instances are not yet registered against
the Gitea organisation; the workflows reference [self-hosted,
on-prem] runner labels per ADR-0015. CI will not actually execute
until the runners are up - that's an infra task.
- Branch protection rules on main (require all five jobs green) are
configured in Gitea UI, not in this commit.
- Lighthouse-prod scheduled job runs only when vars.LHCI_PROD_URL
is set - skipped silently otherwise. To be configured once a prod
environment exists.