From df3f980fa0542ec561d00df4e1aa1d5a890683e1 Mon Sep 17 00:00:00 2001 From: Jon Chery Date: Wed, 12 Aug 2026 22:36:56 +0000 Subject: [PATCH] =?UTF-8?q?fix(P1):=20move=20release=20to=20Gitea=20Action?= =?UTF-8?q?s=20step=20=E2=80=94=20CoreCI=20disk=20full=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CoreCI's SQLite logging fills the runner's disk during go test -race, causing the release job to fail when writing the tarball (3-second failure). The release job ran inside CoreCI's shell-isolated executor which shares the same disk as CoreCI's SQLite DB. Fix: move the release logic (build tarball + upload to Gitea) to a separate Gitea Actions step that runs AFTER coreci run completes. This step runs in the Gitea Actions runner directly (full env, no CoreCI disk constraints). The .coreci.yml now only has build→test jobs. The release is handled by scripts/ci-release.sh called from the Gitea Actions workflow. Architecture: Gitea Actions ci job: 1. Checkout + Set up Go + Install CoreCI 2. coreci run (executes .coreci.yml: build → test) 3. sh scripts/ci-release.sh (build tarball + upload to Gitea API) ---ci--- project: orca phase: 1 milestone: v0.16 status: execute ---/ci--- --- .coreci.yml | 26 ++++------- .gitea/workflows/release.yml | 8 ++++ scripts/ci-release.sh | 90 ++++++++++++++++++++++++++++++++++++ scripts/ci-run.sh | 85 ---------------------------------- 4 files changed, 106 insertions(+), 103 deletions(-) create mode 100755 scripts/ci-release.sh diff --git a/.coreci.yml b/.coreci.yml index abf803a..3d9b358 100644 --- a/.coreci.yml +++ b/.coreci.yml @@ -1,6 +1,6 @@ version: "1" name: orca-ci -description: Orca — offline/CLI-first orchestration engine. Full release flow via CoreCI. +description: Orca — offline/CLI-first orchestration engine. CI pipeline via CoreCI. # CoreCI configuration for orca (v0.16 rewrite — native jobs: format). # @@ -10,19 +10,21 @@ description: Orca — offline/CLI-first orchestration engine. Full release flow # execute. This file uses the native `jobs:`/`invoke:`/`vars:` format # with a DAG via `needs:`. # -# DAG: build → test → release +# DAG: build → test # # The Gitea Actions workflow (.gitea/workflows/release.yml) gates on # `on: push: tags: ['v*']`, so every `coreci run` invocation is already -# a release run — no tag-conditional rules needed here. +# a release run. The release step (build tarball + upload to Gitea) is +# handled by a separate Gitea Actions step AFTER `coreci run` completes, +# because CoreCI's SQLite logging can fill the runner's disk during +# `go test -race`, causing the release job to fail when writing files. # # Each job uses `invoke:` only (no `plugin:`) — CoreCI's validate() # rejects jobs with both plugin and invoke set (mutually exclusive). # Jobs run via the shell-isolated executor (sh -c ). # # CoreCI's ValidateShellCommand forbids shell metacharacters (&|;`><$()) -# in the invoke: string. All complex logic lives in scripts/ci-run.sh, -# which the invoke: field calls as "sh scripts/ci-run.sh ". +# in the invoke: string. All complex logic lives in scripts/ci-run.sh. jobs: # ── build ──────────────────────────────────────────────────────────── @@ -34,16 +36,4 @@ jobs: # ── test (REQ-031: -race) ──────────────────────────────────────────── test: needs: [build] - invoke: "sh scripts/ci-run.sh test" - - # ── release ────────────────────────────────────────────────────────── - # Builds the release tarball, creates/updates the Gitea release with - # binary assets. Handles duplicate release (ship workflow creates - # release first with title+body; this job attaches binary assets). - # GITEA_TOKEN is resolved from env via CoreCI's secret resolver - # (os.Getenv fallback) and forwarded by PassThroughEnv. - release: - needs: [test] - vars: - GITEA_TOKEN: "${{ secrets.GITEA_TOKEN }}" - invoke: "sh scripts/ci-run.sh release" \ No newline at end of file + invoke: "sh scripts/ci-run.sh test" \ No newline at end of file diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 78b8442..d23bb54 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -33,6 +33,14 @@ jobs: run: | coreci run + - name: Build and upload release assets + env: + GITEA_TOKEN: ${{ secrets.PAT_TOKEN }} + VERSION: ${{ gitea.ref_name }} + GIT_COMMIT: ${{ gitea.sha }} + run: | + sh scripts/ci-release.sh + container-orca: runs-on: ubuntu-latest needs: ci diff --git a/scripts/ci-release.sh b/scripts/ci-release.sh new file mode 100755 index 0000000..9c99ca2 --- /dev/null +++ b/scripts/ci-release.sh @@ -0,0 +1,90 @@ +#!/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" \ No newline at end of file diff --git a/scripts/ci-run.sh b/scripts/ci-run.sh index 89b8aa2..d00982b 100755 --- a/scripts/ci-run.sh +++ b/scripts/ci-run.sh @@ -97,91 +97,6 @@ case "$JOB" in go tool cover -func=coverage.out | tail -1 ;; - # ── release ──────────────────────────────────────────────────────── - release) - VERSION="${CI_COMMIT_BRANCH:-dev}" - TARBALL="orca-${VERSION}-linux-amd64.tar.gz" - - if [ -z "${GITEA_TOKEN:-${CI_GITEA_TOKEN:-}}" ]; then - err "GITEA_TOKEN is not set" - fi - GITEA_TOKEN="${GITEA_TOKEN:-${CI_GITEA_TOKEN:-}}" - - info "release ${VERSION} — GITEA_TOKEN length: ${#GITEA_TOKEN}" - - # Clean up disk space — CoreCI's SQLite logging fills the disk. - rm -f coverage.out 2>/dev/null || true - go clean -cache 2>/dev/null || true - - # Use the binary built by the 'build' job (it shares the same workdir). - # Rebuild only if the binary doesn't exist. - if [ ! -x bin/orca ]; then - info "bin/orca not found — rebuilding..." - GIT_COMMIT="${CI_COMMIT_SHA:-unknown}" - BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" - 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" - else - info "using existing bin/orca from build job" - fi - tar -czf "${TARBALL}" -C bin orca 2>&1 || err "tar failed" - sha256sum "${TARBALL}" > SHA256SUMS 2>&1 || err "sha256sum failed" - info "built ${TARBALL}" - - # Create or update the Gitea release directly via the API. - # The CIAgent ship workflow may have already created the release - # (title+body, no binary). Check if it exists first. - info "checking for existing release ${VERSION}..." - RELEASE_ID=$(curl -fsSL \ - "https://git.cloudinit.dev/api/v1/repos/coreci/orca/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 \ - "https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases" \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - -d "{\"tag_name\":\"${VERSION}\",\"name\":\"Orca ${VERSION}\",\"body\":\"Release ${VERSION} built by CoreCI\"}" \ - | 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 \ - "https://git.cloudinit.dev/api/v1/repos/coreci/orca/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 \ - "https://git.cloudinit.dev/api/v1/repos/coreci/orca/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 \ - "https://git.cloudinit.dev/api/v1/repos/coreci/orca/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" - ;; - *) err "unknown job: ${JOB}" ;;