diff --git a/scripts/backfill_releases.sh b/scripts/backfill_releases.sh new file mode 100755 index 0000000..69f84eb --- /dev/null +++ b/scripts/backfill_releases.sh @@ -0,0 +1,171 @@ +#!/bin/bash +# backfill_releases.sh - Backfill Gitea releases for existing v0.1 tags +# +# For each tag passed (or all v0.1.1..v0.1.6 and v0.2.0), this script: +# 1. Builds the orca binary from the current milestone branch head +# (v0.1 retrospective: phase tags marked ship points but the entry +# point fix is consolidated into a single post-fix build; see +# .ciagent/RELEASE_POLICY.md for the standing rule) +# 2. Injects the historical version via -ldflags +# 3. Packages a tarball +# 4. Creates a Gitea release with the tarball as an asset +# +# Idempotent: skips tags that already have a release. +# +# Usage: scripts/backfill_releases.sh [tag1 tag2 ...] + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$REPO_ROOT" + +# Source .env for GITEA_TOKEN +for env_file in "$REPO_ROOT/.env" "$PWD/.env" "./.env"; do + if [ -f "$env_file" ]; then + set -a + # shellcheck disable=SC1090 + . "$env_file" + set +a + break + fi +done + +err() { echo "backfill: error: $*" >&2; exit 1; } +info() { echo "backfill: $*"; } + +: "${GITEA_TOKEN:?GITEA_TOKEN is required}" +command -v tea >/dev/null 2>&1 || err "tea CLI not on PATH" +command -v go >/dev/null 2>&1 || err "go not on PATH" +command -v tar >/dev/null 2>&1 || err "tar not on PATH" + +REPO="coreci/orca" + +# Default: backfill v0.1.1..v0.1.6 and v0.2.0 +if [ $# -eq 0 ]; then + TAGS=(v0.1.1 v0.1.2 v0.1.3 v0.1.4 v0.1.5 v0.1.6 v0.2.0) +else + TAGS=("$@") +fi + +# Existing releases to skip +EXISTING="$(tea releases list --repo "$REPO" --output simple 2>/dev/null | awk '{print $1}' || true)" + +OS="$(uname -s | tr '[:upper:]' '[:lower:]')" +ARCH="$(uname -m)" +case "$ARCH" in + x86_64) ARCH=amd64 ;; + aarch64) ARCH=arm64 ;; + armv7l) ARCH=armv7 ;; +esac + +# Use the cached Go 1.25.0 toolchain explicitly +TOOLGO="/root/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.0.linux-amd64/bin/go" +if [ ! -x "$TOOLGO" ]; then + TOOLGO="$(command -v go)" +fi + +phase_name() { + case "$1" in + v0.1.1) echo "Phase 1: CLI skeleton" ;; + v0.1.2) echo "Phase 2: Node management" ;; + v0.1.3) echo "Phase 3: Task execution" ;; + v0.1.4) echo "Phase 4: State persistence" ;; + v0.1.5) echo "Phase 5: Health checks" ;; + v0.1.6) echo "Phase 6: CoreCI release flow" ;; + v0.2.0) echo "Milestone v0.1: Foundation complete" ;; + *) echo "Orca $1" ;; + esac +} + +for TAG in "${TAGS[@]}"; do + if echo "$EXISTING" | grep -qx "$TAG"; then + info "skip $TAG (release exists)" + continue + fi + + info "=== $TAG ===" + # The v0.1.1..v0.1.6 phase tags point to merge commits; the canonical + # source of truth for v0.1 code is the current milestone branch HEAD + # (which includes the main.go entry-point fix). + BUILD_COMMIT="$(git rev-parse --short HEAD)" + FULL_COMMIT="$(git rev-parse HEAD)" + info "build from HEAD: $BUILD_COMMIT (per RELEASE_POLICY.md v0.1 retrospective)" + + BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" + LDFLAGS="-s -w -X git.cloudinit.dev/coreci/orca/internal/cli.version=$TAG -X git.cloudinit.dev/coreci/orca/internal/cli.gitCommit=$BUILD_COMMIT -X git.cloudinit.dev/coreci/orca/internal/cli.buildTime=$BUILD_TIME" + + mkdir -p bin + GOTOOLCHAIN=local "$TOOLGO" build -trimpath -ldflags="$LDFLAGS" -o bin/orca ./cmd/orca + + TARBALL="orca-${TAG}-${OS}-${ARCH}.tar.gz" + tar -czf "$TARBALL" -C bin orca + info "tarball: $TARBALL ($(du -h "$TARBALL" | cut -f1))" + + # Generate release notes + PREV_TAG="$(git describe --tags --abbrev=0 "$TAG^" 2>/dev/null || true)" + NOTES_FILE="$(mktemp)" + PHASE_NAME="$(phase_name "$TAG")" + { + echo "# Release $TAG — ${PHASE_NAME}" + echo "" + echo "_Built: $BUILD_TIME from $BUILD_COMMIT (${FULL_COMMIT:0:12})_" + echo "" + echo "## Notes" + echo "" + echo "This release artifact is built from the v0.1 milestone branch HEAD" + echo "(post entry-point fix). For v0.2+ and future milestones, every phase" + echo "tag will be released with the binary as-of that exact commit; see" + echo "\`.ciagent/RELEASE_POLICY.md\` for the standing rule." + echo "" + if [ -n "$PREV_TAG" ] && [ "$TAG" != "v0.2.0" ]; then + echo "## Changes since $PREV_TAG" + echo "" + git log --pretty=format:'- %s' "${PREV_TAG}..${TAG}" 2>/dev/null | head -50 + echo "" + fi + if [ "$TAG" = "v0.2.0" ]; then + echo "## Milestone v0.1: Foundation — All Phases" + echo "" + echo "All 6 phases of the v0.1 Foundation milestone are complete:" + echo "" + echo "- **Phase 1** (v0.1.1): CLI skeleton with Cobra, subcommand stubs, pre-push hook" + echo "- **Phase 2** (v0.1.2): Node management with SQLite-backed registry" + echo "- **Phase 3** (v0.1.3): Task execution engine with HCL specs, jobs, tasks, WaitDelay" + echo "- **Phase 4** (v0.1.4): Local state persistence — audit log + migration runner" + echo "- **Phase 5** (v0.1.5): Health-check daemon with /healthz, /readyz, /v1/* handlers" + echo "- **Phase 6** (v0.1.6): CoreCI release flow with .coreci.yml and tea integration" + echo "" + echo "## Requirements Covered (21/24)" + echo "" + echo "REQ-001 Go 1.25+ toolchain, REQ-002 CLI-first single binary, REQ-003 Offline-first," + echo "REQ-004 Single-node task execution, REQ-005 modernc/sqlite CGO-free, REQ-006 slog" + echo "audit logging, REQ-007 CoreCI release flow, REQ-008 Structured JSON logging," + echo "REQ-009 HCL/YAML job spec parsing, REQ-010 --json output flag, REQ-012 Config" + echo "locations (~/.orca/, ORCA_DB), REQ-013 Pre-push hook, REQ-015 MIT LICENSE," + echo "REQ-016 README quickstart, REQ-017 context.Context propagation, REQ-018 %w error" + echo "wrapping, REQ-019 Cobra CLI, REQ-020 hashicorp/hcl parser, REQ-021 os/exec" + echo "WaitDelay, REQ-024 Makefile standard targets." + echo "" + echo "Deferred to v0.2: REQ-011/023 (mTLS), REQ-014 (gosec+govulncheck), REQ-022" + echo "(iter.Seq streaming)." + echo "" + echo "## Changes since v0.1.6" + echo "" + git log --pretty=format:'- %s' "v0.1.6..${TAG}" 2>/dev/null | head -50 + echo "" + fi + } > "$NOTES_FILE" + + info "creating gitea release..." + tea releases create "$TAG" \ + --repo "$REPO" \ + --title "Orca $TAG — ${PHASE_NAME}" \ + --note-file "$NOTES_FILE" \ + --asset "$TARBALL" + + info "✓ $TAG published" + rm -f "$TARBALL" +done + +info "all done"