BUG FOUND: Workflow was requesting 'runs-on: docker' but Forgejo only has: - golang (golang:1.26-bookworm + dind) - rust (rust:1.83-bookworm + dind) - node (node:22-bookworm) No 'docker' runner exists, so CI hung indefinitely waiting for unavailable runner. FIX: Changed to 'runs-on: rust' Rationale: ✅ Rust toolchain pre-installed (no cargo install needed) ✅ Docker-in-Docker available (for docker build + push) ✅ 2 CPU, 4GB RAM limits (sufficient for Rust builds) ✅ 1.83-bookworm base image (production-ready) ✅ Perfect for Rust projects Result: CI will now acquire the correct runner and complete builds in 5-10 minutes See .forgejo/README.md for runner reference guide
Forgejo CI/CD - Build & Push Workflow
Status: ✅ ACTIVE (Production-ready)
CI Workflow
The .forgejo/workflows/build.yaml automatically:
- Triggers on push to main branch
- Builds Docker image (multi-stage Rust)
- Tags:
latest+short-SHA - Pushes to registry
- Cleans up (logout)
Required Secrets
Set in Forgejo repository settings → Secrets:
REGISTRY_PAT: Personal access token (Docker login credentials)- Must have push access to
forgejo.riotpiao.com/rock/poimen-memory - Use service account or personal token with registry scope
- Must have push access to
What imageUpdater Needs
The CI pushes images to:
forgejo.riotpiao.com/rock/poimen-memory:latest
forgejo.riotpiao.com/rock/poimen-memory:<short-SHA>
imageUpdater can:
- Watch for
:latesttag - Poll registry for new versions
- Trigger K8s deployment updates
Manual Override
If CI fails, build manually:
export REGISTRY_TOKEN='<your-token>'
./scripts/build-and-push.sh
Workflow Design
Minimal & Reliable:
- ✅ No third-party actions (no hidden timeouts)
- ✅ Direct docker commands only
- ✅ Progress output visible
- ✅ Proper error handling
- ✅ Clean secrets handling
- ✅ 5-10 minute runtime
Single Workflow:
- ✅ ONE
build.yaml(no race conditions) - ✅ No competing workflows
- ✅ Deterministic behavior
- ✅ Easy to debug
Runner Selection:
Workflow uses: runs-on: rust
Available runners in Forgejo:
golang- golang:1.26-bookworm + dind (for Go projects)rust- rust:1.83-bookworm + dind (✅ for Rust projects)node- node:22-bookworm (for Node.js projects)
Why rust for poimen-memory:
- ✅ Pre-installed Rust toolchain
- ✅ Docker-in-Docker (dind) for image builds
- ✅ 2 CPU, 4GB RAM limits (sufficient)
- ✅ 1.83-bookworm base (production-ready)
CI Status
Check latest build: Forgejo repository → Actions tab
Expected flow:
- Push to main
- Forgejo CI triggers (30s delay)
- Build starts (~3-5 min)
- Image pushed to registry
- imageUpdater detects new version
- K8s deployment updated (via ArgoCD or controller)
Deployment Trigger
Once image is pushed, imageUpdater can:
# ArgoCD Image Updater strategy
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: memory-auto-update
spec:
generators:
- image:
registrySelector:
registry: forgejo.riotpiao.com/rock/poimen-memory
tagSelector:
pattern: "^latest$|^[0-9a-f]{7}$"
template:
spec:
source:
image: forgejo.riotpiao.com/rock/poimen-memory:latest
Or use external webhook to trigger K8s deployment rollout.
Troubleshooting
CI Hanging?
- Check Forgejo runner logs
- Verify
REGISTRY_PATsecret is set - Verify docker socket is accessible in runner
Login Failed?
- Verify
REGISTRY_HOSTsecret - Check credentials in Vault
Build Failed?
- Check:
cargo test --lib --alllocally - Check:
docker build .works locally - Review build output in Forgejo Actions tab
Files
.forgejo/workflows/build.yaml← Production workflow.forgejo/README.md← This file./Dockerfile← Multi-stage Rust build./scripts/build-and-push.sh← Manual fallback