# Gitea Actions Reusable Gitea Actions composite workflows for noctrl infrastructure automation. ## The standard pipeline (since v11) Build once, scan explicitly, promote — the registry is the hand-off between workflows. A push to the default branch builds each architecture exactly once and pushes immutable, never-deployed candidate tags (`sha-[-]`); an explicit Trivy job scans the candidate. A release rebuilds nothing: it re-scans the candidate and retags it server-side. `build.yml` (push to default branch): ``` validate (pre-commit) → build-amd64 ─┐ build-arm64 ─┤→ manifest (multi-arch only) → scan ``` `release.yml` (tag `v*`): ``` scan (candidate of the tagged commit) → promote (sha- → vX) ``` The scan in `release.yml` is the enforcing gate: a release tag can only come into existence behind a scan that passed at promotion time. Candidates carrying CVEs may exist in the registry — nothing consumes `sha-*` tags, so they are inert. Scan and promote jobs always run on `linux,build,amd64` (never on the slow arm runners; vulnerability results are package-based and arch-independent). Before v11, `podman-build-publish@v10` briefly embedded the Trivy gate itself; v11 moved it into the explicit `trivy-scan` action. ## Available Actions ### Podman Build And Publish Builds and optionally pushes OCI container images to `registry.noctrl.eu` using Podman with isolated storage context. Build and candidate-push are deliberately one action: each invocation initializes its own podman storage, so a split build/push pair would have to re-pull what was just built. **Location:** [`./podman-build-publish`](./podman-build-publish) ```yaml - uses: https://gitea.noctrl.eu/public/actions/podman-build-publish@v11 with: image-name: noctrl/myapp tags: | sha-${{ github.sha }}-amd64 registry-username: ${{ secrets.REGISTRY_USERNAME }} registry-password: ${{ secrets.REGISTRY_PASSWORD }} ``` ### Podman Manifest Publish Creates and pushes OCI multi-arch manifest tags to `registry.noctrl.eu` — used to assemble the per-arch candidates into the multi-arch candidate. **Location:** [`./podman-manifest-publish`](./podman-manifest-publish) ```yaml - uses: https://gitea.noctrl.eu/public/actions/podman-manifest-publish@v11 with: image-name: noctrl/myapp manifest-tag: sha-${{ github.sha }} source-tags: | sha-${{ github.sha }}-amd64 sha-${{ github.sha }}-arm64 ``` ### Trivy Scan Scans an image ref in `registry.noctrl.eu` and fails on fixable HIGH/CRITICAL vulnerabilities (severities configurable). Requires `trivy` on the runner (`noctrl/gitea-runner` >= v9). Pin the job to `linux,build,amd64`. **Location:** [`./trivy-scan`](./trivy-scan) ```yaml - uses: https://gitea.noctrl.eu/public/actions/trivy-scan@v11 with: image-name: noctrl/myapp tag: sha-${{ github.sha }} registry-username: ${{ secrets.REGISTRY_USERNAME }} registry-password: ${{ secrets.REGISTRY_PASSWORD }} ``` ### Podman Promote Retags an existing image (or multi-arch manifest list) server-side via `skopeo copy --all` — no rebuild, no transfer, fails if the source tag does not exist. Requires `skopeo` on the runner (`noctrl/gitea-runner` >= v10). **Location:** [`./podman-promote`](./podman-promote) ```yaml - uses: https://gitea.noctrl.eu/public/actions/podman-promote@v11 with: image-name: noctrl/myapp source-tag: sha-${{ github.sha }} target-tag: ${{ github.ref_name }} registry-username: ${{ secrets.REGISTRY_USERNAME }} registry-password: ${{ secrets.REGISTRY_PASSWORD }} ``` ### Android Signing Restores the Android release keystore (`-release.jks` + `keystore.properties`) from repo secrets; no-op when the secret is unset (build stays unsigned). **Location:** [`./android-signing`](./android-signing) ```yaml - uses: https://gitea.noctrl.eu/public/actions/android-signing@v12 with: keystore-b64: ${{ secrets.ANDROID_KEYSTORE_B64 }} keystore-password: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} key-alias: habitude ``` ### Trivy Filesystem Scan Scans the checked-out workspace for vulnerable dependencies (lockfile-based) — for repos that build artifacts (APKs) rather than images. Enforcing by default (fails on fixable HIGH/CRITICAL); `enforce: "false"` is a temporary emergency escape only. Requires committed Gradle lockfiles and the trivy binary on the runner. Pin the job to `linux,build,amd64`. **Location:** [`./trivy-fs-scan`](./trivy-fs-scan) ```yaml - uses: https://gitea.noctrl.eu/public/actions/trivy-fs-scan@v12 ``` ### Deploy Prod Shared deploy body for the `*.podman` infrastructure repos: installs the SSH deploy key, validates the mounted deploy-target env file, and pipes the deploy runner's `deploy-prod.sh` to the production host over SSH. Runs on that host's dedicated deploy runner (`gitea-runner-deploy` image). **Location:** [`./deploy-prod`](./deploy-prod) ```yaml - uses: https://gitea.noctrl.eu/public/actions/deploy-prod@v11 with: deploy-target-file: /run/noctrl/prod-deploy-target.env ssh-key-b64: ${{ secrets.PROD_DEPLOY_SSH_KEY }} target-sha: ${{ github.sha }} ``` ## Usage Reference actions by absolute URL in your workflow: ```yaml - uses: https://gitea.noctrl.eu/public/actions/@ ``` **Ref Options:** - `@v1` — points to tag `v1` - `@main` — points to default branch - `@commit-sha` — points to specific commit ## Repository Secrets Actions reference caller repository secrets. Ensure your repository has required secrets defined: - **REGISTRY_USERNAME** — registry.noctrl.eu authentication username - **REGISTRY_PASSWORD** — registry.noctrl.eu authentication password - **PROD_DEPLOY_SSH_KEY** — base64-encoded SSH deploy key (`*.podman` repos only) Set these in repository **Settings** → **Secrets**. ## Contributing When adding new actions: 1. Create action directory: `./action-name/` 2. Include `action.yaml` (composite action definition) 3. Tag stable versions: `git tag v1`, `git tag v2`, etc. 4. Update this root README