Repository navigation
152 lines (140 loc) · 6.14 KB
/
Copy pathtest-command.yml
File metadata and controls
152 lines (140 loc) · 6.14 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
name: Test command
on:
issue_comment:
types: [created]
permissions:
actions: write
checks: read
contents: read
issues: write
pull-requests: read
jobs:
dispatch:
if: ${{ github.event.issue.pull_request }}
runs-on: ubuntu-latest
steps:
- name: Check command
id: command
env:
BODY: ${{ github.event.comment.body }}
run: |
set -euo pipefail
if [[ "$BODY" != "/test" && "$BODY" != "/run-tests" ]]; then
echo "run=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "run=true" >> "$GITHUB_OUTPUT"
- name: Checkout command configuration
if: steps.command.outputs.run == 'true'
uses: actions/checkout@v4
with:
ref: main
persist-credentials: false
- name: Check maintainer authorization
if: steps.command.outputs.run == 'true'
env:
AUTHOR: ${{ github.event.comment.user.login }}
run: |
set -euo pipefail
if ! grep -Fxq "$AUTHOR" .github/test-command-maintainers; then
echo "::error::$AUTHOR is not authorized to run public contribution tests"
exit 1
fi
- name: Resolve pull request head
if: steps.command.outputs.run == 'true'
id: pr
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
set -euo pipefail
gh api "repos/$REPO/pulls/$PR_NUMBER" \
--jq '[.state, .base.ref, .head.repo.full_name, .head.sha] | @tsv' > "$RUNNER_TEMP/pr.tsv"
read -r state base_repo head_repo head_sha < "$RUNNER_TEMP/pr.tsv"
if [ "$state" != "open" ] || [ "$base_repo" != "main" ] || [ -z "$head_repo" ]; then
echo "::error::only open pull requests targeting main can be tested"
exit 1
fi
{
echo "head_repo=$head_repo"
echo "head_sha=$head_sha"
} >> "$GITHUB_OUTPUT"
- name: Reject commits pushed after the command
if: steps.command.outputs.run == 'true'
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
COMMENT_CREATED_AT: ${{ github.event.comment.created_at }}
run: |
set -euo pipefail
first_seen_at="$(gh api --paginate "repos/$REPO/commits/$HEAD_SHA/check-suites?per_page=100" \
--jq '.check_suites[].created_at' | sort | head -n1)"
if [ -z "$first_seen_at" ]; then
echo "::error::cannot verify when GitHub first saw commit $HEAD_SHA"
exit 1
fi
first_seen_epoch="$(jq -nr --arg timestamp "$first_seen_at" '$timestamp | fromdateiso8601')"
comment_epoch="$(jq -nr --arg timestamp "$COMMENT_CREATED_AT" '$timestamp | fromdateiso8601')"
if [ "$first_seen_epoch" -ge "$comment_epoch" ]; then
gh api "repos/$REPO/issues/$PR_NUMBER/comments" \
--field body="Tests were not dispatched because the current commit was pushed after the /test command. Review the latest changes and comment /test again."
echo "::error::commit $HEAD_SHA was first seen at $first_seen_at, not before the command at $COMMENT_CREATED_AT"
exit 1
fi
- name: Reject dependency changes
if: steps.command.outputs.run == 'true' && steps.pr.outputs.head_repo != github.repository
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
set -euo pipefail
dependency_files="$(gh api --paginate "repos/$REPO/pulls/$PR_NUMBER/files" \
--jq '.[] | select(.filename == "go.mod" or .filename == "go.sum") | .filename')"
if [ -n "$dependency_files" ]; then
gh api "repos/$REPO/issues/$PR_NUMBER/comments" \
--field body="Tests were not dispatched because public contributions cannot change go.mod or go.sum."
echo "::error::public contribution changes dependency files: $dependency_files"
exit 1
fi
- name: Dispatch tests
if: steps.command.outputs.run == 'true'
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
HEAD_REPO: ${{ steps.pr.outputs.head_repo }}
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
run: |
set -euo pipefail
current_head_sha="$(gh api "repos/$REPO/pulls/$PR_NUMBER" --jq '.head.sha')"
if [ "$current_head_sha" != "$HEAD_SHA" ]; then
gh api "repos/$REPO/issues/$PR_NUMBER/comments" \
--field body="Tests were not dispatched because the pull request changed after the /test command. Review the latest changes and comment /test again."
echo "::error::pull request head changed from $HEAD_SHA to $current_head_sha"
exit 1
fi
gh workflow run test.yml \
--repo "$REPO" \
--ref main \
--field pr_head_repo="$HEAD_REPO" \
--field pr_head_sha="$HEAD_SHA" \
--field pr_number="$PR_NUMBER"
- name: Report dispatch
if: steps.command.outputs.run == 'true'
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
run: |
set -euo pipefail
if ! response="$(gh api --include "repos/$REPO/issues/$PR_NUMBER/comments" \
--field body="Test workflow dispatched for commit ${HEAD_SHA:0:12}. Results: https://github.com/$REPO/actions/workflows/test.yml" 2>&1)"; then
echo "$response"
echo "::warning::tests were dispatched, but the confirmation comment could not be posted"
echo "Tests were dispatched for commit ${HEAD_SHA:0:12}, but the confirmation comment could not be posted." >> "$GITHUB_STEP_SUMMARY"
fi