bitflagset 0.0.4

Enum and positional typed bitsets with Set API
Documentation
name: Bench Readme

on:
  workflow_dispatch:
  pull_request:
    paths:
      - "README.md"
      - "benches/**"
      - "src/**"
      - "Cargo.toml"
      - "Cargo.lock"
      - "scripts/update_readme_bench.sh"
      - "scripts/readme_bench_tables.py"
      - ".github/workflows/bench-readme.yml"

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  vs-bitvec-readme:
    name: compare bench + README check
    # workflow_dispatch regenerates the README in update-readme. Running this
    # job too would bench `compare` twice.
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - name: Checkout
        uses: actions/checkout@v4

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

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

      - name: Run compare benchmarks
        run: cargo bench --bench compare

      - name: Check README benchmark tables
        id: readme_check
        run: |
          set +e
          scripts/update_readme_bench.sh --check-structure
          status=$?
          echo "status=$status" >> "$GITHUB_OUTPUT"
          if [[ "${status}" -eq 1 ]]; then
            echo "structural_mismatch=1" >> "$GITHUB_OUTPUT"
          else
            echo "structural_mismatch=0" >> "$GITHUB_OUTPUT"
          fi
          exit 0

      - name: Render benchmark comment
        id: bench_comment
        if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
        run: |
          set -euo pipefail
          args=(--comment)
          if [[ "${{ steps.readme_check.outputs.structural_mismatch }}" == "1" ]]; then
            args+=(--readme-stale)
          fi
          python3 scripts/readme_bench_tables.py "${args[@]}" > "${RUNNER_TEMP}/bench-comment.md"

      - name: Comment benchmark report on PR
        if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
        uses: actions/github-script@v7
        env:
          COMMENT_PATH: ${{ runner.temp }}/bench-comment.md
        with:
          script: |
            const fs = require("fs");
            const marker = "<!-- bench-readme-check -->";
            const body = fs.readFileSync(process.env.COMMENT_PATH, "utf8");
            const { owner, repo } = context.repo;
            const issue_number = context.payload.pull_request.number;
            const comments = await github.paginate(
              github.rest.issues.listComments,
              { owner, repo, issue_number, per_page: 100 }
            );
            const existing = comments.find(
              (comment) =>
                comment.user?.type === "Bot" &&
                typeof comment.body === "string" &&
                comment.body.includes(marker)
            );

            if (existing) {
              await github.rest.issues.updateComment({
                owner,
                repo,
                comment_id: existing.id,
                body,
              });
            } else {
              await github.rest.issues.createComment({
                owner,
                repo,
                issue_number,
                body,
              });
            }

  vs-bitflags-smoke:
    name: vs_bitflags benchmark smoke
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - name: Checkout
        uses: actions/checkout@v4

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

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

      - name: Run vs_bitflags benchmarks
        run: cargo bench --bench vs_bitflags -- --sample-size 20 --warm-up-time 0.1 --measurement-time 0.2

  # Regenerates README benchmark numbers on a GitHub-hosted runner and opens a
  # pull request. The repository setting "Allow GitHub Actions to create and
  # approve pull requests" must be enabled. Pull requests opened with
  # GITHUB_TOKEN do not trigger other workflows.
  update-readme:
    name: regenerate README benchmarks
    if: github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write

    steps:
      - name: Checkout
        uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
        with:
          persist-credentials: false

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable
        with:
          toolchain: 1.86.0

      - name: Cache cargo artifacts
        uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2

      - name: Run compare benchmarks
        run: cargo bench --bench compare

      - name: Regenerate README benchmark tables
        id: readme
        run: |
          set -euo pipefail
          scripts/update_readme_bench.sh
          scripts/update_readme_bench.sh --check
          if git diff --quiet -- README.md; then
            echo "changed=false" >> "${GITHUB_OUTPUT}"
            echo "::notice title=README unchanged::README.md benchmark tables are unchanged."
          else
            echo "changed=true" >> "${GITHUB_OUTPUT}"
          fi

      - name: Commit README and open or update pull request
        if: steps.readme.outputs.changed == 'true'
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GIT_AUTHOR_NAME: github-actions[bot]
          GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
          GIT_COMMITTER_NAME: github-actions[bot]
          GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
        run: |
          set -euo pipefail
          if [[ "${GITHUB_REF_NAME}" == "bench-readme-update" ]]; then
            echo "::error::Dispatch from the branch that should receive the README, not bench-readme-update."
            exit 1
          fi
          git add -- README.md
          git commit -m "Update README benchmark tables from CI" -m "Source commit: ${GITHUB_SHA}"
          gh auth setup-git
          git push --force origin "HEAD:bench-readme-update"
          os_name="$(awk -F= '/^PRETTY_NAME=/{ gsub(/"/, "", $2); print $2; exit }' /etc/os-release)"
          cpu_name="$(lscpu | awk -F: '/^[Mm]odel name:/ { sub(/^[ \t]+/, "", $2); print $2; exit }')"
          rustc_version="$(rustc --version)"
          body_file="${RUNNER_TEMP}/bench-readme-pr.md"
          {
            echo "Benchmark numbers regenerated on a GitHub-hosted runner."
            echo
            echo "- OS: ${os_name}"
            echo "- CPU: ${cpu_name}"
            echo "- rustc: ${rustc_version}"
            printf -- '- Commit: `%s`\n' "${GITHUB_SHA}"
            echo
            echo "These numbers come from a GitHub-hosted runner."
          } > "${body_file}"
          title="Update README benchmark tables"
          existing="$(gh pr list --repo "${GITHUB_REPOSITORY}" --head bench-readme-update --state open --json number --jq '.[0].number // empty')"
          if [[ -n "${existing}" ]]; then
            gh pr edit "${existing}" --repo "${GITHUB_REPOSITORY}" --base "${GITHUB_REF_NAME}" --title "${title}" --body-file "${body_file}"
          else
            gh pr create --repo "${GITHUB_REPOSITORY}" --base "${GITHUB_REF_NAME}" --head bench-readme-update --title "${title}" --body-file "${body_file}"
          fi