#!/usr/bin/env bash # Package AOC backfill release for offline kit # Usage: ./package-backfill-release.sh # Dev mode: COSIGN_ALLOW_DEV_KEY=1 COSIGN_PASSWORD=stellaops-dev DATASET_HASH=dev ./package-backfill-release.sh set -euo pipefail ROOT=$(cd "$(dirname "$0")/../../.." && pwd) OUT_DIR="${OUT_DIR:-$ROOT/out/aoc}" CREATED="${CREATED:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}" DATASET_HASH="${DATASET_HASH:-}" mkdir -p "$OUT_DIR" echo "==> AOC Backfill Release Packaging" echo " Output: $OUT_DIR" echo " Dataset hash: ${DATASET_HASH:-}" # Key resolution (same pattern as advisory-ai packaging) resolve_key() { if [[ -n "${COSIGN_KEY_FILE:-}" && -f "$COSIGN_KEY_FILE" ]]; then echo "$COSIGN_KEY_FILE" elif [[ -n "${COSIGN_PRIVATE_KEY_B64:-}" ]]; then local tmp_key="$OUT_DIR/.cosign.key" echo "$COSIGN_PRIVATE_KEY_B64" | base64 -d > "$tmp_key" chmod 600 "$tmp_key" echo "$tmp_key" elif [[ -f "$ROOT/tools/cosign/cosign.key" ]]; then echo "$ROOT/tools/cosign/cosign.key" elif [[ "${COSIGN_ALLOW_DEV_KEY:-0}" == "1" && -f "$ROOT/tools/cosign/cosign.dev.key" ]]; then echo "[info] Using development key (non-production)" >&2 echo "$ROOT/tools/cosign/cosign.dev.key" else echo "[error] No signing key available. Set COSIGN_PRIVATE_KEY_B64 or COSIGN_ALLOW_DEV_KEY=1" >&2 return 1 fi } # Build AOC CLI if not already built AOC_CLI_PROJECT="$ROOT/src/Aoc/StellaOps.Aoc.Cli/StellaOps.Aoc.Cli.csproj" AOC_CLI_OUT="$OUT_DIR/cli" if [[ -f "$AOC_CLI_PROJECT" ]]; then echo "==> Building AOC CLI..." dotnet publish "$AOC_CLI_PROJECT" \ -c Release \ -o "$AOC_CLI_OUT" \ --no-restore 2>/dev/null || echo "[info] Build skipped (may need restore)" else echo "[info] AOC CLI project not found; using placeholder" mkdir -p "$AOC_CLI_OUT" echo "AOC CLI placeholder - build from src/Aoc/StellaOps.Aoc.Cli/" > "$AOC_CLI_OUT/README.txt" fi # Create backfill runner bundle echo "==> Creating backfill runner bundle..." RUNNER_TAR="$OUT_DIR/aoc-backfill-runner.tar.gz" tar -czf "$RUNNER_TAR" -C "$AOC_CLI_OUT" . # Compute hash sha256() { sha256sum "$1" | awk '{print $1}' } RUNNER_HASH=$(sha256 "$RUNNER_TAR") # Generate manifest echo "==> Generating manifest..." MANIFEST="$OUT_DIR/aoc-backfill-runner.manifest.json" cat > "$MANIFEST" </dev/null || stat -f%z "$RUNNER_TAR") }, "dataset": { "hash": "${DATASET_HASH:-pending}", "status": "$( [[ -n "$DATASET_HASH" ]] && echo "available" || echo "pending-dev-rehearsal" )" }, "signing": { "mode": "$( [[ "${COSIGN_ALLOW_DEV_KEY:-0}" == "1" ]] && echo "development" || echo "production" )" } } EOF # Sign with cosign if available KEY_FILE=$(resolve_key) || true COSIGN="${COSIGN:-$ROOT/tools/cosign/cosign}" DSSE_OUT="$OUT_DIR/aoc-backfill-runner.dsse.json" if [[ -n "${KEY_FILE:-}" ]]; then COSIGN_CMD="${COSIGN:-cosign}" if command -v cosign &>/dev/null; then COSIGN_CMD="cosign" fi echo "==> Signing bundle..." COSIGN_PASSWORD="${COSIGN_PASSWORD:-}" "$COSIGN_CMD" sign-blob \ --key "$KEY_FILE" \ --bundle "$DSSE_OUT" \ --tlog-upload=false \ --yes \ "$RUNNER_TAR" 2>/dev/null || echo "[info] DSSE signing skipped" fi # Generate SBOM placeholder echo "==> Generating SBOM..." SBOM="$OUT_DIR/aoc-backfill-runner.sbom.json" cat > "$SBOM" < Generating provenance..." PROVENANCE="$OUT_DIR/aoc-backfill-runner.provenance.json" cat > "$PROVENANCE" < Generating checksums..." cd "$OUT_DIR" sha256sum aoc-backfill-runner.tar.gz aoc-backfill-runner.manifest.json aoc-backfill-runner.sbom.json > SHA256SUMS # Cleanup temp key [[ -f "$OUT_DIR/.cosign.key" ]] && rm -f "$OUT_DIR/.cosign.key" echo "==> AOC backfill packaging complete" echo " Runner: $RUNNER_TAR" echo " Manifest: $MANIFEST" echo " SBOM: $SBOM" echo " Provenance: $PROVENANCE" echo " Checksums: $OUT_DIR/SHA256SUMS" [[ -f "$DSSE_OUT" ]] && echo " DSSE: $DSSE_OUT"