Files
nyaterm/.github/workflows/rust.yml
T
Kang 505e54b806 feat(ci): implement selective job execution for Rust workflows
- Introduced an `orchestrate` job to determine which CI jobs to run based on changed paths in pull requests.
- Updated Rust workflow to conditionally execute jobs like linting, testing, and plugin SDK based on the selection logic.
- Added a new script `select_rust_jobs.py` to handle job selection logic without requiring a Rust installation.
- Enhanced documentation to explain the new CI execution model and its implications for contributors.
2026-11-02 13:03:16 +08:00

310 lines
9.7 KiB
YAML

name: Rust
on:
workflow_dispatch:
merge_group:
types: [checks_requested]
push:
branches: [main, migration/gpui]
pull_request:
branches: [main, migration/gpui]
types: [opened, synchronize, reopened, labeled]
# No paths filter on purpose. A workflow filtered out by `paths` never runs, so its
# gate job never reports either, which leaves a pull request waiting forever on a
# required status check that will never arrive. Select jobs inside the workflow
# instead, so Rust gate still reports on documentation-only changes.
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: '0'
RUST_BACKTRACE: '1'
jobs:
orchestrate:
name: Select CI jobs
runs-on: ubuntu-24.04
timeout-minutes: 10
outputs:
run_rust: ${{ steps.select.outputs.run_rust }}
run_tmux: ${{ steps.select.outputs.run_tmux }}
run_plugin_sdk: ${{ steps.select.outputs.run_plugin_sdk }}
run_python: ${{ steps.select.outputs.run_python }}
run_workflows: ${{ steps.select.outputs.run_workflows }}
steps:
- name: Checkout tested revision and comparison history
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Test selection rules and workflow gates
run: python -m unittest scripts.tests.test_select_rust_jobs -v
- name: Select jobs for this event
id: select
run: python scripts/ci/select_rust_jobs.py
lint:
name: Lint
needs: [orchestrate]
if: needs.orchestrate.outputs.run_rust == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Rust
uses: ./.github/actions/setup-rust
with:
components: rustfmt, clippy
cache-key: lint
- name: Install Linux system dependencies
uses: ./.github/actions/install-linux-deps
- name: Check formatting
run: cargo fmt --all -- --check
- name: Check architecture boundaries
run: python scripts/ci/check_architecture.py
- name: Run clippy
run: cargo clippy --workspace --all-targets --locked -- -D warnings
test:
name: Test (${{ matrix.label }})
needs: [orchestrate]
if: needs.orchestrate.outputs.run_rust == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- label: linux-x64
os: ubuntu-24.04
- label: macos-arm64
os: macos-15
- label: windows-x64
os: windows-2025
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Rust
uses: ./.github/actions/setup-rust
with:
cache-key: test-${{ matrix.label }}
- name: Install Linux system dependencies
if: runner.os == 'Linux'
uses: ./.github/actions/install-linux-deps
with:
extra_packages: zsh fish
# Keep lifecycle regressions independent of unrelated workspace failures.
- name: Test Windows local shell lifecycle
if: runner.os == 'Windows'
shell: pwsh
run: |
$gitRoot = Split-Path (Split-Path (Get-Command git.exe).Source)
$env:NYATERM_TEST_POSIX_SHELL = Join-Path $gitRoot 'bin/bash.exe'
if (!(Test-Path -LiteralPath $env:NYATERM_TEST_POSIX_SHELL)) {
throw 'Git Bash is required for the ConPTY lifecycle regressions'
}
cargo test -p nyaterm-transport --lib local_shell_integration::lifecycle_tests --locked -- --ignored --test-threads=1
# Cold PowerShell startup must not compete with thousands of parallel UI
# and worker tests. Keep real ConPTY execution covered in its own step.
- name: Test Windows shared terminal execution
if: runner.os == 'Windows'
run: >-
cargo test -p nyaterm-desktop --lib
shared_entry_routes_native_codex_claude_and_external_calls_on_a_hidden_terminal
--locked -- --ignored --test-threads=1
# --no-fail-fast so one crate's failure stops masking every crate after it.
- name: Test workspace
run: cargo test --workspace --locked --no-fail-fast
- name: Install Python for Windows resource tests
if: runner.os == 'Windows'
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Test Windows executable resources
if: runner.os == 'Windows'
run: python -m unittest scripts.tests.test_windows_resources -v
tmux-compatibility:
name: tmux (${{ matrix.tmux }}, ${{ matrix.os }})
needs: [orchestrate]
if: needs.orchestrate.outputs.run_tmux == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-24.04
tmux: 3.2a
- os: ubuntu-24.04
tmux: '3.4'
- os: ubuntu-24.04
tmux: '3.8'
- os: macos-15
tmux: system
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: ./.github/actions/setup-rust
with:
cache-key: tmux-${{ runner.os }}
- name: Install Linux system dependencies
if: runner.os == 'Linux'
uses: ./.github/actions/install-linux-deps
with:
extra_packages: libevent-dev libncurses-dev
- name: Build pinned tmux release
if: runner.os == 'Linux'
shell: bash
env:
TMUX_VERSION: ${{ matrix.tmux }}
run: |
archive="$RUNNER_TEMP/tmux-$TMUX_VERSION.tar.gz"
curl --fail --location --retry 3 \
"https://github.com/tmux/tmux/releases/download/$TMUX_VERSION/tmux-$TMUX_VERSION.tar.gz" \
--output "$archive"
tar -xzf "$archive" -C "$RUNNER_TEMP"
cd "$RUNNER_TEMP/tmux-$TMUX_VERSION"
./configure --prefix="$RUNNER_TEMP/tmux-install"
make -j2
make install
echo "NYATERM_TEST_TMUX=$RUNNER_TEMP/tmux-install/bin/tmux" >> "$GITHUB_ENV"
- name: Locate macOS tmux
if: runner.os == 'macOS'
shell: bash
run: |
command -v tmux || brew install tmux
echo "NYATERM_TEST_TMUX=$(command -v tmux)" >> "$GITHUB_ENV"
- name: Test real Control Mode over SSH
shell: bash
run: |
"$NYATERM_TEST_TMUX" -V
cargo test -p nyaterm-transport --lib real_tmux --locked -- --ignored
plugin-sdk:
name: Plugin SDK
needs: [orchestrate]
if: needs.orchestrate.outputs.run_plugin_sdk == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Rust
uses: ./.github/actions/setup-rust
with:
components: rustfmt
targets: wasm32-unknown-unknown
cache-key: plugin-sdk
- name: Install Linux system dependencies
uses: ./.github/actions/install-linux-deps
- name: Check guest formatting
run: cargo fmt --manifest-path examples/plugins/guests/Cargo.toml --all -- --check
- name: Build SDK guests and test regenerated components
run: python scripts/plugins/build.py --fixtures --check
- name: Verify packaged SDK
run: cargo package --locked -p nyaterm-plugin-api --allow-dirty
python:
name: Release helpers
needs: [orchestrate]
if: needs.orchestrate.outputs.run_python == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
# Deliberately its own job: these need no Rust toolchain and no native
# libraries, so they should not queue behind a workspace build.
- name: Test packaging helpers
run: >-
python -m unittest
scripts.tests.test_check_release_assets
scripts.tests.test_package_native
scripts.tests.test_windows_msi
scripts.tests.test_verify_native_package
scripts.tests.test_generate_release_metadata
scripts.tests.test_bump_version
scripts.tests.test_release_provenance
scripts.tests.test_release_workflow
scripts.tests.test_check_architecture
workflows:
name: Workflow syntax
needs: [orchestrate]
if: needs.orchestrate.outputs.run_workflows == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Run actionlint
run: >-
docker run --rm
-v "${PWD}:/repo"
-w /repo
rhysd/actionlint:1.7.7
# Single always-reporting status check for branch protection. Passes when its
# dependencies succeeded or were skipped, fails when any failed or was cancelled.
gate:
name: Rust gate
runs-on: ubuntu-24.04
needs: [orchestrate, lint, test, tmux-compatibility, plugin-sdk, python, workflows]
if: always()
timeout-minutes: 5
steps:
- name: Check dependency results
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: exit 1