Forgejo workflow templates for CI pipelines. Drop-in starting point for repos across The Chameleon Way.
Copy the template that matches your repo type to .forgejo/workflows/ci.yml, then replace the values marked with # ── ADJUST ──.
# For IaC/OpenTofu repos
cp iac-ci.yml myrepo/.forgejo/workflows/ci.yml
# For Kotlin/Micronaut/Go services
cp service-ci.yml myrepo/.forgejo/workflows/ci.yml
# For Docker image wrapper repos
cp docker-image-ci.yml myrepo/.forgejo/workflows/ci.ymlThen edit ci.yml and adjust the placeholders at the top. No further configuration needed — the templates are designed to work out of the box.
| Template | Target repo type | What it does |
|---|---|---|
iac-ci.yml |
OpenTofu / IaC | Lint (betterlint, tflint), format validation, syntax checks. No deployment. |
service-ci.yml |
Kotlin/Micronaut/Go services | Lint (betterlint, OpenAPI, Gherkin), placeholder for build jobs. Image push/release job commented out — uncomment when ready. |
docker-image-ci.yml |
Docker image wrapper repos (tcwlab internal use) | Lint, build, Trivy security scan with PR comment, multi-arch release to Docker Hub, auto-tag. Most elaborate template. |
All three follow a consistent job pattern: Lint → Build/Test → Security → Release. You can comment out or delete jobs that don't apply to your repo.
Each template has clear # ── ADJUST ── markers for values you must change:
iac-ci.yml:
OPENTOFU_VERSION— fromtcwlab/versions.yamlBETTERLINT_VERSION— fromtcwlab/versions.yamlpermissions:,concurrency:,branches:— to match your project's branching strategy
service-ci.yml:
BETTERLINT_VERSION— fromtcwlab/versions.yaml- Build/test steps — uncomment and adapt the
# TODO: build-Jobsection for your language (Gradle for Kotlin,go buildfor Go, etc.)
docker-image-ci.yml:
IMAGE: tcwlab/<toolname>— replace<toolname>with your image nameBETTERLINT_VERSION,TRIVY_VERSION— fromtcwlab/versions.yaml- Smoke-test command in the build step (currently
docker run ... --version) - Version extraction in the release step (currently
ARG <TOOL>_VERSION=...) - Repository secrets:
DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,FORGEJO_TOKEN
Always pin specific versions, never use latest:
- Images:
tcwlab/betterlint:2.12.0— version numbers shown here are illustrative; for the current set of tags, see GitHub releases for the template tag and the per-image Docker Hub tag pages (e.g.tcwlab/betterlint) - Composite Actions:
@v1or@v1.2.0— major+minor is fine, don't use@main
Pinning ensures your pipeline doesn't break when tcwlab ships a new version. It's your explicit choice when to upgrade.
The ci.yml templates use a shell-based checkout (git init + git fetch),
not actions/checkout. This is deliberate: these jobs run inside the minimal
tcwlab/* images (betterlint, buildx, opentofu), which ship without
Node.js — and the JS-based actions/checkout needs a Node runtime in the
container. A release.yml (semantic-release, which has Node.js) is the only
place where uses: …/actions/checkout@v4 is the right call.
If you copy a template and add a job that runs on the host runner (no
container: block — e.g. a release/build-push job), you may use
actions/checkout@v4 there: the runner has Node.js.
- Templates (this repo) → drop-in YAML files for consumer repos
- Actions (tcwlab/actions) → reusable Composite Actions for fine-grained logic
- Images (tcwlab/{betterlint,opentofu,buildx,trivy,semantic-release}) → Docker Hub
Templates are copied, not referenced via uses:. This means your repo owns the full CI workflow and can edit it freely.
- Source: github.com/tcwlab/templates
- Issues: github.com/tcwlab/templates/issues
Apache-2.0 — The Chameleon Way.