Skip to content

Commit

Permalink
feat: add policy build script to pre-commit hook (#25)
Browse files Browse the repository at this point in the history
This builds and base64 encodes the policy.wasm on each commit
to ensure the action always has the correct version of the OPA
policy bundled.
  • Loading branch information
patheard authored Jun 29, 2021
1 parent 2a48818 commit eaa3ff4
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 58 deletions.
42 changes: 20 additions & 22 deletions dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"format:check": "prettier --check src",
"format:write": "prettier --write src",
"lint": "eslint src",
"policy": "opa build -t wasm -e 'terraform' -e 'terraform/no_changes' -e 'terraform/resource_changes' -e 'terraform/output_changes' ./policy && tar -xzf ./bundle.tar.gz /policy.wasm && mv policy.wasm ./policy && rm bundle.tar.gz",
"policy": "./src/policy/build.sh",
"prepare": "husky install",
"pre-commit": "npm run format:write & npm run build",
"pre-commit": "npm run policy && npm run format:write && npm run build",
"test": "jest"
},
"dependencies": {
Expand Down
10 changes: 5 additions & 5 deletions src/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ const { getPlanChanges } = require("./opa.js");
* Runs the action
*/
const action = async () => {
const isAllowFailure = core.getInput("allow-failure") === "true";
const isComment = core.getInput("comment") === "true";
const isCommentDelete = core.getInput("comment-delete") === "true";
const isTerragrunt = core.getInput("terragrunt") === "true";
const isAllowFailure = core.getBooleanInput("allow-failure");
const isComment = core.getBooleanInput("comment");
const isCommentDelete = core.getBooleanInput("comment-delete");
const isTerragrunt = core.getBooleanInput("terragrunt");

const binary = isTerragrunt ? "terragrunt" : "terraform";
const commentTitle = core.getInput("comment-title");
const directory = core.getInput("directory");
const terraformInit = core.getInput("terraform-init");
const terraformInit = core.getMultilineInput("terraform-init");
const token = core.getInput("github-token");
const octokit = token !== "false" ? github.getOctokit(token) : undefined;

Expand Down
8 changes: 0 additions & 8 deletions src/opa-policy.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/opa.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

const { loadPolicy } = require("@open-policy-agent/opa-wasm");
const { policyWasmBase64 } = require("./opa-policy.js");
const { policyWasmBase64 } = require("./policy/policy.js");

/**
* Uses ./policy/resource-changes.rego OPA policy to examine the JSON generated
Expand Down
25 changes: 25 additions & 0 deletions src/policy/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

POLICY_DIR="$(dirname ${BASH_SOURCE[0]})"

# Build the Open Policy Agent policy WebAssembly module (.wasm) from the .rego files
opa build -t wasm \
-e 'terraform' \
-e 'terraform/no_changes' \
-e 'terraform/resource_changes' \
-e 'terraform/output_changes' "$POLICY_DIR"
tar -xzf bundle.tar.gz /policy.wasm
mv policy.wasm "$POLICY_DIR"
rm bundle.tar.gz

# Base 64 encode and write the policy.js that is used by the action
POLICY_BASE64="$(base64 $POLICY_DIR/policy.wasm)"
echo "
\"use strict\"
// Auto-generated by 'npm run policy'
module.exports = {
policyWasmBase64: \"${POLICY_BASE64}\",
};
" > "$POLICY_DIR"/policy.js
6 changes: 6 additions & 0 deletions src/policy/policy.js

Large diffs are not rendered by default.

Binary file renamed policy/policy.wasm → src/policy/policy.wasm
Binary file not shown.
File renamed without changes.
40 changes: 24 additions & 16 deletions src/action.test.js → test/action.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
const core = require("@actions/core");
const github = require("@actions/github");
const { when } = require("jest-when");
const { execCommand } = require("./command.js");
const { addComment, deleteComment } = require("./github.js");
const { getPlanChanges } = require("./opa.js");
const { action } = require("./action.js");
const { execCommand } = require("../src/command.js");
const { addComment, deleteComment } = require("../src/github.js");
const { getPlanChanges } = require("../src/opa.js");
const { action } = require("../src/action.js");

jest.mock("@actions/core");
jest.mock("@actions/github");
jest.mock("./command.js");
jest.mock("./github.js");
jest.mock("./opa.js");
jest.mock("../src/command.js");
jest.mock("../src/github.js");
jest.mock("../src/opa.js");

describe("action", () => {
beforeEach(() => {
Expand All @@ -22,7 +22,7 @@ describe("action", () => {
test("default flow", async () => {
execCommand.mockReturnValue({ isSuccess: true, output: "{}" });
when(core.getInput).calledWith("directory").mockReturnValue("foo");
when(core.getInput)
when(core.getMultilineInput)
.calledWith("terraform-init")
.mockReturnValue("-backend-config='bucket=some-bucket'");

Expand All @@ -43,8 +43,10 @@ describe("action", () => {
test("terragrunt flow", async () => {
execCommand.mockReturnValue({ isSuccess: true, output: "{}" });
when(core.getInput).calledWith("directory").mockReturnValue("bar");
when(core.getInput).calledWith("terraform-init").mockReturnValue("");
when(core.getInput).calledWith("terragrunt").mockReturnValue("true");
when(core.getMultilineInput)
.calledWith("terraform-init")
.mockReturnValue("");
when(core.getBooleanInput).calledWith("terragrunt").mockReturnValue(true);

await action();

Expand All @@ -63,7 +65,9 @@ describe("action", () => {

test("delete comment", async () => {
execCommand.mockReturnValue({ isSuccess: true, output: "{}" });
when(core.getInput).calledWith("comment-delete").mockReturnValue("true");
when(core.getBooleanInput)
.calledWith("comment-delete")
.mockReturnValue(true);
when(core.getInput)
.calledWith("comment-title")
.mockReturnValue("blueberries");
Expand All @@ -86,7 +90,7 @@ describe("action", () => {
test("add comment", async () => {
execCommand.mockReturnValue({ isSuccess: true, output: "{}" });
getPlanChanges.mockReturnValue({ isChanges: true });
when(core.getInput).calledWith("comment").mockReturnValue("true");
when(core.getBooleanInput).calledWith("comment").mockReturnValue(true);
when(core.getInput)
.calledWith("comment-title")
.mockReturnValue("raspberries");
Expand Down Expand Up @@ -125,17 +129,21 @@ describe("action", () => {

test("allowed to fail", async () => {
execCommand.mockReturnValue({ isSuccess: false });
when(core.getInput).calledWith("allow-failure").mockReturnValue("true");
when(core.getInput).calledWith("comment").mockReturnValue("false");
when(core.getInput).calledWith("comment-delete").mockReturnValue("false");
when(core.getBooleanInput)
.calledWith("allow-failure")
.mockReturnValue(true);
when(core.getBooleanInput).calledWith("comment").mockReturnValue(false);
when(core.getBooleanInput)
.calledWith("comment-delete")
.mockReturnValue(false);

await action();

expect(core.setFailed.mock.calls.length).toBe(0);
});

test("failed validation", async () => {
when(core.getInput).calledWith("comment").mockReturnValue("true");
when(core.getBooleanInput).calledWith("comment").mockReturnValue(true);
when(core.getInput).calledWith("github-token").mockReturnValue("false");

await action();
Expand Down
2 changes: 1 addition & 1 deletion src/command.test.js → test/command.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

const { execCommand } = require("./command.js");
const { execCommand } = require("../src/command.js");
global.console = { log: jest.fn() };

beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/github.test.js → test/github.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const {
commentTemplate,
deleteComment,
removeRefreshOutput,
} = require("./github.js");
} = require("../src/github.js");
global.console = { log: jest.fn() };

// Mock octokit object and return values
Expand Down
2 changes: 1 addition & 1 deletion src/opa.test.js → test/opa.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

const fs = require("fs");
const { getPlanChanges } = require("./opa.js");
const { getPlanChanges } = require("../src/opa.js");

beforeEach(() => {
jest.resetAllMocks();
Expand Down

0 comments on commit eaa3ff4

Please sign in to comment.