docs(admin): document account exit codes; ci: narrow the protected-files marker #827
Workflow file for this run
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 | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| permissions: | |
| contents: read | |
| jobs: | |
| advisories: | |
| name: Dependency Advisories | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: EmbarkStudios/cargo-deny-action@bb137d7af7e4fb67e5f82a49c4fce4fad40782fe # v2 | |
| with: | |
| command: check advisories | |
| fmt: | |
| name: Format Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| with: | |
| components: rustfmt | |
| - name: Check formatting | |
| run: cargo fmt --all --check | |
| clippy: | |
| name: Clippy | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| with: | |
| components: clippy | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Run Clippy | |
| run: cargo clippy --workspace --all-targets -- -D warnings | |
| test: | |
| name: Test (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ ubuntu-latest, macos-latest, windows-latest ] | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Run tests | |
| # Don't use --all-features as integration/golden require external services | |
| # See integration.yml for those tests | |
| run: cargo test --workspace | |
| build: | |
| name: Build (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ ubuntu-latest, macos-latest, windows-latest ] | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Build | |
| run: cargo build --workspace --release | |
| doc: | |
| name: Documentation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Build documentation | |
| run: cargo doc --workspace --no-deps | |
| env: | |
| RUSTDOCFLAGS: -D warnings | |
| # Ensure protected files are not modified without proper process | |
| protected-files: | |
| name: Protected Files Check | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check protected files | |
| env: | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| run: | | |
| # Any change to these needs the marker: a new exit code, a new config | |
| # field or a new schema property extends a contract even when nothing | |
| # existing moves. | |
| PROTECTED_FILES=( | |
| "schemas/output_v1.json" | |
| "crates/cli/src/exit_code.rs" | |
| "crates/core/src/config.rs" | |
| ) | |
| # The command reference is a contract too, but adding a section to it | |
| # is how a new command gets documented — required by AGENTS.md § 3 of | |
| # the Breaking Change process, in fact. Demanding the marker for that | |
| # makes every additive PR claim to be breaking, so these paths need it | |
| # only when existing lines move: a rewritten sentence, a removed flag, | |
| # a deleted or renamed page. | |
| ADDITIVE_OK_FILES=( | |
| "docs/reference/rc/" | |
| ) | |
| BASE="origin/${{ github.base_ref }}" | |
| CHANGED_FILES=$(git diff --name-only "$BASE"...HEAD) | |
| # Paths under a protected prefix, one per line. | |
| matched_paths() { | |
| local protected_path="${1%/}" | |
| printf '%s\n' "$CHANGED_FILES" \ | |
| | grep -E "^$(printf '%s' "$protected_path" | sed 's/[.[\*^$]/\\&/g')(/|$)" || true | |
| } | |
| require_marker() { | |
| local subject="$1" | |
| echo "::warning::Protected file modified: $subject" | |
| echo "This change requires the Breaking Change process. See AGENTS.md." | |
| if ! grep -q "BREAKING" <<< "$PR_BODY"; then | |
| echo "::error::Protected file $subject modified without BREAKING marker in PR description" | |
| return 1 | |
| fi | |
| } | |
| status=0 | |
| for file in "${PROTECTED_FILES[@]}"; do | |
| if [ -n "$(matched_paths "$file")" ]; then | |
| require_marker "$file" || status=1 | |
| fi | |
| done | |
| for file in "${ADDITIVE_OK_FILES[@]}"; do | |
| paths=$(matched_paths "$file") | |
| [ -n "$paths" ] || continue | |
| # Rename detection off on purpose: moving a reference page changes | |
| # where readers and links land, so it should count as a rewrite | |
| # rather than as a no-op. | |
| removed=0 | |
| count=0 | |
| while IFS= read -r path; do | |
| [ -n "$path" ] || continue | |
| count=$((count + 1)) | |
| deleted=$( | |
| git diff --numstat --no-renames "$BASE"...HEAD -- "$path" \ | |
| | awk '{ total += $2 } END { print total + 0 }' | |
| ) | |
| removed=$((removed + deleted)) | |
| done <<< "$paths" | |
| if [ "$removed" -gt 0 ]; then | |
| require_marker "$file ($removed line(s) changed or removed)" || status=1 | |
| else | |
| echo "$file changed by addition only ($count file(s)); no marker required" | |
| fi | |
| done | |
| if [ "$status" -ne 0 ]; then | |
| exit 1 | |
| fi | |
| echo "Protected files check passed" | |
| msrv: | |
| name: Minimum Supported Rust Version | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master | |
| with: | |
| toolchain: "1.92" | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Build with MSRV | |
| run: cargo build --workspace |