opentui_rust 0.2.1

High-performance terminal UI rendering engine with alpha blending and diffed buffers
Documentation
name: Release

on:
  push:
    tags: ['v*']
  workflow_dispatch:
    inputs:
      dry_run:
        description: 'Dry run (skip actual publish)'
        type: boolean
        default: true

concurrency:
  group: release
  cancel-in-progress: false

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always

jobs:
  # Validate before release
  validate:
    name: Validate Release
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4

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

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

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

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

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

      - name: Build docs
        run: cargo doc --no-deps --all-features
        env:
          RUSTDOCFLAGS: -D warnings

      - name: Verify version matches tag
        if: startsWith(github.ref, 'refs/tags/v')
        run: |
          TAG_VERSION="${GITHUB_REF#refs/tags/v}"
          CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          echo "Tag version: $TAG_VERSION"
          echo "Cargo.toml version: $CARGO_VERSION"
          if [[ "$TAG_VERSION" != "$CARGO_VERSION" ]]; then
            echo "::error::Version mismatch! Tag is v$TAG_VERSION but Cargo.toml has $CARGO_VERSION"
            exit 1
          fi

  # Publish to crates.io
  publish:
    name: Publish to crates.io
    needs: validate
    runs-on: ubuntu-latest
    timeout-minutes: 30
    if: startsWith(github.ref, 'refs/tags/v') && !inputs.dry_run
    steps:
      - uses: actions/checkout@v4

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

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

      - name: Publish to crates.io
        run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}

  # Create GitHub Release
  github-release:
    name: Create GitHub Release
    needs: validate
    runs-on: ubuntu-latest
    timeout-minutes: 15
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Extract version
        id: version
        run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Generate changelog
        id: changelog
        run: |
          # Get previous tag
          PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")

          echo "## What's Changed" > CHANGELOG.md
          echo "" >> CHANGELOG.md

          if [[ -n "$PREV_TAG" ]]; then
            git log --pretty=format:"* %s (%h)" $PREV_TAG..HEAD >> CHANGELOG.md
          else
            git log --pretty=format:"* %s (%h)" >> CHANGELOG.md
          fi

          echo "" >> CHANGELOG.md
          echo "" >> CHANGELOG.md
          echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...v${{ steps.version.outputs.version }}" >> CHANGELOG.md

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          name: v${{ steps.version.outputs.version }}
          body_path: CHANGELOG.md
          generate_release_notes: true
          draft: false
          prerelease: ${{ contains(steps.version.outputs.version, '-') }}

    outputs:
      version: ${{ steps.version.outputs.version }}

  # Build documentation for GitHub Pages (optional)
  docs:
    name: Build Documentation
    needs: validate
    runs-on: ubuntu-latest
    timeout-minutes: 15
    if: startsWith(github.ref, 'refs/tags/v')
    permissions:
      contents: read
      pages: write
      id-token: write
    steps:
      - uses: actions/checkout@v4

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

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

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

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

  deploy-docs:
    name: Deploy Documentation
    needs: docs
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v')
    permissions:
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4