chore(deps): updates #32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # yaml-language-server: $schema=https://www.schemastore.org/github-workflow.json | |
| name: Canary | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - "crates/**" | |
| - "proto/**" | |
| - "Cargo.toml" | |
| - "Cargo.lock" | |
| - "Dockerfile" | |
| - ".github/workflows/canary.yml" | |
| workflow_dispatch: | |
| # Cancel in-progress runs when new runs are triggered | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: write | |
| packages: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| # GitHub Container Registry | |
| GHCR_REGISTRY: ghcr.io | |
| GHCR_IMAGE: ${{ github.repository }} | |
| # Docker Hub | |
| DOCKERHUB_IMAGE: inferadb/inferadb-ledger | |
| jobs: | |
| # Detect if library crates changed (vs server-only or CI-only changes) | |
| changes: | |
| name: Changes | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| libraries: ${{ steps.filter.outputs.libraries }} | |
| server: ${{ steps.filter.outputs.server }} | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Check for changes | |
| uses: step-security/paths-filter@6eee183b0d2fd101d3f8ee2935c127bca14c5625 # v3.0.5 | |
| id: filter | |
| with: | |
| filters: | | |
| libraries: | |
| - 'crates/types/**' | |
| - 'crates/store/**' | |
| - 'crates/state/**' | |
| - 'crates/raft/**' | |
| - 'crates/sdk/**' | |
| - 'proto/**' | |
| - 'Cargo.toml' | |
| - 'Cargo.lock' | |
| server: | |
| - 'crates/server/**' | |
| - 'Dockerfile' | |
| # Compute canary version from release-please manifest | |
| version: | |
| name: Version | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| short_sha: ${{ steps.version.outputs.short_sha }} | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Compute canary version | |
| id: version | |
| run: | | |
| # Read next version from release-please manifest | |
| if [ -f ".release-please-manifest.json" ]; then | |
| NEXT_VERSION=$(jq -r '.["." ] // .[] | select(. != null)' .release-please-manifest.json | head -1) | |
| else | |
| NEXT_VERSION="0.1.0" | |
| fi | |
| SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) | |
| DATE=$(date -u +%Y%m%d) | |
| # Use dev.YYYYMMDD.N format for chronological semver sorting | |
| CANARY_VERSION="${NEXT_VERSION}-dev.${DATE}.${{ github.run_number }}+${SHORT_SHA}" | |
| echo "version=${CANARY_VERSION}" >> $GITHUB_OUTPUT | |
| echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT | |
| echo "Canary version: ${CANARY_VERSION}" | |
| # Create GitHub pre-release | |
| create-release: | |
| name: Release | |
| needs: version | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| outputs: | |
| version: ${{ needs.version.outputs.version }} | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Create Pre-Release | |
| uses: step-security/action-gh-release@674f8f866246c6b91bd3f1688ba95e27b2ae8d2e # v2.4.1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: v${{ needs.version.outputs.version }} | |
| name: Canary v${{ needs.version.outputs.version }} | |
| draft: false | |
| prerelease: true | |
| body: | | |
| ⚠️ **This is a canary release for testing purposes.** | |
| Built from commit: ${{ github.sha }} | |
| Install with Docker: | |
| ```bash | |
| docker pull ${{ env.DOCKERHUB_IMAGE }}:canary | |
| # or | |
| docker pull ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}:canary | |
| ``` | |
| - name: Update canary tag | |
| run: | | |
| git tag -f canary | |
| git push -f origin canary | |
| # Build release binaries for multiple platforms (only if server changed) | |
| build-binaries: | |
| name: Build (${{ matrix.name }}) | |
| needs: [changes, version, create-release] | |
| if: needs.changes.outputs.server == 'true' | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| name: Linux AMD64 | |
| target: x86_64-unknown-linux-gnu | |
| artifact_name: inferadb-ledger | |
| asset_name: inferadb-ledger-linux-x86_64 | |
| - os: ubuntu-24.04-arm | |
| name: Linux ARM64 | |
| target: aarch64-unknown-linux-gnu | |
| artifact_name: inferadb-ledger | |
| asset_name: inferadb-ledger-linux-aarch64 | |
| - os: macos-latest | |
| name: macOS Apple Silicon | |
| target: aarch64-apple-darwin | |
| artifact_name: inferadb-ledger | |
| asset_name: inferadb-ledger-macos-aarch64 | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 | |
| with: | |
| toolchain: stable | |
| targets: ${{ matrix.target }} | |
| - name: Install build dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update -qq | |
| sudo apt-get install -y -qq mold protobuf-compiler | |
| - name: Install build dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: brew install protobuf | |
| - name: Setup sccache | |
| uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 | |
| - name: Configure build environment | |
| run: | | |
| echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV | |
| echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV | |
| echo "CARGO_INCREMENTAL=0" >> $GITHUB_ENV | |
| if [[ "${{ runner.os }}" == "Linux" ]]; then | |
| echo "RUSTFLAGS=-C codegen-units=16 -C link-arg=-fuse-ld=mold" >> $GITHUB_ENV | |
| elif [[ "${{ runner.os }}" == "macOS" ]]; then | |
| echo "RUSTFLAGS=-C codegen-units=16" >> $GITHUB_ENV | |
| echo "MACOSX_DEPLOYMENT_TARGET=11.0" >> $GITHUB_ENV | |
| fi | |
| - name: Cache Rust dependencies | |
| uses: step-security/rust-cache@f8fba7098297c8c53a7c9a30575ec2ad4ad85056 # v2.8.2 | |
| with: | |
| shared-key: canary-${{ matrix.os }}-${{ matrix.target }} | |
| - name: Build release binary | |
| run: cargo build --release --target ${{ matrix.target }} --package inferadb-ledger-server | |
| - name: Strip binary | |
| run: strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }} | |
| - name: Generate SBOM | |
| run: | | |
| cargo install cargo-sbom | |
| cargo sbom --output-format spdx_json_2_3 > sbom-${{ matrix.target }}.spdx.json | |
| - name: Compress binary | |
| run: | | |
| cd target/${{ matrix.target }}/release | |
| tar czf ${{ matrix.asset_name }}.tar.gz ${{ matrix.artifact_name }} | |
| - name: Upload binary to release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release upload "v${{ needs.version.outputs.version }}" \ | |
| "target/${{ matrix.target }}/release/${{ matrix.asset_name }}.tar.gz" | |
| - name: Upload SBOM to release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release upload "v${{ needs.version.outputs.version }}" \ | |
| "sbom-${{ matrix.target }}.spdx.json" | |
| # Build and push Docker images (only if server changed) | |
| build-docker: | |
| name: Docker (${{ matrix.name }}) | |
| needs: [changes, version, create-release] | |
| if: needs.changes.outputs.server == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux/amd64 | |
| name: Linux AMD64 | |
| runner: ubuntu-latest | |
| suffix: amd64 | |
| - platform: linux/arm64 | |
| name: Linux ARM64 | |
| runner: ubuntu-24.04-arm | |
| suffix: arm64 | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Docker Buildx | |
| uses: step-security/setup-buildx-action@8c8aef2d414c0b66518fee2b7084e0986f82d7ac # v3.11.1 | |
| - name: Log in to GitHub Container Registry | |
| uses: step-security/docker-login-action@c3e677aae8393bc9c81cfdf9709648720ea4bd4d # v3.6.0 | |
| with: | |
| registry: ${{ env.GHCR_REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 | |
| with: | |
| images: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }} | |
| tags: | | |
| type=raw,value=canary | |
| type=raw,value=canary-${{ needs.version.outputs.short_sha }} | |
| - name: Build and push by digest | |
| id: build | |
| uses: step-security/docker-build-push-action@a8c3d08b23f8be6aeed43eb1a14ce6fe51284438 # v6.18.0 | |
| with: | |
| context: . | |
| platforms: ${{ matrix.platform }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true | |
| cache-from: type=gha,scope=canary-${{ matrix.suffix }} | |
| cache-to: type=gha,mode=max,scope=canary-${{ matrix.suffix }} | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "/tmp/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: digests-canary-${{ matrix.suffix }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Merge platform-specific images into multi-arch manifest (only if server changed) | |
| merge-docker: | |
| name: Docker Manifest | |
| runs-on: ubuntu-latest | |
| needs: [changes, version, build-docker] | |
| if: needs.changes.outputs.server == 'true' | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Download digests | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | |
| with: | |
| path: /tmp/digests | |
| pattern: digests-canary-* | |
| merge-multiple: true | |
| - name: Set up Docker Buildx | |
| uses: step-security/setup-buildx-action@8c8aef2d414c0b66518fee2b7084e0986f82d7ac # v3.11.1 | |
| - name: Log in to GitHub Container Registry | |
| uses: step-security/docker-login-action@c3e677aae8393bc9c81cfdf9709648720ea4bd4d # v3.6.0 | |
| with: | |
| registry: ${{ env.GHCR_REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Log in to Docker Hub | |
| uses: step-security/docker-login-action@c3e677aae8393bc9c81cfdf9709648720ea4bd4d # v3.6.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Create and push manifest to ghcr.io | |
| working-directory: /tmp/digests | |
| run: | | |
| docker buildx imagetools create \ | |
| -t ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}:canary \ | |
| -t ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}:canary-${{ needs.version.outputs.short_sha }} \ | |
| $(printf '${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}@sha256:%s ' *) | |
| - name: Copy manifest to Docker Hub | |
| run: | | |
| docker buildx imagetools create \ | |
| -t ${{ env.DOCKERHUB_IMAGE }}:canary \ | |
| -t ${{ env.DOCKERHUB_IMAGE }}:canary-${{ needs.version.outputs.short_sha }} \ | |
| ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}:canary | |
| - name: Inspect images | |
| run: | | |
| echo "=== ghcr.io ===" | |
| docker buildx imagetools inspect ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}:canary | |
| echo "=== Docker Hub ===" | |
| docker buildx imagetools inspect ${{ env.DOCKERHUB_IMAGE }}:canary | |
| # Generate SBOM for Docker image (only if server changed) | |
| sbom-docker: | |
| name: Docker SBOM | |
| runs-on: ubuntu-latest | |
| needs: [changes, version, merge-docker] | |
| if: needs.changes.outputs.server == 'true' | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Log in to GitHub Container Registry | |
| uses: step-security/docker-login-action@c3e677aae8393bc9c81cfdf9709648720ea4bd4d # v3.6.0 | |
| with: | |
| registry: ${{ env.GHCR_REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate SBOM | |
| uses: anchore/sbom-action@62ad5284b8ced813296287a0b63906cb364b73ee # v0.22.0 | |
| with: | |
| image: ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE }}:canary | |
| artifact-name: docker-sbom.spdx.json | |
| output-file: docker-sbom.spdx.json | |
| - name: Upload SBOM to release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release upload "v${{ needs.version.outputs.version }}" \ | |
| docker-sbom.spdx.json --clobber || true | |
| # Publish crates to crates.io with canary version (only if libraries changed) | |
| publish-crates: | |
| name: Crates | |
| needs: [changes, version, create-release] | |
| if: needs.changes.outputs.libraries == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@881ba7bf39a41cda34ac9e123fb41b44ed08232f # stable | |
| - name: Install protobuf compiler | |
| run: | | |
| sudo apt-get update -qq | |
| sudo apt-get install -y -qq protobuf-compiler | |
| - name: Update crate versions | |
| env: | |
| VERSION: ${{ needs.version.outputs.version }} | |
| run: | | |
| # Update workspace version (strip build metadata for crates.io) | |
| # Dev versions are like 0.1.0-dev.20260201.123+abc1234, but crates.io | |
| # doesn't support build metadata, so we use 0.1.0-dev.20260201.123 | |
| CRATE_VERSION="${VERSION%+*}" | |
| sed -i "s/^version = \".*\"/version = \"${CRATE_VERSION}\"/" Cargo.toml | |
| # Update inter-crate dependency versions to use exact prerelease version | |
| # (semver ranges like ^0.1.0 don't match prereleases) | |
| for crate in inferadb-ledger-types inferadb-ledger-store inferadb-ledger-state inferadb-ledger-raft inferadb-ledger-sdk; do | |
| sed -i "s/\(${crate} = { version = \)\"[^\"]*\"/\1\"=${CRATE_VERSION}\"/" Cargo.toml | |
| done | |
| - name: Cache Rust dependencies | |
| uses: step-security/rust-cache@f8fba7098297c8c53a7c9a30575ec2ad4ad85056 # v2.8.2 | |
| - name: Authenticate with crates.io | |
| uses: rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec # v1.0.3 | |
| id: auth | |
| - name: Publish crates | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} | |
| run: | | |
| for crate in inferadb-ledger-types inferadb-ledger-store inferadb-ledger-state inferadb-ledger-raft inferadb-ledger-sdk; do | |
| echo "Publishing ${crate}..." | |
| cargo publish -p "${crate}" --token "$CARGO_REGISTRY_TOKEN" --allow-dirty | |
| echo "Waiting for crates.io to index..." | |
| sleep 45 | |
| done | |
| # Clean up old canary releases to avoid clutter | |
| # Keeps the last 7 days of releases, or at least the last 10 | |
| cleanup: | |
| name: Cleanup | |
| needs: [create-release] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| packages: write | |
| env: | |
| REPO: ${{ github.repository }} | |
| OWNER: ${{ github.repository_owner }} | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | |
| with: | |
| egress-policy: audit | |
| - name: Clean up old canary releases and tags | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| # Configuration | |
| KEEP_DAYS=7 | |
| MIN_KEEP=10 | |
| echo "=== Cleaning up old canary releases ===" | |
| # Get all canary releases sorted by date (oldest first) | |
| RELEASES=$(gh api "repos/${REPO}/releases" \ | |
| --jq '[.[] | select(.tag_name | test("canary")) | {id: .id, tag: .tag_name, date: .created_at}] | sort_by(.date)') | |
| TOTAL=$(echo "$RELEASES" | jq 'length') | |
| echo "Found $TOTAL canary releases" | |
| if [ "$TOTAL" -le "$MIN_KEEP" ]; then | |
| echo "Only $TOTAL releases exist, keeping all (minimum: $MIN_KEEP)" | |
| exit 0 | |
| fi | |
| # Calculate cutoff date (7 days ago) | |
| CUTOFF_DATE=$(date -d "-${KEEP_DAYS} days" -u +%Y-%m-%dT%H:%M:%SZ) | |
| echo "Cutoff date: $CUTOFF_DATE" | |
| # Find releases older than cutoff, but ensure we keep at least MIN_KEEP | |
| OLD_RELEASES=$(echo "$RELEASES" | jq --arg cutoff "$CUTOFF_DATE" \ | |
| '[.[] | select(.date < $cutoff)]') | |
| OLD_COUNT=$(echo "$OLD_RELEASES" | jq 'length') | |
| # Calculate how many we can actually delete | |
| CAN_DELETE=$((TOTAL - MIN_KEEP)) | |
| if [ "$OLD_COUNT" -gt "$CAN_DELETE" ]; then | |
| TO_DELETE=$CAN_DELETE | |
| else | |
| TO_DELETE=$OLD_COUNT | |
| fi | |
| echo "Releases older than $KEEP_DAYS days: $OLD_COUNT" | |
| echo "Will delete: $TO_DELETE (keeping at least $MIN_KEEP)" | |
| if [ "$TO_DELETE" -eq 0 ]; then | |
| echo "Nothing to delete" | |
| exit 0 | |
| fi | |
| # Delete oldest releases (up to TO_DELETE) | |
| echo "$OLD_RELEASES" | jq -r ".[:$TO_DELETE][] | \"\(.id) \(.tag)\"" | while read -r ID TAG; do | |
| echo "Deleting release: $TAG (ID: $ID)" | |
| gh api -X DELETE "repos/${REPO}/releases/$ID" || true | |
| # Also delete the associated tag | |
| echo "Deleting tag: $TAG" | |
| gh api -X DELETE "repos/${REPO}/git/refs/tags/$TAG" || true | |
| done | |
| echo "=== Cleanup complete ===" | |
| - name: Clean up old GHCR images | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| # Configuration | |
| KEEP_DAYS=7 | |
| MIN_KEEP=10 | |
| PACKAGE_NAME="ledger" | |
| echo "=== Cleaning up old GHCR canary images ===" | |
| # Get all versions of the package, filter to canary tags | |
| VERSIONS=$(gh api "orgs/${OWNER}/packages/container/${PACKAGE_NAME}/versions" \ | |
| --jq '[.[] | select(.metadata.container.tags | any(test("^canary"))) | {id: .id, tags: .metadata.container.tags, date: .created_at}] | sort_by(.date)' 2>/dev/null || echo "[]") | |
| TOTAL=$(echo "$VERSIONS" | jq 'length') | |
| echo "Found $TOTAL canary image versions" | |
| if [ "$TOTAL" -le "$MIN_KEEP" ]; then | |
| echo "Only $TOTAL versions exist, keeping all (minimum: $MIN_KEEP)" | |
| exit 0 | |
| fi | |
| # Calculate cutoff date | |
| CUTOFF_DATE=$(date -d "-${KEEP_DAYS} days" -u +%Y-%m-%dT%H:%M:%SZ) | |
| echo "Cutoff date: $CUTOFF_DATE" | |
| # Find versions older than cutoff | |
| OLD_VERSIONS=$(echo "$VERSIONS" | jq --arg cutoff "$CUTOFF_DATE" \ | |
| '[.[] | select(.date < $cutoff)]') | |
| OLD_COUNT=$(echo "$OLD_VERSIONS" | jq 'length') | |
| # Calculate how many we can delete | |
| CAN_DELETE=$((TOTAL - MIN_KEEP)) | |
| if [ "$OLD_COUNT" -gt "$CAN_DELETE" ]; then | |
| TO_DELETE=$CAN_DELETE | |
| else | |
| TO_DELETE=$OLD_COUNT | |
| fi | |
| echo "Versions older than $KEEP_DAYS days: $OLD_COUNT" | |
| echo "Will delete: $TO_DELETE (keeping at least $MIN_KEEP)" | |
| if [ "$TO_DELETE" -eq 0 ]; then | |
| echo "Nothing to delete" | |
| exit 0 | |
| fi | |
| # Delete oldest versions | |
| echo "$OLD_VERSIONS" | jq -r ".[:$TO_DELETE][] | \"\(.id) \(.tags | join(\", \"))\"" | while read -r ID TAGS; do | |
| echo "Deleting GHCR version: $TAGS (ID: $ID)" | |
| gh api -X DELETE "orgs/${OWNER}/packages/container/${PACKAGE_NAME}/versions/$ID" || true | |
| done | |
| echo "=== GHCR cleanup complete ===" |