Skip to content

Commit 8e0fe49

Browse files
Copilotpranaygp
andauthored
Extract inline GitHub Action scripts to separate files (#494)
* Initial plan * Extract inline scripts to separate files Co-authored-by: pranaygp <[email protected]> * Fix indentation in create-ci-pr.js Co-authored-by: pranaygp <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: pranaygp <[email protected]>
1 parent ad93a6f commit 8e0fe49

File tree

5 files changed

+113
-97
lines changed

5 files changed

+113
-97
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = async ({ github, context }) => {
2+
try {
3+
const permission = await github.rest.repos.getCollaboratorPermissionLevel({
4+
owner: context.repo.owner,
5+
repo: context.repo.repo,
6+
username: context.actor
7+
});
8+
9+
const hasPermission = ['admin', 'write'].includes(permission.data.permission);
10+
console.log(`User ${context.actor} has permission: ${permission.data.permission}`);
11+
return hasPermission ? 'true' : 'false';
12+
} catch (error) {
13+
console.error('Error checking permissions:', error);
14+
return 'false';
15+
}
16+
};

.github/scripts/create-ci-pr.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
module.exports = async ({ github, context, core, exec }, prDetails) => {
2+
const timestamp = new Date().getTime();
3+
const ciBranchName = `ci-test/${prDetails.number}-${timestamp}`;
4+
5+
// Add remote for the external fork if it's from a fork
6+
if (prDetails.head_repo_full_name !== `${context.repo.owner}/${context.repo.repo}`) {
7+
await exec.exec('git', ['remote', 'add', 'external', `https://github.com/${prDetails.head_repo_full_name}.git`]);
8+
await exec.exec('git', ['fetch', 'external', prDetails.head_ref]);
9+
await exec.exec('git', ['checkout', '-b', ciBranchName, `external/${prDetails.head_ref}`]);
10+
} else {
11+
await exec.exec('git', ['fetch', 'origin', prDetails.head_ref]);
12+
await exec.exec('git', ['checkout', '-b', ciBranchName, `origin/${prDetails.head_ref}`]);
13+
}
14+
15+
// Push the new branch to origin
16+
await exec.exec('git', ['push', 'origin', ciBranchName]);
17+
18+
// Create a draft PR
19+
const newPR = await github.rest.pulls.create({
20+
owner: context.repo.owner,
21+
repo: context.repo.repo,
22+
title: `[CI Test] ${prDetails.title}`,
23+
head: ciBranchName,
24+
base: prDetails.base_ref,
25+
body: `🤖 **Automated CI Test PR**
26+
27+
This is an automated PR created to run CI tests for PR #${prDetails.number} by @${prDetails.user}.
28+
29+
**Original PR:** #${prDetails.number}
30+
**Triggered by:** @${context.actor}
31+
**Source branch:** \`${prDetails.head_ref}\`
32+
**Source SHA:** \`${prDetails.head_sha}\`
33+
34+
⚠️ **This PR will be automatically closed once CI completes.** Do not merge this PR.
35+
36+
---
37+
_This PR was created in response to the \`/run-ci\` command in #${prDetails.number}_`,
38+
draft: true
39+
});
40+
41+
// Comment on the original PR
42+
await github.rest.issues.createComment({
43+
owner: context.repo.owner,
44+
repo: context.repo.repo,
45+
issue_number: context.issue.number,
46+
body: `✅ CI test triggered by @${context.actor}!
47+
48+
CI is now running in draft PR #${newPR.data.number}. You can monitor the progress there.
49+
50+
Once the tests complete, you can review the results and the draft PR will be automatically closed.`
51+
});
52+
53+
// Add label to the new PR
54+
await github.rest.issues.addLabels({
55+
owner: context.repo.owner,
56+
repo: context.repo.repo,
57+
issue_number: newPR.data.number,
58+
labels: ['ci-test', 'automated']
59+
});
60+
61+
core.setOutput('ci_pr_number', newPR.data.number);
62+
core.setOutput('ci_branch_name', ciBranchName);
63+
};

.github/scripts/get-pr-details.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = async ({ github, context }) => {
2+
const pr = await github.rest.pulls.get({
3+
owner: context.repo.owner,
4+
repo: context.repo.repo,
5+
pull_number: context.issue.number
6+
});
7+
8+
return {
9+
head_ref: pr.data.head.ref,
10+
head_sha: pr.data.head.sha,
11+
head_repo_full_name: pr.data.head.repo.full_name,
12+
base_ref: pr.data.base.ref,
13+
title: pr.data.title,
14+
number: pr.data.number,
15+
user: pr.data.user.login
16+
};
17+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = async ({ github, context, core }) => {
2+
await github.rest.issues.createComment({
3+
owner: context.repo.owner,
4+
repo: context.repo.repo,
5+
issue_number: context.issue.number,
6+
body: '❌ Only repository admins and maintainers can trigger CI runs. You have insufficient permissions.'
7+
});
8+
core.setFailed('Insufficient permissions to trigger CI');
9+
};

.github/workflows/trigger-ci.yml

Lines changed: 8 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,17 @@ jobs:
2424
github-token: ${{ secrets.GITHUB_TOKEN }}
2525
result-encoding: string
2626
script: |
27-
try {
28-
const permission = await github.rest.repos.getCollaboratorPermissionLevel({
29-
owner: context.repo.owner,
30-
repo: context.repo.repo,
31-
username: context.actor
32-
});
33-
34-
const hasPermission = ['admin', 'write'].includes(permission.data.permission);
35-
console.log(`User ${context.actor} has permission: ${permission.data.permission}`);
36-
return hasPermission ? 'true' : 'false';
37-
} catch (error) {
38-
console.error('Error checking permissions:', error);
39-
return 'false';
40-
}
27+
const script = require('./.github/scripts/check-permissions.js');
28+
return await script({ github, context });
4129
4230
- name: Exit if unauthorized
4331
if: steps.check-permissions.outputs.result != 'true'
4432
uses: actions/github-script@v7
4533
with:
4634
github-token: ${{ secrets.GITHUB_TOKEN }}
4735
script: |
48-
await github.rest.issues.createComment({
49-
owner: context.repo.owner,
50-
repo: context.repo.repo,
51-
issue_number: context.issue.number,
52-
body: '❌ Only repository admins and maintainers can trigger CI runs. You have insufficient permissions.'
53-
});
54-
core.setFailed('Insufficient permissions to trigger CI');
36+
const script = require('./.github/scripts/post-unauthorized-comment.js');
37+
await script({ github, context, core });
5538
5639
- name: Get PR details
5740
if: steps.check-permissions.outputs.result == 'true'
@@ -60,21 +43,8 @@ jobs:
6043
with:
6144
github-token: ${{ secrets.GITHUB_TOKEN }}
6245
script: |
63-
const pr = await github.rest.pulls.get({
64-
owner: context.repo.owner,
65-
repo: context.repo.repo,
66-
pull_number: context.issue.number
67-
});
68-
69-
return {
70-
head_ref: pr.data.head.ref,
71-
head_sha: pr.data.head.sha,
72-
head_repo_full_name: pr.data.head.repo.full_name,
73-
base_ref: pr.data.base.ref,
74-
title: pr.data.title,
75-
number: pr.data.number,
76-
user: pr.data.user.login
77-
};
46+
const script = require('./.github/scripts/get-pr-details.js');
47+
return await script({ github, context });
7848
7949
- name: Checkout repo
8050
if: steps.check-permissions.outputs.result == 'true'
@@ -88,66 +58,7 @@ jobs:
8858
with:
8959
github-token: ${{ secrets.GITHUB_TOKEN }}
9060
script: |
61+
const script = require('./.github/scripts/create-ci-pr.js');
9162
const prDetails = ${{ steps.pr-details.outputs.result }};
92-
const timestamp = new Date().getTime();
93-
const ciBranchName = `ci-test/${prDetails.number}-${timestamp}`;
94-
95-
// Add remote for the external fork if it's from a fork
96-
if (prDetails.head_repo_full_name !== `${context.repo.owner}/${context.repo.repo}`) {
97-
await exec.exec('git', ['remote', 'add', 'external', `https://github.com/${prDetails.head_repo_full_name}.git`]);
98-
await exec.exec('git', ['fetch', 'external', prDetails.head_ref]);
99-
await exec.exec('git', ['checkout', '-b', ciBranchName, `external/${prDetails.head_ref}`]);
100-
} else {
101-
await exec.exec('git', ['fetch', 'origin', prDetails.head_ref]);
102-
await exec.exec('git', ['checkout', '-b', ciBranchName, `origin/${prDetails.head_ref}`]);
103-
}
104-
105-
// Push the new branch to origin
106-
await exec.exec('git', ['push', 'origin', ciBranchName]);
107-
108-
// Create a draft PR
109-
const newPR = await github.rest.pulls.create({
110-
owner: context.repo.owner,
111-
repo: context.repo.repo,
112-
title: `[CI Test] ${prDetails.title}`,
113-
head: ciBranchName,
114-
base: prDetails.base_ref,
115-
body: `🤖 **Automated CI Test PR**
116-
117-
This is an automated PR created to run CI tests for PR #${prDetails.number} by @${prDetails.user}.
118-
119-
**Original PR:** #${prDetails.number}
120-
**Triggered by:** @${context.actor}
121-
**Source branch:** \`${prDetails.head_ref}\`
122-
**Source SHA:** \`${prDetails.head_sha}\`
123-
124-
⚠️ **This PR will be automatically closed once CI completes.** Do not merge this PR.
125-
126-
---
127-
_This PR was created in response to the \`/run-ci\` command in #${prDetails.number}_`,
128-
draft: true
129-
});
130-
131-
// Comment on the original PR
132-
await github.rest.issues.createComment({
133-
owner: context.repo.owner,
134-
repo: context.repo.repo,
135-
issue_number: context.issue.number,
136-
body: `✅ CI test triggered by @${context.actor}!
137-
138-
CI is now running in draft PR #${newPR.data.number}. You can monitor the progress there.
139-
140-
Once the tests complete, you can review the results and the draft PR will be automatically closed.`
141-
});
142-
143-
// Add label to the new PR
144-
await github.rest.issues.addLabels({
145-
owner: context.repo.owner,
146-
repo: context.repo.repo,
147-
issue_number: newPR.data.number,
148-
labels: ['ci-test', 'automated']
149-
});
150-
151-
core.setOutput('ci_pr_number', newPR.data.number);
152-
core.setOutput('ci_branch_name', ciBranchName);
63+
await script({ github, context, core, exec }, prDetails);
15364

0 commit comments

Comments
 (0)