Skip to content

Commit cb9fa56

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

2 files changed

Lines changed: 92 additions & 150 deletions

File tree

Lines changed: 36 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,46 @@
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]
7+
8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.event.workflow_run.id }}
10+
cancel-in-progress: true
3211

3312
jobs:
34-
add-labels:
35-
concurrency:
36-
group: sync-issue-labels-pr-${{ github.event.inputs.pr_number }}
37-
cancel-in-progress: true
13+
apply:
14+
if: github.event.workflow_run.conclusion == 'success'
3815
runs-on: ubuntu-latest
16+
permissions:
17+
pull-requests: write
18+
3919
steps:
40-
- name: Harden the runner
41-
uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
42-
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
20+
- name: Download Artifact
21+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
4922
with:
50-
name: pr-labels-${{ github.event.inputs.pr_number }}
51-
path: artifacts
52-
run-id: ${{ github.event.inputs.upstream_run_id }}
23+
name: pr-labels-data
24+
run-id: ${{ github.event.workflow_run.id }}
5325
github-token: ${{ secrets.GITHUB_TOKEN }}
5426

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
27+
- name: Apply Labels
28+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
12629
with:
127-
github_token: ${{ secrets.GITHUB_TOKEN }}
128-
labels: ${{ steps.read.outputs.labels_multiline }}
129-
number: ${{ steps.read.outputs.pr_number }}
30+
script: |
31+
const fs = require('fs');
32+
if (!fs.existsSync('labels.json')) {
33+
console.log("No payload file found. Nothing to apply.");
34+
return;
35+
}
36+
37+
const data = JSON.parse(fs.readFileSync('labels.json', 'utf8'));
38+
console.log(`Applying labels to PR #${data.pr_number}: ${data.labels.join(', ')}`);
39+
40+
await github.rest.issues.addLabels({
41+
owner: context.repo.owner,
42+
repo: context.repo.repo,
43+
issue_number: data.pr_number,
44+
labels: data.labels
45+
});
46+
console.log("Successfully applied labels!");
Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,41 @@
1-
name: Sync Linked Issue Labels
1+
name: Sync Linked Issue Labels - Compute
22

33
on:
44
pull_request:
55
types: [opened, edited, reopened, synchronize]
66

77
permissions:
8-
pull-requests: write
98
issues: read
109
contents: read
1110

11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
13+
cancel-in-progress: true
14+
1215
jobs:
1316
sync:
1417
runs-on: ubuntu-latest
1518
steps:
1619
- name: Harden Runner
17-
uses: step-security/harden-runner@v2
20+
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
1821
with:
1922
egress-policy: audit
2023

21-
- name: Compute and Apply Labels
22-
uses: actions/github-script@v7
24+
- name: Compute Labels
25+
id: compute
26+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
2327
with:
24-
github-token: ${{ secrets.GITHUB_TOKEN }}
2528
script: |
2629
const prNumber = context.payload.pull_request.number;
27-
30+
console.log(`--- Processing PR #${prNumber} ---`);
31+
2832
const { data: prData } = await github.rest.pulls.get({
29-
owner: context.repo.owner,
30-
repo: context.repo.repo,
31-
pull_number: prNumber
33+
owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber
3234
});
3335
3436
const prAuthor = prData.user.login;
3537
if (/\[bot\]$/i.test(prAuthor) || /dependabot/i.test(prAuthor)) {
36-
console.log("Skipping bot PR.");
38+
console.log(`Skipping bot-authored PR (Author: ${prAuthor})`);
3739
return;
3840
}
3941
@@ -45,37 +47,60 @@ jobs:
4547
}
4648
4749
if (issueNumbers.size === 0) {
48-
console.log("No linked issues found.");
50+
console.log("No linked issues found in the PR description.");
4951
return;
5052
}
5153
52-
const labelsToAdd = new Set();
54+
console.log(`Detected linked issues: #${Array.from(issueNumbers).join(', #')}`);
55+
56+
const discoveredLabels = new Set();
5357
for (const num of issueNumbers) {
5458
try {
5559
const { data: issue } = await github.rest.issues.get({
56-
owner: context.repo.owner,
57-
repo: context.repo.repo,
58-
issue_number: num
60+
owner: context.repo.owner, repo: context.repo.repo, issue_number: num
5961
});
60-
6162
if (!issue.pull_request) {
62-
issue.labels.forEach(l => labelsToAdd.add(typeof l === 'string' ? l : l.name));
63+
const names = (issue.labels || []).map(l => typeof l === 'string' ? l : l.name);
64+
console.log(`Found labels on issue #${num}: [${names.join(', ')}]`);
65+
names.forEach(l => discoveredLabels.add(l));
66+
} else {
67+
console.log(`Skipping #${num} because it is a Pull Request, not an Issue.`);
6368
}
64-
} catch (e) {
65-
console.log(`Could not fetch labels for issue #${num}`);
69+
} catch (e) {
70+
console.log(`Error fetching labels for issue #${num}: ${e.message}`);
6671
}
6772
}
6873
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-
});
74+
const currentLabels = (prData.labels || []).map(l => typeof l === 'string' ? l : l.name);
75+
console.log(`Current PR labels: [${currentLabels.join(', ')}]`);
76+
77+
const newLabels = Array.from(discoveredLabels).filter(label => !currentLabels.includes(label));
78+
79+
if (newLabels.length > 0) {
80+
console.log(`New labels to be added: [${newLabels.join(', ')}]`);
7981
} else {
80-
console.log("No labels discovered from linked issues.");
82+
console.log("No new labels discovered (all found labels are already present).");
8183
}
84+
85+
const fs = require('fs');
86+
const result = { pr_number: prNumber, labels: newLabels };
87+
fs.writeFileSync('labels.json', JSON.stringify(result));
88+
console.log(`Calculated labels: ${newLabels.join(', ')}`);
89+
90+
- name: Check for Labels File
91+
id: check_file
92+
run: |
93+
if [ -f labels.json ]; then
94+
echo "exists=true" >> $GITHUB_OUTPUT
95+
else
96+
echo "exists=false" >> $GITHUB_OUTPUT
97+
fi
98+
99+
- name: Upload Artifact
100+
if: steps.check_file.outputs.exists == 'true'
101+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
102+
if: success()
103+
with:
104+
name: pr-labels-data
105+
path: labels.json
106+
retention-days: 1

0 commit comments

Comments
 (0)