-
Notifications
You must be signed in to change notification settings - Fork 0
224 lines (191 loc) · 8.26 KB
/
Copy pathe2e.yml
File metadata and controls
224 lines (191 loc) · 8.26 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
name: E2E
run-name: e2e ${{ inputs.correlation_id }}
on:
workflow_dispatch:
inputs:
action_sha:
description: "automated-codejson-generator commit to test"
required: true
type: string
pr_number:
description: "The pull request that commit came from"
required: true
type: string
correlation_id:
description: "Lets the caller find this run by name"
required: true
type: string
# One sandbox, so runs have to take turns or they fight over main and each other's
# pull requests. Queue instead of cancelling so cleanup always gets to finish.
concurrency:
group: e2e-sandbox
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
jobs:
e2e:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout sandbox
uses: actions/checkout@v4
- name: Checkout action under test
uses: actions/checkout@v4
with:
repository: DSACMS/automated-codejson-generator
ref: ${{ inputs.action_sha }}
path: .e2e-action
- name: Make the action's Dockerfile resolvable
run: |
# action.yml wants Dockerfile but the repo ships it lowercase, and a local
# action ref is case-sensitive about it.
if [ ! -f .e2e-action/Dockerfile ] && [ -f .e2e-action/dockerfile ]; then
cp .e2e-action/dockerfile .e2e-action/Dockerfile
fi
- name: Build the action image
run: docker build -t codejson-action .e2e-action
- name: Link back to the pull request
run: |
echo "Testing [PR #${{ inputs.pr_number }}](https://github.com/DSACMS/automated-codejson-generator/pull/${{ inputs.pr_number }}) at \`${{ inputs.action_sha }}\`" >> "$GITHUB_STEP_SUMMARY"
- name: Stage a valid code.json
run: cp e2e/fixtures/code.json.good code.json
- name: Validate the good code.json
run: |
# GITHUB_EVENT_NAME can't be set through uses:, so run the image ourselves
# to put the action in validation mode.
docker run --rm \
-e GITHUB_EVENT_NAME=pull_request \
-e GITHUB_ACTION=e2e \
-e INPUT_GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-v "${{ github.workspace }}:/github/workspace" \
codejson-action
- name: Stage a broken code.json
run: cp e2e/fixtures/code.json.broken code.json
- name: Validate the broken code.json
id: validate_broken
continue-on-error: true
run: |
docker run --rm \
-e GITHUB_EVENT_NAME=pull_request \
-e GITHUB_ACTION=e2e \
-e INPUT_GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-v "${{ github.workspace }}:/github/workspace" \
codejson-action
- name: Assert the broken code.json was rejected
run: |
set -euo pipefail
if [ "${{ steps.validate_broken.outcome }}" != "failure" ]; then
echo "::error::The action accepted a code.json that violates the schema."
exit 1
fi
echo "Rejected, as expected."
- name: Restore a valid code.json
run: cp e2e/fixtures/code.json.good code.json
- name: Generate and open a pull request
id: pr_mode
uses: ./.e2e-action
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: main
SKIP_PR: "false"
- name: Assert a pull request was opened
id: pr_assert
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ steps.pr_mode.outputs.pr_url }}
run: |
set -euo pipefail
# sendPR logs its failures and returns normally, so the action exits 0 even
# when it never opened anything. The output is the only real evidence.
if [ -z "${PR_URL:-}" ]; then
echo "::error::No pr_url output, so no pull request was opened."
exit 1
fi
PR_NUMBER="${PR_URL##*/}"
HEAD_REF=$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json headRefName --jq .headRefName)
echo "Opened $PR_URL from $HEAD_REF"
gh api "repos/${GITHUB_REPOSITORY}/contents/code.json?ref=${HEAD_REF}" --jq .content \
| base64 -d > code.json
- name: Assert the generated code.json looks right
run: |
set -euo pipefail
jq -e '.name == "codejson-action-e2e"' code.json > /dev/null
jq -e '.repositoryURL == "https://github.com/DSACMS/codejson-action-e2e"' code.json > /dev/null
jq -e '.laborHours > 0' code.json > /dev/null
jq -e '.date.metadataLastUpdated | length > 0' code.json > /dev/null
- name: Validate the generated code.json
run: |
docker run --rm \
-e GITHUB_EVENT_NAME=pull_request \
-e GITHUB_ACTION=e2e \
-e INPUT_GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-v "${{ github.workspace }}:/github/workspace" \
codejson-action
- name: Restore a valid code.json
run: cp e2e/fixtures/code.json.good code.json
- name: Generate and push straight to main
id: push_mode
uses: ./.e2e-action
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Only needs write access to this repo, which the job token already has.
ADMIN_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: main
SKIP_PR: "true"
- name: Assert the commit landed on main
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
METHOD: ${{ steps.push_mode.outputs.method_used }}
COMMIT_SHA: ${{ steps.push_mode.outputs.commit_sha }}
run: |
set -euo pipefail
# pushDirectlyWithFallback quietly opens a pull request when the push fails,
# so exiting 0 doesn't mean anything landed on main.
if [ "${METHOD:-}" != "direct_push" ]; then
echo "::error::Expected a direct push, got '${METHOD:-<none>}'."
exit 1
fi
gh api "repos/${GITHUB_REPOSITORY}/contents/code.json?ref=main" --jq .content \
| base64 -d > code.json
MAIN_SHA=$(gh api "repos/${GITHUB_REPOSITORY}/commits/main" --jq .sha)
if [ "$MAIN_SHA" != "$COMMIT_SHA" ]; then
echo "::error::main is at ${MAIN_SHA}, but the action reported ${COMMIT_SHA}."
exit 1
fi
echo "Pushed ${COMMIT_SHA} to main."
- name: Validate the pushed code.json
run: |
docker run --rm \
-e GITHUB_EVENT_NAME=pull_request \
-e GITHUB_ACTION=e2e \
-e INPUT_GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-v "${{ github.workspace }}:/github/workspace" \
codejson-action
- name: Reset the sandbox
if: always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# No -e here. Every reset should be attempted even if an earlier one fails.
set -uo pipefail
# Sweep by pattern rather than tracking what this run made, so a run that
# died halfway through still gets cleaned up by the next one.
for BRANCH in $(gh api "repos/${GITHUB_REPOSITORY}/branches?per_page=100" --jq '.[].name' | grep '^code-json-'); do
PR_NUMBER=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -n "$PR_NUMBER" ]; then
gh pr close "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --comment "Closing e2e artifact."
fi
gh api -X DELETE "repos/${GITHUB_REPOSITORY}/git/refs/heads/${BRANCH}"
echo "Removed $BRANCH"
done
BASELINE=$(cat e2e/fixtures/code.json.good)
CURRENT=$(gh api "repos/${GITHUB_REPOSITORY}/contents/code.json?ref=main" --jq .content | base64 -d)
if [ "$BASELINE" != "$CURRENT" ]; then
gh api -X PUT "repos/${GITHUB_REPOSITORY}/contents/code.json" \
-f message="Reset sandbox code.json after e2e" \
-f content="$(base64 -w0 e2e/fixtures/code.json.good)" \
-f branch=main \
-f sha="$(gh api "repos/${GITHUB_REPOSITORY}/contents/code.json?ref=main" --jq .sha)"
echo "Reset code.json on main"
fi