ci-workflows/README.md

2.2 KiB

ci-workflows

Shared reusable Forgejo Actions workflows for every repo on git.capybara.network.

Workflow Tool Fails on
secrets.yml gitleaks, full git history any secret not listed in .gitleaksignore
sast.yml semgrep, p/default any finding not suppressed with nosemgrep or .semgrepignore
deps.yml osv-scanner a known vulnerability in a lockfile or manifest, unless ignored in osv-scanner.toml
lint.yml shellcheck, ruff, hadolint, yamllint, actionlint, tofu fmt + tflint lint errors; each linter runs only if matching files exist

The tools are baked into the runner image (flux-talos, clusters/talos/apps/forgejo-runner/image/Dockerfile); these workflows install nothing at run time.

Using them

Add .forgejo/workflows/checks.yml to a repo:

name: checks
on:
  push:
    branches: [main]
  pull_request:

jobs:
  secrets:
    runs-on: ubuntu-latest
    uses: capyadmin/ci-workflows/.forgejo/workflows/secrets.yml@v1
  sast:
    runs-on: ubuntu-latest
    uses: capyadmin/ci-workflows/.forgejo/workflows/sast.yml@v1
  deps:
    runs-on: ubuntu-latest
    uses: capyadmin/ci-workflows/.forgejo/workflows/deps.yml@v1
  lint:
    runs-on: ubuntu-latest
    uses: capyadmin/ci-workflows/.forgejo/workflows/lint.yml@v1

Two Forgejo 11 constraints shape this, both verified on this instance on 18 Oct 2026:

  • This repo must stay public. The runner fetches a cross-repo reusable workflow anonymously; with the repo private the calling job fails. Never put anything secret here.
  • The calling job needs runs-on. Forgejo 11 expands the reusable workflow in the runner, not the server, so the caller has to be scheduled onto one. GitHub forbids this combination; lint.yml tells actionlint to ignore it.

Inputs (all optional) are documented at the top of each workflow, e.g.:

  lint:
    runs-on: ubuntu-latest
    uses: capyadmin/ci-workflows/.forgejo/workflows/lint.yml@v1
    with:
      ruff-format: true
      shellcheck-severity: error

Versioning

v1 is a moving tag on the latest compatible commit. A change that could newly fail existing callers (a stricter default, a new linter switched on by default) goes out as v2.