Skip to content

Commit 6ac802e

Browse files
wip
1 parent b28a8b9 commit 6ac802e

12 files changed

Lines changed: 239 additions & 140 deletions

File tree

.github/actions/test-check-labels/action.yml

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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+
token:
14+
description: 'GitHub token or PAT used to post comments (defaults to github.token)'
15+
required: false
16+
default: ''
17+
18+
runs:
19+
using: "composite"
20+
steps:
21+
- name: Check robot test labels
22+
uses: actions/github-script@v7
23+
with:
24+
github-token: ${{ inputs.token || github.token }}
25+
script: |
26+
const labelNeeded = '${{ inputs.label-test-robot-needed }}';
27+
const labelDone = '${{ inputs.label-test-robot-done }}';
28+
const { number: pr, head: { sha } } = context.payload.pull_request;
29+
const repo = context.repo;
30+
31+
const postComment = async (body) => {
32+
try {
33+
await github.rest.issues.createComment({ ...repo, issue_number: pr, body });
34+
} catch (err) {
35+
core.warning(`Could not post comment: ${err.message}`);
36+
}
37+
};
38+
39+
const { data: labels } = await github.rest.issues.listLabelsOnIssue({ ...repo, issue_number: pr });
40+
const has = new Set(labels.map(l => l.name));
41+
42+
if (!has.has(labelNeeded)) {
43+
core.info(`\`${labelNeeded}\` not present — no robot testing required.`);
44+
return;
45+
}
46+
47+
if (has.has(labelDone)) {
48+
core.info(`\`${labelDone}\` present — robot testing confirmed.`);
49+
return;
50+
}
51+
52+
const shaLine = sha ? `\n\n**Commit:** \`${sha}\`` : '';
53+
await postComment(
54+
`### ❌ Robot Testing Required\n\n` +
55+
`\`${labelNeeded}\` is present but \`${labelDone}\` has not been added. This PR cannot be merged until robot testing is complete.${shaLine}\n\n` +
56+
`> [!IMPORTANT]\n> Add \`${labelDone}\` once robot testing is complete.`
57+
);
58+
core.setFailed(`\`${labelNeeded}\` is present but \`${labelDone}\` has not been added — robot testing must be completed before merging.`);

.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 { number: pr, head: { sha } } = context.payload.pull_request;
29+
const repo = context.repo;
30+
31+
const postComment = async (body) => {
32+
try {
33+
await github.rest.issues.createComment({ ...repo, issue_number: pr, body });
34+
} catch (err) {
35+
core.warning(`Could not post comment: ${err.message}`);
36+
}
37+
};
38+
39+
const { data: labels } = await github.rest.issues.listLabelsOnIssue({ ...repo, issue_number: pr });
40+
const has = new Set(labels.map(l => l.name));
41+
const shaLine = sha ? `\n\n**Commit:** \`${sha}\`` : '';
42+
43+
if (!has.has(labelDone)) {
44+
if (has.has(labelNeeded)) {
45+
core.warning(`\`${labelDone}\` not found — \`${labelNeeded}\` is present but testing is not confirmed.`);
46+
await postComment(
47+
`### ⚠️ Robot Testing Incomplete\n\n` +
48+
`\`${labelNeeded}\` is present but \`${labelDone}\` has not been added yet.${shaLine}\n\n` +
49+
`> [!WARNING]\n> Add \`${labelDone}\` once robot testing is complete.`
50+
);
51+
} else {
52+
core.info(`\`${labelDone}\` not present — nothing to do.`);
53+
}
54+
return;
55+
}
56+
57+
core.info(`\`${labelDone}\` found — posting confirmation comment.`);
58+
await postComment(
59+
`### ✅ Robot Test Complete\n\n` +
60+
`\`${labelDone}\` has been added — robot testing has been confirmed for this PR.${shaLine}`
61+
);

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

Lines changed: 37 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,65 +19,40 @@ 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 { number: pr, head: { sha } } = context.payload.pull_request;
29+
const repo = context.repo;
30+
31+
const postComment = async (body) => {
32+
try {
33+
await github.rest.issues.createComment({ ...repo, issue_number: pr, body });
34+
} catch (err) {
35+
core.warning(`Could not post comment: ${err.message}`);
36+
}
37+
};
38+
39+
const { data: labels } = await github.rest.issues.listLabelsOnIssue({ ...repo, issue_number: pr });
40+
const has = new Set(labels.map(l => l.name));
41+
42+
if (!has.has(labelDone)) {
43+
core.info(`\`${labelDone}\` not present — nothing to do.`);
44+
return;
45+
}
46+
47+
await github.rest.issues.removeLabel({ ...repo, issue_number: pr, name: labelDone });
48+
core.info(`\`${labelDone}\` removed.`);
49+
50+
const shaLine = sha ? `\n\n**Commit:** \`${sha}\`` : '';
51+
const warning = !has.has(labelNeeded)
52+
? `\n\n> [!WARNING]\n> \`${labelDone}\` was removed but \`${labelNeeded}\` was not present — this PR may not be queued for robot testing.`
53+
: '';
54+
55+
await postComment(
56+
`### 🔄 Robot Test Label Removed\n\n` +
57+
`New commits were pushed. \`${labelDone}\` has been removed and robot testing must be repeated.${shaLine}${warning}`
58+
);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: PR
2+
3+
on:
4+
pull_request:
5+
types: [labeled]
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
cancel-in-progress: true
10+
11+
permissions:
12+
contents: read
13+
pull-requests: write
14+
15+
jobs:
16+
test-robot-label:
17+
if: github.event.label.name == 'test-robot-done'
18+
name: Job
19+
uses: ./.github/workflows/test-robot-label.yml
20+
with:
21+
label-test-robot-done: test-robot-done
22+
label-test-robot-needed: test-robot-needed
23+
24+
test-robot-check:
25+
needs: test-robot-label
26+
if: always() && needs.test-robot-label.result != 'failure'
27+
name: Job
28+
uses: ./.github/workflows/test-robot-check.yml
29+
with:
30+
label-test-robot-done: test-robot-done
31+
label-test-robot-needed: test-robot-needed
32+
33+
ensure-ci-success:
34+
needs: test-robot-check
35+
if: needs.test-robot-check.result != 'skipped'
36+
runs-on: ubuntu-latest
37+
steps:
38+
- name: Run Ensure CI Success
39+
uses: DataDog/ensure-ci-success@v2

.github/workflows/pull-request-test-robot-label.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

.github/workflows/pull-request.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,31 @@ jobs:
1717
test-robot-unlabel:
1818
if: github.event.action == 'synchronize'
1919
name: Job
20-
uses: ./.github/workflows/test-robot-unlabel.yaml
20+
uses: ./.github/workflows/test-robot-unlabel.yml
2121
with:
2222
label-test-robot-done: test-robot-done
2323
label-test-robot-needed: test-robot-needed
2424

25+
test-robot-check:
26+
needs: test-robot-unlabel
27+
if: always() && needs.test-robot-unlabel.result != 'failure'
28+
name: Job
29+
uses: ./.github/workflows/test-robot-check.yml
30+
with:
31+
label-test-robot-done: test-robot-done
32+
label-test-robot-needed: test-robot-needed
33+
34+
allchecks:
35+
needs: test-robot-check
36+
runs-on: ubuntu-latest
37+
name: Job
38+
steps:
39+
- uses: wechuli/allcheckspassed@v2
40+
with:
41+
poll: false
42+
2543
# build:
26-
# needs: test-robot-unlabel
44+
# needs: test-robot-check
2745
# if: always() && needs.test-robot-unlabel.result != 'failure'
2846
# name: Job
29-
# uses: ./.github/workflows/build.yaml
47+
# uses: ./.github/workflows/build.yml

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ permissions:
1919
jobs:
2020
build:
2121
name: Job
22-
uses: ./.github/workflows/build.yaml
22+
uses: ./.github/workflows/build.yml
2323

2424
promote:
2525
name: Job

0 commit comments

Comments
 (0)