Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: CI

on:
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: devfolioco/typescript-coverage-report@Add-Github-Action
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
38 changes: 38 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: "Typescript Coverage Report"
author: "Preet Parekh <[email protected]>"
description: "Github Actin for generating TypeScript coverage reports"
branding:
icon: "search"
color: "orange"
inputs:
name:
description: |
The name of the check ("Typescript Coverage Report" by default).
In case of multiple Typescript Coverage Report Actions, use `name` to prevent GitHub from overwriting results.
For example, "Check Public API" and "Check Internal API".
# annotations:
# description: "Use annotation (enabled by default)"
# fail-on-breaking:
# description: "Fail on breaking changes (enabled by default)"
# schema:
# description: |
# Ref and Path to GraphQL Schema (e.g. "master:schema.graphql")
# * Ref is needed where 'endpoint' is not defined
# required: true
# endpoint:
# description: |
# Url to your GraphQL API
# When using an endpoint, 'schema' should point to a file (without a reference - branch name for example)
github-token:
description: "Github Token"
# experimental_merge:
# description: |
# Merge Pull Request's branch with the target branch to get the schema.
# Helps to get the correct state of schema when Pull Request is behind the target branch
# (disabled by default)
# outputs:
# changes:
# description: "Total number of changes"
runs:
using: "node12"
main: "action/index.js"
1 change: 1 addition & 0 deletions action/index.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions action/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as core from "@actions/core";

import { run } from "./run";

run().catch((e) => {
core.setFailed(e.message || e);
});
78 changes: 78 additions & 0 deletions action/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import * as core from "@actions/core";
import * as github from "@actions/github";

import { generate } from "../src/lib/reporters/markdown";
import getCoverage from "../src/lib/getCoverage";
import { getCurrentCommitSha, noWhiteSpace, updateCheckRun } from "./utils";

const CHECK_NAME = "Typescript Coverage Report";

export const run = async (): Promise<void> => {
core.info(`Typescript Coverage Reporter started`);

const ref = process.env.GITHUB_SHA;
const commitSha = getCurrentCommitSha();

const githubURL = process.env.GITHUB_SERVER_URL;
const githubHeadRef = process.env.GITHUB_HEAD_REF;
const githubRepo = process.env.GITHUB_REPOSITORY;

const baseURL = `${githubURL}/${githubRepo}/tree/${githubHeadRef}`;

core.info(`Ref: ${ref}`);
core.info(`Commit SHA: ${commitSha}`);

/**
* env:
* GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
*/
const token = core.getInput("github-token") || process.env.GITHUB_TOKEN;
const checkName = core.getInput("name") || CHECK_NAME;

if (!token) {
return core.setFailed("Github Token is missing");
}

const octokit = github.getOctokit(token);

// repo
const { owner, repo } = github.context.repo;

core.info(`Creating a check named "${checkName}"`);

const check = await octokit.checks.create({
owner,
repo,
name: checkName,
// eslint-disable-next-line @typescript-eslint/camelcase
head_sha: commitSha,
status: "in_progress"
});

const checkId = check.data.id;

core.info(`Check ID: ${checkId}`);

const threshold = 90;

const coverageResult = await getCoverage();
const markdownReport = generate(coverageResult, threshold, baseURL);

const coverage = coverageResult.percentage.toFixed(2);

const summary = [
"The following is the Typescript Coverage Report for this Pull Request",
"## Indicators",
`🟥 -> Indicates that the file has failed the type threshold (${threshold}%)`,
`🟩 -> Indicates that the file has passed the type threshold (${threshold}%)`
];

updateCheckRun(octokit, checkId, {
conclusion: "neutral",
output: {
title: `${coverage}% Coverage`,
summary: summary.join('\n'),
text: markdownReport
}
});
};
70 changes: 70 additions & 0 deletions action/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as github from "@actions/github";
import * as core from "@actions/core";
import { RestEndpointMethodTypes } from "@octokit/rest";
import { execSync } from "child_process";

function getCurrentCommitSha() {
const sha = execSync(`git rev-parse HEAD`).toString().trim();

try {
const msg = execSync(`git show ${sha} -s --format=%s`).toString().trim();
const PR_MSG = /Merge (\w+) into \w+/i;

if (PR_MSG.test(msg)) {
const result = PR_MSG.exec(msg);

if (result) {
return result[1];
}
}
} catch (e) {
//
}
return sha;
}

type OctokitInstance = ReturnType<typeof github.getOctokit>;

type UpdateCheckRunOptions = Required<
Pick<
RestEndpointMethodTypes["checks"]["update"]["parameters"],
"conclusion" | "output"
>
>;

async function updateCheckRun(
octokit: OctokitInstance,
checkId: number,
{ conclusion, output }: UpdateCheckRunOptions
) {
core.info(`Updating check: ${checkId}`);
await octokit.checks.update({
// eslint-disable-next-line @typescript-eslint/camelcase
check_run_id: checkId,
// eslint-disable-next-line @typescript-eslint/camelcase
completed_at: new Date().toISOString(),
status: "completed",
...github.context.repo,
conclusion,
output
});

// Fail
if (conclusion === "failure") {
return core.setFailed(output.title!);
}
}

/**
* @todo Remove this
*/
function noWhiteSpace(strings, ...placeholders) {
// Build the string as normal, combining all the strings and placeholders:
const withSpace: string = strings.reduce(
(result, string, i) => result + placeholders[i - 1] + string
);
const withoutSpace = withSpace.replace(/\s\s+/g, " ");
return withoutSpace;
}

export { getCurrentCommitSha, updateCheckRun, noWhiteSpace };
Loading