# S4 — Build and publish pipelines in Gitea

Status: IMPLEMENTED

Agreed after the grill-me review; shared understanding confirmed.

## User story

As a maintainer, I want every branch push to build and test the application,
so that broken changes are detected and successful main-branch builds provide
identifiable Docker images in our own registry.

## Agreed environment and feasibility

- Gitea and its container registry run on the existing Synology.
- The existing development mini-PC runs the Gitea Actions runner, separately from
  Gitea. No additional hardware is available or required.
- Gitea supports push-triggered Actions workflows and a runner on a separate
  machine. Codex can implement the repository configuration and assist with the
  installation and configuration required on the existing machines.
- Gitea was inspected as version 1.25.4. Match the runner and workflow setup to
  the installed version rather than assuming newer documentation applies.
- The mini-PC was inspected as Linux x86_64 with a Docker client installed, but
  without a reachable Docker daemon. Configuring a working daemon is part of S4.
- The current internal Gitea/registry endpoint is `http://192.168.2.28:3000`.
  Use that endpoint over the trusted internal network and explicitly configure
  Docker clients that need registry access to trust this particular HTTP registry.
  Introducing HTTPS is outside S4.
- The runner and job containers need access to Gitea, the registry and dependency
  download sources. The runner connects to Gitea; it needs no public incoming port.
- The mini-PC must be on, awake and running the runner. Jobs wait while it is
  unavailable; S4 does not promise unattended availability when the PC is off.

References:

- [Gitea 1.25 Actions quickstart](https://docs.gitea.com/1.25/usage/actions/quickstart/)
- [Gitea 1.25 Actions design](https://docs.gitea.com/1.25/usage/actions/design/)
- [Gitea container registry](https://docs.gitea.com/usage/packages/container/)

## Scope

### In scope

- Version-controlled Gitea Actions workflows and supporting build configuration.
- Enable Actions as needed at instance and repository level, configure Docker on
  the mini-PC, and install, register and configure its runner.
- Build and test both backend and frontend for every push to every branch,
  including newly created branches, except when the author intentionally uses a
  supported skip marker such as `[skip ci]`. Separate tag and pull-request event workflows
  are not required; branch pushes also check changes used in pull requests.
- Build two runnable Docker images: backend and frontend.
- Run end-to-end tests against those built containers before publication.
- Publish both images only from successful builds of the `main` branch to the
  container registry on the Synology.
- Configure registry authentication and the necessary secrets outside Git.
- Preserve failure diagnostics and document operation and recovery.
- Demonstrate a real successful pipeline and images that can be pulled back.

### Out of scope

- Automatic deployment, starting application containers on the Synology, and OTAP.
  Starting temporary containers for pipeline tests is in scope.
- New linting or static-analysis gates, such as ESLint or Sonar. Existing tests,
  including architecture tests, remain mandatory.
- Merge or release policies, separate tag/release workflows, and automatic image
  deletion or retention cleanup. Published images remain available for now.
- Multi-architecture images, HTTPS setup, new hardware or provisioning additional
  infrastructure.

## Build and verification behavior

1. Every ordinary branch push runs backend and frontend builds and their existing
   tests. Explicit Gitea-supported skip markers are an accepted maintainer-approved
   opt-out.
2. Backend verification includes the existing unit, integration/system and
   architecture tests. Current entry point: `mvn clean verify` using Java 25.
3. Frontend verification uses the lockfile (`npm ci`), unit tests (`npm test`) and
   production build (`npm run build`) with a supported Node version.
4. Build both Docker images on every branch, including branches that cannot
   publish. The current Dockerfile only covers the backend; frontend packaging
   must be added as part of implementation.
5. The frontend image serves the production Angular build, supports direct SPA
   route navigation, and forwards `/api` requests to the backend container.
   Container addressing/configuration is an implementation choice.
6. Run the existing Playwright end-to-end suite with Chromium against the built
   frontend/backend containers, through the frontend's API forwarding. Adapt the
   existing development-server test configuration as necessary: the acceptance
   run must exercise the actual images, not development servers.
7. Determine the intended server's CPU architecture during implementation. Build
   for that single target architecture and run the end-to-end tests on that same
   architecture. Do not infer the Synology's architecture from the mini-PC.
   Any architecture mismatch must be resolved and tested on the existing hardware
   before claiming acceptance.
8. A failed build or test fails the pipeline and prevents publication. Test
   containers are temporary and are cleaned up after the run, including failure.

## Publication and image identity

- Publish separate backend and frontend images under the repository owner's
  namespace in the existing Gitea container registry. Document the exact names.
- Feature branches must not publish application images.
- Both images from a main-branch commit use the full Git commit SHA as their tag.
  This identifies the matching pair independently of moving tags.
- Once both commit images have been successfully published, reruns verify/reuse
  them without overwriting either commit tag.
- Publication succeeds only when both images are published and can be pulled
  back from the registry. A partial publication fails the pipeline; one image may
  already exist. A rerun preserves that image and may publish the missing image.
- After both commit images are available, update the moving `main` tags only if
  the commit is still the current main-branch head. Serialize/coordinate that
  operation so an older, slower pipeline cannot move `main` backwards.
- The two moving tags are not an atomic pair. Use the same commit SHA on both
  images when an exact matching pair is needed. A failure updating a moving tag
  must be visible as a pipeline failure and recoverable through a rerun.
- No automatic deletion of published images is introduced in S4.

## Failure diagnostics and operation

- Failed pipelines retain available test reports, container logs, and Playwright
  traces and screenshots for fourteen days. Collect available diagnostics even
  when a preceding step fails; do not hide the original failure.
- Provide a short management guide covering:
  - Docker/runner installation, registration, startup and required access.
  - Gitea instance/repository Actions settings and registry configuration.
  - Required credentials, permissions and secret names, without secret values.
  - Which settings exist outside Git and how to reproduce them.
  - Trigger behavior, mini-PC availability and queued jobs.
  - Image names, tags and commands to pull a matching image pair.
  - Finding diagnostics, rerunning failed jobs and completing partial publication.
  - The target architecture and how it was established.
- Keep registry credentials and registration tokens out of repository files and
  logs; use the relevant secret settings.

## Acceptance criteria

- [x] A push to any branch, including a new branch, starts a pipeline, except for
      an explicit supported skip marker chosen by the author.
- [x] Backend and frontend build and all existing tests, including architecture
      and Playwright end-to-end tests, pass before publication is permitted.
- [x] Every branch builds both Docker images; end-to-end tests exercise those
      images through the frontend and its `/api` forwarding.
- [x] A failing build or test fails the pipeline without publishing images.
- [x] A successful feature-branch pipeline publishes no application images.
- [x] A successful `main` pipeline publishes both images to the Synology registry
      with the full commit SHA; both images can be pulled back.
- [x] Published commit images are preserved on rerun; partial publication can be
      completed without overwriting an existing commit image.
- [x] Moving `main` tags are updated only after both commit images are available,
      and an older pipeline cannot move them backwards.
- [x] Publication or pull-verification failure makes the pipeline fail, even if
      some images have already been uploaded.
- [x] Available failure diagnostics are retained for fourteen days, and temporary
      test containers are cleaned up on success and failure.
- [x] The runner operates on the existing mini-PC, with Gitea and the registry on
      the existing Synology; no additional hardware is needed.
- [x] The single target architecture is established and the images are tested on
      that architecture using the existing hardware.
- [x] A management guide records setup, external settings, secrets, image usage
      and recovery, including the need to keep the mini-PC/runner available.
- [x] Actual pipeline runs demonstrate successful main-branch publication,
      feature-branch checks without publication, and failure blocking publication.

## Implementation handoff

This specification captures the agreed design. It does not install the runner,
change server settings or implement the pipeline. S4 is complete only when the
configuration, documentation and operational acceptance evidence are delivered;
workflow files alone are insufficient.


## Implementation progress

Repository implementation and local Docker verification are available. See
[management instructions](../../docs/gitea-ci.md) and
[validation evidence](../../docs/s4-validation.md).

Backend verification (20 tests), frontend verification (14 tests), both runtime
image builds and both Playwright tests against the containers passed. Fifteen
Java CI publication/configuration tests pass. The runner binary and user-service
configuration are installed on the mini-PC.

The maintainer confirmed the Synology as `x86_64` / `linux/amd64`. Gitea secrets
and the target-platform variable are configured; the runner is registered and
online. Registry login succeeded. Real feature runs #1 and #3 passed, including
container E2E; deliberate failure run #2 blocked the build/publication path and
provided downloadable diagnostics.

PR #1 was subsequently merged by the maintainer. Main run #7 succeeded for
commit `2356a31aa612c8b0ce4b386a0a65da6589e23285`, publishing and pulling both
full-SHA images and both main aliases. Registry digests are recorded in the
validation evidence.

The final real-registry probes confirmed partial-publication recovery, immutable
commit-tag preservation on rerun and stale-main protection in isolated validation
repositories. Application manifests remained unchanged. The maintainer confirmed
that the Synology app.ini has no actions section, so Gitea 1.25.4's documented
90-day artifact and 365-day log defaults apply; the workflow requests fourteen
days for diagnostic artifacts. Explicit skip markers are accepted by the
maintainer. All acceptance criteria are met; see the validation evidence for
probe details, digests and the distinction from full Gitea workflow reruns.
