Skip to content

Commit

Permalink
Merge pull request #11 from byu-oit/feature/custom-comment-prefix
Browse files Browse the repository at this point in the history
added ability to specify a comment title
  • Loading branch information
yoshutch authored Jul 21, 2020
2 parents d4eb37a + 32c19d5 commit 168d38d
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 39 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
working-directory: __tests__
terraform-plan-file: ../test-plan.tfplan
comment-title: Terraform Plan in different dir

test-action-without-tf-wrapper: # make sure the action works without the terraform wrapper
name: Test without TF wrapper
Expand All @@ -66,6 +67,7 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
working-directory: __tests__
terraform-plan-file: test-plan.tfplan
comment-title: Terraform Plan without wrapper

test-action-at-root: # make sure the action works with terraform dir as root dir
name: Test from Root
Expand All @@ -83,4 +85,5 @@ jobs:
- uses: ./
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
terraform-plan-file: test-plan.tfplan
terraform-plan-file: test-plan.tfplan
comment-title: Terraform Plan from root
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ jobs:
* `github-token` - (**required**) pass in the GitHub token to make comments on the PR
* `working-directory` - (_optional_) the directory of the terraform configuration files (defaults to `.`)
* `terraform-plan-file` - (**required**) Filename of the terraform plan (relative to `working-directory`)
* `comment-title` - (_optional_) Title for the comment this action will make on your pull request (defaults to `Terraform Plan`)

**note**: the `comment-title` is used to determine which PR comment to update.
For instance if you have two of these actions in one PR with the same `comment-title` then they will both try to update the same comment.

## Output
This action will create a comment on your PR like:
Expand All @@ -53,7 +57,9 @@ GitHub Actions will run the entry point from the action.yml.
In our case, that happens to be /dist/index.js.

Actions run from GitHub repos.
We don't want to check in node_modules. Hence, we package the app using `yarn run pack`.
We don't want to check in node_modules.
Hence, we package the app using `yarn run pack`.
Make sure you run `yarn run pack` before committing/pushing.

### Modifying Source Code
Just run `yarn install` locally.
Expand Down
64 changes: 49 additions & 15 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ const pr: PullRequest = {
body: '',
html_url: ''
}
const basicTestPlan: TerraformPlan = {
resource_changes: [
{
address: 'local_file.fake_file',
type: 'local_file',
name: 'fake_file',
change: {
actions: [Action.delete, Action.create]
}
}
]
}
process.env['GITHUB_REPOSITORY'] = 'https://github.com/byu-oit/github-action-tf-plan-comment'

test('Test Basic Plan Summary', async () => {
Expand All @@ -17,20 +29,13 @@ test('Test Basic Plan Summary', async () => {
html_url: 'https://test/workflow/url'
})

const commenter = new PlanCommenter(github.getOctokit('fake'), 1234, pr)
const plan: TerraformPlan = {
resource_changes: [
{
address: 'local_file.fake_file',
type: 'local_file',
name: 'fake_file',
change: {
actions: [Action.delete, Action.create]
}
}
]
}
const summary = await commenter.planSummaryBody(plan)
const commenter = new PlanCommenter({
octokit: github.getOctokit('fake'),
runId: 1234,
pr
})

const summary = await commenter.planSummaryBody(basicTestPlan)
const expected = `## Terraform Plan:
will **replace (delete then create)** 1 resource:
* local_file - fake_file
Expand All @@ -42,10 +47,39 @@ will **replace (delete then create)** 1 resource:
})

test('Test Empty Plan Summary', async () => {
const commenter = new PlanCommenter(github.getOctokit('fake'), 1234, pr)
const commenter = new PlanCommenter({
octokit: github.getOctokit('fake'),
runId: 1234,
pr
})
const emptyPlan: TerraformPlan = {}
const summary = await commenter.planSummaryBody(emptyPlan)
const expected = `## Terraform Plan:
No changes detected`
expect(summary).toEqual(expected)
})

test('Test Basic Plan with custom title', async () => {
const scope = nock('https://api.github.com')
.get(/.*/)
.reply(200, {
html_url: 'https://test/workflow/url'
})

const commenter = new PlanCommenter({
octokit: github.getOctokit('fake'),
runId: 1234,
pr,
commentTitle: 'Test Plan Title'
})

const summary = await commenter.planSummaryBody(basicTestPlan)
const expected = `## Test Plan Title:
will **replace (delete then create)** 1 resource:
* local_file - fake_file
[see details](https://test/workflow/url)`
expect(summary).toEqual(expected)

scope.done()
})
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ inputs:
required: false
description: Directory of the terraform configuration
default: .
comment-title:
required: false
description: Title of the comment
default: Terraform Plan
runs:
using: 'node12'
main: 'dist/index.js'
30 changes: 19 additions & 11 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1740,13 +1740,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlanCommenter = exports.noChangesComment = exports.commentPrefix = void 0;
exports.PlanCommenter = exports.noChangesComment = void 0;
const core = __importStar(__webpack_require__(470));
const exec = __importStar(__webpack_require__(986));
const github = __importStar(__webpack_require__(469));
const types_1 = __webpack_require__(251);
exports.commentPrefix = '## Terraform Plan:';
exports.noChangesComment = '## Terraform Plan:\nNo changes detected';
exports.noChangesComment = 'No changes detected';
async function run() {
try {
core.debug('got inside the action');
Expand All @@ -1758,6 +1757,7 @@ async function run() {
core.debug('got pull request');
const planFileName = core.getInput('terraform-plan-file');
const workingDir = core.getInput('working-directory');
const commentTitle = core.getInput('comment-title');
const json = await jsonFromPlan(workingDir, planFileName);
const terraformPlan = JSON.parse(json);
core.debug('successfully parsed json');
Expand All @@ -1767,7 +1767,12 @@ async function run() {
core.setFailed('No GITHUB_RUN_ID found');
return;
}
const commenter = new PlanCommenter(github.getOctokit(token), runId, pr);
const commenter = new PlanCommenter({
octokit: github.getOctokit(token),
runId,
pr,
commentTitle
});
await commenter.commentWithPlanSummary(terraformPlan);
}
catch (error) {
Expand Down Expand Up @@ -1804,10 +1809,12 @@ async function jsonFromPlan(workingDir, planFileName) {
return json[0];
}
class PlanCommenter {
constructor(octokit, runId, pr) {
this.octokit = octokit;
this.runId = runId;
this.pr = pr;
constructor(options) {
this.octokit = options.octokit;
this.runId = options.runId;
this.pr = options.pr;
this.commentPrefix =
options.commentTitle === undefined ? '## Terraform Plan:' : `## ${options.commentTitle}:`;
}
async commentWithPlanSummary(terraformPlan) {
const body = await this.planSummaryBody(terraformPlan);
Expand All @@ -1818,7 +1825,8 @@ class PlanCommenter {
});
let previousCommentId = null;
for (const comment of comments.data) {
if (comment.user.login === 'github-actions[bot]' && comment.body.startsWith(exports.commentPrefix)) {
if (comment.user.login === 'github-actions[bot]' &&
comment.body.startsWith(this.commentPrefix)) {
previousCommentId = comment.id;
}
}
Expand Down Expand Up @@ -1850,7 +1858,7 @@ class PlanCommenter {
const toReplace = [];
const toUpdate = [];
if (!terraformPlan.resource_changes) {
return exports.noChangesComment;
return `${this.commentPrefix}\n${exports.noChangesComment}`;
}
for (const resourceChange of terraformPlan.resource_changes) {
const actions = resourceChange.change.actions;
Expand Down Expand Up @@ -1878,7 +1886,7 @@ class PlanCommenter {
core.debug(`toUpdate: ${toUpdate}`);
core.debug(`toReplace: ${toReplace}`);
core.debug(`toDelete: ${toDelete}`);
let body = `${exports.commentPrefix}\n`;
let body = `${this.commentPrefix}\n`;
body += PlanCommenter.resourcesToChangeSection('create', toCreate);
body += PlanCommenter.resourcesToChangeSection('update', toUpdate);
body += PlanCommenter.resourcesToChangeSection('**delete**', toDelete);
Expand Down
40 changes: 29 additions & 11 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {GitHub} from '@actions/github/lib/utils'
import {Action, PullRequest, TerraformPlan} from './types'
import {ExecOptions} from '@actions/exec'

export const commentPrefix = '## Terraform Plan:'
export const noChangesComment = '## Terraform Plan:\nNo changes detected'
export const noChangesComment = 'No changes detected'

async function run(): Promise<void> {
try {
Expand All @@ -21,6 +20,7 @@ async function run(): Promise<void> {

const planFileName = core.getInput('terraform-plan-file')
const workingDir = core.getInput('working-directory')
const commentTitle = core.getInput('comment-title')

const json = await jsonFromPlan(workingDir, planFileName)
const terraformPlan: TerraformPlan = JSON.parse(json)
Expand All @@ -33,7 +33,12 @@ async function run(): Promise<void> {
return
}

const commenter = new PlanCommenter(github.getOctokit(token), runId, pr)
const commenter = new PlanCommenter({
octokit: github.getOctokit(token),
runId,
pr,
commentTitle
})
await commenter.commentWithPlanSummary(terraformPlan)
} catch (error) {
core.setFailed(error.message)
Expand Down Expand Up @@ -73,15 +78,25 @@ async function jsonFromPlan(workingDir: string, planFileName: string): Promise<s
return json[0]
}

export class PlanCommenter {
interface PlanCommenterOptions {
octokit: InstanceType<typeof GitHub>
runId: number
pr: PullRequest
commentTitle?: string | undefined
}

constructor(octokit: InstanceType<typeof GitHub>, runId: number, pr: PullRequest) {
this.octokit = octokit
this.runId = runId
this.pr = pr
export class PlanCommenter {
octokit: InstanceType<typeof GitHub>
runId: number
pr: PullRequest
commentPrefix: string

constructor(options: PlanCommenterOptions) {
this.octokit = options.octokit
this.runId = options.runId
this.pr = options.pr
this.commentPrefix =
options.commentTitle === undefined ? '## Terraform Plan:' : `## ${options.commentTitle}:`
}

async commentWithPlanSummary(terraformPlan: TerraformPlan): Promise<number> {
Expand All @@ -93,7 +108,10 @@ export class PlanCommenter {
})
let previousCommentId: number | null = null
for (const comment of comments.data) {
if (comment.user.login === 'github-actions[bot]' && comment.body.startsWith(commentPrefix)) {
if (
comment.user.login === 'github-actions[bot]' &&
comment.body.startsWith(this.commentPrefix)
) {
previousCommentId = comment.id
}
}
Expand Down Expand Up @@ -125,7 +143,7 @@ export class PlanCommenter {
const toReplace = []
const toUpdate = []
if (!terraformPlan.resource_changes) {
return noChangesComment
return `${this.commentPrefix}\n${noChangesComment}`
}

for (const resourceChange of terraformPlan.resource_changes) {
Expand Down Expand Up @@ -154,7 +172,7 @@ export class PlanCommenter {
core.debug(`toReplace: ${toReplace}`)
core.debug(`toDelete: ${toDelete}`)

let body = `${commentPrefix}\n`
let body = `${this.commentPrefix}\n`
body += PlanCommenter.resourcesToChangeSection('create', toCreate)
body += PlanCommenter.resourcesToChangeSection('update', toUpdate)
body += PlanCommenter.resourcesToChangeSection('**delete**', toDelete)
Expand Down

0 comments on commit 168d38d

Please sign in to comment.