Files
template-go-agent/.gitea/workflows/cd.yml
T
mathias add5428e2f
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
ci(cd): call the shared build-image script instead of inlining it (infra#309)
A template is the highest-leverage copy of anything. This one carried its
own inline build step, so every generated repo was born with a private
fork of the build logic -- which is how rootless buildah reached a dozen
repos before infra#241, and why the fix then had to be rediscovered here
weeks after the app repos were done.

The step now calls .gitea/build-image.sh, a byte-identical copy of
mathias/infra's ci-templates/build-image.sh. Generated repos inherit the
script and the call; adding the new repo to infra's adopters.txt puts it
under the drift gate.

Invoked as `bash .gitea/build-image.sh` rather than relying on the exec
bit: files written through the Gitea API land 0644, and a template whose
CI depends on a file mode is a trap for every repo generated from it.
2026-08-25 08:52:26 +00:00

133 lines
5.0 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: CD
"on":
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]
env:
IMAGE: __PROJECT_NAME__
jobs:
check:
name: Lint / Test / Vet
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: false
- name: Install toolchain
run: |
go version
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh \
| sh -s -- -b "$(go env GOPATH)/bin" v2.11.4
- name: Run checks
run: task check
build:
name: Build & Import
needs: check
runs-on: self-hosted
# __PROJECT_NAME__/__MODULE_PATH__ are placeholders substituted only when
# a repo is generated from this template -- on the raw template repo
# itself they're still literal, and `IMAGE: __PROJECT_NAME__` contains
# uppercase letters, which the registry rejects outright ("repository
# name must be lowercase"). Build/deploy can never succeed here; skip
# them on this repo so its own CI reads green on what it can actually
# validate (the check job).
if: github.event_name != 'pull_request' && github.repository != 'mathias/template-go-agent'
outputs:
image-tag: ${{ steps.meta.outputs.sha-tag }}
steps:
- uses: actions/checkout@v4
- name: Derive image tags
id: meta
run: |
SHA=$(git rev-parse --short HEAD)
echo "sha-tag=${SHA}" >> "$GITHUB_OUTPUT"
# infra#309: the implementation lives in .gitea/build-image.sh, a
# byte-identical copy of mathias/infra's ci-templates/build-image.sh.
# Do not edit it here -- edit the canonical file, run `task ci:sync`,
# and infra's drift gate will name any repo still carrying an old copy.
#
# This matters more in a template than anywhere else: every repo
# generated from here inherits its CI, so a template that carries the
# build LOGIC manufactures a new copy of every bug in it. That is
# precisely how rootless buildah (infra#241) reached a dozen repos, and
# why the fix then had to be rediscovered here weeks later. A template
# that carries a CALL manufactures nothing.
#
# NEW REPOS: add yourself to mathias/infra's ci-templates/adopters.txt so
# the gate keeps this copy current. Until you do, the copy is unmanaged
# and will silently fall behind.
#
# `bash <script>` rather than executing it directly: files written via
# the Gitea API land 0644, and CI that depends on a file mode is a trap.
- name: Build and push to local registry
env:
SHA_TAG: ${{ steps.meta.outputs.sha-tag }}
GIT_SHA: ${{ github.sha }}
run: bash .gitea/build-image.sh
deploy:
name: Deploy via GitOps
needs: build
runs-on: self-hosted
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- name: Update image tag in infra repo
env:
IMAGE_TAG: ${{ needs.build.outputs.image-tag }}
DEPLOY_KEY: ${{ secrets.INFRA_DEPLOY_KEY }}
run: |
set -euo pipefail
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_infra
chmod 600 ~/.ssh/id_infra
ssh-keyscan -p 30022 10.0.1.20 >> ~/.ssh/known_hosts 2>/dev/null
export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_infra -o IdentitiesOnly=yes"
rm -rf /tmp/infra
git clone -b main ssh://git@10.0.1.20:30022/mathias/infra.git /tmp/infra
cd /tmp/infra
DEPLOYMENT="k3s/apps/__PROJECT_NAME__/deployment.yaml"
sed -i "s|image: localhost:5000/__PROJECT_NAME__:.*|image: localhost:5000/__PROJECT_NAME__:${IMAGE_TAG}|" "$DEPLOYMENT"
grep -q "localhost:5000/__PROJECT_NAME__:${IMAGE_TAG}" "$DEPLOYMENT" \
|| { echo "✗ image tag patch failed"; exit 1; }
if git diff --quiet "$DEPLOYMENT"; then
echo "ℹ image tag unchanged — skipping push"
else
git -c user.name="__PROJECT_NAME__ CI" \
-c user.email="ci@__PROJECT_NAME__.local" \
commit -m "chore(deploy): __PROJECT_NAME__ → ${IMAGE_TAG}" "$DEPLOYMENT"
git push origin main
echo "✓ pushed to infra repo"
fi
shred -u ~/.ssh/id_infra
- name: Trigger Flux reconcile
run: |
kubectl -n flux-system annotate gitrepository flux-system \
reconcile.fluxcd.io/requestedAt="$(date +%s)" --overwrite
kubectl -n flux-system annotate kustomization apps \
reconcile.fluxcd.io/requestedAt="$(date +%s)" --overwrite
- name: Verify rollout
run: |
kubectl rollout status deployment/__PROJECT_NAME__ \
--namespace __PROJECT_NAME__ \
--timeout=120s \
|| {
kubectl get pods -n __PROJECT_NAME__ -o wide
kubectl get events -n __PROJECT_NAME__ --sort-by='.lastTimestamp' | tail -20
exit 1
}