Test Coverage Improvements (#141)

* Test Coverage Improvements

* Update env.js
This commit is contained in:
James Ives 2020-01-19 15:33:14 -05:00 committed by GitHub
parent e2cddf199d
commit 109bba8860
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 185 additions and 68 deletions

View File

@ -1 +1 @@
process.env.UNIT_TEST = "true";
process.env.UNIT_TEST = "true"

View File

@ -1,4 +1,4 @@
import { execute } from "../src/execute";
import { execute, stdout } from "../src/execute";
import { exec } from "@actions/exec";
jest.mock("@actions/exec", () => ({
@ -7,6 +7,7 @@ jest.mock("@actions/exec", () => ({
describe("execute", () => {
it("should be called with the correct arguments", async () => {
await stdout("hello");
await execute("echo Montezuma", "./");
expect(exec).toBeCalledWith("echo Montezuma", [], {

View File

@ -5,9 +5,15 @@ process.env["GITHUB_SHA"] = "123";
import { action } from "../src/constants";
import { deploy, generateBranch, init, switchToBaseBranch } from "../src/git";
import { execute } from "../src/execute";
import { setFailed } from "@actions/core";
const originalAction = JSON.stringify(action);
jest.mock("@actions/core", () => ({
setFailed: jest.fn(),
getInput: jest.fn()
}));
jest.mock("../src/execute", () => ({
execute: jest.fn()
}));
@ -21,6 +27,7 @@ describe("git", () => {
it("should execute three commands if a GitHub token is provided", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
gitHubToken: "123",
pusher: {
name: "asd",
@ -36,6 +43,7 @@ describe("git", () => {
it("should execute three commands if a Access token is provided", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
accessToken: "123",
pusher: {
name: "asd",
@ -52,14 +60,18 @@ describe("git", () => {
it("should fail if there is no provided GitHub Token or Access Token", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
pusher: {
name: "asd",
email: "as@cat"
}
},
gitHubToken: null,
accessToken: null,
ssh: null
});
const call = await init();
expect(setFailed).toBeCalledTimes(1);
expect(execute).toBeCalledTimes(0);
expect(call).toBe("Initialization step complete...");
});
@ -67,6 +79,7 @@ describe("git", () => {
it("should fail if the build folder begins with a /", async () => {
Object.assign(action, {
accessToken: "123",
branch: "branch",
build: "/",
pusher: {
name: "asd",
@ -76,6 +89,7 @@ describe("git", () => {
const call = await init();
expect(setFailed).toBeCalledTimes(1);
expect(execute).toBeCalledTimes(0);
expect(call).toBe("Initialization step complete...");
});
@ -83,6 +97,7 @@ describe("git", () => {
it("should fail if the build folder begins with a ./", async () => {
Object.assign(action, {
accessToken: "123",
branch: "branch",
build: "./",
pusher: {
name: "asd",
@ -91,7 +106,7 @@ describe("git", () => {
});
const call = await init();
expect(setFailed).toBeCalledTimes(1);
expect(execute).toBeCalledTimes(0);
expect(call).toBe("Initialization step complete...");
});
@ -99,6 +114,7 @@ describe("git", () => {
it("should not fail if root is used", async () => {
Object.assign(action, {
accessToken: "123",
branch: "branch",
build: ".",
pusher: {
name: "asd",
@ -114,15 +130,52 @@ describe("git", () => {
});
describe("generateBranch", () => {
it("should execute five commands", async () => {
it("should execute six commands", async () => {
Object.assign(action, {
accessToken: "123",
branch: "branch",
build: ".",
pusher: {
name: "asd",
email: "as@cat"
}
});
const call = await generateBranch();
expect(execute).toBeCalledTimes(6);
expect(call).toBe("Deployment branch creation step complete... ✅");
});
it("should fail if there is no branch", async () => {
Object.assign(action, {
accessToken: "123",
branch: null,
build: ".",
pusher: {
name: "asd",
email: "as@cat"
}
});
const call = await generateBranch();
expect(execute).toBeCalledTimes(0);
expect(setFailed).toBeCalledTimes(1);
expect(call).toBe("Deployment branch creation step complete... ✅");
});
});
describe("switchToBaseBranch", () => {
it("should execute one command", async () => {
Object.assign(action, {
accessToken: "123",
branch: "branch",
build: ".",
pusher: {
name: "asd",
email: "as@cat"
}
});
const call = await switchToBaseBranch();
expect(execute).toBeCalledTimes(1);
expect(call).toBe("Switched to the base branch...");
@ -133,6 +186,7 @@ describe("git", () => {
it("should execute five commands", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
gitHubToken: "123",
pusher: {
name: "asd",
@ -146,5 +200,61 @@ describe("git", () => {
expect(execute).toBeCalledTimes(18);
expect(call).toBe("Commit step complete...");
});
it("should execute five commands with clean options", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
gitHubToken: "123",
pusher: {
name: "asd",
email: "as@cat"
},
clean: true,
cleanExclude: '["cat", "montezuma"]'
});
const call = await deploy();
// Includes the call to generateBranch
expect(execute).toBeCalledTimes(18);
expect(call).toBe("Commit step complete...");
});
it("should gracefully handle incorrectly formatted clean exclude items", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
gitHubToken: "123",
pusher: {
name: "asd",
email: "as@cat"
},
clean: true,
cleanExclude: '["cat, "montezuma"]' // There is a syntax errror in the string.
});
const call = await deploy();
// Includes the call to generateBranch
expect(execute).toBeCalledTimes(18);
expect(call).toBe("Commit step complete...");
});
it("should stop early if there is nothing to commit", async () => {
Object.assign(action, {
build: "build",
branch: "branch",
gitHubToken: "123",
pusher: {
name: "asd",
email: "as@cat"
},
isTest: false // Setting this env variable to false means there will never be anything to commit and the action will exit early.
});
await deploy();
expect(execute).toBeCalledTimes(12);
});
});
});

View File

@ -7,24 +7,24 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const core_1 = require("@actions/core");
const github = __importStar(require("@actions/github"));
const { pusher, repository } = github.context.payload;
exports.workspace = process.env.GITHUB_WORKSPACE;
exports.folder = core.getInput("FOLDER", { required: true });
exports.isTest = process.env.UNIT_TEST;
exports.folder = core_1.getInput("FOLDER", { required: true });
exports.root = ".";
// Required action data.
exports.action = {
accessToken: core.getInput("ACCESS_TOKEN"),
baseBranch: core.getInput("BASE_BRANCH"),
accessToken: core_1.getInput("ACCESS_TOKEN"),
baseBranch: core_1.getInput("BASE_BRANCH"),
build: exports.folder,
branch: core.getInput("BRANCH"),
commitMessage: core.getInput("COMMIT_MESSAGE"),
clean: core.getInput("CLEAN"),
cleanExclude: core.getInput("CLEAN_EXCLUDE"),
branch: core_1.getInput("BRANCH"),
commitMessage: core_1.getInput("COMMIT_MESSAGE"),
clean: core_1.getInput("CLEAN"),
cleanExclude: core_1.getInput("CLEAN_EXCLUDE"),
defaultBranch: process.env.GITHUB_SHA ? process.env.GITHUB_SHA : "master",
ssh: core.getInput("SSH"),
isTest: process.env.UNIT_TEST,
ssh: core_1.getInput("SSH"),
email: pusher && pusher.email
? pusher.email
: `${process.env.GITHUB_ACTOR ||
@ -32,13 +32,13 @@ exports.action = {
gitHubRepository: repository && repository.full_name
? repository.full_name
: process.env.GITHUB_REPOSITORY,
gitHubToken: core.getInput("GITHUB_TOKEN"),
gitHubToken: core_1.getInput("GITHUB_TOKEN"),
name: pusher && pusher.name
? pusher.name
: process.env.GITHUB_ACTOR
? process.env.GITHUB_ACTOR
: "GitHub Pages Deploy Action",
targetFolder: core.getInput("TARGET_FOLDER")
targetFolder: core_1.getInput("TARGET_FOLDER")
};
// Token Types
exports.tokenType = exports.action.ssh

View File

@ -10,6 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", { value: true });
const exec_1 = require("@actions/exec");
// Stores the output from execute.
let output;
/** Wrapper around the GitHub toolkit exec command which returns the output.
* Also allows you to easily toggle the current working directory.
* @param {String} cmd = The command to execute.
@ -18,16 +20,18 @@ const exec_1 = require("@actions/exec");
*/
function execute(cmd, cwd) {
return __awaiter(this, void 0, void 0, function* () {
let output = "";
output = "";
yield exec_1.exec(cmd, [], {
cwd,
listeners: {
stdout: (data) => {
output += data.toString().trim();
}
stdout
}
});
return Promise.resolve(output);
});
}
exports.execute = execute;
function stdout(data) {
output += data.toString().trim();
}
exports.stdout = stdout;

View File

@ -8,18 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const core_1 = require("@actions/core");
const constants_1 = require("./constants");
const execute_1 = require("./execute");
const util_1 = require("./util");
const constants_1 = require("./constants");
/** Generates the branch if it doesn't exist on the remote.
* @returns {Promise}
*/
@ -29,18 +22,14 @@ function init() {
if (util_1.isNullOrUndefined(constants_1.action.accessToken) &&
util_1.isNullOrUndefined(constants_1.action.gitHubToken) &&
util_1.isNullOrUndefined(constants_1.action.ssh)) {
return core.setFailed("You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.");
}
const sshAuthenticated = yield execute_1.execute(`ssh -T git@github.com | wc -l`, constants_1.workspace);
if (constants_1.action.ssh && !sshAuthenticated) {
return core.setFailed(`You're not authenticated with SSH. Please double check your deploy token configuration and try again.`);
}
else if (constants_1.action.ssh && sshAuthenticated) {
console.log("SSH is correctly authenticated, proceeding... 🔑");
core_1.setFailed("You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.");
throw "No deployment token/method was provided.";
}
if (constants_1.action.build.startsWith("/") || constants_1.action.build.startsWith("./")) {
return core.setFailed(`The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly.`);
core_1.setFailed(`The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly.`);
throw "Incorrectly formatted build folder.";
}
console.log(`Deploying using ${constants_1.tokenType}... 🔑`);
yield execute_1.execute(`git init`, constants_1.workspace);
yield execute_1.execute(`git config user.name ${constants_1.action.name}`, constants_1.workspace);
yield execute_1.execute(`git config user.email ${constants_1.action.email}`, constants_1.workspace);
@ -49,7 +38,7 @@ function init() {
yield execute_1.execute(`git fetch`, constants_1.workspace);
}
catch (error) {
core.setFailed(`There was an error initializing the repository: ${error}`);
console.log(`There was an error initializing the repository: ${error}`);
}
finally {
return Promise.resolve("Initialization step complete...");
@ -73,6 +62,9 @@ exports.switchToBaseBranch = switchToBaseBranch;
function generateBranch() {
return __awaiter(this, void 0, void 0, function* () {
try {
if (util_1.isNullOrUndefined(constants_1.action.branch)) {
throw "Branch is required.";
}
console.log(`Creating ${constants_1.action.branch} branch... 🔧`);
yield switchToBaseBranch();
yield execute_1.execute(`git checkout --orphan ${constants_1.action.branch}`, constants_1.workspace);
@ -82,7 +74,7 @@ function generateBranch() {
yield execute_1.execute(`git fetch`, constants_1.workspace);
}
catch (error) {
core.setFailed(`There was an error creating the deployment branch: ${error}`);
core_1.setFailed(`There was an error creating the deployment branch: ${error}`);
}
finally {
return Promise.resolve("Deployment branch creation step complete... ✅");
@ -131,7 +123,7 @@ function deploy() {
? `--delete ${excludes} --exclude CNAME --exclude .nojekyll`
: ""} --exclude .ssh --exclude .git --exclude .github ${constants_1.action.build === constants_1.root ? `--exclude ${temporaryDeploymentDirectory}` : ""}`, constants_1.workspace);
const hasFilesToCommit = yield execute_1.execute(`git status --porcelain`, temporaryDeploymentDirectory);
if (!hasFilesToCommit && !constants_1.isTest) {
if (!hasFilesToCommit && !constants_1.action.isTest) {
console.log("There is nothing to commit. Exiting... ✅");
return Promise.resolve();
}

View File

@ -1,24 +1,24 @@
import * as core from "@actions/core";
import { getInput } from "@actions/core";
import * as github from "@actions/github";
const { pusher, repository } = github.context.payload;
export const workspace: any = process.env.GITHUB_WORKSPACE;
export const folder = core.getInput("FOLDER", { required: true });
export const isTest = process.env.UNIT_TEST;
export const folder = getInput("FOLDER", { required: true });
export const root = ".";
// Required action data.
export const action = {
accessToken: core.getInput("ACCESS_TOKEN"),
baseBranch: core.getInput("BASE_BRANCH"),
accessToken: getInput("ACCESS_TOKEN"),
baseBranch: getInput("BASE_BRANCH"),
build: folder,
branch: core.getInput("BRANCH"),
commitMessage: core.getInput("COMMIT_MESSAGE"),
clean: core.getInput("CLEAN"),
cleanExclude: core.getInput("CLEAN_EXCLUDE"),
branch: getInput("BRANCH"),
commitMessage: getInput("COMMIT_MESSAGE"),
clean: getInput("CLEAN"),
cleanExclude: getInput("CLEAN_EXCLUDE"),
defaultBranch: process.env.GITHUB_SHA ? process.env.GITHUB_SHA : "master",
ssh: core.getInput("SSH"),
isTest: process.env.UNIT_TEST,
ssh: getInput("SSH"),
email:
pusher && pusher.email
? pusher.email
@ -28,14 +28,14 @@ export const action = {
repository && repository.full_name
? repository.full_name
: process.env.GITHUB_REPOSITORY,
gitHubToken: core.getInput("GITHUB_TOKEN"),
gitHubToken: getInput("GITHUB_TOKEN"),
name:
pusher && pusher.name
? pusher.name
: process.env.GITHUB_ACTOR
? process.env.GITHUB_ACTOR
: "GitHub Pages Deploy Action",
targetFolder: core.getInput("TARGET_FOLDER")
targetFolder: getInput("TARGET_FOLDER")
};
// Token Types

View File

@ -1,5 +1,8 @@
import { exec } from "@actions/exec";
// Stores the output from execute.
let output: string;
/** Wrapper around the GitHub toolkit exec command which returns the output.
* Also allows you to easily toggle the current working directory.
* @param {String} cmd = The command to execute.
@ -7,16 +10,18 @@ import { exec } from "@actions/exec";
* @returns {Promise} - The output from the command.
*/
export async function execute(cmd: string, cwd: string): Promise<any> {
let output = "";
output = "";
await exec(cmd, [], {
cwd,
listeners: {
stdout: (data: Buffer) => {
output += data.toString().trim();
}
stdout
}
});
return Promise.resolve(output);
}
export function stdout(data: any) {
output += data.toString().trim();
}

View File

@ -1,7 +1,6 @@
import * as core from "@actions/core";
import { setFailed } from "@actions/core";
import {
action,
isTest,
repositoryPath,
root,
tokenType,
@ -20,15 +19,19 @@ export async function init(): Promise<any> {
isNullOrUndefined(action.gitHubToken) &&
isNullOrUndefined(action.ssh)
) {
return core.setFailed(
setFailed(
"You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true."
);
throw "No deployment token/method was provided.";
}
if (action.build.startsWith("/") || action.build.startsWith("./")) {
return core.setFailed(
setFailed(
`The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly.`
);
throw "Incorrectly formatted build folder.";
}
console.log(`Deploying using ${tokenType}... 🔑`);
@ -39,7 +42,7 @@ export async function init(): Promise<any> {
await execute(`git remote add origin ${repositoryPath}`, workspace);
await execute(`git fetch`, workspace);
} catch (error) {
core.setFailed(`There was an error initializing the repository: ${error}`);
console.log(`There was an error initializing the repository: ${error}`);
} finally {
return Promise.resolve("Initialization step complete...");
}
@ -64,6 +67,10 @@ export async function switchToBaseBranch(): Promise<any> {
*/
export async function generateBranch(): Promise<any> {
try {
if (isNullOrUndefined(action.branch)) {
throw "Branch is required.";
}
console.log(`Creating ${action.branch} branch... 🔧`);
await switchToBaseBranch();
await execute(`git checkout --orphan ${action.branch}`, workspace);
@ -75,9 +82,7 @@ export async function generateBranch(): Promise<any> {
await execute(`git push ${repositoryPath} ${action.branch}`, workspace);
await execute(`git fetch`, workspace);
} catch (error) {
core.setFailed(
`There was an error creating the deployment branch: ${error}`
);
setFailed(`There was an error creating the deployment branch: ${error}`);
} finally {
return Promise.resolve("Deployment branch creation step complete... ✅");
}
@ -149,7 +154,7 @@ export async function deploy(): Promise<any> {
temporaryDeploymentDirectory
);
if (!hasFilesToCommit && !isTest) {
if (!hasFilesToCommit && !action.isTest) {
console.log("There is nothing to commit. Exiting... ✅");
return Promise.resolve();
}