diff --git a/.dagger/src/blumeops_ci/main.py b/.dagger/src/blumeops_ci/main.py index 433faed..f24b9e8 100644 --- a/.dagger/src/blumeops_ci/main.py +++ b/.dagger/src/blumeops_ci/main.py @@ -233,6 +233,27 @@ class BlumeopsCi: .file(f"/output/{output_file}") ) + @function + async def validate_workflows( + self, + src: dagger.Directory, + runner_version: str = "12.7.0", + ) -> str: + """Validate Forgejo Actions workflow files against runner schema. + + Runs forgejo-runner validate (available v9.0+) against all workflow + files in .forgejo/workflows/. Returns validation output. Fails if + any workflow has schema errors. + """ + return await ( + dag.container() + .from_(f"code.forgejo.org/forgejo/runner:{runner_version}") + .with_directory("/workspace", src) + .with_workdir("/workspace") + .with_exec(["forgejo-runner", "validate", "--directory", "."]) + .stdout() + ) + @function async def flake_update( self, src: dagger.Directory, flake_path: str = "nixos/ringtail" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1797afc..1f5950a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -89,6 +89,16 @@ repos: args: ['-config-file', '.github/actionlint.yaml'] files: ^\.forgejo/workflows/ + # Forgejo workflow schema validation (via Dagger + forgejo-runner validate) + - repo: local + hooks: + - id: validate-workflows + name: validate-workflows + entry: mise run validate-workflows + language: system + files: ^\.forgejo/workflows/ + pass_filenames: false + # Container version consistency - repo: local hooks: diff --git a/argocd/manifests/forgejo-runner/configmap.yaml b/argocd/manifests/forgejo-runner/configmap.yaml index 18d5448..3b0df5b 100644 --- a/argocd/manifests/forgejo-runner/configmap.yaml +++ b/argocd/manifests/forgejo-runner/configmap.yaml @@ -5,6 +5,7 @@ metadata: namespace: forgejo-runner data: config.yaml: | + # Reviewed against v12.7.0 defaults (2026-02-22) log: level: info @@ -12,6 +13,7 @@ data: file: /data/.runner capacity: 2 timeout: 3h + shutdown_timeout: 3h # Env vars injected into all job containers envs: DOCKER_HOST: tcp://127.0.0.1:2375 diff --git a/docs/changelog.d/upgrade-forgejo-runner-v12.infra.md b/docs/changelog.d/upgrade-forgejo-runner-v12.infra.md new file mode 100644 index 0000000..d9d2672 --- /dev/null +++ b/docs/changelog.d/upgrade-forgejo-runner-v12.infra.md @@ -0,0 +1 @@ +Prepare forgejo-runner v12 upgrade: review config compatibility, add workflow schema validation via Dagger, wire pre-commit hook diff --git a/docs/how-to/forgejo-runner/review-runner-config-v12.md b/docs/how-to/forgejo-runner/review-runner-config-v12.md index 96a5ca7..63406e3 100644 --- a/docs/how-to/forgejo-runner/review-runner-config-v12.md +++ b/docs/how-to/forgejo-runner/review-runner-config-v12.md @@ -1,6 +1,5 @@ --- title: Review Runner Config for v12 -status: active modified: 2026-02-22 tags: - how-to @@ -12,48 +11,26 @@ tags: Compare the current runner ConfigMap against the v12.7.0 default config to identify new, changed, or deprecated keys. -## Background +## Findings -The runner config in `argocd/manifests/forgejo-runner/configmap.yaml` was written for v6.3.1. Six major versions may have introduced new config keys, changed defaults, or deprecated options. +Compared `forgejo-runner generate-config` output from v6.3.1 and v12.7.0. Our config is minimal and remains valid for v12. -## Current Config +### New sections in v12 (not adopted) -```yaml -log: - level: info -runner: - file: /data/.runner - capacity: 2 - timeout: 3h - envs: - DOCKER_HOST: tcp://127.0.0.1:2375 - TZ: America/Los_Angeles -container: - network: "host" - docker_host: tcp://127.0.0.1:2375 -``` - -## Steps - -1. Fetch the v12.7.0 example config: - ```fish - curl -L "https://code.forgejo.org/forgejo/runner/raw/tag/v12.7.0/.forgejo-runner.example.yaml" - ``` -2. Diff against our current config — note new sections/keys -3. Check the release notes for each major version (v7–v12) for config-related changes: - - v7.0: `FORGEJO_*` env vars (backward compat with `GITHUB_*`) - - v8.0: Default container image change - - v12.7: `server.connections` for multi-server polling; secret URLs; ephemeral mode -4. Decide which new keys to adopt (if any) and update the ConfigMap -5. Pay attention to `container.valid_volumes` and `container.options` (added in v6.x for security) — we may want to configure these - -## Key Areas to Check - -- **`container.valid_volumes`** — allowlist for volume mounts in job containers (security hardening from v6.x) -- **`container.options`** — allowlist for container options -- **`runner.envs`** — are `FORGEJO_*` vars needed alongside `GITHUB_*`? -- **Ephemeral mode** (v12.7) — one-shot runners that de-register after a job. Not needed now but worth noting. - **`server.connections`** — multi-server polling. Not needed (single Forgejo instance). +- **`cache.secret_url`** — load cache secret from file URL. Not needed. +- **`runner.report_retry`** — retry config for log uploads. Defaults are fine. + +### Changed semantics + +- **`container.docker_host`** — v12 supports `unix://` and `ssh://` URLs. Our explicit `tcp://127.0.0.1:2375` still correct for DinD sidecar. +- **`cache`** section restructured with proxy/server split and better docs. We don't configure cache, so defaults apply. + +### Config update applied + +Added `shutdown_timeout: 3h` to allow graceful job completion on pod termination (v12 default, was missing from our v6 config). Added review date comment. + +`container.valid_volumes` and `container.options` left empty — our jobs use host networking and don't mount volumes. Can harden later if needed. ## Related diff --git a/docs/how-to/forgejo-runner/validate-workflows-against-v12.md b/docs/how-to/forgejo-runner/validate-workflows-against-v12.md index fd53a81..dec5d1c 100644 --- a/docs/how-to/forgejo-runner/validate-workflows-against-v12.md +++ b/docs/how-to/forgejo-runner/validate-workflows-against-v12.md @@ -1,6 +1,5 @@ --- title: Validate Workflows Against v12 -status: active modified: 2026-02-22 tags: - how-to @@ -12,70 +11,32 @@ tags: Run `forgejo-runner validate` (available from v9.0+) against all workflow files to catch schema issues before upgrading the k8s runner daemon. -## Background +## Result -Forgejo-runner v8.0 introduced workflow schema validation — workflows that don't pass are rejected at runtime. v9.0 made this stricter and added a `validate` CLI command. Since we're jumping from v6.3.1, we've never run validation. All six workflows in `.forgejo/workflows/` need checking. +All 6 workflows pass v12.7.0 schema validation with no changes needed: -## Approach: Dagger Pipeline - -Add a `validate_workflows` function to the [[dagger]] module (`.dagger/src/blumeops_ci/main.py`). This runs `forgejo-runner validate` inside the upstream runner container — no host-side binary management, reproducible, and version-pinned. - -```python -@function -async def validate_workflows( - self, - src: dagger.Directory, - runner_version: str = "12.7.0", -) -> str: - """Validate Forgejo Actions workflow files against runner schema.""" - return await ( - dag.container() - .from_(f"code.forgejo.org/forgejo/runner:{runner_version}") - .with_directory("/workspace", src) - .with_workdir("/workspace") - .with_exec([ - "sh", "-c", - "for f in .forgejo/workflows/*.yaml; do " - ' echo "=== $f ===" && forgejo-runner validate "$f"; ' - "done" - ]) - .stdout() - ) -``` - -Invoke locally with: - -```fish -dagger call validate-workflows --src=. -``` - -### Permanent guardrail - -Once the function exists, wire it into CI as a pre-commit hook or a mise task (`mise run validate-workflows`). This prevents future workflow regressions regardless of runner version changes. The `runner_version` parameter lets us pin to whatever version the k8s runner is actually running. - -## Workflows to Validate - -| File | Complexity | Notes | -|------|-----------|-------| -| `build-container.yaml` | High | Matrix strategy, conditional steps | -| `build-container-nix.yaml` | High | Matrix strategy, conditional steps | -| `build-blumeops.yaml` | High | Multi-step release pipeline | -| `deploy-fly.yaml` | Low | Simple deploy | -| `cv-deploy.yaml` | Medium | Version resolution + deploy | -| `branch-cleanup.yaml` | Low | Scheduled + manual dispatch | - -## Fix any failures - -If validation fails, fix the workflow schema issues in the same PR as the runner upgrade. Common issues in the v8/v9 changelog: -- Invalid `type:` values in `workflow_dispatch.inputs` -- Incorrect `if:` expression syntax -- Undeclared or misspelled keys +- `branch-cleanup.yaml` — OK +- `build-blumeops.yaml` — OK +- `build-container-nix.yaml` — OK +- `build-container.yaml` — OK +- `cv-deploy.yaml` — OK +- `deploy-fly.yaml` — OK ## Deliverables -1. `validate_workflows` function in `.dagger/src/blumeops_ci/main.py` -2. All 6 workflows passing validation (fix any schema issues) -3. A mise task or pre-commit hook wiring `dagger call validate-workflows` for ongoing use +1. `validate_workflows` function added to `.dagger/src/blumeops_ci/main.py` + - Uses `forgejo-runner validate --directory .` inside the upstream runner container + - `runner_version` parameter (default `12.7.0`) pins to deployed version +2. `mise run validate-workflows` task wired to `dagger call validate-workflows` +3. Pre-commit hook triggers on `.forgejo/workflows/` changes + +## Usage + +```fish +mise run validate-workflows +# or directly: +dagger call validate-workflows --src=. +``` ## Related diff --git a/mise-tasks/validate-workflows b/mise-tasks/validate-workflows new file mode 100755 index 0000000..e541870 --- /dev/null +++ b/mise-tasks/validate-workflows @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +#MISE description="Validate Forgejo workflow files against runner schema" + +set -euo pipefail + +dagger call validate-workflows --src=.