when: - event: tag steps: - name: test image: golang:1.25 commands: - go test -race ./... backend_options: kubernetes: serviceAccountName: default resources: requests: memory: 512Mi cpu: 1 limits: memory: 2Gi cpu: 2 # Build every binary into dist/ (consumed by the RPM step) plus the # cross-platform binaries attached to the Gitea release. Each tool is a # separate main package, so they are built individually per os/arch. - name: build image: git.unkin.net/unkin/almalinux9-gobuilder:20260606 commands: - make build VERSION=${CI_COMMIT_TAG} # Shell variables/expansions are escaped as $$ so Woodpecker leaves them # for the shell instead of substituting them (as pipeline vars) at parse # time. ${CI_COMMIT_TAG} is a real Woodpecker var and stays single-$. - | for entry in "agentpr:./cmd/agentpr" "watchpr:./cmd/watchpr" "agentws:./cmd/agentws" "agentvault:./cmd/agentvault"; do name="$${entry%%:*}"; pkg="$${entry##*:}" for osarch in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64; do os="$${osarch%/*}"; arch="$${osarch#*/}" GOOS="$$os" GOARCH="$$arch" \ go build -ldflags="-s -w -X main.version=${CI_COMMIT_TAG}" \ -o "$${name}-$${os}-$${arch}" "$$pkg" done done depends_on: [test] backend_options: kubernetes: serviceAccountName: default resources: requests: memory: 512Mi cpu: 1 limits: memory: 2Gi cpu: 2 # Package the built binaries + generated shell completions into an RPM. - name: package image: git.unkin.net/unkin/almalinux9-rpmbuilder:latest commands: - ./scripts/build-rpm.sh ${CI_COMMIT_TAG} depends_on: [build] backend_options: kubernetes: serviceAccountName: default resources: requests: memory: 512Mi cpu: 1 limits: memory: 2Gi cpu: 2 # Publish the RPM to the artifactapi local rpm repo (a real yum repo; # repodata regenerates automatically). - name: upload-rpm image: git.unkin.net/unkin/almalinux9-base:20260606 commands: - | HOST="https://artifactapi.k8s.syd1.au.unkin.net" REPO="rpm-internal" for rpm in dist/*.rpm; do FILE=$$(basename "$$rpm") # artifactapi has no HEAD route (returns 405); probe with GET against # the served path (RPMs are stored under Packages/) to avoid re-upload. code=$$(curl -s -o /dev/null -w '%{http_code}' "$$HOST/api/v2/remotes/$$REPO/files/Packages/$$FILE" || true) if [ "$$code" = "200" ]; then echo "$$FILE already exists in $$REPO (HTTP $$code); skipping upload" continue fi echo "Uploading $$FILE to $$REPO (existence probe returned $$code)" curl -f -X PUT \ "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" \ -H "Content-Type: application/x-rpm" \ --data-binary @"$$rpm" done depends_on: [package] backend_options: kubernetes: serviceAccountName: default resources: requests: memory: 128Mi cpu: 100m limits: memory: 512Mi cpu: 500m # Cut a Gitea release with the cross-platform binaries attached. - name: release image: git.unkin.net/unkin/almalinux9-base:20260606 environment: RELEASER_TOKEN: from_secret: RELEASER_TOKEN commands: - | curl --output /usr/local/bin/tea https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/gitea-dl/tea/0.12.0/tea-0.12.0-linux-amd64 && chmod +x /usr/local/bin/tea tea logins add --name gitea --url https://git.unkin.net --token "$${RELEASER_TOKEN}" --no-version-check # $$ escapes shell vars/substitutions so Woodpecker doesn't blank them # at parse time; ${CI_COMMIT_TAG}/${CI_REPO} are real Woodpecker vars. # Find the previous release tag for the changelog range. Several tags can # point at the same commit, so we skip tags on the current commit and # pick the newest semver tag that is a real ancestor of this one. CUR_SHA=$$(git rev-list -n1 "${CI_COMMIT_TAG}") PREV_TAG="" for t in $$(git tag --sort=-v:refname); do [ "$$t" = "${CI_COMMIT_TAG}" ] && continue [ "$$(git rev-list -n1 "$$t")" = "$$CUR_SHA" ] && continue if git merge-base --is-ancestor "$$t" "${CI_COMMIT_TAG}" 2>/dev/null; then PREV_TAG="$$t"; break fi done if [ -n "$$PREV_TAG" ]; then NOTES=$$(git log "$${PREV_TAG}..${CI_COMMIT_TAG}" --pretty=format:"- %s") else NOTES=$$(git log --pretty=format:"- %s") fi tea releases create --tag "${CI_COMMIT_TAG}" --title "${CI_COMMIT_TAG}" --note "$${NOTES}" --login gitea --repo "${CI_REPO}" # The build step writes the cross-compiled binaries into the workspace # root; the package step writes the RPM to dist/. Generate a checksums # manifest over everything we attach so downloads can be verified. RPM=$$(ls dist/*.rpm 2>/dev/null | head -1) ASSETS="agentpr-linux-amd64 agentpr-linux-arm64 agentpr-darwin-amd64 agentpr-darwin-arm64 watchpr-linux-amd64 watchpr-linux-arm64 watchpr-darwin-amd64 watchpr-darwin-arm64 agentws-linux-amd64 agentws-linux-arm64 agentws-darwin-amd64 agentws-darwin-arm64 agentvault-linux-amd64 agentvault-linux-arm64 agentvault-darwin-amd64 agentvault-darwin-arm64" [ -n "$$RPM" ] && ASSETS="$$ASSETS $$RPM" sha256sum $$ASSETS > sha256sums.txt tea releases assets create "${CI_COMMIT_TAG}" $$ASSETS sha256sums.txt \ --login gitea --repo "${CI_REPO}" depends_on: [upload-rpm] backend_options: kubernetes: serviceAccountName: default resources: requests: memory: 128Mi cpu: 100m limits: memory: 512Mi cpu: 500m