Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lint: add eslint config, fix lint issues, enforce clean lint status pre-commit and in CI #64

Closed
wants to merge 8 commits into from
Closed
2 changes: 2 additions & 0 deletions .eslintignore
@@ -0,0 +1,2 @@
dist/
node_modules/
59 changes: 59 additions & 0 deletions .eslintrc.json
@@ -0,0 +1,59 @@
{
"plugins": ["jest", "@typescript-eslint"],
"extends": ["plugin:github/es6"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"project": "./tsconfig.json"
},
"rules": {
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"no-console": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-ignore": "error",
"camelcase": "off",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
"@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-object-literal-type-assertion": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-interface": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"semi": "off",
"@typescript-eslint/semi": ["error", "always"],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error"
},
"env": {
"node": true,
"es6": true,
"jest/globals": true
}
}
19 changes: 19 additions & 0 deletions .github/workflows/lint.yml
@@ -0,0 +1,19 @@
name: Build and Analyze

on:
pull_request:
push:
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: v14
- uses: actions/checkout@v2
- run: yarn
- run: yarn build
- run: yarn format-check
- run: yarn lint
1 change: 1 addition & 0 deletions .husky/.gitignore
@@ -0,0 +1 @@
_
4 changes: 4 additions & 0 deletions .husky/pre-commit
@@ -0,0 +1,4 @@
#!/bin/sh
yarn build && git add dist/index.js
yarn format-check
yarn lint
2 changes: 2 additions & 0 deletions .prettierignore
@@ -0,0 +1,2 @@
dist/
node_modules/
11 changes: 11 additions & 0 deletions .prettierrc.json
@@ -0,0 +1,11 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "avoid",
"parser": "typescript"
}
15 changes: 8 additions & 7 deletions dist/index.js
Expand Up @@ -5862,7 +5862,7 @@ async function main() {
}
console.log({ eventName, sha, headSha, branch, owner, repo, GITHUB_RUN_ID });
const token = core.getInput('access_token', { required: true });
const workflow_id = core.getInput('workflow_id', { required: false });
const workflow_id_input = core.getInput('workflow_id', { required: false });
const ignore_sha = core.getInput('ignore_sha', { required: false }) === 'true';
console.log(`Found token: ${token ? 'yes' : 'no'}`);
const workflow_ids = [];
Expand All @@ -5872,13 +5872,14 @@ async function main() {
repo,
run_id: Number(GITHUB_RUN_ID)
});
if (workflow_id) {
workflow_id.replace(/\s/g, '')
.split(',')
.forEach(n => workflow_ids.push(n));
if (workflow_id_input) {
const workflow_ids_input = workflow_id_input.replace(/\s/g, '').split(',');
for (const id of workflow_ids_input) {
workflow_ids.push(parseInt(id, 10));
}
}
else {
workflow_ids.push(String(current_run.workflow_id));
workflow_ids.push(current_run.workflow_id);
}
console.log(`Found workflow_id: ${JSON.stringify(workflow_ids)}`);
await Promise.all(workflow_ids.map(async (workflow_id) => {
Expand All @@ -5887,7 +5888,7 @@ async function main() {
owner,
repo,
workflow_id,
branch,
branch
});
const branchWorkflows = data.workflow_runs.filter(run => run.head_branch === branch);
console.log(`Found ${branchWorkflows.length} runs for workflow ${workflow_id} on branch ${branch}`);
Expand Down
14 changes: 12 additions & 2 deletions package.json
Expand Up @@ -4,14 +4,24 @@
"main": "dist/index.js",
"license": "MIT",
"scripts": {
"build": "ncc build src/index.ts --license LICENSES.txt"
"build": "ncc build src/index.ts --license LICENSES.txt",
"format": "prettier --write '**/*.ts'",
"format-check": "prettier --check '**/*.ts'",
"lint": "eslint src/**/*.ts",
"prepare": "husky install"
},
"dependencies": {
"@actions/core": "1.2.6",
"@actions/github": "4.0.0"
},
"devDependencies": {
"@typescript-eslint/parser": "^2.8.0",
"@vercel/ncc": "0.27.0",
"typescript": "4.1.5"
"eslint": "^5.16.0",
"eslint-plugin-github": "^2.0.0",
"eslint-plugin-jest": "^22.21.0",
"prettier": "2.2.1",
"typescript": "4.1.5",
"husky": "^6.0.0"
}
}
93 changes: 52 additions & 41 deletions src/index.ts
Expand Up @@ -9,8 +9,14 @@ if (!core) {
throw new Error('Module not found: core');
}

async function main() {
const { eventName, sha, ref, repo: { owner, repo }, payload } = github.context;
async function main(): Promise<void> {
const {
eventName,
sha,
ref,
repo: { owner, repo },
payload
} = github.context;
const { GITHUB_RUN_ID } = process.env;

let branch = ref.slice(11);
Expand All @@ -25,10 +31,10 @@ async function main() {

console.log({ eventName, sha, headSha, branch, owner, repo, GITHUB_RUN_ID });
const token = core.getInput('access_token', { required: true });
const workflow_id = core.getInput('workflow_id', { required: false });
const workflow_id_input = core.getInput('workflow_id', { required: false });
const ignore_sha = core.getInput('ignore_sha', { required: false }) === 'true';
console.log(`Found token: ${token ? 'yes' : 'no'}`);
const workflow_ids: string[] = [];
const workflow_ids: number[] = [];
const octokit = github.getOctokit(token);

const { data: current_run } = await octokit.actions.getWorkflowRun({
Expand All @@ -37,54 +43,59 @@ async function main() {
run_id: Number(GITHUB_RUN_ID)
});

if (workflow_id) {
if (workflow_id_input) {
// The user provided one or more workflow id
workflow_id.replace(/\s/g, '')
.split(',')
.forEach(n => workflow_ids.push(n));
const workflow_ids_input = workflow_id_input.replace(/\s/g, '').split(',');
for (const id of workflow_ids_input) {
workflow_ids.push(parseInt(id, 10));
}
} else {
// The user did not provide workflow id so derive from current run
workflow_ids.push(String(current_run.workflow_id));
workflow_ids.push(current_run.workflow_id);
}

console.log(`Found workflow_id: ${JSON.stringify(workflow_ids)}`);

await Promise.all(workflow_ids.map(async (workflow_id) => {
try {
const { data } = await octokit.actions.listWorkflowRuns({
owner,
repo,
// @ts-ignore
workflow_id,
branch,
});

const branchWorkflows = data.workflow_runs.filter(run => run.head_branch === branch);
console.log(`Found ${branchWorkflows.length} runs for workflow ${workflow_id} on branch ${branch}`);
console.log(branchWorkflows.map(run => `- ${run.html_url}`).join('\n'));

const runningWorkflows = branchWorkflows.filter(run =>
(ignore_sha || run.head_sha !== headSha) &&
run.status !== 'completed' &&
new Date(run.created_at) < new Date(current_run.created_at)
);
console.log(`with ${runningWorkflows.length} runs to cancel.`);

for (const {id, head_sha, status, html_url} of runningWorkflows) {
console.log('Canceling run: ', {id, head_sha, status, html_url});
const res = await octokit.actions.cancelWorkflowRun({
await Promise.all(
workflow_ids.map(async workflow_id => {
try {
const { data } = await octokit.actions.listWorkflowRuns({
owner,
repo,
run_id: id
workflow_id,
branch
});
console.log(`Cancel run ${id} responded with status ${res.status}`);

const branchWorkflows = data.workflow_runs.filter(run => run.head_branch === branch);
console.log(
`Found ${branchWorkflows.length} runs for workflow ${workflow_id} on branch ${branch}`
);
console.log(branchWorkflows.map(run => `- ${run.html_url}`).join('\n'));

const runningWorkflows = branchWorkflows.filter(
run =>
(ignore_sha || run.head_sha !== headSha) &&
run.status !== 'completed' &&
new Date(run.created_at) < new Date(current_run.created_at)
);
console.log(`with ${runningWorkflows.length} runs to cancel.`);

for (const { id, head_sha, status, html_url } of runningWorkflows) {
console.log('Canceling run: ', { id, head_sha, status, html_url });
const res = await octokit.actions.cancelWorkflowRun({
owner,
repo,
run_id: id
});
console.log(`Cancel run ${id} responded with status ${res.status}`);
}
} catch (e) {
const msg = e.message || e;
console.log(`Error while canceling workflow_id ${workflow_id}: ${msg}`);
}
} catch (e) {
const msg = e.message || e;
console.log(`Error while canceling workflow_id ${workflow_id}: ${msg}`);
}
console.log('')
}));
console.log('');
})
);
}

main()
Expand Down