termaxa 0.19.6

A cooperative gate for the shell commands AI coding agents run — command previews, automatic backups, allow/ask/deny policy, and audit logging.
name: Release

# Tag a version to cut a release:  git tag v0.10.6 && git push origin v0.10.6
on:
  push:
    tags: ["v*"]

permissions:
  contents: write

jobs:
  # Gate: a tag on a commit that can't pass checks must never publish.
  check:
    name: fmt + clippy + test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@v2
      - name: Format check
        run: cargo fmt --all -- --check
      # Blocking, matching CI since v0.16. The `continue-on-error` here said
      # "matches CI: clippy non-fatal (for now)" and stopped matching the
      # moment CI flipped - which made the RELEASE gate weaker than the PR
      # gate, exactly backwards for the job whose own comment says a tag that
      # cannot pass checks must never publish.
      - name: Clippy
        run: cargo clippy --all-targets -- -D warnings
      - name: Tests
        run: cargo test --all

  build:
    name: ${{ matrix.target }}
    needs: check
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          # musl, statically linked: the glibc build needed 2.39 (ubuntu-24.04's)
          # and would not start on Debian 12 or Ubuntu 22.04 (found Sep 19, 2026,
          # building the playground image). Same asset name.
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            name: termaxa-linux-x86_64
          - os: macos-latest
            target: x86_64-apple-darwin
            name: termaxa-macos-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            name: termaxa-macos-arm64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            name: termaxa-windows-x86_64.exe
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
      - name: musl toolchain
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: sudo apt-get update && sudo apt-get install -y musl-tools
      - name: Build
        run: cargo build --release --target ${{ matrix.target }}
      - name: Stage binary (unix)
        if: runner.os != 'Windows'
        run: |

          cp target/${{ matrix.target }}/release/termaxa ${{ matrix.name }}
          chmod +x ${{ matrix.name }}
      - name: Stage binary (windows)
        if: runner.os == 'Windows'
        run: cp target/${{ matrix.target }}/release/termaxa.exe ${{ matrix.name }}
      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.name }}
          path: ${{ matrix.name }}
          if-no-files-found: error

  # Runs exactly once: creates the release, attaches all binaries,
  # generates notes a single time.
  release:
    name: publish release
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download all binaries
        uses: actions/download-artifact@v4
        with:
          path: dist
          merge-multiple: true
      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          files: dist/*
          fail_on_unmatched_files: true
          generate_release_notes: true

  # Opens the winget update PR on microsoft/winget-pkgs from the published
  # release, so no one runs `wingetcreate` by hand. Needs a classic PAT
  # with `public_repo` in the WINGET_TOKEN secret (it pushes to the
  # devdoc83/winget-pkgs fork and opens the PR); the first package
  # submission (#424831) took 55 days of human validation, updates are
  # auto-validated and usually merge within a day. Skipped, not failed, when
  # the token is absent, so a release never depends on it.
  winget:
    name: winget update PR
    needs: release
    runs-on: windows-latest
    if: ${{ !contains(github.ref_name, '-') }}
    # A courtesy job, not part of the release: the assets are published by
    # the job before it, and a winget hiccup must not paint the release red.
    continue-on-error: true
    steps:
      - name: Version without the v
        id: ver
        shell: bash
        run: echo "v=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
      - name: Open the winget PR
        if: ${{ env.WINGET_TOKEN != '' }}
        uses: vedantmgoyal9/winget-releaser@main
        with:
          identifier: Termaxa.Termaxa
          version: ${{ steps.ver.outputs.v }}
          release-tag: ${{ github.ref_name }}
          # The winget-pkgs fork is under the maintainer's account, not the
          # org: the default (`github.repository_owner` = termaxa) made the
          # first run fail with "Could not resolve to a Repository with the
          # name 'termaxa/winget-pkgs'" (v0.19.5, Sep 27, 2026).
          fork-user: devdoc83
          installers-regex: 'termaxa-windows-x86_64\.exe$'
          token: ${{ secrets.WINGET_TOKEN }}
        env:
          WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }}