securetar 0.1.1

Rust reader primitives for SecureTar v3 encrypted streams (used in Home Assistant backups)
Documentation
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow

name: ci

permissions:
  contents: read

on:
  push:
    branches: [main]
    tags:
      - "v*"
  pull_request:

env:
  CARGO_TERM_COLOR: always
  SODIUM_USE_PKG_CONFIG: "1"

jobs:
  stable:
    runs-on: ubuntu-latest

    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Install native dependencies
        run: sudo apt-get update && sudo apt-get install -y pkg-config libsodium-dev

      - name: Cache Rust build artifacts
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: ${{ github.workflow }}-${{ github.job }}

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

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

      - name: Run tests
        run: cargo test --locked --all-targets --all-features

      - name: Build package
        run: cargo package --locked --verbose --all-features

  msrv:
    runs-on: ubuntu-latest

    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@1.85

      - name: Install native dependencies
        run: sudo apt-get update && sudo apt-get install -y pkg-config libsodium-dev

      - name: Cache Rust build artifacts
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: ${{ github.workflow }}-${{ github.job }}

      - name: Check MSRV
        run: cargo check --locked --all-targets --all-features

  release:
    runs-on: ubuntu-latest
    needs:
      - stable
      - msrv
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    permissions:
      contents: write

    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Validate tag format
        run: |
          if ! printf '%s\n' "${GITHUB_REF_NAME}" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
            echo "Tag '${GITHUB_REF_NAME}' must match vX.Y.Z" >&2
            exit 1
          fi

      - name: Read crate version
        run: |
          version=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n1)
          if [ -z "${version}" ]; then
            echo "Failed to read version from Cargo.toml" >&2
            exit 1
          fi
          if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
            echo "Tag ${GITHUB_REF_NAME} does not match Cargo.toml version ${version}" >&2
            exit 1
          fi

      - name: Extract release notes from changelog
        id: changelog
        run: |
          version="${GITHUB_REF_NAME#v}"
          release_notes=$(
            awk '
              BEGIN { in_section = 0 }
              $0 ~ "^## Version " version " \\(" { in_section = 1; next }
              in_section && $0 ~ "^## " { exit }
              in_section { print }
            ' version="${version}" CHANGELOG.md
          )

          if [ -z "${release_notes}" ]; then
            echo "No CHANGELOG.md section found for version ${version}" >&2
            exit 1
          fi

          {
            echo "release_notes<<EOF"
            printf "%s\n" "${release_notes}"
            echo "EOF"
          } >> "${GITHUB_OUTPUT}"

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Install native dependencies
        run: sudo apt-get update && sudo apt-get install -y pkg-config libsodium-dev

      - name: Publish crate
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish --locked

      - name: Create GitHub release
        uses: actions/github-script@v9
        env:
          RELEASE_NOTES: ${{ steps.changelog.outputs.release_notes }}
        with:
          script: |
            const { owner, repo } = context.repo;
            const tagName = context.ref.replace("refs/tags/", "");
            await github.rest.repos.createRelease({
              owner,
              repo,
              tag_name: tagName,
              name: tagName,
              body: process.env.RELEASE_NOTES,
              target_commitish: context.sha,
            });