wami 0.10.0

Who Am I - Multicloud Identity, IAM, STS, and SSO operations library for Rust
Documentation
name: Auto Release

on:
  push:
    branches:
      - main
  workflow_dispatch:
    inputs:
      bump_type:
        description: 'Version bump type'
        required: true
        type: choice
        options:
          - patch
          - minor
          - major
        default: 'patch'

permissions:
  contents: write
  pages: write
  id-token: write

jobs:
  check-and-release:
    runs-on: ubuntu-latest
    outputs:
      should_release: ${{ steps.check.outputs.should_release }}
      bump_type: ${{ steps.check.outputs.bump_type }}
      new_version: ${{ steps.version.outputs.new_version }}
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Check if should release
        id: check
        run: |
          # Skip if commit message contains [skip ci] or [skip release]
          if git log -1 --pretty=%B | grep -qE '\[skip (ci|release)\]'; then
            echo "should_release=false" >> $GITHUB_OUTPUT
            echo "Skipping release (found skip marker)"
            exit 0
          fi
          
          # Check for existing tag on current commit
          if git describe --exact-match --tags HEAD 2>/dev/null; then
            echo "should_release=false" >> $GITHUB_OUTPUT
            echo "Skipping release (commit already tagged)"
            exit 0
          fi
          
          # Determine bump type from commits since last tag
          LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
          
          if [ -z "$LAST_TAG" ]; then
            COMMITS=$(git log --pretty=format:"%s" HEAD)
          else
            COMMITS=$(git log --pretty=format:"%s" ${LAST_TAG}..HEAD)
          fi
          
          echo "Recent commits:"
          echo "$COMMITS"
          
          # Manual override from workflow_dispatch
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            BUMP_TYPE="${{ github.event.inputs.bump_type }}"
            echo "Manual release requested: $BUMP_TYPE"
          # Check for breaking changes (major)
          elif echo "$COMMITS" | grep -qE "^[a-z]+(\(.+\))?!:|BREAKING CHANGE:"; then
            BUMP_TYPE="major"
          # Check for features (minor)
          elif echo "$COMMITS" | grep -qE "^feat(\(.+\))?:"; then
            BUMP_TYPE="minor"
          # Check for fixes (patch)
          elif echo "$COMMITS" | grep -qE "^(fix|perf|refactor|docs|style|test|chore)(\(.+\))?:"; then
            BUMP_TYPE="patch"
          else
            echo "should_release=false" >> $GITHUB_OUTPUT
            echo "No conventional commits found - skipping release"
            exit 0
          fi
          
          echo "should_release=true" >> $GITHUB_OUTPUT
          echo "bump_type=$BUMP_TYPE" >> $GITHUB_OUTPUT
          echo "Will create $BUMP_TYPE release"

      - name: Calculate new version
        if: steps.check.outputs.should_release == 'true'
        id: version
        run: |
          CURRENT=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
          echo "Current version: $CURRENT"
          
          IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
          
          case "${{ steps.check.outputs.bump_type }}" in
            major)
              MAJOR=$((MAJOR + 1))
              MINOR=0
              PATCH=0
              ;;
            minor)
              MINOR=$((MINOR + 1))
              PATCH=0
              ;;
            patch)
              PATCH=$((PATCH + 1))
              ;;
          esac
          
          NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
          echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
          echo "New version: $NEW_VERSION"

      - name: Update version in Cargo.toml
        if: steps.check.outputs.should_release == 'true'
        run: |
          NEW_VERSION="${{ steps.version.outputs.new_version }}"
          sed -i.bak "s/^version = \".*\"/version = \"$NEW_VERSION\"/" Cargo.toml
          rm Cargo.toml.bak
          
          echo "Updated Cargo.toml:"
          grep "^version" Cargo.toml

      - name: Update Cargo.lock
        if: steps.check.outputs.should_release == 'true'
        run: cargo update -p wami --precise ${{ steps.version.outputs.new_version }}

      - name: Install git-cliff
        if: steps.check.outputs.should_release == 'true'
        run: |
          wget https://github.com/orhun/git-cliff/releases/download/v2.4.0/git-cliff-2.4.0-x86_64-unknown-linux-gnu.tar.gz
          tar -xzf git-cliff-2.4.0-x86_64-unknown-linux-gnu.tar.gz
          sudo mv git-cliff-2.4.0/git-cliff /usr/local/bin/
          git-cliff --version

      - name: Generate changelog
        if: steps.check.outputs.should_release == 'true'
        run: |
          NEW_VERSION="${{ steps.version.outputs.new_version }}"
          git-cliff --config cliff.toml --tag "v$NEW_VERSION" --output CHANGELOG.md

      - name: Commit and tag
        if: steps.check.outputs.should_release == 'true'
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          
          NEW_VERSION="${{ steps.version.outputs.new_version }}"
          
          git add Cargo.toml Cargo.lock CHANGELOG.md
          git commit -m "chore(release): v$NEW_VERSION [skip ci]"
          git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"
          git push origin main
          git push origin "v$NEW_VERSION"

  build-docs:
    needs: check-and-release
    if: needs.check-and-release.outputs.should_release == 'true'
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          ref: v${{ needs.check-and-release.outputs.new_version }}

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

      - name: Cache
        uses: Swatinem/rust-cache@v2

      - name: Build docs
        run: |
          cargo doc --no-deps --all-features
          echo '<meta http-equiv="refresh" content="0; url=wami">' > target/doc/index.html

      - name: Setup Pages
        uses: actions/configure-pages@v5
        continue-on-error: true

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v4
        with:
          path: 'target/doc'

      - name: Deploy
        id: deployment
        uses: actions/deploy-pages@v4
        continue-on-error: true

  create-release:
    needs: [check-and-release, build-docs]
    if: needs.check-and-release.outputs.should_release == 'true'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          ref: v${{ needs.check-and-release.outputs.new_version }}
          fetch-depth: 0

      - name: Extract changelog
        run: |
          VERSION="${{ needs.check-and-release.outputs.new_version }}"
          
          # Extract release notes from CHANGELOG
          awk '/^## \['"$VERSION"'\]/,/^## \[/' CHANGELOG.md | \
            sed '1d;$d' | \
            sed '/^$/d' > release-notes.md
          
          if [ ! -s release-notes.md ]; then
            echo "Release v$VERSION" > release-notes.md
            echo "" >> release-notes.md
            echo "See [CHANGELOG.md](./CHANGELOG.md) for details." >> release-notes.md
          fi
          
          echo "Release notes:"
          cat release-notes.md

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: v${{ needs.check-and-release.outputs.new_version }}
          name: v${{ needs.check-and-release.outputs.new_version }}
          body_path: release-notes.md
          draft: false
          prerelease: false

  publish-crate:
    needs: [check-and-release, create-release]
    if: needs.check-and-release.outputs.should_release == 'true'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        with:
          ref: v${{ needs.check-and-release.outputs.new_version }}

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

      - name: Cache
        uses: Swatinem/rust-cache@v2

      - name: Test
        run: cargo test --all-features

      - name: Package
        run: cargo package

      - name: Publish
        if: env.CARGO_TOKEN != ''
        run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
        env:
          CARGO_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        continue-on-error: false

      - name: Note
        if: env.CARGO_TOKEN == ''
        run: echo "::warning::CARGO_REGISTRY_TOKEN not set - skipping crates.io publish"
        env:
          CARGO_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}