Skip to content

Commit

Permalink
Add tests (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhuleatt authored Oct 29, 2020
1 parent 8660c48 commit 276388d
Show file tree
Hide file tree
Showing 14 changed files with 5,342 additions and 372 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/deploy-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
run: npm ci
- name: Check that Prettier was run
run: npm run format:check
- name: Test
run: npm run test
- name: Deploy to Firebase Hosting preview channel
id: firebase_hosting_preview
uses: ./
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
.firebase/*
**/*.d.ts
**/*.d.ts
demo/.firebase/hosting.*.cache
8 changes: 8 additions & 0 deletions babel.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// babel config for jest tests
// https://jestjs.io/docs/en/getting-started#using-typescript
module.exports = {
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript",
],
};
2 changes: 1 addition & 1 deletion bin/action.min.js

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/en/configuration.html
*/

export default {
// Automatically clear mock calls and instances between every test
clearMocks: true,

// A preset that is used as a base for Jest's configuration
preset: "ts-jest",

// The test environment that will be used for testing
testEnvironment: "node",
};
5,253 changes: 4,924 additions & 329 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.3",
"@actions/github": "^2.1.1",
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1",
"@babel/preset-typescript": "^7.12.1",
"@tsconfig/node12": "^1.0.7",
"@types/jest": "^26.0.15",
"@types/tmp": "^0.2.0",
"babel-jest": "^26.6.0",
"husky": "^4.2.5",
"jest": "^26.6.0",
"microbundle": "^0.12.3",
"prettier": "^2.1.2",
"pretty-quick": "^3.0.2",
"tmp": "^0.2.1",
"ts-jest": "^26.4.1",
"ts-node": "^9.0.0",
"typescript": "^4.0.3"
},
"scripts": {
"format:check": "prettier . --list-different",
"format": "prettier --write .",
"build": "microbundle -f cjs --target node --compress --no-sourcemap src/index.ts",
"build:watch": "microbundle watch -f cjs --target node --compress --no-sourcemap src/index.ts"
"build:watch": "microbundle watch -f cjs --target node --compress --no-sourcemap src/index.ts",
"test": "jest"
},
"husky": {
"hooks": {
Expand Down
41 changes: 28 additions & 13 deletions src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { exec } from "@actions/exec";

export type SiteDeploy = {
site: string;
target: string | undefined;
target?: string;
url: string;
expireTime: string;
};
Expand All @@ -36,33 +36,47 @@ export type ChannelSuccessResult = {
export type ProductionSuccessResult = {
status: "success";
result: {
hosting: string;
hosting: string | string[];
};
};

export type DeployConfig = {
projectId: string;
expires: string;
channelId: string;
target: string;
target?: string;
};

export type productionDeployConfig = {
export type ProductionDeployConfig = {
projectId: string;
target?: string;
};

export function interpretChannelDeployResult(
deployResult: ChannelSuccessResult
): { expireTime: string; urls: string[] } {
const allSiteResults = Object.values(deployResult.result);

const expireTime = allSiteResults[0].expireTime;
const urls = allSiteResults.map((siteResult) => siteResult.url);

return {
expireTime,
urls,
};
}

async function execWithCredentials(
firebase,
args: string[],
projectId,
gacFilename,
debug: boolean = false
) {
let deployOutputBuf: Buffer[] = [];

try {
await exec(
firebase,
"npx firebase-tools",
[
...args,
...(projectId ? ["--project", projectId] : []),
Expand Down Expand Up @@ -91,7 +105,7 @@ async function execWithCredentials(
console.log(
"Retrying deploy with the --debug flag for better error output"
);
return execWithCredentials(firebase, args, projectId, gacFilename, true);
await execWithCredentials(args, projectId, gacFilename, true);
} else {
throw e;
}
Expand All @@ -102,11 +116,13 @@ async function execWithCredentials(
: ""; // output from the CLI
}

export async function deploy(gacFilename: string, deployConfig: DeployConfig) {
const { projectId, expires, channelId, target } = deployConfig;
export async function deployPreview(
gacFilename: string,
deployConfig: DeployConfig
) {
const { projectId, channelId, target, expires } = deployConfig;

const deploymentText = await execWithCredentials(
"npx firebase-tools",
[
"hosting:channel:deploy",
channelId,
Expand All @@ -117,7 +133,7 @@ export async function deploy(gacFilename: string, deployConfig: DeployConfig) {
gacFilename
);

const deploymentResult = JSON.parse(deploymentText) as
const deploymentResult = JSON.parse(deploymentText.trim()) as
| ChannelSuccessResult
| ErrorResult;

Expand All @@ -126,12 +142,11 @@ export async function deploy(gacFilename: string, deployConfig: DeployConfig) {

export async function deployProductionSite(
gacFilename,
productionDeployConfig: productionDeployConfig
productionDeployConfig: ProductionDeployConfig
) {
const { projectId, target } = productionDeployConfig;

const deploymentText = await execWithCredentials(
"npx firebase-tools",
["deploy", "--only", `hosting${target ? ":" + target : ""}`],
projectId,
gacFilename
Expand Down
33 changes: 15 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,17 @@ import { context, GitHub } from "@actions/github";
import { existsSync } from "fs";
import { createCheck } from "./createCheck";
import { createGacFile } from "./createGACFile";
import { deploy, deployProductionSite, ErrorResult } from "./deploy";
import {
deployPreview,
deployProductionSite,
ErrorResult,
interpretChannelDeployResult,
} from "./deploy";
import { getChannelId } from "./getChannelId";
import { postOrUpdateComment } from "./postOrUpdateComment";
import {
getURLsMarkdownFromChannelDeployResult,
postChannelSuccessComment,
} from "./postOrUpdateComment";

// Inputs defined in action.yml
const expires = getInput("expires");
Expand Down Expand Up @@ -104,21 +112,19 @@ async function run() {
const channelId = getChannelId(configuredChannelId, context);

startGroup(`Deploying to Firebase preview channel ${channelId}`);
const deployment = await deploy(gacFilename, {
const deployment = await deployPreview(gacFilename, {
projectId,
expires,
channelId,
target,
});
endGroup();

if (deployment.status === "error") {
throw Error((deployment as ErrorResult).error);
}
endGroup();

const allSiteResults = Object.values(deployment.result);
const expireTime = allSiteResults[0].expireTime;
const urls = allSiteResults.map((siteResult) => siteResult.url);
const { expireTime, urls } = interpretChannelDeployResult(deployment);

setOutput("urls", urls);
setOutput("expire_time", expireTime);
Expand All @@ -132,24 +138,15 @@ async function run() {
if (token && isPullRequest) {
const commitId = context.payload.pull_request?.head.sha.substring(0, 7);

await postOrUpdateComment(
github,
context,
`
Visit the preview URL for this PR (updated for commit ${commitId}):
${urlsListMarkdown}
<sub>(expires ${new Date(expireTime).toUTCString()})</sub>`.trim()
);
await postChannelSuccessComment(github, context, deployment, commitId);
}

await finish({
details_url: urls[0],
conclusion: "success",
output: {
title: `Deploy preview succeeded`,
summary: urlsListMarkdown,
summary: getURLsMarkdownFromChannelDeployResult(deployment),
},
});
} catch (e) {
Expand Down
63 changes: 54 additions & 9 deletions src/postOrUpdateComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,59 @@
import { endGroup, startGroup } from "@actions/core";
import { GitHub } from "@actions/github";
import { Context } from "@actions/github/lib/context";
import {
ChannelSuccessResult,
interpretChannelDeployResult,
ErrorResult,
} from "./deploy";

const BOT_SIGNATURE =
"<sub>🔥 via [Firebase Hosting GitHub Action](https://github.com/marketplace/actions/deploy-to-firebase-hosting) 🌎</sub>";

export function isCommentByBot(comment): boolean {
return comment.user.type === "Bot" && comment.body.includes(BOT_SIGNATURE);
}

export function getURLsMarkdownFromChannelDeployResult(
result: ChannelSuccessResult
): string {
const { urls } = interpretChannelDeployResult(result);

return urls.length === 1
? `[${urls[0]}](${urls[0]})`
: urls.map((url) => `- [${url}](${url})`).join("\n");
}

export function getChannelDeploySuccessComment(
result: ChannelSuccessResult,
commit: string
) {
const urlList = getURLsMarkdownFromChannelDeployResult(result);
const { expireTime } = interpretChannelDeployResult(result);

return `
Visit the preview URL for this PR (updated for commit ${commit}):
${urlList}
<sub>(expires ${new Date(expireTime).toUTCString()})</sub>
${BOT_SIGNATURE}`.trim();
}

export async function postChannelSuccessComment(
github: GitHub | undefined,
context: Context,
result: ChannelSuccessResult,
commit: string
) {
const commentMarkdown = getChannelDeploySuccessComment(result, commit);

return postOrUpdateComment(github, context, commentMarkdown);
}

// create a PR comment, or update one if it already exists
export async function postOrUpdateComment(
async function postOrUpdateComment(
github: GitHub | undefined,
context: Context,
commentMarkdown: string
Expand All @@ -36,21 +86,16 @@ export async function postOrUpdateComment(

const comment = {
...commentInfo,
body:
commentMarkdown +
"\n\n<sub>🔥 via [Firebase Hosting GitHub Action](https://github.com/marketplace/actions/deploy-to-firebase-hosting) 🌎</sub>",
body: commentMarkdown,
};

startGroup(`Updating PR comment`);
startGroup(`Commenting on PR`);
let commentId;
try {
const comments = (await github.issues.listComments(commentInfo)).data;
for (let i = comments.length; i--; ) {
const c = comments[i];
if (
c.user.type === "Bot" &&
/<sub>[\s\n]*🔥 via \[Firebase Hosting GitHub Action/.test(c.body)
) {
if (isCommentByBot(c)) {
commentId = c.id;
break;
}
Expand Down
Loading

0 comments on commit 276388d

Please sign in to comment.