relswap 0.0.11

Signed-release install/update engine with durable activation and crash recovery
Documentation
name: Release

on:
  push:
    tags:
      - "v*"
  # A dispatched run passes through `Verify release ref` like any other, so it only proceeds from
  # a tag whose name matches the manifest version - it cannot publish from a branch.
  workflow_dispatch:

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

permissions:
  contents: read

jobs:
  publish:
    name: publish to crates.io
    runs-on: ubuntu-latest
    environment: release
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: dtolnay/rust-toolchain@1.88
      - uses: Swatinem/rust-cache@v2

      - name: Verify release ref
        shell: bash
        run: |
          set -euo pipefail
          version="$(cargo metadata --locked --no-deps --format-version 1 | python3 -c \
            'import json,sys; print(json.load(sys.stdin)["packages"][0]["version"])')"
          test "$GITHUB_REF_NAME" = "v$version"
          git fetch --no-tags origin main
          git merge-base --is-ancestor "$GITHUB_SHA" origin/main

      - name: Test release package
        run: cargo test --locked --all-features

      - name: Verify package
        run: cargo publish --locked --dry-run

      - name: Authenticate with crates.io
        id: crates_io
        uses: rust-lang/crates-io-auth-action@v1

      - name: Publish to crates.io
        run: cargo publish --locked
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.crates_io.outputs.token }}

  github_release:
    name: create GitHub release
    needs: publish
    # A dispatched run reaches this job with `publish` already failed, because the version it would
    # upload is by definition one crates.io has: that is what makes the "release exists" branch
    # below testable without a real release. A pushed tag still requires the upload to have
    # succeeded, so a page never advertises a version the registry does not have.
    if: >-
      ${{ !cancelled() && startsWith(github.ref, 'refs/tags/v')
      && (needs.publish.result == 'success' || github.event_name == 'workflow_dispatch') }}
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      # Publishing a release from the GitHub website creates the tag as a side effect, so that path
      # reaches this job with the page already written by hand - and hand-written notes beat
      # generated ones. This only fills the gap left by a tag pushed from a clone, where nothing
      # else ever creates the page. An existing release is left exactly as published.
      - name: Create release if the tag has none
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ github.ref_name }}
        run: |
          set -euo pipefail
          if gh release view "$TAG" -R "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
            echo "$TAG already has a release page; leaving it as published."
            exit 0
          fi
          gh release create "$TAG" -R "$GITHUB_REPOSITORY" \
            --verify-tag \
            --title "relswap ${TAG#v}" \
            --generate-notes