-
Notifications
You must be signed in to change notification settings - Fork 0
310 lines (271 loc) · 10.8 KB
/
Copy pathself-test.yml
File metadata and controls
310 lines (271 loc) · 10.8 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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
name: Self Test
on:
push:
branches:
- main
paths:
- action.yml
- README.md
- .github/workflows/self-test.yml
pull_request:
paths:
- action.yml
- README.md
- .github/workflows/self-test.yml
workflow_dispatch:
permissions:
contents: read
jobs:
integration:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
steps:
- name: Check out action source
uses: actions/checkout@v6
with:
path: action-src
- name: Credential helper returns x-access-token (unit)
shell: bash
run: |
set -euo pipefail
# The fixture below uses a local file-based remote that never invokes a
# credential helper, so this is the only place the HTTPS helper output is
# exercised directly. The helper string MUST stay byte-identical to the one
# configured by the 'Configure Git credential helper' step in action.yml.
export GIT_CONFIG_NOSYSTEM=1
export GIT_TERMINAL_PROMPT=0
TMP_CFG="$(mktemp)"
export GIT_CONFIG_GLOBAL="$TMP_CFG"
# The helper command is stored literally; $GITCOVERAGE_GIT_TOKEN is expanded
# by the helper at git-invocation time, not here.
# shellcheck disable=SC2016
git config --global 'credential.https://github.com.helper' \
'!f() { if test "$1" = get && test -n "${GITCOVERAGE_GIT_TOKEN}"; then echo "username=x-access-token"; echo "password=${GITCOVERAGE_GIT_TOKEN}"; fi; }; f'
# The token value must never be written into the config file.
if grep -q 'unit-test-token-123' "$TMP_CFG"; then
echo "token value leaked into git config" >&2
exit 1
fi
# Token present: helper returns x-access-token and the token as password.
# 'git credential fill' requires the trailing blank line; use printf for LF.
out="$(printf 'protocol=https\nhost=github.com\n\n' | env GITCOVERAGE_GIT_TOKEN=unit-test-token-123 git credential fill)"
printf '%s\n' "$out" | grep -q '^username=x-access-token$'
printf '%s\n' "$out" | grep -q '^password=unit-test-token-123$'
# Empty token: helper emits nothing, so no credentials are returned.
empty_out="$(printf 'protocol=https\nhost=github.com\n\n' | env GITCOVERAGE_GIT_TOKEN= git credential fill 2>/dev/null || true)"
if printf '%s\n' "$empty_out" | grep -q '^password='; then
echo "credential helper leaked a password with an empty token" >&2
exit 1
fi
rm -f "$TMP_CFG"
echo "credential helper unit test passed"
- name: Prepare local fixture repository
shell: bash
run: |
set -euo pipefail
git init --bare remote.git
git init .
git config user.email "ci@example.com"
git config user.name "CI"
git checkout -b main
mkdir -p reports
echo "initial" > reports/report.html
git add reports/report.html
git commit -m "init fixture"
git remote add origin "remote.git"
git push -u origin main
git tag v-test
git push origin v-test
# Branch used to verify Windows-only branch-name filtering.
# '=' is Git-valid but rejected by our Windows compatibility regex.
git branch 'feat=compat'
git push origin 'feat=compat'
# Branches used to verify exact remote branch checks.
git branch 'foo/coverage'
git push origin 'foo/coverage'
git branch 'only/partial'
git push origin 'only/partial'
# Detached/tag-only commit (not contained by any remote branch)
git checkout --detach
echo "detached-only" > detached-only.txt
git add detached-only.txt
git commit -m "detached tag fixture"
git tag v-detached
git push origin v-detached
git checkout main
# Simulate a dirty tracked file before the action runs
echo "dirty workspace" > reports/report.html
# Ensure explicit branch validation does not depend on local origin/* refs
git update-ref -d refs/remotes/origin/main || true
- name: Run action in pull request context (should skip)
id: pr_skip
uses: ./action-src
env:
GITCOVERAGE_EVENT_NAME: pull_request
GITCOVERAGE_PR_HEAD_REPO_FORK: "false"
with:
coverage: "99%"
branch: main
report: reports/report.html
- name: Run action with fork-head context (should skip)
id: fork_head_skip
uses: ./action-src
env:
GITCOVERAGE_EVENT_NAME: workflow_dispatch
GITCOVERAGE_PR_HEAD_REPO_FORK: "true"
with:
coverage: "98%"
branch: main
report: reports/report.html
- name: Verify pull request runs did not publish
shell: bash
run: |
set -euo pipefail
test "${{ steps.pr_skip.outputs.should-publish }}" = "false"
test "${{ steps.fork_head_skip.outputs.should-publish }}" = "false"
if git --git-dir=remote.git rev-parse --verify refs/heads/gitcoverage >/dev/null 2>&1; then
echo "pull request skip path created gitcoverage branch" >&2
exit 1
fi
echo "pull request skip path did not publish (verified)"
- name: Run action with explicit branch on dirty workspace
uses: ./action-src
with:
coverage: "81.2%"
branch: main
report: reports/report.html
run-on-pull-request: true
- name: Run action with Windows-restricted branch charset
id: windows_branch
continue-on-error: true
uses: ./action-src
with:
coverage: "80%"
branch: "feat=compat"
run-on-pull-request: true
- name: Verify Windows-only branch filter
shell: bash
run: |
set -euo pipefail
if [[ "${RUNNER_OS}" == "Windows" ]]; then
test "${{ steps.windows_branch.outcome }}" = "failure"
else
test "${{ steps.windows_branch.outcome }}" = "success"
fi
- name: Run action with partial branch-name match (should fail)
id: partial_branch
continue-on-error: true
uses: ./action-src
with:
coverage: "80%"
branch: "partial"
run-on-pull-request: true
- name: Verify partial branch-name match failed
shell: bash
run: |
set -euo pipefail
test "${{ steps.partial_branch.outcome }}" = "failure"
- name: Verify explicit branch run
shell: bash
run: |
set -euo pipefail
test "$(cat reports/report.html)" = "dirty workspace"
git --git-dir=remote.git rev-parse --verify refs/heads/gitcoverage >/dev/null
files="$(git --git-dir=remote.git ls-tree --name-only -r gitcoverage)"
echo "$files" | grep -Fx "main/badge.svg"
echo "$files" | grep -Fx "main/report.html"
- name: Verify no credential helper configured without token
shell: bash
run: |
set -euo pipefail
# The runs so far passed no 'token', so the action must not have registered
# a credential helper. Read the action's global config (the action exports
# GIT_CONFIG_GLOBAL via GITHUB_ENV when it uses an isolated config). Check the
# scoped key only, to tolerate any helper a runner may preconfigure.
SERVER_URL="${GITHUB_SERVER_URL:-https://github.com}"
SERVER_URL="${SERVER_URL%/}"
helpers="$(git config --global --get-all "credential.${SERVER_URL}.helper" || true)"
test -z "$helpers"
echo "no credential helper configured without token (verified)"
- name: Run action in tag-triggered mode
uses: ./action-src
env:
GITCOVERAGE_REF_TYPE: tag
GITCOVERAGE_REF_NAME: v-test
GITCOVERAGE_REF: refs/tags/v-test
GITCOVERAGE_HEAD_REF: ""
with:
coverage: "82%"
run-on-pull-request: true
- name: Verify tag-triggered run
shell: bash
run: |
set -euo pipefail
git clone remote.git verify >/dev/null 2>&1
pushd verify >/dev/null
git checkout gitcoverage
test -f main/badge.svg
test ! -f main/report.html
popd >/dev/null
- name: Run action for detached tag (should fail)
id: detached_tag
continue-on-error: true
uses: ./action-src
env:
GITCOVERAGE_REF_TYPE: tag
GITCOVERAGE_REF_NAME: v-detached
GITCOVERAGE_REF: refs/tags/v-detached
GITCOVERAGE_HEAD_REF: ""
with:
coverage: "77%"
run-on-pull-request: true
- name: Verify detached tag run failed
shell: bash
run: |
set -euo pipefail
test "${{ steps.detached_tag.outcome }}" = "failure"
- name: Run action with token (regression)
uses: ./action-src
with:
coverage: "75%"
branch: main
token: ${{ github.token }}
run-on-pull-request: true
- name: Verify credential helper cleared after token run
shell: bash
run: |
set -euo pipefail
# Pushes here target the local file remote, which never invokes the helper,
# so this proves the token input does not regress the push and that the
# always() cleanup removed the helper afterwards.
SERVER_URL="${GITHUB_SERVER_URL:-https://github.com}"
SERVER_URL="${SERVER_URL%/}"
helpers="$(git config --global --get-all "credential.${SERVER_URL}.helper" || true)"
test -z "$helpers"
echo "credential helper cleared after successful token run (verified)"
- name: Run action with token on invalid branch (should fail)
id: token_failure
continue-on-error: true
uses: ./action-src
with:
coverage: "70%"
branch: "partial"
token: ${{ github.token }}
run-on-pull-request: true
- name: Verify failed token run still cleared credential helper
shell: bash
run: |
set -euo pipefail
test "${{ steps.token_failure.outcome }}" = "failure"
# The always() cleanup must run even when an earlier step fails.
SERVER_URL="${GITHUB_SERVER_URL:-https://github.com}"
SERVER_URL="${SERVER_URL%/}"
helpers="$(git config --global --get-all "credential.${SERVER_URL}.helper" || true)"
test -z "$helpers"
echo "credential helper cleared after failed token run (verified)"