runnerctl 0.3.0

Manage independent ephemeral GitHub Actions runner pools on one Docker host
name: Publish

on:
  release:
    types: [published]

permissions:
  contents: read

concurrency:
  group: crates-io-publish
  cancel-in-progress: false

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - name: Check out the release tag
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.release.tag_name }}
          fetch-depth: 0

      - name: Reject prerelease releases
        if: ${{ github.event.release.prerelease }}
        run: |
          echo "Prerelease GitHub releases are not published to crates.io."
          exit 1

      - name: Install stable Rust
        run: rustup toolchain install stable --profile minimal --component rustfmt --component clippy

      - name: Verify release tag
        env:
          RELEASE_TAG: ${{ github.event.release.tag_name }}
        run: |
          version="$(cargo +stable metadata --no-deps --format-version 1 | jq -er '.packages[] | select(.name == "runnerctl") | .version')"
          expected_tag="v${version}"
          if [[ "$RELEASE_TAG" != "$expected_tag" ]]; then
            echo "Release tag '$RELEASE_TAG' does not match expected tag '$expected_tag' from Cargo.toml."
            exit 1
          fi

      - name: Check formatting
        run: cargo +stable fmt --check

      - name: Run clippy
        run: cargo +stable clippy --all-targets --locked -- -D warnings

      - name: Run tests
        run: cargo +stable test --locked

      - name: Validate crate publication
        run: cargo +stable publish --dry-run --locked

      - name: Validate runner image
        run: |
          python3 scripts/update-runner.py --check
          docker build -t local/runnerctl-test-base:1 runner
          docker build -t local/runnerctl-test:1 -f tests/Dockerfile .
          bash tests/entrypoint.sh
          bash tests/docker-socket.sh
          cargo +stable test --locked docker_ -- --ignored --nocapture

  image:
    needs: validate
    permissions:
      contents: read
      packages: write
    uses: ./.github/workflows/runner-image.yml
    with:
      tag: ${{ github.event.release.tag_name }}

  publish:
    needs: image
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.release.tag_name }}
      - run: rustup toolchain install stable --profile minimal
      - name: Verify the image is publicly pullable
        env:
          IMAGE_TAG: ${{ github.event.release.tag_name }}
          IMAGE_OWNER: ${{ github.repository_owner }}
        run: |
          mkdir -p "$RUNNER_TEMP/anonymous-docker"
          docker --config "$RUNNER_TEMP/anonymous-docker" manifest inspect "ghcr.io/$IMAGE_OWNER/runnerctl-runner:$IMAGE_TAG" >/dev/null
      - name: Publish crate
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo +stable publish --locked