Skip to content

Commit 4da764b

Browse files
wip
1 parent 0bb76bc commit 4da764b

5 files changed

Lines changed: 162 additions & 115 deletions

File tree

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,37 @@
1-
# General: "test-robot-needed" and "test-robot-done" should be the default values of two inputs.
2-
# 1. It should check if "test-robot-needed" label is present.
3-
# 2. It should check if "test-robot-done" label is present.
4-
# 3. If "test-robot-needed" is present and "test-robot-done" is not present, it should fail with an error message saying "PR needs robot testing but is not marked as test-robot-done."
1+
name: "Robot Test Check Labels"
2+
description: "Fails if test-robot-needed is present but test-robot-done is not."
3+
4+
inputs:
5+
label-test-robot-needed:
6+
description: 'Label indicating the PR needs robot testing'
7+
required: false
8+
default: 'test-robot-needed'
9+
label-test-robot-done:
10+
description: 'Label indicating the PR has been robot-tested'
11+
required: false
12+
default: 'test-robot-done'
13+
14+
runs:
15+
using: "composite"
16+
steps:
17+
- name: Check robot test labels
18+
uses: actions/github-script@v7
19+
with:
20+
script: |
21+
const labelNeeded = '${{ inputs.label-test-robot-needed }}';
22+
const labelDone = '${{ inputs.label-test-robot-done }}';
23+
const pr = context.payload.pull_request.number;
24+
25+
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
26+
...context.repo,
27+
issue_number: pr,
28+
});
29+
const labelNames = new Set(currentLabels.map(l => l.name));
30+
31+
if (labelNames.has(labelNeeded) && !labelNames.has(labelDone)) {
32+
core.setFailed(
33+
`PR requires robot testing but is missing the expected label.\n` +
34+
` Expected label : \`${labelDone}\`\n` +
35+
` Reason : \`${labelNeeded}\` is present — robot testing must be completed and the PR marked with \`${labelDone}\` before merging.`
36+
);
37+
}

.github/actions/test-robot-label/action.yml

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ name: "Robot Test Label"
22
description: "When the test-robot-done label is added, posts a comment confirming the robot test status."
33

44
inputs:
5+
label-test-robot-needed:
6+
description: 'Label indicating the PR needs robot testing'
7+
required: false
8+
default: 'test-robot-needed'
59
label-test-robot-done:
610
description: 'Label indicating the PR has been robot-tested'
711
required: false
@@ -15,52 +19,43 @@ runs:
1519
using: "composite"
1620
steps:
1721
- name: Comment on label added
18-
shell: python3 {0}
19-
env:
20-
GH_TOKEN: ${{ inputs.token || github.token }}
21-
PR_NUMBER: ${{ github.event.pull_request.number }}
22-
REPO: ${{ github.repository }}
23-
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
24-
LABEL_DONE: ${{ inputs.label-test-robot-done }}
25-
run: |
26-
import os, json, sys, urllib.request, urllib.error
27-
28-
token = os.environ['GH_TOKEN']
29-
repo = os.environ['REPO']
30-
pr = os.environ['PR_NUMBER']
31-
sha = os.environ.get('COMMIT_SHA', '').strip()
32-
label = os.environ['LABEL_DONE']
33-
34-
headers = {
35-
'Authorization': f'Bearer {token}',
36-
'Accept': 'application/vnd.github+json',
37-
'X-GitHub-Api-Version': '2022-11-28',
38-
'Content-Type': 'application/json',
39-
}
40-
41-
def gh(method, path, body=None):
42-
req = urllib.request.Request(
43-
f'https://api.github.com{path}',
44-
data=json.dumps(body).encode() if body else None,
45-
headers=headers,
46-
method=method,
47-
)
48-
try:
49-
with urllib.request.urlopen(req) as r:
50-
return json.loads(r.read())
51-
except urllib.error.HTTPError as e:
52-
print(f'GitHub API error {e.code}: {e.read().decode()}', file=sys.stderr)
53-
sys.exit(1)
54-
55-
labels = {l['name'] for l in gh('GET', f'/repos/{repo}/issues/{pr}/labels')}
56-
57-
if label not in labels:
58-
print(f'Label `{label}` not found — nothing to do.')
59-
sys.exit(0)
60-
61-
sha_line = f'\n**Commit:** `{sha}`' if sha else ''
62-
body = (
63-
f'### \u2705 Robot Test Complete\n\n'
64-
f'This PR has been marked `{label}`, confirming robot testing has passed.{sha_line}'
65-
)
66-
gh('POST', f'/repos/{repo}/issues/{pr}/comments', {'body': body})
22+
uses: actions/github-script@v7
23+
with:
24+
github-token: ${{ inputs.token || github.token }}
25+
script: |
26+
const labelDone = '${{ inputs.label-test-robot-done }}';
27+
const labelNeeded = '${{ inputs.label-test-robot-needed }}';
28+
const pr = context.payload.pull_request.number;
29+
const sha = context.payload.pull_request.head.sha;
30+
31+
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
32+
...context.repo,
33+
issue_number: pr,
34+
});
35+
const labelNames = new Set(currentLabels.map(l => l.name));
36+
37+
if (!labelNames.has(labelDone)) {
38+
if (labelNames.has(labelNeeded)) {
39+
const shaLine = sha ? `\n**Commit:** \`${sha}\`` : '';
40+
await github.rest.issues.createComment({
41+
...context.repo,
42+
issue_number: pr,
43+
body:
44+
`### ⚠️ Robot Testing Incomplete\n\n` +
45+
`\`${labelNeeded}\` is present but \`${labelDone}\` has not been added — ` +
46+
`this PR has not been confirmed as robot-tested.${shaLine}`,
47+
});
48+
} else {
49+
core.info(`Label \`${labelDone}\` not found — nothing to do.`);
50+
}
51+
return;
52+
}
53+
54+
const shaLine = sha ? `\n**Commit:** \`${sha}\`` : '';
55+
await github.rest.issues.createComment({
56+
...context.repo,
57+
issue_number: pr,
58+
body:
59+
`### ✅ Robot Test Complete\n\n` +
60+
`This PR has been marked \`${labelDone}\`, confirming robot testing has passed.${shaLine}`,
61+
});

.github/actions/test-robot-unlabel/action.yml

Lines changed: 40 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,65 +19,43 @@ runs:
1919
using: "composite"
2020
steps:
2121
- name: Remove label and comment
22-
shell: python3 {0}
23-
env:
24-
GH_TOKEN: ${{ inputs.token || github.token }}
25-
PR_NUMBER: ${{ github.event.pull_request.number }}
26-
REPO: ${{ github.repository }}
27-
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
28-
LABEL_DONE: ${{ inputs.label-test-robot-done }}
29-
LABEL_NEEDED: ${{ inputs.label-test-robot-needed }}
30-
run: |
31-
import os, json, sys, urllib.request, urllib.error, urllib.parse
32-
33-
token = os.environ['GH_TOKEN']
34-
repo = os.environ['REPO']
35-
pr = os.environ['PR_NUMBER']
36-
sha = os.environ.get('COMMIT_SHA', '').strip()
37-
label_done = os.environ['LABEL_DONE']
38-
label_needed = os.environ['LABEL_NEEDED']
39-
40-
headers = {
41-
'Authorization': f'Bearer {token}',
42-
'Accept': 'application/vnd.github+json',
43-
'X-GitHub-Api-Version': '2022-11-28',
44-
'Content-Type': 'application/json',
45-
}
46-
47-
def gh(method, path, body=None):
48-
req = urllib.request.Request(
49-
f'https://api.github.com{path}',
50-
data=json.dumps(body).encode() if body else None,
51-
headers=headers,
52-
method=method,
53-
)
54-
try:
55-
with urllib.request.urlopen(req) as r:
56-
content = r.read()
57-
return json.loads(content) if content else None
58-
except urllib.error.HTTPError as e:
59-
print(f'GitHub API error {e.code}: {e.read().decode()}', file=sys.stderr)
60-
sys.exit(1)
61-
62-
labels = {l['name'] for l in gh('GET', f'/repos/{repo}/issues/{pr}/labels')}
63-
64-
if label_done not in labels:
65-
print(f'Label `{label_done}` not present — nothing to do.')
66-
sys.exit(0)
67-
68-
safe_label = urllib.parse.quote(label_done, safe='')
69-
gh('DELETE', f'/repos/{repo}/issues/{pr}/labels/{safe_label}')
70-
71-
sha_line = f'\n**Commit:** `{sha}`' if sha else ''
72-
warning = (
73-
f'\n\n> [!WARNING]\n'
74-
f'> `{label_done}` was removed but `{label_needed}` was not present —'
75-
f' this PR may not be queued for robot testing.'
76-
) if label_needed not in labels else ''
77-
78-
body = (
79-
f'### 🔄 Robot Test Label Removed\n\n'
80-
f'`{label_done}` has been removed due to new commits pushed to this PR.{sha_line}'
81-
f'{warning}'
82-
)
83-
gh('POST', f'/repos/{repo}/issues/{pr}/comments', {'body': body})
22+
uses: actions/github-script@v7
23+
with:
24+
github-token: ${{ inputs.token || github.token }}
25+
script: |
26+
const labelDone = '${{ inputs.label-test-robot-done }}';
27+
const labelNeeded = '${{ inputs.label-test-robot-needed }}';
28+
const pr = context.payload.pull_request.number;
29+
const sha = context.payload.pull_request.head.sha;
30+
31+
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
32+
...context.repo,
33+
issue_number: pr,
34+
});
35+
const labelNames = new Set(currentLabels.map(l => l.name));
36+
37+
if (!labelNames.has(labelDone)) {
38+
core.info(`Label \`${labelDone}\` not present — nothing to do.`);
39+
return;
40+
}
41+
42+
await github.rest.issues.removeLabel({
43+
...context.repo,
44+
issue_number: pr,
45+
name: labelDone,
46+
});
47+
48+
const shaLine = sha ? `\n**Commit:** \`${sha}\`` : '';
49+
const warning = !labelNames.has(labelNeeded)
50+
? `\n\n> [!WARNING]\n` +
51+
`> \`${labelDone}\` was removed but \`${labelNeeded}\` was not present — ` +
52+
`this PR may not be queued for robot testing.`
53+
: '';
54+
55+
await github.rest.issues.createComment({
56+
...context.repo,
57+
issue_number: pr,
58+
body:
59+
`### 🔄 Robot Test Label Removed\n\n` +
60+
`\`${labelDone}\` has been removed due to new commits pushed to this PR.${shaLine}${warning}`,
61+
});

.github/workflows/pull-request.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ jobs:
2222
label-test-robot-done: test-robot-done
2323
label-test-robot-needed: test-robot-needed
2424

25+
test-robot-check-labels:
26+
needs: test-robot-unlabel
27+
if: always() && needs.test-robot-unlabel.result != 'failure'
28+
name: Job
29+
uses: ./.github/workflows/test-robot-check-labels.yaml
30+
with:
31+
label-test-robot-done: test-robot-done
32+
label-test-robot-needed: test-robot-needed
33+
2534
# build:
2635
# needs: test-robot-unlabel
2736
# if: always() && needs.test-robot-unlabel.result != 'failure'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Robot Test Check Labels
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
label-test-robot-done:
7+
description: 'Label name indicating the PR has been test-robot-done'
8+
type: string
9+
required: false
10+
default: 'test-robot-done'
11+
label-test-robot-needed:
12+
description: 'Label name indicating the PR needs robot testing'
13+
type: string
14+
required: false
15+
default: 'test-robot-needed'
16+
17+
permissions:
18+
contents: read
19+
pull-requests: read
20+
21+
jobs:
22+
test-robot-check-labels:
23+
name: Robot Test Check Labels
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: Check Robot Test Labels
29+
uses: ./.github/actions/test-check-labels
30+
with:
31+
label-test-robot-done: ${{ inputs.label-test-robot-done }}
32+
label-test-robot-needed: ${{ inputs.label-test-robot-needed }}

0 commit comments

Comments
 (0)