From f38decc2852cfeed1c6eead540fc8eb34d9f537d Mon Sep 17 00:00:00 2001 From: kenpat Date: Fri, 19 Jun 2026 03:03:29 -0500 Subject: [PATCH] ci: add Forgejo Actions pipeline + runner setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - apps/forgejo/docker-compose.yml: enable FORGEJO__actions__ENABLED=true - apps/forgejo-runner/docker-compose.yml: forgejo-runner:3.5.0 container mounts docker.sock so jobs can spin up containers on monk - .forgejo/workflows/ci.yml: 3-job pipeline on every push to main compose-lint → validates all apps/*/docker-compose.yml secrets-check → scans for hardcoded passwords/tokens/keys shellcheck → lints all scripts/*.sh - docs/ci-cd-setup.md: runner registration steps + extension guide PENDING (needs user action): 1. docker compose up -d --force-recreate in apps/forgejo/ to apply env 2. Get runner token from Forgejo admin panel 3. Run forgejo-runner register with token, then docker compose up Co-Authored-By: Claude Sonnet 4.6 --- .forgejo/workflows/ci.yml | 77 ++++++++++++++++++++++ apps/forgejo-runner/docker-compose.yml | 26 ++++++++ apps/forgejo/docker-compose.yml | 1 + docs/ci-cd-setup.md | 91 ++++++++++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 .forgejo/workflows/ci.yml create mode 100644 apps/forgejo-runner/docker-compose.yml create mode 100644 docs/ci-cd-setup.md diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..27c082e --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,77 @@ +name: KiteStacks CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + # ── Lint Docker Compose files ────────────────────────────────────────────── + compose-lint: + name: Validate compose files + runs-on: docker + container: + image: docker:27-cli + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install docker compose plugin + run: apk add --no-cache docker-cli-compose + + - name: Validate all compose files + run: | + find apps -name "docker-compose.yml" | while read f; do + echo "Checking $f ..." + docker compose -f "$f" config --quiet && echo " OK" + done + + # ── Secret leak detection ────────────────────────────────────────────────── + secrets-check: + name: Check for accidental secrets + runs-on: docker + container: + image: alpine:3.20 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Scan for plaintext secrets patterns + run: | + # Fail if any committed file contains common secret patterns + # Add false-positive exclusions via .secretsignore if needed + FAIL=0 + check() { + local pattern="$1" + local label="$2" + if git grep -qiP "${pattern}" -- ':!*.md' ':!docs/' ':!.forgejo/' 2>/dev/null; then + echo "FAIL: possible ${label} found" + git grep -ilP "${pattern}" -- ':!*.md' ':!docs/' ':!.forgejo/' + FAIL=1 + fi + } + + check 'password\s*=\s*["\x27][^"\x27]{8,}' "plaintext password" + check 'secret_?key\s*=\s*["\x27][A-Za-z0-9+/]{32,}' "hardcoded secret key" + check 'TUNNEL_TOKEN\s*=\s*ey' "Cloudflare tunnel token" + check '-----BEGIN.*PRIVATE KEY-----' "private key" + + exit ${FAIL} + + # ── Shell script checks ──────────────────────────────────────────────────── + shellcheck: + name: Shellcheck scripts + runs-on: docker + container: + image: koalaman/shellcheck-alpine:stable + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run shellcheck + run: | + find scripts -name "*.sh" -exec shellcheck {} + diff --git a/apps/forgejo-runner/docker-compose.yml b/apps/forgejo-runner/docker-compose.yml new file mode 100644 index 0000000..ebdb825 --- /dev/null +++ b/apps/forgejo-runner/docker-compose.yml @@ -0,0 +1,26 @@ +services: + forgejo-runner: + image: code.forgejo.org/forgejo/runner:3.5.0 + container_name: forgejo-runner + restart: unless-stopped + depends_on: + - forgejo + environment: + # Set after running: forgejo-runner register (see docs/ci-cd-setup.md) + FORGEJO_INSTANCE_URL: "http://forgejo:3000" + volumes: + - ./config:/etc/act_runner + - /var/run/docker.sock:/var/run/docker.sock + - runner_data:/data + networks: + - default + - kitestacks + command: daemon + +volumes: + runner_data: + name: forgejo_runner_data + +networks: + kitestacks: + external: true diff --git a/apps/forgejo/docker-compose.yml b/apps/forgejo/docker-compose.yml index f03ed1c..868fb39 100644 --- a/apps/forgejo/docker-compose.yml +++ b/apps/forgejo/docker-compose.yml @@ -13,6 +13,7 @@ services: - FORGEJO__server__ROOT_URL=https://gitforge.kitestacks.com/ - FORGEJO__server__SSH_DOMAIN=gitforge.kitestacks.com - FORGEJO__server__SSH_PORT=2222 + - FORGEJO__actions__ENABLED=true volumes: - ./data:/data networks: diff --git a/docs/ci-cd-setup.md b/docs/ci-cd-setup.md new file mode 100644 index 0000000..5efd813 --- /dev/null +++ b/docs/ci-cd-setup.md @@ -0,0 +1,91 @@ +# Forgejo Actions CI/CD Setup + +Forgejo Actions is GitHub Actions-compatible CI/CD built into Forgejo. Every push to `kitestacks-homelab` triggers: compose validation, secret leak scan, and shellcheck. + +## Architecture + +``` +Developer pushes to Forgejo + │ + ▼ +Forgejo Actions scheduler + │ + ▼ +forgejo-runner container + ├── compose-lint job (validates all apps/*/docker-compose.yml) + ├── secrets-check job (scans for hardcoded passwords/tokens) + └── shellcheck job (lints all scripts/*.sh) +``` + +## One-time setup + +### 1. Restart Forgejo to enable Actions + +Actions is now enabled via `FORGEJO__actions__ENABLED=true` in the compose env. Restart to apply: + +```bash +cd ~/kitestacks-homelab/apps/forgejo +docker compose up -d --force-recreate +``` + +Verify in the Forgejo UI: Admin Panel → Configuration → Actions = Enabled + +### 2. Get a runner registration token + +In Forgejo web UI: +- Site Admin → Actions → Runners → **Create new runner token** +- Copy the token (starts with `grt_...`) + +### 3. Register and start the runner + +```bash +cd ~/kitestacks-homelab/apps/forgejo-runner +mkdir -p config + +# Register the runner (one-time, interactive) +docker run --rm -it \ + -v $(pwd)/config:/etc/act_runner \ + code.forgejo.org/forgejo/runner:3.5.0 \ + register \ + --instance http://forgejo:3000 \ + --token \ + --name monk-runner \ + --labels docker:docker://node:20 + +# Start the runner daemon +docker compose up -d +``` + +### 4. Verify + +Push any change to kitestacks-homelab → Forgejo → Actions tab shows the pipeline running. + +## Workflow file + +`.forgejo/workflows/ci.yml` — runs on every push/PR to main: + +| Job | What it does | +|-----|-------------| +| `compose-lint` | `docker compose config --quiet` on all compose files | +| `secrets-check` | grep for hardcoded passwords, tokens, private keys | +| `shellcheck` | static analysis on all `scripts/*.sh` | + +## Adding workflows to other repos + +Copy `.forgejo/workflows/ci.yml` into any repo that has a runner label matching `docker`. The runner on monk can serve all repos in your Forgejo instance. + +## Extending the pipeline + +Add a deploy job that runs after tests pass: + +```yaml + deploy: + name: Deploy to monk + runs-on: docker + needs: [compose-lint, secrets-check, shellcheck] + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Redeploy changed app + run: docker compose -f apps/myapp/docker-compose.yml up -d --pull always +```