feat!: replace funty with platform-num, remove LinkType #31
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD Pipeline | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| workflow_dispatch: | |
| inputs: | |
| release_mode: | |
| description: 'Manual release mode' | |
| required: true | |
| type: choice | |
| default: 'instant' | |
| options: | |
| - instant | |
| - changelog-pr | |
| bump_type: | |
| description: 'Version bump type' | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| description: | |
| description: 'Release description (optional)' | |
| required: false | |
| type: string | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUSTFLAGS: -Dwarnings | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }} | |
| CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }} | |
| jobs: | |
| # === DETECT CHANGES - determines which jobs should run === | |
| detect-changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'workflow_dispatch' | |
| outputs: | |
| rs-changed: ${{ steps.changes.outputs.rs-changed }} | |
| toml-changed: ${{ steps.changes.outputs.toml-changed }} | |
| docs-changed: ${{ steps.changes.outputs.docs-changed }} | |
| workflow-changed: ${{ steps.changes.outputs.workflow-changed }} | |
| any-code-changed: ${{ steps.changes.outputs.any-code-changed }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Detect changes | |
| id: changes | |
| env: | |
| GITHUB_EVENT_NAME: ${{ github.event_name }} | |
| GITHUB_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: rust-script scripts/detect-code-changes.rs | |
| # === CHANGELOG CHECK - only runs on PRs with code changes === | |
| changelog: | |
| name: Changelog Fragment Check | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes] | |
| if: github.event_name == 'pull_request' && needs.detect-changes.outputs.any-code-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Check for changelog fragments | |
| env: | |
| GITHUB_BASE_REF: ${{ github.base_ref }} | |
| run: rust-script scripts/check-changelog-fragment.rs | |
| # === VERSION CHECK - prevents manual version modification in PRs === | |
| version-check: | |
| name: Version Modification Check | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Check for manual version changes | |
| env: | |
| GITHUB_EVENT_NAME: ${{ github.event_name }} | |
| GITHUB_HEAD_REF: ${{ github.head_ref }} | |
| GITHUB_BASE_REF: ${{ github.base_ref }} | |
| run: rust-script scripts/check-version-modification.rs | |
| # === LINT AND FORMAT CHECK === | |
| lint: | |
| name: Lint and Format Check | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes] | |
| if: | | |
| always() && !cancelled() && ( | |
| github.event_name == 'push' || | |
| github.event_name == 'workflow_dispatch' || | |
| needs.detect-changes.outputs.rs-changed == 'true' || | |
| needs.detect-changes.outputs.toml-changed == 'true' || | |
| needs.detect-changes.outputs.docs-changed == 'true' || | |
| needs.detect-changes.outputs.workflow-changed == 'true' | |
| ) | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| - name: Run Clippy | |
| run: cargo clippy --all-targets --all-features | |
| - name: Check file size limit | |
| run: rust-script scripts/check-file-size.rs | |
| # === TEST === | |
| test: | |
| name: Test (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| needs: [detect-changes, changelog] | |
| if: always() && !cancelled() && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || needs.changelog.result == 'success' || needs.changelog.result == 'skipped') | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Run tests | |
| run: cargo test --all-features --verbose | |
| - name: Run doc tests | |
| run: cargo test --doc --verbose | |
| # === CODE COVERAGE === | |
| coverage: | |
| name: Code Coverage | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes] | |
| if: | | |
| always() && !cancelled() && ( | |
| github.event_name == 'push' || | |
| github.event_name == 'workflow_dispatch' || | |
| needs.detect-changes.outputs.rs-changed == 'true' || | |
| needs.detect-changes.outputs.toml-changed == 'true' | |
| ) | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: llvm-tools-preview | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-coverage- | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/install-action@cargo-llvm-cov | |
| - name: Generate code coverage | |
| run: cargo llvm-cov --all-features --lcov --output-path lcov.info | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: lcov.info | |
| fail_ci_if_error: false | |
| # === BUILD === | |
| build: | |
| name: Build Package | |
| runs-on: ubuntu-latest | |
| needs: [lint, test] | |
| if: always() && !cancelled() && needs.lint.result == 'success' && needs.test.result == 'success' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo registry | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-build- | |
| - name: Build release | |
| run: cargo build --release --verbose | |
| - name: Check package | |
| run: cargo package --list --allow-dirty | |
| # === AUTO RELEASE === | |
| auto-release: | |
| name: Auto Release | |
| needs: [lint, test, build] | |
| if: | | |
| always() && !cancelled() && | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| needs.build.result == 'success' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Configure git | |
| run: rust-script scripts/git-config.rs | |
| - name: Determine bump type from changelog fragments | |
| id: bump_type | |
| run: rust-script scripts/get-bump-type.rs | |
| - name: Check if version already released or no fragments | |
| id: check | |
| env: | |
| HAS_FRAGMENTS: ${{ steps.bump_type.outputs.has_fragments }} | |
| run: rust-script scripts/check-release-needed.rs | |
| - name: Collect changelog and bump version | |
| id: version | |
| if: steps.check.outputs.should_release == 'true' && steps.check.outputs.skip_bump != 'true' | |
| run: | | |
| rust-script scripts/version-and-commit.rs \ | |
| --bump-type "${{ steps.bump_type.outputs.bump_type }}" | |
| - name: Get current version | |
| id: current_version | |
| if: steps.check.outputs.should_release == 'true' | |
| run: rust-script scripts/get-version.rs | |
| - name: Build release | |
| if: steps.check.outputs.should_release == 'true' | |
| run: cargo build --release | |
| - name: Publish to Crates.io | |
| if: steps.check.outputs.should_release == 'true' | |
| id: publish-crate | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }} | |
| CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }} | |
| run: rust-script scripts/publish-crate.rs | |
| - name: Create GitHub Release | |
| if: steps.check.outputs.should_release == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| RELEASE_VERSION="${{ steps.version.outputs.new_version }}" | |
| if [ -z "$RELEASE_VERSION" ]; then | |
| RELEASE_VERSION="${{ steps.current_version.outputs.version }}" | |
| fi | |
| rust-script scripts/create-github-release.rs --release-version "$RELEASE_VERSION" --repository "${{ github.repository }}" | |
| # === MANUAL INSTANT RELEASE === | |
| manual-release: | |
| name: Instant Release | |
| needs: [lint, test, build] | |
| if: | | |
| always() && !cancelled() && | |
| github.event_name == 'workflow_dispatch' && | |
| github.event.inputs.release_mode == 'instant' && | |
| needs.build.result == 'success' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Configure git | |
| run: rust-script scripts/git-config.rs | |
| - name: Collect changelog fragments | |
| run: rust-script scripts/collect-changelog.rs | |
| - name: Version and commit | |
| id: version | |
| env: | |
| BUMP_TYPE: ${{ github.event.inputs.bump_type }} | |
| DESCRIPTION: ${{ github.event.inputs.description }} | |
| run: rust-script scripts/version-and-commit.rs --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}" | |
| - name: Build release | |
| if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true' | |
| run: cargo build --release | |
| - name: Publish to Crates.io | |
| if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true' | |
| id: publish-crate | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }} | |
| CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }} | |
| run: rust-script scripts/publish-crate.rs | |
| - name: Create GitHub Release | |
| if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: rust-script scripts/create-github-release.rs --release-version "${{ steps.version.outputs.new_version }}" --repository "${{ github.repository }}" | |
| # === DEPLOY DOCUMENTATION === | |
| deploy-docs: | |
| name: Deploy Rust Documentation | |
| needs: [auto-release, manual-release] | |
| if: | | |
| always() && !cancelled() && ( | |
| needs.auto-release.result == 'success' || | |
| needs.manual-release.result == 'success' | |
| ) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: main | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build documentation | |
| run: cargo doc --no-deps --all-features | |
| - name: Deploy to GitHub Pages | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: target/doc | |
| destination_dir: rust | |
| keep_files: true | |
| # === MANUAL CHANGELOG PR === | |
| changelog-pr: | |
| name: Create Changelog PR | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'changelog-pr' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install rust-script | |
| run: cargo install rust-script | |
| - name: Create changelog fragment | |
| env: | |
| BUMP_TYPE: ${{ github.event.inputs.bump_type }} | |
| DESCRIPTION: ${{ github.event.inputs.description }} | |
| run: rust-script scripts/create-changelog-fragment.rs --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}" | |
| - name: Create Pull Request | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| commit-message: 'chore: add changelog for manual ${{ github.event.inputs.bump_type }} release' | |
| branch: changelog-manual-release-${{ github.run_id }} | |
| delete-branch: true | |
| title: 'chore: manual ${{ github.event.inputs.bump_type }} release' | |
| body: | | |
| ## Manual Release Request | |
| This PR was created by a manual workflow trigger to prepare a **${{ github.event.inputs.bump_type }}** release. | |
| ### Release Details | |
| - **Type:** ${{ github.event.inputs.bump_type }} | |
| - **Description:** ${{ github.event.inputs.description || 'Manual release' }} | |
| - **Triggered by:** @${{ github.actor }} | |
| ### Next Steps | |
| 1. Review the changelog fragment in this PR | |
| 2. Merge this PR to main | |
| 3. The automated release workflow will publish to crates.io and create a GitHub release |