fusabi-stdlib-ext 0.1.6

Extended standard library modules and domain packs for Fusabi
Documentation
name: Release

on:
  push:
    tags:
      - 'v*.*.*'

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

permissions:
  contents: write
  packages: write

jobs:
  validate:
    name: Validate Release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Extract version from tag
        id: extract_version
        run: |
          TAG=${GITHUB_REF#refs/tags/}
          VERSION=${TAG#v}
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "tag=$TAG" >> $GITHUB_OUTPUT

      - name: Verify Cargo.toml version matches tag
        run: |
          CARGO_VERSION=$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)
          if [ "$CARGO_VERSION" != "${{ steps.extract_version.outputs.version }}" ]; then
            echo "ERROR: Cargo.toml version ($CARGO_VERSION) does not match tag (${{ steps.extract_version.outputs.version }})"
            exit 1
          fi

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

      - name: Run clippy
        run: cargo clippy --all-features -- -D warnings -A unused-imports -A unused-variables -A unused-doc-comments -A clippy::unwrap-or-default -A unexpected_cfgs

      - name: Check documentation
        run: cargo doc --all-features --no-deps
        env:
          RUSTDOCFLAGS: -D warnings --cfg docsrs -A unexpected_cfgs -A rustdoc::broken_intra_doc_links

  build:
    name: Build Release
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Build release
        run: cargo build --release --all-features

      - name: Package crate
        run: cargo package --allow-dirty

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: crate-package
          path: target/package/fusabi-stdlib-ext-*.crate

  changelog:
    name: Generate Changelog
    needs: validate
    runs-on: ubuntu-latest
    outputs:
      changelog: ${{ steps.changelog.outputs.changelog }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Extract version from tag
        id: extract_version
        run: |
          TAG=${GITHUB_REF#refs/tags/}
          VERSION=${TAG#v}
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "tag=$TAG" >> $GITHUB_OUTPUT

      - name: Extract changelog for this version
        id: changelog
        run: |
          # Extract changelog section for current version
          VERSION="${{ steps.extract_version.outputs.version }}"

          # Check if CHANGELOG.md exists and has content for this version
          if grep -q "\[$VERSION\]" CHANGELOG.md; then
            # Extract content between version headers
            CHANGELOG=$(sed -n "/\[$VERSION\]/,/^## \[/p" CHANGELOG.md | sed '$d' | tail -n +2)
            echo "Found changelog for version $VERSION"
          else
            CHANGELOG="Release $VERSION"
            echo "No changelog found for version $VERSION, using default"
          fi

          # Save to file for multiline content
          echo "$CHANGELOG" > changelog.txt

          # Also set as output (escaped)
          {
            echo 'changelog<<EOF'
            cat changelog.txt
            echo EOF
          } >> $GITHUB_OUTPUT

      - name: Upload changelog
        uses: actions/upload-artifact@v4
        with:
          name: changelog
          path: changelog.txt

  publish-crates-io:
    name: Publish to crates.io
    needs: [validate, build, changelog]
    runs-on: ubuntu-latest
    if: github.repository == 'fusabi-lang/fusabi-stdlib-ext'
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Publish to crates.io
        run: cargo publish --allow-dirty
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }}
        continue-on-error: true

  github-release:
    name: Create GitHub Release
    needs: [validate, build, changelog, publish-crates-io]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Extract version from tag
        id: extract_version
        run: |
          TAG=${GITHUB_REF#refs/tags/}
          VERSION=${TAG#v}
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "tag=$TAG" >> $GITHUB_OUTPUT

      - name: Download changelog
        uses: actions/download-artifact@v4
        with:
          name: changelog

      - name: Download crate package
        uses: actions/download-artifact@v4
        with:
          name: crate-package

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          name: Release ${{ steps.extract_version.outputs.tag }}
          body_path: changelog.txt
          files: |
            fusabi-stdlib-ext-*.crate
          draft: false
          prerelease: ${{ contains(steps.extract_version.outputs.version, 'alpha') || contains(steps.extract_version.outputs.version, 'beta') || contains(steps.extract_version.outputs.version, 'rc') }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Post-release notification
        run: |
          echo "::notice::Release ${{ steps.extract_version.outputs.tag }} created successfully"
          echo "::notice::crates.io: https://crates.io/crates/fusabi-stdlib-ext/${{ steps.extract_version.outputs.version }}"
          echo "::notice::docs.rs: https://docs.rs/fusabi-stdlib-ext/${{ steps.extract_version.outputs.version }}"

  benchmark:
    name: Performance Benchmarks
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Run benchmarks
        run: |
          if [ -d "benches" ]; then
            cargo bench --all-features || echo "No benchmarks found or benchmarks failed"
          else
            echo "No benchmark directory found, skipping"
          fi

      - name: Upload benchmark results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: benchmark-results
          path: target/criterion/
          if-no-files-found: ignore