Skip to content

Coalesce bold runs and close them at block boundaries #253

Coalesce bold runs and close them at block boundaries

Coalesce bold runs and close them at block boundaries #253

Workflow file for this run

name: Rust Checks and Release
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: 'Manual release type'
required: true
type: choice
options:
- patch
- minor
- major
description:
description: 'Manual release description (optional)'
required: false
type: string
# Concurrency: Only one workflow run per branch at a time
# - For main branch (releases): cancel older runs to prevent blocking newer releases
# - For PR branches: queue runs to avoid cancelling checks on force-pushes
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref == 'refs/heads/main' }}
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -Dwarnings
# Support both CARGO_REGISTRY_TOKEN (cargo's native env var) and CARGO_TOKEN (for backwards compatibility)
CARGO_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }}
defaults:
run:
working-directory: rust
jobs:
# === DETECT CHANGES - determines which jobs should run ===
detect-changes:
name: Rust - Detect Changes
runs-on: ubuntu-latest
if: github.event_name != 'workflow_dispatch'
outputs:
rust-code-changed: ${{ steps.changes.outputs.rust-code-changed }}
rust-changed: ${{ steps.changes.outputs.rust-changed }}
rust-scripts-changed: ${{ steps.changes.outputs.rust-scripts-changed }}
rust-workflow-changed: ${{ steps.changes.outputs.rust-workflow-changed }}
any-rust-code-changed: ${{ steps.changes.outputs.any-rust-code-changed }}
any-code-changed: ${{ steps.changes.outputs.any-code-changed }}
docs-changed: ${{ steps.changes.outputs.docs-changed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect changes
id: changes
working-directory: .
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: node scripts/detect-code-changes.mjs
# === PUBLISHABLE CHANGES CHECK ===
# Warns when PR touches publishable paths without version bump
# This is informational — auto-release on main handles the gap
publishable-check:
name: Rust - Publishable Changes Check
runs-on: ubuntu-latest
needs: [detect-changes]
if: github.event_name == 'pull_request' && needs.detect-changes.outputs.any-rust-code-changed == 'true'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for publishable changes without version bump
working-directory: .
env:
GITHUB_BASE_REF: ${{ github.base_ref }}
run: node scripts/check-publishable-changes.mjs
# Linting and formatting - runs when Rust-relevant files change
lint:
name: Rust - 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.any-rust-code-changed == 'true' ||
needs.detect-changes.outputs.docs-changed == 'true'
)
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/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 -- -D warnings
# Test matrix: Rust on multiple OS - only runs when Rust code changes
test:
name: Rust - Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: [detect-changes]
if: |
always() && !cancelled() && (
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.any-rust-code-changed == 'true'
)
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/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
- name: Run Google Docs public-document live integration tests (issue #90)
working-directory: rust
env:
GDOCS_INTEGRATION: '1'
run: cargo test --test integration gdocs_public_doc::live -- --nocapture
timeout-minutes: 10
# Build check - only runs when Rust code changes
build:
name: Rust - Build
runs-on: ubuntu-latest
needs: [lint, test]
if: |
!cancelled() &&
needs.lint.result == 'success' &&
needs.test.result == 'success'
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Build release
run: cargo build --release
- name: Check package
run: cargo package --list --allow-dirty
- name: Build Docker image
run: docker build -t web-capture-rust .
# Release - only runs on main after tests pass (for push events)
# Self-healing: detects unreleased commits and auto-bumps patch version
release:
name: Rust - Release
needs: [lint, test, build]
if: |
!cancelled() &&
github.ref == 'refs/heads/main' &&
github.event_name == 'push' &&
needs.build.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24.x'
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Check if release is needed
id: release_check
run: node ../scripts/rust-check-release-needed.mjs
- name: Auto-bump patch version for unreleased changes
if: steps.release_check.outputs.should_release == 'true' && steps.release_check.outputs.needs_auto_bump == 'true'
id: auto_bump
# Uses scripts/safe-git-push.mjs for fetch+rebase+retry so concurrent
# pushes from the JS release workflow don't cause non-fast-forward
# rejections. See docs/case-studies/issue-94.
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
node ../scripts/rust-version-bump.mjs --bump-type patch --description "Auto-release unreleased changes"
git add -A
NEW_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
git commit -m "chore(rust): auto-bump to ${NEW_VERSION} for unreleased changes"
node ../scripts/safe-git-push.mjs --branch main
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
echo "Auto-bumped to ${NEW_VERSION}"
- name: Determine release version
id: version
run: |
if [ -n "${{ steps.auto_bump.outputs.version }}" ]; then
echo "version=${{ steps.auto_bump.outputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${{ steps.release_check.outputs.version }}" >> $GITHUB_OUTPUT
fi
- name: Build release
if: steps.release_check.outputs.should_release == 'true'
run: cargo build --release
- name: Publish to crates.io
if: steps.release_check.outputs.should_release == 'true'
id: publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }}
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
run: node ../scripts/rust-publish-crate.mjs
- name: Create GitHub Release
if: steps.publish.outputs.published == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node ../scripts/rust-create-github-release.mjs --release-version "${{ steps.version.outputs.version }}" --repository "${{ github.repository }}" --commit-sha "${{ github.sha }}"
# Manual Instant Release
instant-release:
name: Rust - Instant Release
if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'instant'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24.x'
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
rust/target
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Version and commit
id: version
run: node ../scripts/rust-version-and-commit.mjs --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}"
- name: Publish to crates.io
if: steps.version.outputs.version_committed == 'true'
id: publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }}
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
run: node ../scripts/rust-publish-crate.mjs
- name: Create GitHub Release
if: steps.version.outputs.version_committed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node ../scripts/rust-create-github-release.mjs --release-version "${{ steps.version.outputs.version }}" --repository "${{ github.repository }}" --description "${{ github.event.inputs.description }}" --commit-sha "${{ github.sha }}"
# Manual Changelog PR - creates a PR with version bump for review before release
changelog-pr:
name: Rust - 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@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24.x'
- name: Bump version in Cargo.toml and CHANGELOG.md
working-directory: .
run: |
cd rust
node ../scripts/rust-version-bump.mjs --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(rust): bump version (${{ github.event.inputs.bump_type }})'
branch: changelog-rust-manual-release-${{ github.run_id }}
delete-branch: true
title: 'chore(rust): manual ${{ github.event.inputs.bump_type }} release'
body: |
## Manual Release Request (Rust)
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 version bump and changelog in this PR
2. Merge this PR to main
3. The automated release workflow will publish to crates.io and create a GitHub release