Skip to content

Commit a7f58bf

Browse files
committed
chore: improve script
Signed-off-by: Manish Dait <daitmanish88@gmail.com>
1 parent 7f745d8 commit a7f58bf

2 files changed

Lines changed: 87 additions & 148 deletions

File tree

Lines changed: 32 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,42 @@
1-
name: Add Linked Issue Labels to PR
1+
name: Sync Linked Issue Labels - Apply
22

33
on:
4-
workflow_dispatch:
5-
inputs:
6-
upstream_run_id:
7-
description: "Upstream compute workflow run ID"
8-
required: true
9-
type: string
10-
pr_number:
11-
description: "Pull request number"
12-
required: true
13-
type: string
14-
dry_run:
15-
description: "Dry run flag"
16-
required: false
17-
type: string
18-
default: "true"
19-
is_fork_pr:
20-
description: "Fork PR flag"
21-
required: false
22-
type: string
23-
default: "false"
24-
defaults:
25-
run:
26-
shell: bash
27-
permissions:
28-
actions: read
29-
issues: write
30-
contents: read
31-
pull-requests: write
4+
workflow_run:
5+
workflows: ["Sync Linked Issue Labels - Compute"]
6+
types: [completed]
327

338
jobs:
34-
add-labels:
35-
concurrency:
36-
group: sync-issue-labels-pr-${{ github.event.inputs.pr_number }}
37-
cancel-in-progress: true
9+
apply:
10+
if: github.event.workflow_run.conclusion == 'success'
3811
runs-on: ubuntu-latest
12+
permissions:
13+
pull-requests: write
14+
3915
steps:
40-
- name: Harden the runner
41-
uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
16+
- name: Download Artifact
17+
uses: actions/download-artifact@v4
4218
with:
43-
egress-policy: audit
44-
45-
- name: Download labels artifact
46-
id: download
47-
continue-on-error: true
48-
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
49-
with:
50-
name: pr-labels-${{ github.event.inputs.pr_number }}
51-
path: artifacts
52-
run-id: ${{ github.event.inputs.upstream_run_id }}
19+
name: pr-labels-${{ github.event.workflow_run.pull_requests[0].number }}
20+
run-id: ${{ github.event.workflow_run.id }}
5321
github-token: ${{ secrets.GITHUB_TOKEN }}
5422

55-
- name: Read labels payload
56-
id: read
57-
env:
58-
INPUT_PR_NUMBER: ${{ github.event.inputs.pr_number }}
59-
INPUT_IS_FORK_PR: ${{ github.event.inputs.is_fork_pr }}
60-
INPUT_DRY_RUN: ${{ github.event.inputs.dry_run }}
61-
run: |
62-
labels_file="artifacts/labels.json"
63-
if [ ! -f "$labels_file" ]; then
64-
echo "::error::Labels artifact not found. Cross-workflow handoff is broken."
65-
echo "labels=[]" >> "$GITHUB_OUTPUT"
66-
echo "labels_count=0" >> "$GITHUB_OUTPUT"
67-
echo "labels_multiline=" >> "$GITHUB_OUTPUT"
68-
echo "pr_number=$INPUT_PR_NUMBER" >> "$GITHUB_OUTPUT"
69-
echo "is_fork_pr=$INPUT_IS_FORK_PR" >> "$GITHUB_OUTPUT"
70-
echo "dry_run=$INPUT_DRY_RUN" >> "$GITHUB_OUTPUT"
71-
echo "source_event=workflow_dispatch" >> "$GITHUB_OUTPUT"
72-
exit 1
73-
fi
74-
labels=$(jq -c '.labels // []' "$labels_file")
75-
pr_number=$(jq -r '.pr_number // 0' "$labels_file")
76-
is_fork_pr=$(jq -r '.is_fork_pr // false' "$labels_file")
77-
dry_run=$(jq -r '.dry_run // "true"' "$labels_file")
78-
source_event=$(jq -r '.source_event // ""' "$labels_file")
79-
labels_multiline=$(jq -r '.labels // [] | .[]' "$labels_file")
80-
labels_count=$(echo "$labels" | jq 'length')
81-
echo "labels=$labels" >> "$GITHUB_OUTPUT"
82-
echo "labels_count=$labels_count" >> "$GITHUB_OUTPUT"
83-
{
84-
echo "labels_multiline<<EOF"
85-
echo "$labels_multiline"
86-
echo "EOF"
87-
} >> "$GITHUB_OUTPUT"
88-
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
89-
echo "is_fork_pr=$is_fork_pr" >> "$GITHUB_OUTPUT"
90-
echo "dry_run=$dry_run" >> "$GITHUB_OUTPUT"
91-
echo "source_event=$source_event" >> "$GITHUB_OUTPUT"
92-
93-
- name: Validate labels payload
94-
id: validate
95-
run: |
96-
if [ "$PR_NUMBER" = "0" ] || [ "$(echo "$LABELS" | jq -r '. | length')" = "0" ]; then
97-
echo "Invalid payload: pr_number=$PR_NUMBER or labels empty. Skipping label addition."
98-
echo "valid_payload=false" >> "$GITHUB_OUTPUT"
99-
else
100-
echo "valid_payload=true" >> "$GITHUB_OUTPUT"
101-
fi
102-
env:
103-
PR_NUMBER: ${{ steps.read.outputs.pr_number }}
104-
LABELS: ${{ steps.read.outputs.labels }}
105-
106-
- name: Determine if labels should be applied
107-
id: should_apply
108-
run: |
109-
if [ "${{ steps.read.outputs.is_fork_pr }}" = "true" ]; then
110-
echo "apply=false" >> "$GITHUB_OUTPUT"
111-
echo "reason=fork PR" >> "$GITHUB_OUTPUT"
112-
elif [ "${{ steps.validate.outputs.valid_payload }}" != "true" ]; then
113-
echo "apply=false" >> "$GITHUB_OUTPUT"
114-
echo "reason=invalid payload" >> "$GITHUB_OUTPUT"
115-
elif [ "${{ steps.read.outputs.source_event }}" = "workflow_dispatch" ] && [ "${{ steps.read.outputs.dry_run }}" = "true" ]; then
116-
echo "apply=false" >> "$GITHUB_OUTPUT"
117-
echo "reason=dry run" >> "$GITHUB_OUTPUT"
118-
else
119-
echo "apply=true" >> "$GITHUB_OUTPUT"
120-
echo "reason=" >> "$GITHUB_OUTPUT"
121-
fi
122-
123-
- name: Add labels to PR
124-
if: ${{ steps.should_apply.outputs.apply == 'true' }}
125-
uses: actions-ecosystem/action-add-labels@1a9c3715c0037e96b97bb38cb4c4b56a1f1d4871 # main
23+
- name: Apply Labels
24+
uses: actions/github-script@v7
12625
with:
127-
github_token: ${{ secrets.GITHUB_TOKEN }}
128-
labels: ${{ steps.read.outputs.labels_multiline }}
129-
number: ${{ steps.read.outputs.pr_number }}
26+
script: |
27+
const fs = require('fs');
28+
if (!fs.existsSync('labels_payload.json')) {
29+
console.log("No payload file found. Nothing to apply.");
30+
return;
31+
}
32+
33+
const data = JSON.parse(fs.readFileSync('labels_payload.json', 'utf8'));
34+
console.log(`Applying labels to PR #${data.pr_number}: ${data.labels.join(', ')}`);
35+
36+
await github.rest.issues.addLabels({
37+
owner: context.repo.owner,
38+
repo: context.repo.repo,
39+
issue_number: data.pr_number,
40+
labels: data.labels
41+
});
42+
console.log("Successfully applied labels!");

.github/workflows/sync-issue-labels-compute.yml

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,26 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- name: Harden Runner
17-
uses: step-security/harden-runner@v2
17+
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
1818
with:
1919
egress-policy: audit
2020

21-
- name: Compute and Apply Labels
22-
uses: actions/github-script@v7
21+
- name: Compute Labels
22+
id: compute
23+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
2324
with:
24-
github-token: ${{ secrets.GITHUB_TOKEN }}
2525
script: |
2626
const prNumber = context.payload.pull_request.number;
27-
27+
console.log(`--- Processing PR #${prNumber} ---`);
28+
2829
const { data: prData } = await github.rest.pulls.get({
29-
owner: context.repo.owner,
30-
repo: context.repo.repo,
31-
pull_number: prNumber
30+
owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber
3231
});
3332
3433
const prAuthor = prData.user.login;
3534
if (/\[bot\]$/i.test(prAuthor) || /dependabot/i.test(prAuthor)) {
36-
console.log("Skipping bot PR.");
35+
console.log(`Skipping bot-authored PR (Author: ${prAuthor})`);
36+
core.setOutput('skip', 'true');
3737
return;
3838
}
3939
@@ -45,37 +45,63 @@ jobs:
4545
}
4646
4747
if (issueNumbers.size === 0) {
48-
console.log("No linked issues found.");
48+
console.log("No linked issues found in the PR description.");
49+
core.setOutput('has_new_labels', 'false');
50+
core.setOutput('skip', 'false');
4951
return;
5052
}
53+
console.log(`Detected linked issues: #${Array.from(issueNumbers).join(', #')}`);
5154
52-
const labelsToAdd = new Set();
55+
const discoveredLabels = new Set();
5356
for (const num of issueNumbers) {
5457
try {
5558
const { data: issue } = await github.rest.issues.get({
56-
owner: context.repo.owner,
57-
repo: context.repo.repo,
58-
issue_number: num
59+
owner: context.repo.owner, repo: context.repo.repo, issue_number: num
5960
});
60-
6161
if (!issue.pull_request) {
62-
issue.labels.forEach(l => labelsToAdd.add(typeof l === 'string' ? l : l.name));
62+
const names = (issue.labels || []).map(l => typeof l === 'string' ? l : l.name);
63+
console.log(`Found labels on issue #${num}: [${names.join(', ')}]`);
64+
names.forEach(l => discoveredLabels.add(l));
65+
} else {
66+
console.log(`Skipping #${num} because it is a Pull Request, not an Issue.`);
6367
}
64-
} catch (e) {
65-
console.log(`Could not fetch labels for issue #${num}`);
68+
} catch (e) {
69+
console.log(`Error fetching labels for issue #${num}: ${e.message}`);
6670
}
6771
}
6872
69-
if (labelsToAdd.size > 0) {
70-
const labelList = Array.from(labelsToAdd);
71-
console.log(`Adding labels: ${labelList.join(', ')}`);
72-
73-
await github.rest.issues.addLabels({
74-
owner: context.repo.owner,
75-
repo: context.repo.repo,
76-
issue_number: prNumber,
77-
labels: labelList
78-
});
73+
const currentLabels = (prData.labels || []).map(l => typeof l === 'string' ? l : l.name);
74+
console.log(`Current PR labels: [${currentLabels.join(', ')}]`);
75+
76+
const newLabels = Array.from(discoveredLabels).filter(label => !currentLabels.includes(label));
77+
78+
if (newLabels.length > 0) {
79+
console.log(`New labels to be added: [${newLabels.join(', ')}]`);
7980
} else {
80-
console.log("No labels discovered from linked issues.");
81+
console.log("No new labels discovered (all found labels are already present).");
8182
}
83+
84+
core.setOutput('labels', JSON.stringify(newLabels));
85+
core.setOutput('has_new_labels', newLabels.length > 0 ? 'true' : 'false');
86+
core.setOutput('skip', 'false');
87+
88+
const fs = require('fs');
89+
const result = { pr_number: prNumber, labels: newLabels };
90+
fs.writeFileSync('labels.json', JSON.stringify(result));
91+
console.log(`Calculated labels: ${newLabels.join(', ')}`);
92+
93+
- name: Upload Artifact
94+
run: |
95+
if [ -f labels.json ]; then
96+
echo "Labels found, uploading..."
97+
else
98+
echo "No labels to upload."
99+
exit 0
100+
fi
101+
102+
- uses: actions/upload-artifact@v4
103+
if: success()
104+
with:
105+
name: pr-labels-${{ github.event.pull_request.number }}
106+
path: labels.json
107+
retention-days: 1

0 commit comments

Comments
 (0)