# Drop-in Gitea Actions pipeline for a pnpm + Turborepo monorepo. # Copy to /.gitea/workflows/ci-cd.yaml. # # It discovers every app with a Dockerfile and every chart under helm-charts/, builds them, # and — only on the default branch or a tag — pushes images and OCI Helm charts to Harbor. # # Prerequisites (see the devsecops-ci-cd-gitea skill): # Gitea GLOBAL variables (Site Admin -> Actions -> Variables), set once for all orgs: # HL_V1_HARBOR_ADDRESS e.g. harbor-v1.apps.lego-cloud.eu # HL_V1_HARBOR_ROBOT_GITEA_ACTIONS_V1_USERNAME e.g. robot$gondor-v1+gitea-actions-v1 # HL_V1_HARBOR_PROJECT (optional; defaults to gondor-v1 below) # Gitea ORG secret (per org, Settings -> Actions -> Secrets): # HL_V1_HARBOR_ROBOT_GITEA_ACTIONS_V1_SECRET # # TODO before first run: # - set `runs-on` to your runner's label (its jobs must provide docker, helm, git) name: ci-cd on: push: branches: [test, main] tags: ["v*"] pull_request: branches: [test, main] env: HARBOR_ADDRESS: ${{ vars.HL_V1_HARBOR_ADDRESS }} HARBOR_USERNAME: ${{ vars.HL_V1_HARBOR_ROBOT_GITEA_ACTIONS_V1_USERNAME }} HARBOR_SECRET: ${{ secrets.HL_V1_HARBOR_ROBOT_GITEA_ACTIONS_V1_SECRET }} HARBOR_PROJECT: ${{ vars.HL_V1_HARBOR_PROJECT || 'gondor-v1' }} jobs: build-and-push-images: runs-on: [self-hosted] # TODO: set to your runner label (needs docker + git) steps: - name: Checkout uses: actions/checkout@v4 - name: Compute tag and publish flag id: meta run: | set -euo pipefail if [ "${GITHUB_REF_TYPE}" = "tag" ]; then TAG="${GITHUB_REF_NAME}" else TAG="$(git rev-parse --short HEAD)" fi if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then PUBLISH=false elif [ "${GITHUB_REF_TYPE}" = "tag" ] \ || [ "${GITHUB_REF_NAME}" = "test" ] \ || [ "${GITHUB_REF_NAME}" = "main" ]; then PUBLISH=true else PUBLISH=false fi echo "tag=${TAG}" >> "$GITHUB_OUTPUT" echo "publish=${PUBLISH}" >> "$GITHUB_OUTPUT" echo "Tag=${TAG} Publish=${PUBLISH}" - name: Log in to Harbor (publish runs only) if: steps.meta.outputs.publish == 'true' run: | set -euo pipefail echo "${HARBOR_SECRET}" | docker login "${HARBOR_ADDRESS}" -u "${HARBOR_USERNAME}" --password-stdin - name: Build and push images env: TAG: ${{ steps.meta.outputs.tag }} PUBLISH: ${{ steps.meta.outputs.publish }} run: | set -euo pipefail shopt -s nullglob found=0 for df in applications-backend/*/Dockerfile applications-frontend/*/Dockerfile; do found=1 app="$(basename "$(dirname "$df")")" image="${HARBOR_ADDRESS}/${HARBOR_PROJECT}/${app}" echo "::group::${app}" # Build context is the REPOSITORY ROOT — the Dockerfile runs turbo prune / COPY . . docker build -f "$df" -t "${image}:${TAG}" . if [ "${PUBLISH}" = "true" ]; then docker push "${image}:${TAG}" # moving :latest on branch builds only (never on tags) if [ "${GITHUB_REF_TYPE}" != "tag" ]; then docker tag "${image}:${TAG}" "${image}:latest" docker push "${image}:latest" fi else echo "PUBLISH=false — built ${image}:${TAG}, not pushing" fi echo "::endgroup::" done [ "${found}" = "1" ] || echo "No Dockerfiles found under applications-backend/* or applications-frontend/*" - name: Log out if: always() && steps.meta.outputs.publish == 'true' run: docker logout "${HARBOR_ADDRESS}" || true package-and-push-charts: runs-on: [self-hosted] # TODO: set to your runner label (needs helm + git) needs: build-and-push-images steps: - name: Checkout uses: actions/checkout@v4 - name: Compute publish flag id: meta run: | set -euo pipefail if [ "${GITHUB_REF_TYPE}" = "tag" ]; then TAG="${GITHUB_REF_NAME#v}" else TAG="" fi if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then PUBLISH=false elif [ "${GITHUB_REF_TYPE}" = "tag" ] \ || [ "${GITHUB_REF_NAME}" = "test" ] \ || [ "${GITHUB_REF_NAME}" = "main" ]; then PUBLISH=true else PUBLISH=false fi echo "tag=${TAG}" >> "$GITHUB_OUTPUT" echo "publish=${PUBLISH}" >> "$GITHUB_OUTPUT" - name: Log in to Harbor (publish runs only) if: steps.meta.outputs.publish == 'true' run: | set -euo pipefail echo "${HARBOR_SECRET}" | helm registry login "${HARBOR_ADDRESS}" -u "${HARBOR_USERNAME}" --password-stdin - name: Lint, package and push charts env: TAG: ${{ steps.meta.outputs.tag }} PUBLISH: ${{ steps.meta.outputs.publish }} run: | set -euo pipefail shopt -s nullglob mkdir -p .cicd-charts found=0 for chart in helm-charts/*/Chart.yaml; do found=1 dir="$(dirname "$chart")" echo "::group::$(basename "$dir")" helm lint "$dir" if [ -n "${TAG}" ]; then # On a tag build, align chart + app version with the release tag. helm package "$dir" -d .cicd-charts --version "${TAG}" --app-version "${TAG}" else helm package "$dir" -d .cicd-charts fi echo "::endgroup::" done [ "${found}" = "1" ] || { echo "No charts under helm-charts/*"; exit 0; } if [ "${PUBLISH}" = "true" ]; then for tgz in .cicd-charts/*.tgz; do helm push "$tgz" "oci://${HARBOR_ADDRESS}/${HARBOR_PROJECT}/charts" done else echo "PUBLISH=false — packaged charts, not pushing" fi - name: Log out if: always() && steps.meta.outputs.publish == 'true' run: helm registry logout "${HARBOR_ADDRESS}" || true