#!/bin/sh # ci-release.sh — Build and upload release assets to Gitea. # Called by .gitea/workflows/release.yml as a separate step AFTER # `coreci run` completes. This runs in the Gitea Actions runner directly # (not inside CoreCI's shell-isolated executor), so it has full env # access and no disk-space constraints from CoreCI's SQLite logging. # # Environment variables (from Gitea Actions step env): # GITEA_TOKEN — Gitea API token (from PAT_TOKEN secret) # VERSION — tag name (from gitea.ref_name) # GIT_COMMIT — commit SHA (from gitea.sha) set -u GITEA_URL="${GITEA_URL:-https://git.cloudinit.dev}" GITEA_OWNER="${GITEA_OWNER:-coreci}" GITEA_REPO="${GITEA_REPO:-orca}" info() { echo "ci-release: $*"; } err() { echo "ci-release: error: $*" >&2; exit 1; } if [ -z "${GITEA_TOKEN:-}" ]; then err "GITEA_TOKEN is not set"; fi if [ -z "${VERSION:-}" ]; then err "VERSION is not set"; fi GIT_COMMIT="${GIT_COMMIT:-unknown}" BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" TARBALL="orca-${VERSION}-linux-amd64.tar.gz" info "building release ${VERSION} (commit ${GIT_COMMIT:0:12})..." # Build the release binary with version injection. LDFLAGS="-s -w \ -X git.cloudinit.dev/coreci/orca/internal/cli.version=${VERSION} \ -X git.cloudinit.dev/coreci/orca/internal/cli.gitCommit=${GIT_COMMIT} \ -X git.cloudinit.dev/coreci/orca/internal/cli.buildTime=${BUILD_TIME}" mkdir -p bin go build -trimpath -ldflags="${LDFLAGS}" -o bin/orca ./cmd/orca 2>&1 || err "go build failed" # Package the tarball and checksums. tar -czf "${TARBALL}" -C bin orca || err "tar failed" sha256sum "${TARBALL}" > SHA256SUMS || err "sha256sum failed" info "built ${TARBALL} ($(wc -c < "${TARBALL}") bytes)" # Check if the release already exists (the CIAgent ship workflow may # have created it with title+body but no binary assets). info "checking for existing release ${VERSION}..." RELEASE_ID=$(curl -fsSL \ "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/tags/${VERSION}" \ -H "Authorization: token ${GITEA_TOKEN}" \ | python3 -c "import json,sys; r=json.load(sys.stdin); print(r.get('id',''))" 2>/dev/null || echo "") if [ -z "${RELEASE_ID}" ]; then info "creating new release ${VERSION}..." RELEASE_ID=$(curl -fsSL -X POST \ "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases" \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${VERSION}\",\"name\":\"Orca ${VERSION}\",\"body\":\"Release ${VERSION} built by CoreCI pipeline\"}" \ | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || echo "") if [ -z "${RELEASE_ID}" ]; then err "failed to create release ${VERSION}" fi info "created release ID ${RELEASE_ID}" else info "release ${VERSION} already exists (ID ${RELEASE_ID}) — attaching assets" fi # Attach tarball and SHA256SUMS to the release. info "attaching ${TARBALL} to release ${RELEASE_ID}..." curl -fsSL -X POST \ "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/${RELEASE_ID}/assets?name=${TARBALL}" \ -H "Authorization: token ${GITEA_TOKEN}" \ -F "attachment=@${TARBALL}" 2>&1 || err "failed to attach ${TARBALL}" info "attaching SHA256SUMS to release ${RELEASE_ID}..." curl -fsSL -X POST \ "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/${RELEASE_ID}/assets?name=SHA256SUMS" \ -H "Authorization: token ${GITEA_TOKEN}" \ -F "attachment=@SHA256SUMS" 2>&1 || err "failed to attach SHA256SUMS" # Verify assets are actually attached (REQ-097, gate C-21). ASSET_COUNT=$(curl -fsSL \ "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/tags/${VERSION}" \ -H "Authorization: token ${GITEA_TOKEN}" \ | python3 -c "import json,sys; print(len(json.load(sys.stdin).get('attachments',[])))" 2>/dev/null || echo "0") info "release ${VERSION} has ${ASSET_COUNT} assets" if [ "${ASSET_COUNT}" -lt 2 ]; then err "assets not attached after upload (REQ-097, C-21) — got ${ASSET_COUNT}" fi info "release ${VERSION} published with ${ASSET_COUNT} binary assets"