-
Notifications
You must be signed in to change notification settings - Fork 1
210 lines (180 loc) · 8.36 KB
/
Copy pathci.yml
File metadata and controls
210 lines (180 loc) · 8.36 KB
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
name: CI
on:
push:
branches: [master]
pull_request:
workflow_dispatch:
# A second push to the same branch makes the first run's answer stale, and a real-tmux suite is too
# expensive to keep running for an answer nobody will read.
# Cancel a superseded run only on a pull request, where a new push genuinely replaces the answer.
# On master every commit's run stands on its own: grouping them all together meant re-running an
# older commit cancelled the newest one, which is the opposite of what a green history needs.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
whitespace:
name: git diff --check (pull request base)
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
# Trailing whitespace and a blank line at EOF are invisible in the rendered diff GitHub shows
# in review. This is the same check `git apply --whitespace=warn` runs, against exactly what
# the pull request changes rather than the whole tree.
- name: No trailing whitespace or blank line at EOF
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: git diff --check "$BASE_SHA...$HEAD_SHA"
check:
name: check (JDK ${{ matrix.java }})
runs-on: ubuntu-latest
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
# 25 is the baseline the library compiles against; the newest GA feature release is here
# because a library is run on JDKs its author never chose, and the ones that break it break
# at runtime.
java: ['25', '27']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Install tmux
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y tmux
tmux -V
# Gradle itself runs on the baseline in every lane: its plugins, the formatter among them,
# reach into javac internals a newer JDK is free to change. The lane's JDK runs the tests.
- uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6
with:
distribution: temurin
java-version: |
${{ matrix.java }}
25
- uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6
with:
# The wrapper jar is a binary this repository executes, so its checksum is verified against
# the ones Gradle published rather than trusted because it is committed here.
validate-wrappers: true
# A venv keeps tmuxp off HOME: `pip install --user` lands there, and the
# tests that need it replace HOME.
- name: Install the optional workspace Python test runtime
run: |
python3 -m venv "$RUNNER_TEMP/workspace-python"
"$RUNNER_TEMP/workspace-python/bin/python" -m pip install 'tmuxp==1.74.0'
echo "TMUX_WORKSPACE_TEST_PYTHON=$RUNNER_TEMP/workspace-python/bin/python" >> "$GITHUB_ENV"
# Runs every check task instead of stopping at the first failure, so one run names them all.
- run: ./gradlew :libtmux-mcp:test check --stacktrace --continue -Plibtmux.testJdk=${{ matrix.java }}
# A real-tmux suite that leaves servers running would be invisible here and expensive on a
# developer's machine. The runner is discarded either way, so this is the only place the
# question gets asked for free.
- name: No tmux server outlived the suite
if: always()
run: |
if pids="$(pgrep tmux)"; then
echo "::error::tmux processes survived the suite"
for pid in $pids; do ps -o command= -p "$pid" || true; done
exit 1
else
status=$?
if [ "$status" -ne 1 ]; then exit "$status"; fi
fi
echo "no tmux server survived the suite"
- name: Publish to a local repository
run: ./gradlew publishToMavenLocal --stacktrace
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: failure()
with:
name: reports-jdk${{ matrix.java }}
path: '**/build/reports/**'
retention-days: 7
# A release without the upload: the version a tag would publish, signed by a key made for this run,
# checked against what the Central Portal refuses, then resolved by builds of their own that see
# only those coordinates (module-tests/README.md). Nothing leaves the runner and no secret is read.
rehearse-release:
name: release rehearsal
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Install tmux
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y tmux
- uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6
with:
distribution: temurin
java-version: '25'
- uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6
with:
validate-wrappers: true
- name: Work out the version a release would publish
run: |
version="$(sed -n 's/^libtmuxVersion=//p' gradle.properties)"
echo "VERSION=${version%-SNAPSHOT}" >> "$GITHUB_ENV"
- name: Make a signing key for this run
run: |
gpg --batch --pinentry-mode loopback --passphrase '' \
--quick-gen-key 'libtmux release rehearsal <rehearsal@invalid>' rsa3072 sign 1d
# The key reaches Gradle for this step only, so no log header prints it.
- name: Stage the release
run: |
ORG_GRADLE_PROJECT_signingInMemoryKey="$(gpg --armor --export-secret-keys)" \
./gradlew publishAllPublicationsToStagingRepository -PlibtmuxVersion="$VERSION" --stacktrace
- name: The staged release is what Central accepts
run: tools/verify-staged-release.sh "$VERSION"
- name: Builds of their own resolve the staged release
run: |
./gradlew -p module-tests/java run --stacktrace -PlibtmuxVersion="$VERSION"
./gradlew -p module-tests/kotlin run --stacktrace -PlibtmuxVersion="$VERSION"
./gradlew -p module-tests/scala run --stacktrace -PlibtmuxVersion="$VERSION"
module-tests/sbt/sbtw -Dlibtmux.version="$VERSION" core/run cats/run ox/run direct/run
./gradlew -p module-tests/cli run --stacktrace -PlibtmuxVersion="$VERSION"
check-macos:
name: check (macOS)
runs-on: macos-latest
timeout-minutes: 20
# Reported, never gating: hosted macOS runners fail this lane for reasons of their own too often
# for its result to decide a merge or a release. Its failures still show in the run.
continue-on-error: true
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Install tmux and Bash
run: |
brew install tmux bash
echo "$(brew --prefix bash)/bin" >> "$GITHUB_PATH"
tmux -V
- uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6
with:
distribution: temurin
java-version: '25'
- uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6
with:
validate-wrappers: true
# Runs every check task instead of stopping at the first failure, so one run names them all.
- run: ./gradlew :libtmux-mcp:test check --stacktrace --continue
- name: No tmux server outlived the suite
if: always()
run: |
if pids="$(pgrep tmux)"; then
echo "::error::tmux processes survived the suite"
for pid in $pids; do ps -o command= -p "$pid" || true; done
exit 1
else
status=$?
if [ "$status" -ne 1 ]; then exit "$status"; fi
fi
echo "no tmux server survived the suite"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: failure()
with:
name: reports-macos
path: '**/build/reports/**'
retention-days: 7