Skip to content

Commit dc6ce44

Browse files
authored
Separate out github-scripts to external files (#187)
1 parent 9e8a101 commit dc6ce44

9 files changed

+206
-155
lines changed

action.yml

Lines changed: 21 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,8 @@ runs:
6161
with:
6262
retries: 3
6363
script: |
64-
const { data: get_pull_request } = await github.rest.pulls.get({
65-
owner: context.repo.owner,
66-
pull_number: context.issue.number,
67-
repo: context.repo.repo,
68-
});
69-
const add_pending_status = await github.rest.repos.createCommitStatus({
70-
context: "${{ github.workflow }}",
71-
owner: context.repo.owner,
72-
repo: context.repo.repo,
73-
sha: get_pull_request.head.sha,
74-
state: "pending",
75-
target_url: "${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }}",
76-
});
77-
return {
78-
sha: get_pull_request.head.sha
79-
};
64+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/add_commit_status.js`);
65+
await script({ github, context, core });
8066
8167
# For subsequent commits on the PR branch, automatically re-run the most
8268
# recently added "-tf=plan" comment instead of manually re-triggering it.
@@ -87,45 +73,30 @@ runs:
8773
with:
8874
retries: 3
8975
script: |
90-
const { data: list_comments } = await github.rest.issues.listComments({
91-
issue_number: context.issue.number,
92-
owner: context.repo.owner,
93-
per_page: 100,
94-
repo: context.repo.repo,
95-
});
96-
const get_comment = list_comments
97-
.sort((a, b) => b.id - a.id)
98-
.find((comment) => /^-tf=plan/.test(comment.body));
99-
return {
100-
body: get_comment.body,
101-
id: get_comment.id,
102-
};
76+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/find_comment.js`);
77+
await script({ github, context, core });
10378
10479
# Add PR comment reaction to indicate that the workflow is running.
10580
- name: Add reaction
10681
id: reaction
10782
if: steps.comment.outcome == 'success' || steps.commit.outcome == 'success'
10883
env:
109-
comment_id: ${{ github.event.comment.id || fromJSON(steps.comment.outputs.result)['id'] }}
84+
comment_id: ${{ github.event.comment.id || steps.comment.outputs.id }}
11085
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
11186
with:
11287
result-encoding: string
11388
retries: 3
11489
script: |
115-
return (await github.rest.reactions.createForIssueComment({
116-
comment_id: process.env.comment_id,
117-
content: "eyes",
118-
owner: context.repo.owner,
119-
repo: context.repo.repo,
120-
})).data.id;
90+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/add_reaction.js`);
91+
await script({ github, context, core });
12192
12293
# Split and trim the PR comment, then parse it as an array of objects.
12394
# E.g., {tf:apply, chdir:path/to/dir, auto-approve:true}.
12495
- name: Parse command
12596
id: command
12697
if: steps.comment.outcome == 'success' || steps.commit.outcome == 'success'
12798
env:
128-
comment_body: ${{ github.event.comment.body || fromJSON(steps.comment.outputs.result)['body'] }}
99+
comment_body: ${{ github.event.comment.body || steps.comment.outputs.body }}
129100
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
130101
with:
131102
retries: 3
@@ -158,19 +129,8 @@ runs:
158129
with:
159130
retries: 3
160131
script: |
161-
const add_label = await github.rest.issues.addLabels({
162-
issue_number: context.issue.number,
163-
labels: ["tf:${{ fromJSON(steps.command.outputs.result)['tf'] }}"],
164-
owner: context.repo.owner,
165-
repo: context.repo.repo,
166-
});
167-
const update_label = await github.rest.issues.updateLabel({
168-
color: "${{ inputs.cli_uses == 'tofu' && 'FFDA18' || '5C4EE5' }}",
169-
description: "Pull requests that ${{ fromJSON(steps.command.outputs.result)['tf'] }} TF code",
170-
name: "tf:${{ fromJSON(steps.command.outputs.result)['tf'] }}",
171-
owner: context.repo.owner,
172-
repo: context.repo.repo,
173-
});
132+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/add_pr_label.js`);
133+
await script({ github, context, label: "${{ fromJSON(steps.command.outputs.result)['tf'] }}", cli_uses: "${{ inputs.cli_uses }}" });
174134
175135
# If apply_require_approval is set to "true", then verify that the PR
176136
# review state is approved. If not, then exit the workflow with a failure.
@@ -180,15 +140,8 @@ runs:
180140
with:
181141
retries: 3
182142
script: |
183-
const { data: list_reviews } = await github.rest.pulls.listReviews({
184-
owner: context.repo.owner,
185-
pull_number: context.issue.number,
186-
repo: context.repo.repo,
187-
});
188-
if (list_reviews.at(-1)
189-
?.state !== "APPROVED") {
190-
core.setFailed("PR review approval is required when apply_require_approval is set to true.");
191-
}
143+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/check_pr_approval.js`);
144+
await script({ github, context, core });
192145
193146
- name: Setup Terraform
194147
if: inputs.cli_uses == 'terraform' || inputs.cli_uses == ''
@@ -346,25 +299,14 @@ runs:
346299
result-encoding: string
347300
retries: 3
348301
script: |
349-
const { data: list_artifacts } = await github.rest.actions.listArtifactsForRepo({
350-
name: "${{ steps.arguments.outputs.tf_plan_id }}",
351-
owner: context.repo.owner,
352-
per_page: 100,
353-
repo: context.repo.repo,
354-
});
355-
const download_artifact = await github.rest.actions.downloadArtifact({
356-
archive_format: "zip",
357-
artifact_id: list_artifacts.artifacts[0].id,
358-
owner: context.repo.owner,
359-
repo: context.repo.repo,
360-
});
361-
return download_artifact.url;
302+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/get_tf_plan_file.js`);
303+
await script({ github, context, core, tf_plan_id: "${{ steps.arguments.outputs.tf_plan_id }}" });
362304
363305
# Download and unzip the TF plan file to the specified working directory.
364306
- name: Download and unzip TF plan file
365307
if: fromJSON(steps.command.outputs.result)['tf'] == 'apply' && fromJSON(steps.command.outputs.result)['auto-approve'] == ''
366308
shell: bash
367-
run: wget -O "${{ steps.arguments.outputs.tf_plan_id }}" "${{ steps.artifact_url.outputs.result }}" && unzip "${{ steps.arguments.outputs.tf_plan_id }}" -d "${{ steps.arguments.outputs.tf_cwd }}"
309+
run: wget -O "${{ steps.arguments.outputs.tf_plan_id }}" "${{ steps.artifact_url.outputs.link }}" && unzip "${{ steps.arguments.outputs.tf_plan_id }}" -d "${{ steps.arguments.outputs.tf_cwd }}"
368310

369311
- name: TF apply
370312
id: apply
@@ -409,8 +351,8 @@ runs:
409351
- name: Comment TF output
410352
if: ${{ (success() || failure()) && steps.render.outcome == 'success' }}
411353
env:
412-
comment_id: ${{ github.event.comment.id || fromJSON(steps.comment.outputs.result)['id'] }}
413-
reaction_id: ${{ steps.reaction.outputs.result }}
354+
comment_id: ${{ github.event.comment.id || steps.comment.outputs.id }}
355+
reaction_id: ${{ steps.reaction.outputs.id }}
414356
tf_command: ${{ steps.command.outputs.result }}
415357
tf_fmt: ${{ steps.render.outputs.tf_fmt }}
416358
tf_output: ${{ steps.render.outputs.tf_output }}
@@ -419,78 +361,8 @@ runs:
419361
with:
420362
retries: 3
421363
script: |
422-
// Display latest TF change summary as the output header.
423-
const comment_summary = process.env.tf_output
424-
.split("\n")
425-
.reverse()
426-
.find((line) => /^(Apply|Plan|Error|No changes)/.test(line)) ||
427-
"View TF result…";
428-
429-
// Display truncated TF fmt diff, if present.
430-
const comment_fmt = process.env.tf_fmt ?
431-
`<details><summary>Diff of format changes.</summary>
432-
433-
\`\`\`diff
434-
${process.env.tf_fmt}
435-
\`\`\`
436-
</details>` :
437-
"";
438-
439-
// Display the: TF command, TF output, and workflow authorship.
440-
// Include the TFPLAN name in a hidden footer as a unique identifier.
441-
const comment_body = `
442-
\`${process.env.tf_command}\`
443-
${comment_fmt}
444-
<details><summary>${comment_summary}</br>
445-
446-
###### ${{ github.workflow }} by @${{ github.actor }} via [${{ github.event_name }}](${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }}) at ${{ github.event.pull_request.updated_at || github.event.comment.updated_at }}.</summary>
447-
448-
\`\`\`hcl
449-
${process.env.tf_output}
450-
\`\`\`
451-
</details>
452-
<!-- ${process.env.tf_plan_id} -->`;
453-
454-
// Check if the bot has commented on the PR using the TFPLAN identifier.
455-
const { data: list_comments } = await github.rest.issues.listComments({
456-
issue_number: context.issue.number,
457-
owner: context.repo.owner,
458-
per_page: 100,
459-
repo: context.repo.repo,
460-
});
461-
const bot_comment = list_comments.find((comment) => {
462-
return (
463-
comment.user.type === "Bot" &&
464-
comment.body.includes(`<!-- ${process.env.tf_plan_id} -->`)
465-
);
466-
});
467-
468-
// Delete PR comment reaction to indicate that the workflow has ended.
469-
const delete_reaction = await github.rest.reactions.deleteForIssueComment({
470-
comment_id: process.env.comment_id,
471-
owner: context.repo.owner,
472-
reaction_id: process.env.reaction_id,
473-
repo: context.repo.repo,
474-
});
475-
476-
// If a bot comment exists with a matching TFPLAN identifier, then update
477-
// the comment, otherwise create a new comment. This prevents the bot
478-
// from creating a new comment on every run of this workflow.
479-
if (bot_comment) {
480-
await github.rest.issues.updateComment({
481-
body: comment_body,
482-
comment_id: bot_comment.id,
483-
owner: context.repo.owner,
484-
repo: context.repo.repo,
485-
});
486-
} else {
487-
await github.rest.issues.createComment({
488-
body: comment_body,
489-
issue_number: context.issue.number,
490-
owner: context.repo.owner,
491-
repo: context.repo.repo,
492-
});
493-
}
364+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/comment_tf_output.js`);
365+
await script({ github, context, sha: "${{ steps.commit.outputs.sha }}", job_status: "${{ job.status }}" });
494366
495367
# On issue_comment, update commit status with job status before exiting.
496368
- name: Update commit status
@@ -499,11 +371,5 @@ runs:
499371
with:
500372
retries: 3
501373
script: |
502-
const add_pending_status = await github.rest.repos.createCommitStatus({
503-
context: "${{ github.workflow }}",
504-
owner: context.repo.owner,
505-
repo: context.repo.repo,
506-
sha: "${{ fromJSON(steps.commit.outputs.result)['sha'] }}",
507-
state: "${{ job.status }}",
508-
target_url: "${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }}",
509-
});
374+
const script = require(`${process.env.GITHUB_ACTION_PATH}/scripts/update_commit_status.js`);
375+
await script({ github, context, sha: "${{ steps.commit.outputs.sha }}", job_status: "${{ job.status }}" });

scripts/add_commit_status.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module.exports = async ({ github, context, core }) => {
2+
// Fetch the pull request to get the head SHA.
3+
const { data: get_pull_request } = await github.rest.pulls.get({
4+
owner: context.repo.owner,
5+
pull_number: context.issue.number,
6+
repo: context.repo.repo,
7+
});
8+
9+
// Add a pending status to the pull request.
10+
const add_pending_status = await github.rest.repos.createCommitStatus({
11+
context: context.workflow,
12+
owner: context.repo.owner,
13+
repo: context.repo.repo,
14+
sha: get_pull_request.head.sha,
15+
state: "pending",
16+
target_url: `${context.payload.repository.html_url}/actions/runs/${context.runId}`,
17+
});
18+
19+
core.setOutput("sha", get_pull_request.head.sha);
20+
};

scripts/add_pr_label.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module.exports = async ({ github, context, label, cli_uses }) => {
2+
// Add a TF command label to the pull request.
3+
const add_label = await github.rest.issues.addLabels({
4+
issue_number: context.issue.number,
5+
labels: [`tf:${label}`],
6+
owner: context.repo.owner,
7+
repo: context.repo.repo,
8+
});
9+
10+
// Update the TF command label color to match the CLI used.
11+
const color = cli_uses === "tofu" ? "FFDA18" : "5C4EE5";
12+
const update_label = await github.rest.issues.updateLabel({
13+
color: color,
14+
description: `Pull requests that ${label} TF code`,
15+
name: `tf:${label}`,
16+
owner: context.repo.owner,
17+
repo: context.repo.repo,
18+
});
19+
};

scripts/add_reaction.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = async ({ github, context, core }) => {
2+
// Add a reaction to the comment to indicate it is being processed.
3+
const { data: add_reaction } =
4+
await github.rest.reactions.createForIssueComment({
5+
comment_id: process.env.comment_id,
6+
content: "eyes",
7+
owner: context.repo.owner,
8+
repo: context.repo.repo,
9+
});
10+
11+
core.setOutput("id", add_reaction.id);
12+
};

scripts/check_pr_approval.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = async ({ github, context, core }) => {
2+
// Fetch the pull request to get the list of reviews.
3+
const { data: list_reviews } = await github.rest.pulls.listReviews({
4+
owner: context.repo.owner,
5+
pull_number: context.issue.number,
6+
repo: context.repo.repo,
7+
});
8+
9+
// Check if the latest review is approved.
10+
if (list_reviews.at(-1)?.state !== "APPROVED") {
11+
core.setFailed("PR review approval is required when apply_require_approval is set to true.");
12+
}
13+
};

scripts/comment_tf_output.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
module.exports = async ({ github, context }) => {
2+
// Display latest TF change summary as the output header.
3+
const comment_summary = process.env.tf_output
4+
.split("\n")
5+
.reverse()
6+
.find((line) => /^(Apply|Plan|Error|No changes)/.test(line)) ||
7+
"View TF result…";
8+
9+
// Display truncated TF fmt diff, if present.
10+
const comment_fmt = process.env.tf_fmt ?
11+
`<details><summary>Diff of format changes.</summary>
12+
13+
\`\`\`diff
14+
${process.env.tf_fmt}
15+
\`\`\`
16+
</details>` :
17+
"";
18+
19+
// Display the: TF command, TF output, and workflow authorship.
20+
// Include the TFPLAN name in a hidden footer as a unique identifier.
21+
const comment_body = `
22+
\`${process.env.tf_command}\`
23+
${comment_fmt}
24+
<details><summary>${comment_summary}</br>
25+
26+
###### ${context.workflow} by @${context.actor} via [${context.eventName}](${context.payload.repository.html_url}/actions/runs/${context.runId}) at ${context.payload.pull_request?.updated_at || context.payload.comment?.updated_at}.</summary>
27+
28+
\`\`\`hcl
29+
${process.env.tf_output}
30+
\`\`\`
31+
</details>
32+
<!-- ${process.env.tf_plan_id} -->`;
33+
34+
// Check if the bot has commented on the PR using the TFPLAN identifier.
35+
const { data: list_comments } = await github.rest.issues.listComments({
36+
issue_number: context.issue.number,
37+
owner: context.repo.owner,
38+
per_page: 100,
39+
repo: context.repo.repo,
40+
});
41+
const bot_comment = list_comments.find((comment) => {
42+
return (
43+
comment.user.type === "Bot" &&
44+
comment.body.includes(`<!-- ${process.env.tf_plan_id} -->`)
45+
);
46+
});
47+
48+
// Delete PR comment reaction to indicate that the workflow has ended.
49+
const delete_reaction = await github.rest.reactions.deleteForIssueComment({
50+
comment_id: process.env.comment_id,
51+
owner: context.repo.owner,
52+
reaction_id: process.env.reaction_id,
53+
repo: context.repo.repo,
54+
});
55+
56+
// If a bot comment exists with a matching TFPLAN identifier, then update
57+
// the comment, otherwise create a new comment. This prevents the bot
58+
// from creating a new comment on every run of this workflow.
59+
if (bot_comment) {
60+
await github.rest.issues.updateComment({
61+
body: comment_body,
62+
comment_id: bot_comment.id,
63+
owner: context.repo.owner,
64+
repo: context.repo.repo,
65+
});
66+
} else {
67+
await github.rest.issues.createComment({
68+
body: comment_body,
69+
issue_number: context.issue.number,
70+
owner: context.repo.owner,
71+
repo: context.repo.repo,
72+
});
73+
}
74+
};

0 commit comments

Comments
 (0)