Add initial eslint setup (#88)
This commit is contained in:
		
							
								
								
									
										16
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| { | ||||
|   "env": { "node": true, "jest": true }, | ||||
|   "parser": "@typescript-eslint/parser", | ||||
|   "parserOptions": { "ecmaVersion": 2020, "sourceType": "module" }, | ||||
|   "extends": [ | ||||
|     "eslint:recommended", | ||||
|     "plugin:@typescript-eslint/eslint-recommended", | ||||
|     "plugin:@typescript-eslint/recommended", | ||||
|     "plugin:import/errors", | ||||
|     "plugin:import/warnings", | ||||
|     "plugin:import/typescript", | ||||
|     "plugin:prettier/recommended", | ||||
|     "prettier/@typescript-eslint" | ||||
|   ], | ||||
|   "plugins": ["@typescript-eslint", "jest"] | ||||
| } | ||||
							
								
								
									
										12
									
								
								.github/workflows/workflow.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/workflow.yml
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1,5 @@ | ||||
| name: Tests | ||||
|  | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
| @ -14,14 +15,16 @@ on: | ||||
| jobs: | ||||
|   test: | ||||
|     name: Test on ${{ matrix.os }} | ||||
|  | ||||
|     strategy: | ||||
|       matrix: | ||||
|         os: [ubuntu-latest, windows-latest, macOS-latest] | ||||
|  | ||||
|     runs-on: ${{ matrix.os }} | ||||
|      | ||||
|  | ||||
|     steps: | ||||
|     - uses: actions/checkout@v1 | ||||
|        | ||||
|  | ||||
|     - uses: actions/setup-node@v1 | ||||
|       with: | ||||
|         node-version: '12.x' | ||||
| @ -29,7 +32,12 @@ jobs: | ||||
|     - run: npm ci | ||||
|  | ||||
|     - name: Prettier Format Check | ||||
|       if: matrix.os == 'ubuntu-latest' | ||||
|       run: npm run format-check | ||||
|  | ||||
|     - name: ESLint Check | ||||
|       if: matrix.os == 'ubuntu-latest' | ||||
|       run: npm run lint | ||||
|  | ||||
|     - name: Build & Test | ||||
|       run: npm run test | ||||
|  | ||||
| @ -1,9 +1,7 @@ | ||||
| import * as core from "@actions/core"; | ||||
| import * as exec from "@actions/exec"; | ||||
| import * as io from "@actions/io"; | ||||
|  | ||||
| import * as path from "path"; | ||||
|  | ||||
| import * as cacheHttpClient from "../src/cacheHttpClient"; | ||||
| import { Inputs } from "../src/constants"; | ||||
| import { ArtifactCacheEntry } from "../src/contracts"; | ||||
| @ -107,7 +105,7 @@ test("restore with no cache found", async () => { | ||||
|     const stateMock = jest.spyOn(core, "saveState"); | ||||
|  | ||||
|     const clientMock = jest.spyOn(cacheHttpClient, "getCacheEntry"); | ||||
|     clientMock.mockImplementation(_ => { | ||||
|     clientMock.mockImplementation(() => { | ||||
|         return Promise.resolve(null); | ||||
|     }); | ||||
|  | ||||
| @ -134,7 +132,7 @@ test("restore with server error should fail", async () => { | ||||
|     const stateMock = jest.spyOn(core, "saveState"); | ||||
|  | ||||
|     const clientMock = jest.spyOn(cacheHttpClient, "getCacheEntry"); | ||||
|     clientMock.mockImplementation(_ => { | ||||
|     clientMock.mockImplementation(() => { | ||||
|         throw new Error("HTTP Error Occurred"); | ||||
|     }); | ||||
|  | ||||
| @ -168,7 +166,7 @@ test("restore with restore keys and no cache found", async () => { | ||||
|     const stateMock = jest.spyOn(core, "saveState"); | ||||
|  | ||||
|     const clientMock = jest.spyOn(cacheHttpClient, "getCacheEntry"); | ||||
|     clientMock.mockImplementation(_ => { | ||||
|     clientMock.mockImplementation(() => { | ||||
|         return Promise.resolve(null); | ||||
|     }); | ||||
|  | ||||
| @ -202,7 +200,7 @@ test("restore with cache found", async () => { | ||||
|         archiveLocation: "www.actionscache.test/download" | ||||
|     }; | ||||
|     const getCacheMock = jest.spyOn(cacheHttpClient, "getCacheEntry"); | ||||
|     getCacheMock.mockImplementation(_ => { | ||||
|     getCacheMock.mockImplementation(() => { | ||||
|         return Promise.resolve(cacheEntry); | ||||
|     }); | ||||
|     const tempPath = "/foo/bar"; | ||||
| @ -278,7 +276,7 @@ test("restore with cache found for restore key", async () => { | ||||
|         archiveLocation: "www.actionscache.test/download" | ||||
|     }; | ||||
|     const getCacheMock = jest.spyOn(cacheHttpClient, "getCacheEntry"); | ||||
|     getCacheMock.mockImplementation(_ => { | ||||
|     getCacheMock.mockImplementation(() => { | ||||
|         return Promise.resolve(cacheEntry); | ||||
|     }); | ||||
|     const tempPath = "/foo/bar"; | ||||
|  | ||||
| @ -1,22 +1,23 @@ | ||||
| require('nock').disableNetConnect(); | ||||
| require("nock").disableNetConnect(); | ||||
|  | ||||
| module.exports = { | ||||
|   clearMocks: true, | ||||
|   moduleFileExtensions: ['js', 'ts'], | ||||
|   testEnvironment: 'node', | ||||
|   testMatch: ['**/*.test.ts'], | ||||
|   testRunner: 'jest-circus/runner', | ||||
|   transform: { | ||||
|     '^.+\\.ts$': 'ts-jest' | ||||
|   }, | ||||
|   verbose: true | ||||
| } | ||||
|     clearMocks: true, | ||||
|     moduleFileExtensions: ["js", "ts"], | ||||
|     testEnvironment: "node", | ||||
|     testMatch: ["**/*.test.ts"], | ||||
|     testRunner: "jest-circus/runner", | ||||
|     transform: { | ||||
|         "^.+\\.ts$": "ts-jest" | ||||
|     }, | ||||
|     verbose: true | ||||
| }; | ||||
|  | ||||
| const processStdoutWrite = process.stdout.write.bind(process.stdout) | ||||
| const processStdoutWrite = process.stdout.write.bind(process.stdout); | ||||
| // eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||||
| process.stdout.write = (str, encoding, cb) => { | ||||
|   // Core library will directly call process.stdout.write for commands | ||||
|   // We don't want :: commands to be executed by the runner during tests | ||||
|   if (!str.match(/^::/)) { | ||||
|     return processStdoutWrite(str, encoding, cb); | ||||
|   } | ||||
| } | ||||
|     // Core library will directly call process.stdout.write for commands | ||||
|     // We don't want :: commands to be executed by the runner during tests | ||||
|     if (!str.match(/^::/)) { | ||||
|         return processStdoutWrite(str, encoding, cb); | ||||
|     } | ||||
| }; | ||||
|  | ||||
							
								
								
									
										924
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										924
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										12
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
									
									
									
									
								
							| @ -7,8 +7,9 @@ | ||||
|   "scripts": { | ||||
|     "build": "tsc", | ||||
|     "test": "tsc --noEmit && jest --coverage", | ||||
|     "format": "prettier --write **/*.ts", | ||||
|     "format-check": "prettier --check **/*.ts", | ||||
|     "lint": "eslint '**/*.ts' --cache", | ||||
|     "format": "prettier --write '**/*.ts'", | ||||
|     "format-check": "prettier --check '**/*.ts'", | ||||
|     "release": "ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && git add -f dist/" | ||||
|   }, | ||||
|   "repository": { | ||||
| @ -34,7 +35,14 @@ | ||||
|     "@types/nock": "^11.1.0", | ||||
|     "@types/node": "^12.0.4", | ||||
|     "@types/uuid": "^3.4.5", | ||||
|     "@typescript-eslint/eslint-plugin": "^2.7.0", | ||||
|     "@typescript-eslint/parser": "^2.7.0", | ||||
|     "@zeit/ncc": "^0.20.5", | ||||
|     "eslint": "^6.6.0", | ||||
|     "eslint-config-prettier": "^6.5.0", | ||||
|     "eslint-plugin-import": "^2.18.2", | ||||
|     "eslint-plugin-jest": "^23.0.3", | ||||
|     "eslint-plugin-prettier": "^3.1.1", | ||||
|     "jest": "^24.8.0", | ||||
|     "jest-circus": "^24.7.1", | ||||
|     "nock": "^11.7.0", | ||||
|  | ||||
| @ -1,13 +1,40 @@ | ||||
| import * as core from "@actions/core"; | ||||
| import * as fs from "fs"; | ||||
|  | ||||
| import { BearerCredentialHandler } from "typed-rest-client/Handlers"; | ||||
| import { HttpClient } from "typed-rest-client/HttpClient"; | ||||
| import { IHttpClientResponse } from "typed-rest-client/Interfaces"; | ||||
| import { RestClient, IRequestOptions } from "typed-rest-client/RestClient"; | ||||
|  | ||||
| import { IRequestOptions, RestClient } from "typed-rest-client/RestClient"; | ||||
| import { ArtifactCacheEntry } from "./contracts"; | ||||
|  | ||||
| function getCacheUrl(): string { | ||||
|     // Ideally we just use ACTIONS_CACHE_URL | ||||
|     const cacheUrl: string = ( | ||||
|         process.env["ACTIONS_CACHE_URL"] || | ||||
|         process.env["ACTIONS_RUNTIME_URL"] || | ||||
|         "" | ||||
|     ).replace("pipelines", "artifactcache"); | ||||
|     if (!cacheUrl) { | ||||
|         throw new Error( | ||||
|             "Cache Service Url not found, unable to restore cache." | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     core.debug(`Cache Url: ${cacheUrl}`); | ||||
|     return cacheUrl; | ||||
| } | ||||
|  | ||||
| function createAcceptHeader(type: string, apiVersion: string): string { | ||||
|     return `${type};api-version=${apiVersion}`; | ||||
| } | ||||
|  | ||||
| function getRequestOptions(): IRequestOptions { | ||||
|     const requestOptions: IRequestOptions = { | ||||
|         acceptHeader: createAcceptHeader("application/json", "5.2-preview.1") | ||||
|     }; | ||||
|  | ||||
|     return requestOptions; | ||||
| } | ||||
|  | ||||
| export async function getCacheEntry( | ||||
|     keys: string[] | ||||
| ): Promise<ArtifactCacheEntry | null> { | ||||
| @ -43,16 +70,6 @@ export async function getCacheEntry( | ||||
|     return cacheResult; | ||||
| } | ||||
|  | ||||
| export async function downloadCache( | ||||
|     cacheEntry: ArtifactCacheEntry, | ||||
|     archivePath: string | ||||
| ): Promise<void> { | ||||
|     const stream = fs.createWriteStream(archivePath); | ||||
|     const httpClient = new HttpClient("actions/cache"); | ||||
|     const downloadResponse = await httpClient.get(cacheEntry.archiveLocation!); | ||||
|     await pipeResponseToStream(downloadResponse, stream); | ||||
| } | ||||
|  | ||||
| async function pipeResponseToStream( | ||||
|     response: IHttpClientResponse, | ||||
|     stream: NodeJS.WritableStream | ||||
| @ -64,7 +81,21 @@ async function pipeResponseToStream( | ||||
|     }); | ||||
| } | ||||
|  | ||||
| export async function saveCache(stream: NodeJS.ReadableStream, key: string) { | ||||
| export async function downloadCache( | ||||
|     cacheEntry: ArtifactCacheEntry, | ||||
|     archivePath: string | ||||
| ): Promise<void> { | ||||
|     const stream = fs.createWriteStream(archivePath); | ||||
|     const httpClient = new HttpClient("actions/cache"); | ||||
|     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||||
|     const downloadResponse = await httpClient.get(cacheEntry.archiveLocation!); | ||||
|     await pipeResponseToStream(downloadResponse, stream); | ||||
| } | ||||
|  | ||||
| export async function saveCache( | ||||
|     stream: NodeJS.ReadableStream, | ||||
|     key: string | ||||
| ): Promise<void> { | ||||
|     const cacheUrl = getCacheUrl(); | ||||
|     const token = process.env["ACTIONS_RUNTIME_TOKEN"] || ""; | ||||
|     const bearerCredentialHandler = new BearerCredentialHandler(token); | ||||
| @ -93,32 +124,3 @@ export async function saveCache(stream: NodeJS.ReadableStream, key: string) { | ||||
|  | ||||
|     core.info("Cache saved successfully"); | ||||
| } | ||||
|  | ||||
| function getRequestOptions(): IRequestOptions { | ||||
|     const requestOptions: IRequestOptions = { | ||||
|         acceptHeader: createAcceptHeader("application/json", "5.2-preview.1") | ||||
|     }; | ||||
|  | ||||
|     return requestOptions; | ||||
| } | ||||
|  | ||||
| function createAcceptHeader(type: string, apiVersion: string): string { | ||||
|     return `${type};api-version=${apiVersion}`; | ||||
| } | ||||
|  | ||||
| function getCacheUrl(): string { | ||||
|     // Ideally we just use ACTIONS_CACHE_URL | ||||
|     let cacheUrl: string = ( | ||||
|         process.env["ACTIONS_CACHE_URL"] || | ||||
|         process.env["ACTIONS_RUNTIME_URL"] || | ||||
|         "" | ||||
|     ).replace("pipelines", "artifactcache"); | ||||
|     if (!cacheUrl) { | ||||
|         throw new Error( | ||||
|             "Cache Service Url not found, unable to restore cache." | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     core.debug(`Cache Url: ${cacheUrl}`); | ||||
|     return cacheUrl; | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| /* eslint-disable @typescript-eslint/no-namespace */ | ||||
| export namespace Inputs { | ||||
|     export const Key = "key"; | ||||
|     export const Path = "path"; | ||||
|  | ||||
| @ -1,14 +1,12 @@ | ||||
| import * as core from "@actions/core"; | ||||
| import { exec } from "@actions/exec"; | ||||
| import * as io from "@actions/io"; | ||||
|  | ||||
| import * as path from "path"; | ||||
|  | ||||
| import * as cacheHttpClient from "./cacheHttpClient"; | ||||
| import { Inputs, State } from "./constants"; | ||||
| import * as utils from "./utils/actionUtils"; | ||||
|  | ||||
| async function run() { | ||||
| async function run(): Promise<void> { | ||||
|     try { | ||||
|         // Validate inputs, this can cause task failure | ||||
|         let cachePath = utils.resolvePath( | ||||
|  | ||||
| @ -1,15 +1,13 @@ | ||||
| import * as core from "@actions/core"; | ||||
| import { exec } from "@actions/exec"; | ||||
|  | ||||
| import * as io from "@actions/io"; | ||||
| import * as fs from "fs"; | ||||
| import * as path from "path"; | ||||
|  | ||||
| import * as cacheHttpClient from "./cacheHttpClient"; | ||||
| import { Inputs, State } from "./constants"; | ||||
| import * as utils from "./utils/actionUtils"; | ||||
|  | ||||
| async function run() { | ||||
| async function run(): Promise<void> { | ||||
|     try { | ||||
|         const state = utils.getCacheState(); | ||||
|  | ||||
|  | ||||
| @ -4,7 +4,6 @@ import * as fs from "fs"; | ||||
| import * as os from "os"; | ||||
| import * as path from "path"; | ||||
| import * as uuidV4 from "uuid/v4"; | ||||
|  | ||||
| import { Outputs, State } from "../constants"; | ||||
| import { ArtifactCacheEntry } from "../contracts"; | ||||
|  | ||||
| @ -50,10 +49,18 @@ export function isExactKeyMatch( | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export function setCacheState(state: ArtifactCacheEntry): void { | ||||
|     core.saveState(State.CacheResult, JSON.stringify(state)); | ||||
| } | ||||
|  | ||||
| export function setCacheHitOutput(isCacheHit: boolean): void { | ||||
|     core.setOutput(Outputs.CacheHit, isCacheHit.toString()); | ||||
| } | ||||
|  | ||||
| export function setOutputAndState( | ||||
|     key: string, | ||||
|     cacheResult?: ArtifactCacheEntry | ||||
| ) { | ||||
| ): void { | ||||
|     setCacheHitOutput(isExactKeyMatch(key, cacheResult)); | ||||
|     // Store the cache result if it exists | ||||
|     cacheResult && setCacheState(cacheResult); | ||||
| @ -65,14 +72,6 @@ export function getCacheState(): ArtifactCacheEntry | undefined { | ||||
|     return (stateData && JSON.parse(stateData)) as ArtifactCacheEntry; | ||||
| } | ||||
|  | ||||
| export function setCacheState(state: ArtifactCacheEntry) { | ||||
|     core.saveState(State.CacheResult, JSON.stringify(state)); | ||||
| } | ||||
|  | ||||
| export function setCacheHitOutput(isCacheHit: boolean) { | ||||
|     core.setOutput(Outputs.CacheHit, isCacheHit.toString()); | ||||
| } | ||||
|  | ||||
| export function resolvePath(filePath: string): string { | ||||
|     if (filePath[0] === "~") { | ||||
|         const home = os.homedir(); | ||||
|  | ||||
| @ -5,7 +5,7 @@ function getInputName(name: string): string { | ||||
|     return `INPUT_${name.replace(/ /g, "_").toUpperCase()}`; | ||||
| } | ||||
|  | ||||
| export function setInput(name: string, value: string) { | ||||
| export function setInput(name: string, value: string): void { | ||||
|     process.env[getInputName(name)] = value; | ||||
| } | ||||
|  | ||||
| @ -15,14 +15,14 @@ interface CacheInput { | ||||
|     restoreKeys?: string[]; | ||||
| } | ||||
|  | ||||
| export function setInputs(input: CacheInput) { | ||||
| export function setInputs(input: CacheInput): void { | ||||
|     setInput(Inputs.Path, input.path); | ||||
|     setInput(Inputs.Key, input.key); | ||||
|     input.restoreKeys && | ||||
|         setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n")); | ||||
| } | ||||
|  | ||||
| export function clearInputs() { | ||||
| export function clearInputs(): void { | ||||
|     delete process.env[getInputName(Inputs.Path)]; | ||||
|     delete process.env[getInputName(Inputs.Key)]; | ||||
|     delete process.env[getInputName(Inputs.RestoreKeys)]; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 BSKY
					BSKY