ci: add Forgejo Actions pipeline + runner setup
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
dbcf51993d
commit
f38decc285
4 changed files with 195 additions and 0 deletions
77
.forgejo/workflows/ci.yml
Normal file
77
.forgejo/workflows/ci.yml
Normal file
|
|
@ -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 {} +
|
||||||
26
apps/forgejo-runner/docker-compose.yml
Normal file
26
apps/forgejo-runner/docker-compose.yml
Normal file
|
|
@ -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
|
||||||
|
|
@ -13,6 +13,7 @@ services:
|
||||||
- FORGEJO__server__ROOT_URL=https://gitforge.kitestacks.com/
|
- FORGEJO__server__ROOT_URL=https://gitforge.kitestacks.com/
|
||||||
- FORGEJO__server__SSH_DOMAIN=gitforge.kitestacks.com
|
- FORGEJO__server__SSH_DOMAIN=gitforge.kitestacks.com
|
||||||
- FORGEJO__server__SSH_PORT=2222
|
- FORGEJO__server__SSH_PORT=2222
|
||||||
|
- FORGEJO__actions__ENABLED=true
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
networks:
|
networks:
|
||||||
|
|
|
||||||
91
docs/ci-cd-setup.md
Normal file
91
docs/ci-cd-setup.md
Normal file
|
|
@ -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 <paste-grt-token-here> \
|
||||||
|
--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
|
||||||
|
```
|
||||||
Loading…
Add table
Add a link
Reference in a new issue