feat(cli): consolidate maintenance surface under wright update #790
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 | |
| # --------------------------------------------------------------------------- | |
| # Trigger rules | |
| # --------------------------------------------------------------------------- | |
| # Push to main: capability checks are selected by changed paths, just like PRs. | |
| # Broad changes still run the full convergence set. | |
| # PR: capability checks are selected by changed paths. Broad/core changes | |
| # (Cargo workspace, scripts, test inputs, CI itself) expand to the | |
| # full check set; narrow path changes run only the relevant capability. | |
| # Docs-only changes skip CI entirely. | |
| on: | |
| push: | |
| branches: ["main"] | |
| paths-ignore: | |
| - "**/*.md" | |
| - "docs/**" | |
| - "!benchmarks/**/*.md" | |
| pull_request: | |
| paths-ignore: | |
| - "**/*.md" | |
| - "docs/**" | |
| - "!benchmarks/**/*.md" | |
| permissions: | |
| contents: read | |
| # --------------------------------------------------------------------------- | |
| # Path filter: determines which capability jobs run on PRs and pushes. | |
| # --------------------------------------------------------------------------- | |
| jobs: | |
| paths: | |
| name: Detect paths | |
| runs-on: ubuntu-latest | |
| outputs: | |
| rust_core: ${{ steps.filter.outputs.rust_core }} | |
| opy: ${{ steps.filter.outputs.rust_core }} | |
| lpp: ${{ steps.filter.outputs.rust_core }} | |
| cli: ${{ steps.filter.outputs.rust_core }} | |
| dist: ${{ steps.filter.outputs.dist }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Filter paths | |
| id: filter | |
| uses: dorny/paths-filter@v4 | |
| with: | |
| filters: | | |
| rust_core: | |
| - 'Cargo.toml' | |
| - 'Cargo.lock' | |
| - 'rust-toolchain' | |
| - 'rust-toolchain.toml' | |
| - '.cargo/**' | |
| - 'src/**' | |
| - 'crates/**' | |
| - 'tests/fixtures/**' | |
| - 'scripts/**' | |
| - 'benchmarks/**' | |
| - '.github/workflows/**' | |
| dist: | |
| - 'dist/**' | |
| - 'install.sh' | |
| - 'install.ps1' | |
| - 'Cargo.toml' | |
| - 'Cargo.lock' | |
| - 'rust-toolchain' | |
| - 'rust-toolchain.toml' | |
| - '.cargo/**' | |
| - 'src/**' | |
| - 'crates/**' | |
| - 'tests/fixtures/**' | |
| - 'scripts/**' | |
| - '.github/workflows/**' | |
| # ------------------------------------------------------------------------- | |
| # [1] RUST QUALITY & TESTS (fundamental gate) | |
| # All other Rust-based jobs depend on this. | |
| # ------------------------------------------------------------------------- | |
| rust-quality: | |
| name: Rust (stable) | |
| needs: paths | |
| if: needs.paths.outputs.rust_core == 'true' | |
| uses: wrightkit/.github/.github/workflows/rust-quality.yml@a83d0f1b4cbcb5b81fb0426e3a5aea1db0899fb5 | |
| with: | |
| toolchain: stable | |
| cache-shared-key: linux-quality-stable-dev-test | |
| all-features: true | |
| # The reusable quality workflow installs its requested toolchain, but the | |
| # repository rust-toolchain.toml remains authoritative for bare Cargo | |
| # commands. Keep the MSRV gate local so every command explicitly selects | |
| # 1.85.0 and cannot silently fall back to stable. | |
| rust-msrv: | |
| name: Rust (1.85.0) | |
| needs: paths | |
| if: needs.paths.outputs.rust_core == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Install Rust (1.85.0) | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: 1.85.0 | |
| components: rustfmt, clippy | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-quality-1.85.0-dev-test | |
| cache-targets: true | |
| cache-all-crates: false | |
| cache-workspace-crates: false | |
| cache-bin: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| cache-on-failure: false | |
| - name: Check formatting | |
| run: cargo +1.85.0 fmt --all -- --check | |
| # Keep the surviving owner-independent Wright crates on the declared | |
| # MSRV. The provider-backed consumer crates are covered by the stable | |
| # full-workspace gate and the dedicated integration jobs below. | |
| - name: Clippy (independent crates) | |
| run: >- | |
| cargo +1.85.0 clippy --locked --all-targets --all-features | |
| -p wright-analyzer -p wright-transform -p wright-lpp -- -D warnings | |
| - name: Test (independent crates) | |
| run: >- | |
| cargo +1.85.0 test --locked --all-targets --all-features | |
| -p wright-analyzer -p wright-transform -p wright-lpp | |
| # ------------------------------------------------------------------------- | |
| # [1a] WRIGHT CLI ARTIFACT (stable/debug executable for compatible jobs) | |
| # Build this exact workflow revision once. Consumers below need the CLI | |
| # executable only; jobs with another output or test-build identity stay | |
| # independent. | |
| # ------------------------------------------------------------------------- | |
| wright-cli-build: | |
| name: Build CLI | |
| needs: [paths, rust-quality, rust-msrv] | |
| if: needs.paths.outputs.opy == 'true' || needs.paths.outputs.cli == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-quality-stable-dev-test | |
| cache-targets: true | |
| cache-all-crates: false | |
| cache-workspace-crates: false | |
| cache-bin: false | |
| save-if: false | |
| cache-on-failure: false | |
| - name: Build CLI | |
| run: cargo build --locked -p wright-cli | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: wright-cli-linux-stable-debug | |
| path: target/debug/wright | |
| if-no-files-found: error | |
| - name: Record CLI provenance | |
| shell: bash | |
| run: | | |
| digest="$(sha256sum target/debug/wright | cut -d ' ' -f1)" | |
| { | |
| printf '%s\n\n' '## Wright CLI artifact' | |
| printf -- "- Revision: \`%s\`\n" "$GITHUB_SHA" | |
| printf '%s\n' '- Build identity: stable / debug / ubuntu-latest' | |
| printf -- "- SHA-256: \`%s\`\n" "$digest" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| # ------------------------------------------------------------------------- | |
| # [1b] WORKSHOP REAL-PROJECT INTEGRATION (Wright's released Workshop consumer) | |
| # Runs the owner-pinned real-project inputs through the actual `wright` | |
| # check/lint commands. The source snapshots and residual expectations remain | |
| # owned by the released workshop-rs corpus. | |
| # ------------------------------------------------------------------------- | |
| workshop-integration: | |
| name: Workshop (${{ matrix.project }}) | |
| needs: [paths, rust-quality, rust-msrv, wright-cli-build] | |
| if: needs.paths.outputs.rust_core == 'true' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: true | |
| matrix: | |
| include: | |
| - project: ai-pve | |
| expected_exit: 0 | |
| - project: bastion | |
| expected_exit: 0 | |
| # The pinned owner corpus admits this project's residual as a | |
| # source-level failure; the other projects must remain clean. | |
| - project: defend | |
| expected_exit: 1 | |
| - project: illari | |
| expected_exit: 0 | |
| - project: rework | |
| expected_exit: 0 | |
| steps: | |
| - name: Checkout Wright | |
| uses: actions/checkout@v7 | |
| - name: Checkout workshop-rs | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: wrightkit/workshop-rs | |
| ref: f1f3c58f790e9aede9300ca6421698f2503f5f62 # v0.3.11 | |
| path: workshop-rs-pinned | |
| - name: Download CLI artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: wright-cli-linux-stable-debug | |
| path: target/debug | |
| - name: Prepare CLI executable | |
| run: chmod +x target/debug/wright | |
| - name: Run public CLI dogfood | |
| env: | |
| EXPECTED_EXIT: ${{ matrix.expected_exit }} | |
| PROJECT: workshop-rs-pinned/crates/workshop-rs/tests/fixtures/real-projects/${{ matrix.project }}.ow | |
| run: | | |
| set -euo pipefail | |
| run_workflow() { | |
| local command="$1" | |
| local output | |
| local status | |
| set +e | |
| output="$(target/debug/wright "$command" --kind workshop "$PROJECT" --format json)" | |
| status=$? | |
| set -e | |
| if [[ "$status" -ne "$EXPECTED_EXIT" ]]; then | |
| echo "wright $command returned $status; expected $EXPECTED_EXIT for $PROJECT" >&2 | |
| return 1 | |
| fi | |
| jq -e \ | |
| --arg command "$command" \ | |
| --argjson process_exit "$status" \ | |
| '( | |
| .wright.contract == "wright-result/v1" and | |
| .command == $command and | |
| .exit == $process_exit and | |
| .ok == ($process_exit == 0) and | |
| (.diagnostics | type == "array") and | |
| (all(.diagnostics[]; type == "object")) and | |
| ([.diagnostics[] | select(.stage == "internal")] | length == 0) | |
| )' <<<"$output" >/dev/null | |
| printf '%s' "$output" | |
| } | |
| check_output="$(run_workflow check)" | |
| lint_output="$(run_workflow lint)" | |
| jq -e -n \ | |
| --argjson check "$check_output" \ | |
| --argjson lint "$lint_output" \ | |
| '( | |
| $check.diagnostics == $lint.diagnostics and | |
| $check.ok == $lint.ok and | |
| $check.exit == $lint.exit and | |
| ($lint.result.program.rules | numbers | . > 0) | |
| )' >/dev/null | |
| # ------------------------------------------------------------------------- | |
| # [2] PRODUCT INTEGRATION (Wright-owned provider and product contracts) | |
| # The source-language owners test language semantics. Wright tests its | |
| # provider seam, provider distribution success path, failure routing, and | |
| # user-facing product behavior directly. | |
| # ------------------------------------------------------------------------- | |
| opy-integration: | |
| name: Product integration | |
| needs: [paths, rust-quality, rust-msrv, wright-cli-build] | |
| if: needs.paths.outputs.opy == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| - name: Download CLI artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: wright-cli-linux-stable-debug | |
| path: target/debug | |
| - name: Prepare CLI executable | |
| run: chmod +x target/debug/wright | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-quality-stable-dev-test | |
| cache-targets: true | |
| cache-all-crates: false | |
| cache-workspace-crates: false | |
| cache-bin: false | |
| save-if: false | |
| cache-on-failure: false | |
| - name: Run provider/product tests | |
| run: >- | |
| cargo test --locked | |
| -p wright-driver --test driver --test source_provider --test service | |
| --test workshop_provider | |
| - name: Run CLI/embedding tests | |
| run: >- | |
| cargo test --locked | |
| -p wright-cli --test cli --test diagnostics_schema --test serve | |
| && cargo test --locked -p wright-consumer --test consumer | |
| - name: Install pinned OPY provider | |
| run: target/debug/wright update provider opy --version 0.1.38 | |
| - name: Compile OPY via provider | |
| run: >- | |
| target/debug/wright compile tests/fixtures/opy/basic-rule.opy | |
| --profile compat | |
| # ------------------------------------------------------------------------- | |
| # [3] LPP INTEGRATION (Wright's Language Provider Protocol client contract) | |
| # ------------------------------------------------------------------------- | |
| lpp-integration: | |
| name: LPP integration | |
| needs: [paths, rust-quality, rust-msrv] | |
| if: needs.paths.outputs.lpp == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Wright | |
| uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-quality-stable-dev-test | |
| cache-targets: true | |
| cache-all-crates: false | |
| cache-workspace-crates: false | |
| cache-bin: false | |
| save-if: false | |
| cache-on-failure: false | |
| # The mock provider is built from the pinned language-provider-protocol | |
| # commit the integration tests were validated against (merged LPP v1, | |
| # PR wrightkit/language-provider-protocol#2 plus docs-only follow-ups). | |
| - name: Checkout LPP | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: wrightkit/language-provider-protocol | |
| ref: 416b293e26e6fb2d29061608a493a7aecd2ce14f | |
| path: language-provider-protocol | |
| - name: Build mock provider | |
| run: cargo build --locked -p lpp-mock-provider | |
| working-directory: language-provider-protocol | |
| # REQUIRED: these suites self-skip when LPP_MOCK_PROVIDER is absent, | |
| # so the variable must be set here for them to run at all. | |
| - name: Run LPP tests | |
| env: | |
| LPP_MOCK_PROVIDER: ${{ github.workspace }}/language-provider-protocol/target/debug/lpp-mock-provider | |
| run: >- | |
| cargo test --locked -p wright-lpp -p wright-driver | |
| --test mock_provider --test lpp --test provider_edit | |
| # ------------------------------------------------------------------------- | |
| # [4] CLI BEHAVIOR (Wright CLI GitHub Actions renderer smoke test) | |
| # Validates CLI output format in a real GitHub Actions environment. | |
| # Related to #164 (user-facing GHA renderer); this job validates the | |
| # repository CI integration, not the renderer semantics layer. | |
| # ------------------------------------------------------------------------- | |
| cli-behavior: | |
| name: CLI behavior | |
| needs: [paths, rust-quality, rust-msrv, wright-cli-build] | |
| if: needs.paths.outputs.cli == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| - name: Download CLI artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: wright-cli-linux-stable-debug | |
| path: target/debug | |
| - name: Prepare CLI executable | |
| run: chmod +x target/debug/wright | |
| - name: Test GitHub Actions renderer | |
| run: scripts/test-cli-github-actions.sh target/debug/wright | |
| # ------------------------------------------------------------------------- | |
| # [5] BENCHMARK (performance evidence) | |
| # Non-blocking on PRs; records regression-detectable output as artifact. | |
| # Depends on rust-quality so a fundamental failure skips benchmark time. | |
| # ------------------------------------------------------------------------- | |
| benchmark: | |
| name: Benchmarks | |
| needs: [paths, rust-quality, rust-msrv] | |
| if: needs.paths.outputs.opy == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-quality-stable-dev-test | |
| cache-targets: true | |
| cache-all-crates: false | |
| cache-workspace-crates: false | |
| cache-bin: false | |
| save-if: false | |
| cache-on-failure: false | |
| - name: Build benchmarks | |
| run: cargo build --locked -p wright-bench | |
| - name: Run benchmarks | |
| id: bench | |
| run: target/debug/wright-bench | |
| - name: Validate agent benchmark scenarios | |
| run: | | |
| cargo build --locked -p wright-cli | |
| python3 benchmarks/agent/agent_bench.py validate | |
| python3 -m unittest discover -s benchmarks/agent | |
| - name: Upload benchmark report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: benchmark-report | |
| path: target/wright-bench-report.json | |
| # ------------------------------------------------------------------------- | |
| # [8] DISTRIBUTION VALIDATION (cross-platform package/binary smoke) | |
| # When source changes are in scope, this remains gated on the relevant Rust | |
| # and integration jobs. Distribution-only changes run this job directly. | |
| # ------------------------------------------------------------------------- | |
| dist-cli-build: | |
| name: Build dist (${{ matrix.os }}) | |
| needs: | |
| - paths | |
| - rust-quality | |
| - rust-msrv | |
| - opy-integration | |
| - lpp-integration | |
| if: | | |
| always() && | |
| needs.paths.outputs.dist == 'true' && | |
| (needs.rust-quality.result == 'success' || needs.paths.outputs.rust_core != 'true') && | |
| (needs.rust-msrv.result == 'success' || needs.paths.outputs.rust_core != 'true') && | |
| (needs.opy-integration.result == 'success' || needs.paths.outputs.opy != 'true') && | |
| (needs.lpp-integration.result == 'success' || needs.paths.outputs.lpp != 'true') | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - ubuntu-latest | |
| - macos-15 | |
| - windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: dist-validation-${{ runner.os }}-stable-dev | |
| cache-targets: false | |
| cache-all-crates: false | |
| cache-workspace-crates: false | |
| cache-bin: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| cache-on-failure: false | |
| - name: Build CLI and LSP | |
| shell: bash | |
| run: cargo build --locked -p wright-cli -p wright-lsp | |
| - name: Upload distribution binaries | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: wright-dist-cli-${{ matrix.os }} | |
| path: | | |
| target/debug/wright | |
| target/debug/wright.exe | |
| target/debug/wright-lsp | |
| target/debug/wright-lsp.exe | |
| if-no-files-found: error | |
| dist-validation: | |
| name: Dist validation (${{ matrix.channel }}, ${{ matrix.os }}) | |
| needs: | |
| - paths | |
| - rust-quality | |
| - rust-msrv | |
| - opy-integration | |
| - lpp-integration | |
| - dist-cli-build | |
| if: | | |
| always() && | |
| needs.paths.outputs.dist == 'true' && | |
| (needs.rust-quality.result == 'success' || needs.paths.outputs.rust_core != 'true') && | |
| (needs.rust-msrv.result == 'success' || needs.paths.outputs.rust_core != 'true') && | |
| (needs.opy-integration.result == 'success' || needs.paths.outputs.opy != 'true') && | |
| (needs.lpp-integration.result == 'success' || needs.paths.outputs.lpp != 'true') && | |
| needs.dist-cli-build.result == 'success' | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| channel: install.sh | |
| - os: macos-15 | |
| channel: install.sh | |
| - os: macos-15 | |
| channel: Homebrew | |
| - os: windows-latest | |
| channel: install.ps1 | |
| - os: windows-latest | |
| channel: Scoop | |
| - os: windows-latest | |
| channel: WinGet | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: "3.12" | |
| - name: Install Scoop | |
| if: matrix.channel == 'Scoop' | |
| shell: pwsh | |
| run: ./scripts/setup-scoop.ps1 | |
| - name: Enable WinGet local manifests | |
| if: matrix.channel == 'WinGet' | |
| shell: pwsh | |
| run: winget settings --enable LocalManifestFiles | |
| - name: Download distribution binaries | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: wright-dist-cli-${{ matrix.os }} | |
| path: target/debug | |
| - name: Prepare distribution executables | |
| if: runner.os != 'Windows' | |
| run: chmod +x target/debug/wright target/debug/wright-lsp | |
| - name: Validate package metadata and installers | |
| if: matrix.channel == 'install.sh' || matrix.channel == 'install.ps1' | |
| run: python scripts/verify-dist.py | |
| - name: Test install.sh (functional) | |
| if: matrix.channel == 'install.sh' | |
| run: scripts/test-install.sh | |
| - name: Test install.sh (native smoke) | |
| if: matrix.channel == 'install.sh' | |
| run: python scripts/test-distribution-install-sh.py | |
| - name: Test install.ps1 (channel) | |
| if: matrix.channel == 'install.ps1' | |
| shell: pwsh | |
| run: ./scripts/test-install.ps1 | |
| - name: Test install.ps1 (R2 smoke) | |
| if: matrix.channel == 'install.ps1' | |
| shell: pwsh | |
| run: ./scripts/test-install-r2.ps1 | |
| - name: Test Homebrew channel | |
| if: matrix.channel == 'Homebrew' | |
| run: python scripts/test-distribution-homebrew.py | |
| - name: Test Scoop channel | |
| if: matrix.channel == 'Scoop' | |
| run: python scripts/test-distribution-scoop.py | |
| - name: Test WinGet channel | |
| if: matrix.channel == 'WinGet' | |
| run: python scripts/test-distribution-winget.py |