name: wai key · Windows # What holds `wai key` on Windows, where no other job builds it: a seed made under an access list for # its account alone, refused when another account may read it, and `--key ` on the operations # that sign (wai-rs/src/bin/wai_cli/win_acl.rs, tests/cli_key.rs). It runs the binary's own tests and # tests/cli_toolchain.rs too, as they stand on that system. The Unix side is in wai-catalogue.yml, and # the macOS keychain in wai-key-keychain.yml, a workflow of its own so that a change here does not # start that runner. # # It runs on one thing alone: a change to a path below, in a pull request's own diff or in a push to # main. The forge's filter matches a push's delta, so a rebase can fire it; the gate (on Linux) reads # the pull request's own diff, and the Windows job does not start without it. On a push to main the # gate has no pull request to read and answers `true`, so the push's own filter decides: work lands # as direct commits to main. The paths are what decides the behaviour: # key.rs, win_acl.rs and the test; out.rs, which alone sends a private file through win_acl.rs; # conform/adapter.rs, whose cmd line for Windows only this job's tests run; and wai/.gitattributes, # which decides whether a checkout under core.autocrlf, as this runner's is, keeps the bytes of the # files the binary embeds or compares. Not wai-rs/Cargo.toml, which nearly every change to the crate # touches. # # Not a required status, as wai-byte-equality.yml's Windows leg is not. A job on an offline runner # stays pending and never settles. # A pull request's newer push supersedes its older run. A push to main does not: a cancelled run # would leave that push's change run on Windows by nothing, so each push to main takes its own group. concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }} cancel-in-progress: true on: push: branches: [main] paths: - 'wai/wai-rs/src/bin/wai_cli/dx/key.rs' - 'wai/wai-rs/src/bin/wai_cli/win_acl.rs' - 'wai/wai-rs/src/bin/wai_cli/out.rs' - 'wai/wai-rs/src/bin/wai_cli/dx/conform/adapter.rs' - 'wai/wai-rs/tests/cli_key.rs' - 'wai/.gitattributes' - '.github/workflows/wai-key-windows.yml' pull_request: paths: - 'wai/wai-rs/src/bin/wai_cli/dx/key.rs' - 'wai/wai-rs/src/bin/wai_cli/win_acl.rs' - 'wai/wai-rs/src/bin/wai_cli/out.rs' - 'wai/wai-rs/src/bin/wai_cli/dx/conform/adapter.rs' - 'wai/wai-rs/tests/cli_key.rs' - 'wai/.gitattributes' - '.github/workflows/wai-key-windows.yml' jobs: relevant: name: does this change touch it runs-on: gate outputs: run: ${{ steps.gate.outputs.run }} steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - id: gate run: | set -euo pipefail r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-key-windows.yml \ "${{ github.event.pull_request.base.sha }}" \ "${{ github.event.pull_request.head.sha }}") echo "this change touches wai key on Windows: $r" echo "run=$r" >> "$GITHUB_OUTPUT" tests: name: wai key and the toolchain's tests · windows needs: relevant if: needs.relevant.outputs.run == 'true' runs-on: windows timeout-minutes: 45 env: # The runner's host is shared with its other jobs, so a modest build, with no debug information: # a clean target of about 2 GiB, measured on that host. CARGO_BUILD_JOBS: '8' CARGO_PROFILE_DEV_DEBUG: '0' # The floor of the disk check below, in GiB: the checkout and that target, and room for the # jobs beside it. DISK_FLOOR_GIB: '8' steps: - uses: actions/checkout@v5 # Infrastructure first, so a full disk does not read as a failure of `wai key`. - name: "infrastructure: this runner's disk has room for the job" shell: pwsh run: | Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force $root = [System.IO.Path]::GetPathRoot($PWD.Path) $free = [System.IO.DriveInfo]::new($root).AvailableFreeSpace Write-Output "${root}: $([math]::Floor($free / 1GB)) GiB free" if ($free -lt ([int64]$env:DISK_FLOOR_GIB * 1GB)) { Write-Output "::error::infrastructure: $root has $([math]::Floor($free / 1GB)) GiB free, below the floor of $env:DISK_FLOOR_GIB GiB: not a failure of wai key" exit 1 } # The pin comes from rust-toolchain.toml; this makes sure it is there. The runner's user owns # rustup, and its default is left as it is for the host's other jobs. - name: Put cargo on PATH, and Rust 1.99.1 on the host shell: pwsh run: | $ErrorActionPreference = 'Stop' Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force $cargo = Join-Path $HOME '.cargo\bin' $cargo | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append $env:PATH = "$cargo;$env:PATH" $ErrorActionPreference = 'Continue' rustup toolchain install 1.99.1 --profile minimal if ($LASTEXITCODE -ne 0) { throw "rustup failed" } # What the access-list tests ran as. An elevated session's default owner differs from a limited # one's, so a result here says which it is about. - name: The account and token this job runs as shell: pwsh run: | Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force $id = [Security.Principal.WindowsIdentity]::GetCurrent() $admin = ([Security.Principal.WindowsPrincipal]$id).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) Write-Output "account $($id.Name), SID $($id.User.Value), elevated: $admin" - name: The tests shell: pwsh working-directory: wai/wai-rs run: | $ErrorActionPreference = 'Stop' Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force # As the release job does. Nothing here reads it, so the tests see what a person's shell gives. Remove-Item Env:CI -ErrorAction SilentlyContinue $log = Join-Path $env:RUNNER_TEMP 'test.log' # cargo writes its progress to stderr; the exit status is what counts. $ErrorActionPreference = 'Continue' cargo test --locked --no-default-features --features quickstart --bin wai --test cli_key --test cli_toolchain --no-fail-fast *> $log $rc = $LASTEXITCODE $ErrorActionPreference = 'Stop' Get-Content $log if ($rc -ne 0) { throw "the tests failed ($rc)" } $text = Get-Content $log -Raw if ($text -notmatch '(?m)^test result: ok\. [1-9][0-9]* passed; 0 failed') { throw "no test ran" } # What only this system compiles: each by name, so a change of cfg cannot leave it out. foreach ($t in @( 'access_lists::a_keystore_in_a_folder_every_user_shares_gets_what_one_in_a_profile_gets', 'access_lists::a_seed_another_account_may_read_signs_nothing_until_the_fix_it_names', 'access_lists::the_default_keystore_under_appdata_works_end_to_end', 'out::win_acl::tests::a_file_and_a_directory_are_this_accounts_from_their_creation', 'dx::conform::adapter::tests::cmd_gets_the_command_line_as_it_is_written' )) { if ($text -notmatch ('(?m)^test ' + [regex]::Escape($t) + ' \.\.\. ok\r?$')) { throw "the test $t did not run and pass" } } # The runner removes a stale workspace only after a day; this one's target goes now. - name: Free the target directory if: always() shell: pwsh run: | Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force Remove-Item -Recurse -Force wai\wai-rs\target -ErrorAction SilentlyContinue