Gitea Actions
Use this for Gitea-hosted CI/CD, especially when GitHub Actions examples need to be adapted to Gitea's runner, token, and network model.
Project Fit Check
Before changing workflows:
- Read
AGENTS.md, existing.gitea/workflows/*.yml, runner docs, deployment docs, and repo variables/secrets conventions. - Detect the Gitea version, act_runner version, runner labels, container mode, and whether jobs run on Docker, host shell, or custom images.
- Verify which GitHub Actions syntax is actually supported by the installed Gitea version before copying examples.
- Keep secrets, registry credentials, and deploy tokens scoped to the smallest workflow that needs them.
- If current behavior depends on self-hosted network topology, document the assumption in the workflow or agent docs.
Workflow Rules
- Put workflows under
.gitea/workflows/. - Prefer explicit
on:triggers and path filters for expensive jobs. - Pin third-party actions when possible; avoid floating major tags for sensitive deploy paths.
- Keep preflight, verify, build, image, and deploy jobs separate enough that failures point to a real layer.
- Use concurrency/cancel-in-progress when repeated pushes to the same ref should not burn runner capacity.
- Keep cache keys tied to lockfiles and relevant runtime versions.
- Upload artifacts only when they help debugging or deployment.
- After any automated workflow mutation (fan-out, codegen, bulk step inject),
parse every touched YAML file before push. Insert steps under an existing
steps:list with the same indent as siblings. - If a job uses sparse-checkout, include every path that job invokes. Prefer a
helper directory pattern (for example
scripts/ci/) over one-file lists. - Soft-skip writing a job summary when
GITHUB_STEP_SUMMARYis unset (local runs). Do not soft-fail summary or otheralways()helper steps in CI to hide a missing sparse path; fix the checkout list instead. - On self-hosted Gitea, prefer raw
docker/docker buildxfor image builds. If you keepdocker/build-push-action, set job envDOCKER_BUILD_RECORD_UPLOAD=falseandDOCKER_BUILD_SUMMARY=falseso the Complete job does not upload.dockerbuildrecords via the GitHub Artifact API.
Runner Rules
- Match
runs-onlabels to registered runner labels exactly. - Know whether job containers can reach the Gitea host, package registry, Docker socket, private networks, and deployment targets.
- Avoid privileged runners by default.
- Treat runner filesystem state as disposable unless explicitly managed.
- Document any required host mounts or Docker-in-Docker assumptions.
Token And Secret Rules
- Use
GITEA_TOKENonly for the permissions the workflow needs. - Prefer repo or org variables for non-secret configuration.
- Never echo tokens, Docker auth JSON, private keys, or provider credentials.
- For private package/container registries, use one clear auth path and test it in the job image that actually pulls or pushes.
- Rotate or invalidate deploy tokens when workflow scope changes.
Migration From GitHub Actions
When porting:
- Check unsupported syntax first: permissions, reusable workflows, services, cache/action versions, OIDC, environments, and marketplace actions.
- Replace GitHub-specific APIs, URLs, and token assumptions.
- Validate action sources and whether the runner can fetch them.
- Test on a small branch before wiring deploy jobs.
- Keep the workflow readable; do not recreate GitHub-specific complexity if Gitea offers a simpler local path.
Verification
yamllintor parser check when available- dry-run or test branch workflow for new CI paths
- one failing-path check for secrets/registry/network assumptions when feasible
git diffreview for accidental secret insertion
Red Flags
- copied GitHub workflow with no Gitea compatibility review
- broad token permissions for read-only jobs
- deploy job triggered on every branch
- runner label that exists only on one machine but is undocumented
- cache key that ignores lockfiles
- private registry auth configured in one container but used in another
docker/build-push-actionon self-hosted Gitea withoutDOCKER_BUILD_RECORD_UPLOAD=false(Complete-jobCreateArtifacttimeouts after a successful registry push)- sparse-checkout file lists that omit scripts or helpers the job still runs (exit 127 after an otherwise successful deploy or verify)
- workflow YAML left unparsed after automated step injection (de-indented steps at column 0 that break Actions parse only after merge)