1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
name: CI
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [master, windows]
paths-ignore:
- "website/**"
- ".github/APPROVED_CONTRIBUTORS"
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
conventional-commits:
if: github.event_name != 'push' || github.ref_name == 'master'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- name: Validate commit subjects
if: github.event_name == 'push'
run: python3 scripts/conventional_commits.py --range "${{ github.event.before }}..${{ github.event.after }}"
- name: Validate PR title
if: github.event_name == 'pull_request'
run: python3 scripts/conventional_commits.py "${{ github.event.pull_request.title }}"
check:
name: check (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
kind: unix
nextest_filter: all()
- os: macos-latest
kind: unix
nextest_filter: not binary(live_handoff)
- os: windows-latest
kind: windows
runs-on: ${{ matrix.os }}
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Install Rust
if: matrix.kind == 'unix'
uses: dtolnay/rust-toolchain@stable
- name: Install Rust
if: matrix.kind == 'windows'
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
- name: Install Rust tools
if: matrix.kind == 'unix'
uses: taiki-e/install-action@b550161ef8a7bc4f2a671c0b03a18ac9ccedea1e # v2
with:
tool: just,cargo-nextest
- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
with:
version: 0.15.2
- name: Install macOS build tools
if: runner.os == 'macOS'
run: brew install cmake ninja
- name: Restore cargo cache
uses: Swatinem/rust-cache@v2
with:
cache-bin: false
key: ${{ matrix.os }}
- name: Run checks
if: matrix.kind == 'unix'
run: just ci '${{ matrix.nextest_filter }}'
- name: Run Windows checks
if: matrix.kind == 'windows'
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
function Invoke-Checked {
param([string]$Command, [string[]]$Arguments)
& $Command @Arguments
if ($LASTEXITCODE -ne 0) {
throw "command failed with exit code $LASTEXITCODE`: $Command $($Arguments -join ' ')"
}
}
Invoke-Checked cargo @("fmt", "--check")
Invoke-Checked cargo @("clippy", "--bin", "herdr", "--locked", "--target", "x86_64-pc-windows-msvc", "--", "-D", "warnings")
Invoke-Checked cargo @("test", "--locked", "--target", "x86_64-pc-windows-msvc", "--bin", "herdr", "windows_")
Invoke-Checked cargo @("test", "--locked", "--target", "x86_64-pc-windows-msvc", "--bin", "herdr", "server::client_transport::tests")
Invoke-Checked cargo @("build", "--locked", "--target", "x86_64-pc-windows-msvc")
- name: Smoke ConPTY pane
if: matrix.kind == 'windows'
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$env:HERDR_SESSION = "ci-windows-$env:GITHUB_RUN_ID-$env:GITHUB_RUN_ATTEMPT"
$exe = Join-Path $PWD "target\x86_64-pc-windows-msvc\debug\herdr.exe"
& $exe --version
& $exe --default-config | Out-Null
$server = Start-Process -FilePath $exe -ArgumentList "server" -PassThru -WindowStyle Hidden
try {
$deadline = (Get-Date).AddSeconds(10)
do {
Start-Sleep -Milliseconds 250
$status = & $exe status server 2>&1
if ($LASTEXITCODE -eq 0 -and (($status -join "`n") -match "status: running")) {
break
}
} while ((Get-Date) -lt $deadline)
if ((Get-Date) -ge $deadline) {
throw "server did not become ready"
}
& $exe agent start smoke -- "$env:ComSpec" /K dir
Start-Sleep -Seconds 2
$read = & $exe agent read smoke --source recent --lines 40 --format text
$text = $read -join "`n"
if ($text -notmatch "File\(s\)" -or $text -notmatch "Dir\(s\)") {
throw "pane read did not include cmd.exe directory output: $text"
}
} finally {
& $exe server stop 2>$null
Wait-Process -Id $server.Id -Timeout 10 -ErrorAction SilentlyContinue
}
|