diff --git a/.eslintrc.json b/.eslintrc.json index 241986aa..a427f9e5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,14 +4,53 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 9, - "sourceType": "module" + "sourceType": "module", + "project": "./tsconfig.json" }, "rules": { - "no-unused-vars": "off", "eslint-comments/no-use": "off", "import/no-namespace": "off", + "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "error", - "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}] + "@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/camelcase": "error", + "@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", + "no-extra-parens": "off", + "@typescript-eslint/no-extra-parens": "error", + "@typescript-eslint/no-extraneous-class": "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", "never"], + "@typescript-eslint/type-annotation-spacing": "error", + "@typescript-eslint/unbound-method": "error" }, "env": { "node": true, diff --git a/packages/core/__tests__/lib.test.ts b/packages/core/__tests__/lib.test.ts index a21b51e1..b1f638c8 100644 --- a/packages/core/__tests__/lib.test.ts +++ b/packages/core/__tests__/lib.test.ts @@ -1,6 +1,9 @@ +import {ExitCode} from '@actions/exit' import * as os from 'os' import * as core from '../src/core' +/* eslint-disable @typescript-eslint/unbound-method */ + const testEnvVars = { 'my var': '', 'special char var \r\n];': '', @@ -103,18 +106,18 @@ describe('@actions/core', () => { it('setNeutral sets the correct exit code', () => { core.setFailed('Failure message') - expect(process.exitCode).toBe(1) + expect(process.exitCode).toBe(ExitCode.Failure) }) it('setFailure sets the correct exit code and failure message', () => { core.setFailed('Failure message') - expect(process.exitCode).toBe(1) + expect(process.exitCode).toBe(ExitCode.Failure) assertWriteCalls([`##[error]Failure message${os.EOL}`]) }) it('setFailure escapes the failure message', () => { core.setFailed('Failure \r\n\nmessage\r') - expect(process.exitCode).toBe(1) + expect(process.exitCode).toBe(ExitCode.Failure) assertWriteCalls([`##[error]Failure %0D%0A%0Amessage%0D${os.EOL}`]) }) @@ -150,7 +153,7 @@ describe('@actions/core', () => { }) // Assert that process.stdout.write calls called only with the given arguments. -function assertWriteCalls(calls: string[]) { +function assertWriteCalls(calls: string[]): void { expect(process.stdout.write).toHaveBeenCalledTimes(calls.length) for (let i = 0; i < calls.length; i++) { diff --git a/packages/core/src/command.ts b/packages/core/src/command.ts index b277bfb2..73c27aed 100644 --- a/packages/core/src/command.ts +++ b/packages/core/src/command.ts @@ -2,6 +2,10 @@ import * as os from 'os' // For internal use, subject to change. +interface CommandProperties { + [key: string]: string +} + /** * Commands * @@ -14,25 +18,25 @@ import * as os from 'os' */ export function issueCommand( command: string, - properties: any, + properties: CommandProperties, message: string -) { +): void { const cmd = new Command(command, properties, message) process.stdout.write(cmd.toString() + os.EOL) } -export function issue(name: string, message: string) { +export function issue(name: string, message: string): void { issueCommand(name, {}, message) } const CMD_PREFIX = '##[' class Command { - constructor( - command: string, - properties: {[key: string]: string}, - message: string - ) { + private readonly command: string + private readonly message: string + private readonly properties: CommandProperties + + constructor(command: string, properties: CommandProperties, message: string) { if (!command) { command = 'missing.command' } @@ -42,11 +46,7 @@ class Command { this.message = message } - command: string - message: string - properties: {[key: string]: string} - - toString() { + toString(): string { let cmdStr = CMD_PREFIX + this.command if (this.properties && Object.keys(this.properties).length > 0) { @@ -67,7 +67,7 @@ class Command { // safely append the message - avoid blowing up when attempting to // call .replace() if message is not a string for some reason - const message: string = `${this.message || ''}` + const message = `${this.message || ''}` cmdStr += escapeData(message) return cmdStr diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 408b9ad1..f63ef1c6 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -18,7 +18,7 @@ export interface InputOptions { * @param name the name of the variable to set * @param val the value of the variable */ -export function exportVariable(name: string, val: string) { +export function exportVariable(name: string, val: string): void { process.env[name] = val issueCommand('set-env', {name}, val) } @@ -28,7 +28,7 @@ export function exportVariable(name: string, val: string) { * @param name the name of the variable to set * @param val value of the secret */ -export function exportSecret(name: string, val: string) { +export function exportSecret(name: string, val: string): void { exportVariable(name, val) issueCommand('set-secret', {}, val) } @@ -57,7 +57,7 @@ export function getInput(name: string, options?: InputOptions): string { /** * Sets the action status to neutral */ -export function setNeutral() { +export function setNeutral(): void { process.exitCode = ExitCode.Neutral } @@ -66,7 +66,7 @@ export function setNeutral() { * When the action exits it will be with an exit code of 1 * @param message add error issue message */ -export function setFailed(message: string) { +export function setFailed(message: string): void { process.exitCode = ExitCode.Failure error(message) } @@ -79,7 +79,7 @@ export function setFailed(message: string) { * Writes debug message to user log * @param message debug message */ -export function debug(message: string) { +export function debug(message: string): void { issueCommand('debug', {}, message) } @@ -87,7 +87,7 @@ export function debug(message: string) { * Adds an error issue * @param message error issue message */ -export function error(message: string) { +export function error(message: string): void { issue('error', message) } @@ -95,6 +95,6 @@ export function error(message: string) { * Adds an warning issue * @param message warning issue message */ -export function warning(message: string) { +export function warning(message: string): void { issue('warning', message) } diff --git a/packages/exit/__tests__/exit.test.ts b/packages/exit/__tests__/exit.test.ts index 31ae074f..f7de0e99 100644 --- a/packages/exit/__tests__/exit.test.ts +++ b/packages/exit/__tests__/exit.test.ts @@ -1,5 +1,7 @@ import * as exit from '../src/exit' +/* eslint-disable @typescript-eslint/unbound-method */ + it('exits successfully', () => { jest.spyOn(process, 'exit').mockImplementation() exit.success() diff --git a/packages/exit/src/exit.ts b/packages/exit/src/exit.ts index ecea2961..81ef86e2 100644 --- a/packages/exit/src/exit.ts +++ b/packages/exit/src/exit.ts @@ -24,20 +24,20 @@ export enum ExitCode { /** * Exit the action as a success. */ -export function success() { +export function success(): void { process.exit(ExitCode.Success) } /** * Exit the action as a failure. */ -export function failure() { +export function failure(): void { process.exit(ExitCode.Failure) } /** * Exit the action neither a success or a failure */ -export function neutral() { +export function neutral(): void { process.exit(ExitCode.Neutral) } diff --git a/packages/toolkit/__tests__/exit.test.ts b/packages/toolkit/__tests__/exit.test.ts index d3901977..f7e1111b 100644 --- a/packages/toolkit/__tests__/exit.test.ts +++ b/packages/toolkit/__tests__/exit.test.ts @@ -2,6 +2,8 @@ import * as exitPkg from '@actions/exit' import {Signale} from 'signale' import {Exit} from '../src/exit' +/* eslint-disable @typescript-eslint/unbound-method */ + jest.mock('@actions/exit') const tests: [keyof Exit, keyof Signale][] = [ diff --git a/packages/toolkit/__tests__/toolkit.test.ts b/packages/toolkit/__tests__/toolkit.test.ts index d8dd3254..2a88b4d8 100644 --- a/packages/toolkit/__tests__/toolkit.test.ts +++ b/packages/toolkit/__tests__/toolkit.test.ts @@ -2,6 +2,8 @@ import * as exitPkg from '@actions/exit' import {Signale} from 'signale' import {Toolkit} from '../src/toolkit' +/* eslint-disable @typescript-eslint/unbound-method */ + jest.mock('@actions/exit') describe('.run', () => { diff --git a/packages/toolkit/src/exit.ts b/packages/toolkit/src/exit.ts index 69000aac..101a4dd7 100644 --- a/packages/toolkit/src/exit.ts +++ b/packages/toolkit/src/exit.ts @@ -10,7 +10,7 @@ export class Exit { /** * Stop the action with a "success" status. */ - success(message?: string) { + success(message?: string): void { if (message) this.logger.success(message) exit.success() } @@ -18,7 +18,7 @@ export class Exit { /** * Stop the action with a "neutral" status. */ - neutral(message?: string) { + neutral(message?: string): void { if (message) this.logger.info(message) exit.neutral() } @@ -26,7 +26,7 @@ export class Exit { /** * Stop the action with a "failed" status. */ - failure(message?: string) { + failure(message?: string): void { if (message) this.logger.fatal(message) exit.failure() } diff --git a/packages/toolkit/src/toolkit.ts b/packages/toolkit/src/toolkit.ts index 255b9c48..4d563473 100644 --- a/packages/toolkit/src/toolkit.ts +++ b/packages/toolkit/src/toolkit.ts @@ -6,7 +6,7 @@ export type ActionFn = (tools: Toolkit) => unknown /** * Options used to customize an instance of [[Toolkit]] */ -export type ToolkitOptions = { +export interface ToolkitOptions { /** * A custom Signale instance to use */ @@ -30,7 +30,7 @@ export class Toolkit { * If an error occurs, the error will be logged and the action will exit as a * failure. */ - static async run(func: ActionFn, opts?: ToolkitOptions) { + static async run(func: ActionFn, opts?: ToolkitOptions): Promise { const tools = new Toolkit(opts) try { @@ -69,7 +69,7 @@ export class Toolkit { /** * Ensure that the given keys are in the environment. */ - private checkRequiredEnv(keys: string[]) { + private checkRequiredEnv(keys: string[]): void { const missingEnv = keys.filter(key => !process.env.hasOwnProperty(key)) if (missingEnv.length === 0) return @@ -84,7 +84,7 @@ export class Toolkit { /** * Wrap a Signale logger so that its a callable class. */ - private wrapLogger(logger: Signale) { + private wrapLogger(logger: Signale): Signale & LoggerFunc { // Create a callable function const fn = logger.info.bind(logger) // Add the log methods onto the function