Files
devsecops-ci-cd-gitea-3darch/SKILL.md
T

12 KiB

name, description, license, metadata, compatibility
name description license metadata compatibility
devsecops-ci-cd-gitea--3darch Generate and maintain Gitea Actions CI/CD pipelines that build & publish Docker images and Helm charts for every application in a pnpm + Turborepo monorepo, pushing both to a Harbor registry. Use when adding or fixing a `.gitea/workflows/*` pipeline; building or pushing container images from `applications-backend/<svc>/Dockerfile` or `applications-frontend/<app>/Dockerfile`; packaging and pushing OCI Helm charts from `helm-charts/<chart>/`; wiring `docker login` / `helm registry login` against Harbor with a robot account; setting the Gitea Actions secrets and variables a pipeline needs; or debugging a runner that can't authenticate, can't find Docker, or can't reach an action — even when the user only says "the CI/CD thing", "the docker pipeline", or names their monorepo. Proprietary
author version spec
home-v1-skills-code-agent 1.0 agentskills.io/specification
Targets Gitea Actions (act_runner, GitHub-Actions-compatible) pushing to a Harbor OCI registry, for pnpm + Turborepo monorepos (see the development-monorepo-pnpm skill). Requires a runner whose jobs can run docker and helm. Designed for Claude Code, Cline, GitHub Copilot, OpenAI Codex, and other compatible agents.

DevSecOps CI/CD — Gitea Actions → Harbor

3D Architecture Wizzard Project Adoption

This is the primary project-adopted skill for 3D Architecture Wizzard (3darch).

Project engineering peers:

Generate the pipeline that turns a monorepo push into published images and charts: for every app that has a Dockerfile, build and push its image; for every chart under helm-charts/, package and push it as an OCI artifact. Both land in Harbor, authenticated by a project robot account whose credential lives in Gitea Actions secrets/variables.

This skill owns the pipeline up to "the artifact is in Harbor". Deploying that artifact to the cluster is the development-gitops-argo-cd skill's job — see Handoff.

When to use — and which reference to open

The task Read
Wire or fix registry login (docker login / helm registry login), robot accounts, the Gitea secret/variable names, or the "bake into the runner" alternative references/harbor-auth.md
Understand or edit the pipeline itself — jobs, discovery loops, tag derivation, PR-vs-publish gating, turbo prune references/pipeline-workflow.md
Confirm where Dockerfiles and charts live, how image/chart names are derived, which Harbor project to push to references/conventions.md
Drop a working pipeline into a repo copy assets/workflows/ci-cd.yaml → <repo>/.gitea/workflows/ci-cd.yaml

The mental model

git push ─▶ act_runner ─▶ [ discover apps ]
                          ├─ applications-backend/<svc>/Dockerfile ─▶ docker build (repo root) ─▶ push  harbor/<project>/<svc>:<tag>
                          ├─ applications-frontend/<app>/Dockerfile ─▶ docker build (repo root) ─▶ push  harbor/<project>/<app>:<tag>
                          └─ helm-charts/<chart>/Chart.yaml         ─▶ helm package            ─▶ push  oci://harbor/<project>/charts

Everything the runner needs to authenticate comes from one org secret + two global variables (below). Nothing sensitive is committed to the repo.

1. Registry authentication (the "docker thing")

Harbor push/pull uses a project-scoped robot account — a non-human account with a long username and a generated secret. The pipeline logs in with it; it never uses a person's credentials. Full model and how the robot is created (palantir harbor:robot:* tasks) → references/harbor-auth.md.

The pipeline reads exactly three values:

Kind Name Scope in Gitea Example value
Variable HL_V1_HARBOR_ADDRESS global (Site Admin → Actions → Variables) harbor-v1.apps.lego-cloud.eu
Variable HL_V1_HARBOR_ROBOT_GITEA_ACTIONS_V1_USERNAME global robot$gondor-v1+gitea-actions-v1
Secret HL_V1_HARBOR_ROBOT_GITEA_ACTIONS_V1_SECRET org (per org, Settings → Actions → Secrets) (the robot's generated secret)

Why this split: the username and address are not secret, so they go in variables — and variables have a global level, so you set them once for all organisations. Gitea has no global-secret level, so the one genuinely sensitive value is an org secret — the single per-org chore when you onboard a new org.

Login, in every job that touches the registry:

echo "${HARBOR_SECRET}" | docker login "${HARBOR_ADDRESS}" -u "${HARBOR_USERNAME}" --password-stdin
echo "${HARBOR_SECRET}" | helm  registry login "${HARBOR_ADDRESS}" -u "${HARBOR_USERNAME}" --password-stdin

Alternative — bake the login into the runner. If you would rather not attach a secret per org at all, pre-seed the runner's Docker config.json so every job is pre-authenticated. It trades central rotation for zero per-org setup. Steps in references/harbor-auth.md §4.

2. What gets built, and from where

Discovery is convention-driven — the pipeline finds work, you don't list it. Details and the naming rules in references/conventions.md; the essentials:

  • Images: one per applications-backend/*/Dockerfile and applications-frontend/*/Dockerfile. The image repository is the application directory name. Build context is the repository root (docker build -f <path>/Dockerfile … .) because the Dockerfile runs turbo prune over the whole monorepo — building from the app directory will fail.
  • Charts: one per helm-charts/*/Chart.yaml. Charts are centralized under helm-charts/ at the repo root, not co-located inside the app directory. Do not look for applications-frontend/<app>/helm — that is not where charts live in this monorepo family.
  • Tag: the git tag on a tag build, otherwise the short commit SHA. On the default branch the image also gets a moving latest. See references/pipeline-workflow.md §Tagging.

3. Publish gating — build always, push selectively

Trigger Images Charts
pull request / feature branch build only (verify it compiles) helm lint + helm package (verify)
push to default branch (test) or main build and push package and push
tag v* build and push (tagged with the git tag) package and push

A PR must never publish — it proves the artifact builds, nothing more. The template computes a PUBLISH flag from the event; do not remove it.

4. Installing the pipeline into a monorepo

  1. Copy assets/workflows/ci-cd.yaml → <repo>/.gitea/workflows/ci-cd.yaml.
  2. Set runs-on: to your runner's label (see Gotchas — it must be a label whose jobs provide docker, helm, and git). Set HL_V1_HARBOR_PROJECT (default gondor-v1) to the Harbor project the robot can push to.
  3. Ensure the three Gitea values from §1 exist (2 global variables once; 1 org secret per org).
  4. Commit, push a throwaway branch, and confirm the run builds without pushing.
  5. Merge to the default branch and confirm images + charts appear in Harbor.

Handoff

This skill stops at published to Harbor. To roll the new image/chart into the cluster, hand the image reference and tag to development-gitops-argo-cd: the tag flows through the Copier variables into the Helm values Argo CD syncs. Never wire a raw kubectl apply into this pipeline — deployment is GitOps's responsibility, and a pipeline that also deploys bypasses the one source of truth for cluster state.

Gotchas

  • Build context is the repo root, always. docker build -f applications-backend/<svc>/Dockerfile … . The Dockerfile's COPY . . + turbo prune need the whole monorepo. Building from the app directory fails with missing lockfile / workspace errors.
  • Charts are centralized, not co-located. They live in helm-charts/<chart>/. An app can ship an image with no chart, and a chart can exist with no matching app — discover the two independently, do not assume a 1:1 pairing.
  • Gitea has no global secrets — only global variables. The username/address are variables (global, set once); the robot secret is an org secret (per org). Do not try to create a "global secret"; the admin Actions page only offers global variables.
  • The robot secret is only shown once, at creation. Harbor never reveals it again on GET. It's cached under palantir .harbor/<project>-<robot>.yml (git-ignored). To rotate, re-run the palantir robot task, then update the Gitea org secret. See references/harbor-auth.md.
  • runs-on maps to a container image — it must have docker, helm, git. turbo prune runs inside the image build, so the job itself needs Node only if you add pre-build steps; the default template needs just docker + helm + git. A bare node:alpine label has no docker CLI and the build step will fail with docker: not found.
  • Marketplace actions may not resolve. Gitea proxies actions/* to github.com by default; if the runner has no egress, actions/checkout fails. The template keeps action use to actions/checkout@v4 only and documents a git clone fallback in references/pipeline-workflow.md.
  • Frontend build args are public. A frontend image bakes its build-time env into the bundle. Never pass a secret as a --build-arg; anything per-environment on the frontend is fetched at runtime, not built in.
  • helm push needs an OCI-enabled Helm ≥ 3.8 and a prior helm registry login. Without the login step, helm push fails with unauthorized even though docker login succeeded — they are separate credential stores.
  • Never docker login with -p on the command line. Use --password-stdin; a -p argument lands in the process list and the runner logs.