diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 00f116c..9874717 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -7,7 +7,7 @@ on: - completed env: - IMAGE_NAME: alpine:3.10.3 + IMAGE_NAME: knqyf263/vuln-image jobs: test1: diff --git a/__tests__/downloader.test.ts b/__tests__/downloader.test.ts new file mode 100644 index 0000000..c7c8a8e --- /dev/null +++ b/__tests__/downloader.test.ts @@ -0,0 +1,99 @@ +import * as fs from 'fs'; +import { removeTrivyCmd } from './helper'; +import { Downloader } from '../src/downloader'; + +const downloader = new Downloader(); + +describe('Check Platform', () => { + test('is Liniux', () => { + const result = downloader.checkPlatform('linux'); + expect(result).toBe('Linux'); + }); + + test('is Darwin', () => { + const result = downloader.checkPlatform('darwin'); + expect(result).toBe('macOS'); + }); + + test('is not linux and darwin', () => { + expect(() => { + downloader.checkPlatform('other'); + }).toThrowError('Sorry, other is not supported.'); + }); +}); + +describe('getDownloadUrl', () => { + test('with latest version and linux', async () => { + const version = 'latest'; + const os = 'Linux'; + const result = await downloader.getDownloadUrl(version, os); + expect(result).toMatch( + /releases\/download\/v[0-9]+\.[0-9]+\.[0-9]+\/trivy_[0-9]+\.[0-9]+\.[0-9]+_Linux-64bit\.tar\.gz$/ + ); + }); + + test('with 0.18.3 and macOS', async () => { + const version = '0.18.3'; + const os = 'macOS'; + const result = await downloader.getDownloadUrl(version, os); + expect(result).toMatch( + /releases\/download\/v0\.18\.3\/trivy_0\.18\.3_macOS-64bit\.tar\.gz$/ + ); + }); + + test('with non-supported version', async () => { + const version = 'none'; + const os = 'Linux'; + await expect(downloader.getDownloadUrl(version, os)).rejects.toThrowError( + 'Could not find Trivy asset that you specified.' + ); + }); + + test('with non-supported os', async () => { + const version = 'latest'; + const os = 'none'; + await expect(downloader.getDownloadUrl(version, os)).rejects.toThrowError( + 'Could not find Trivy asset that you specified.' + ); + }); +}); + +describe('Download trivy command', () => { + afterAll(() => { + removeTrivyCmd('__tests__'); + }); + + test('with valid download URL and save in __tests__', async () => { + let downloadUrl = 'https://github.com/aquasecurity/trivy'; + downloadUrl += '/releases/download/v0.18.3/trivy_0.18.3_Linux-64bit.tar.gz'; + const savePath = './__tests__'; + await expect( + downloader.downloadTrivyCmd(downloadUrl, savePath) + ).resolves.toEqual(`${savePath}/trivy`); + }, 300000); + + test('with invalid download URL', async () => { + const downloadUrl = 'https://github.com/this_is_invalid'; + await expect(downloader.downloadTrivyCmd(downloadUrl)).rejects.toThrow(); + }); +}); + +describe('Trivy command', () => { + beforeAll(() => { + fs.writeFileSync('./trivy', ''); + }); + + afterAll(() => { + removeTrivyCmd('.'); + }); + + test('exists', () => { + const result = downloader.trivyExists('.'); + expect(result).toBeTruthy(); + }); + + test('does not exist', () => { + const result = downloader.trivyExists('src'); + expect(result).toBeFalsy(); + }); +}); diff --git a/__tests__/helper.ts b/__tests__/helper.ts new file mode 100644 index 0000000..89061f2 --- /dev/null +++ b/__tests__/helper.ts @@ -0,0 +1,11 @@ +import * as fs from 'fs'; +import { Downloader } from '../src/downloader'; + +const downloader = new Downloader(); + +export function removeTrivyCmd(path: string) { + path = path.replace(/\/trivy$/, ''); + if (downloader.trivyExists(path)) { + fs.unlinkSync(`${path}/trivy`); + } +} diff --git a/__tests__/trivy.test.ts b/__tests__/trivy.test.ts index 56af097..08a9476 100644 --- a/__tests__/trivy.test.ts +++ b/__tests__/trivy.test.ts @@ -1,98 +1,15 @@ -import { Downloader, Trivy } from '../src/trivy'; -import { unlinkSync, writeFileSync } from 'fs'; +import * as fs from 'fs'; +import { Downloader } from '../src/downloader'; +import { Trivy } from '../src/trivy'; import { Vulnerability, TrivyOption } from '../src/interface'; +import { removeTrivyCmd } from './helper'; const downloader = new Downloader(); const trivy = new Trivy(); -function removeTrivyCmd(path: string) { - path = path.replace(/\/trivy$/, ''); - if (downloader.trivyExists(path)) { - unlinkSync(`${path}/trivy`); - } -} - -describe('Platform', () => { - test('is Liniux', () => { - const result = downloader['checkPlatform']('linux'); - expect(result).toBe('Linux'); - }); - - test('is Darwin', () => { - const result = downloader['checkPlatform']('darwin'); - expect(result).toBe('macOS'); - }); - - test('is not linux and darwin', () => { - expect(() => { - downloader['checkPlatform']('other'); - }).toThrowError('Sorry, other is not supported.'); - }); -}); - -describe('getDownloadUrl', () => { - test('with latest version and linux', async () => { - const version = 'latest'; - const os = 'Linux'; - const result = await downloader['getDownloadUrl'](version, os); - expect(result).toMatch( - /releases\/download\/v[0-9]+\.[0-9]+\.[0-9]+\/trivy_[0-9]+\.[0-9]+\.[0-9]+_Linux-64bit\.tar\.gz$/ - ); - }); - - test('with 0.2.0 and macOS', async () => { - const version = '0.2.0'; - const os = 'macOS'; - const result = await downloader['getDownloadUrl'](version, os); - expect(result).toMatch( - /releases\/download\/v0\.2\.0\/trivy_0\.2\.0_macOS-64bit\.tar\.gz$/ - ); - }); - - test('with non-supported version', async () => { - const version = 'none'; - const os = 'Linux'; - await expect( - downloader['getDownloadUrl'](version, os) - ).rejects.toThrowError( - 'Cloud not be found a Trivy asset that you specified.' - ); - }); - - test('with non-supported os', async () => { - const version = 'latest'; - const os = 'none'; - await expect( - downloader['getDownloadUrl'](version, os) - ).rejects.toThrowError( - 'Cloud not be found a Trivy asset that you specified.' - ); - }); -}); - -describe('Download trivy command', () => { - afterAll(() => { - removeTrivyCmd('__tests__'); - }); - - test('with valid download URL and save in __tests__', async () => { - let downloadUrl = 'https://github.com/aquasecurity/trivy'; - downloadUrl += '/releases/download/v0.2.1/trivy_0.2.1_Linux-64bit.tar.gz'; - const savePath = './__tests__'; - await expect( - downloader['downloadTrivyCmd'](downloadUrl, savePath) - ).resolves.toEqual(`${savePath}/trivy`); - }, 300000); - - test('with invalid download URL', async () => { - const downloadUrl = 'https://github.com/this_is_invalid'; - await expect(downloader['downloadTrivyCmd'](downloadUrl)).rejects.toThrow(); - }); -}); - describe('Trivy command', () => { beforeAll(() => { - writeFileSync('./trivy', ''); + fs.writeFileSync('./trivy', ''); }); afterAll(() => { @@ -115,9 +32,9 @@ describe('Trivy scan', () => { const image: string = 'alpine:3.10'; beforeAll(async () => { - trivyPath = !downloader.trivyExists('./__tests__') - ? await downloader.download('latest', './__tests__') - : './__tests__/trivy'; + trivyPath = !downloader.trivyExists(__dirname) + ? await downloader.download('latest', __dirname) + : `${__dirname}/trivy`; }, 300000); afterAll(() => { diff --git a/package.json b/package.json index 1d84e69..1241fc8 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,9 @@ "author": "homoluctus", "license": "MIT", "dependencies": { - "@actions/core": "^1.2.6", - "@actions/github": "^1.1.0", + "@actions/core": "^1.2.7", + "@actions/github": "^4.0.0", + "@octokit/rest": "^18.5.6", "node-fetch": "^2.6.1", "tar": "^5.0.5" }, diff --git a/src/downloader.ts b/src/downloader.ts new file mode 100644 index 0000000..3664bd6 --- /dev/null +++ b/src/downloader.ts @@ -0,0 +1,116 @@ +import fs from 'fs'; +import zlib from 'zlib'; +import tar from 'tar'; +import * as core from '@actions/core'; +import { Octokit } from '@octokit/rest'; +import fetch, { Response } from 'node-fetch'; + +export class Downloader { + readonly trivyRepo = { + owner: 'aquasecurity', + repo: 'trivy', + }; + + async download( + version: string, + trivyCmdDir: string = __dirname + ): Promise { + const os = this.checkPlatform(process.platform); + const downloadUrl = await this.getDownloadUrl(version, os); + console.debug(`Download URL: ${downloadUrl}`); + const trivyCmdBaseDir = process.env.GITHUB_WORKSPACE || trivyCmdDir; + const trivyCmdPath = await this.downloadTrivyCmd( + downloadUrl, + trivyCmdBaseDir + ); + console.debug(`Trivy Command Path: ${trivyCmdPath}`); + return trivyCmdPath; + } + + checkPlatform(platform: string): string { + switch (platform) { + case 'linux': + return 'Linux'; + case 'darwin': + return 'macOS'; + default: + const errorMsg = `Sorry, ${platform} is not supported. + Trivy support Linux, MacOS, FreeBSD and OpenBSD.`; + throw new Error(errorMsg); + } + } + + async getDownloadUrl(version: string, os: string): Promise { + try { + const response = await this.getAssets(version); + const filename = `trivy_${response.version}_${os}-64bit.tar.gz`; + for (const asset of response.assets) { + if (asset.name === filename) { + return asset.browser_download_url; + } + } + throw new Error(`${filename} does not include in GitHub releases`); + } catch (err) { + core.error(err.message); + + const errMsg = `Could not find Trivy asset that you specified. + Version: ${version} + OS: ${os} + `; + throw new Error(errMsg); + } + } + + async getAssets( + version: string + ): Promise<{ + assets: any; + version: string; + }> { + let response; + const client = new Octokit(); + + if (version === 'latest') { + response = await client.repos.getLatestRelease({ ...this.trivyRepo }); + version = response.data.tag_name.replace(/v/, ''); + } else { + response = await client.repos.getReleaseByTag({ + ...this.trivyRepo, + tag: `v${version}`, + }); + } + + return { assets: response.data.assets, version }; + } + + async downloadTrivyCmd( + downloadUrl: string, + savedPath: string = '.' + ): Promise { + const response: Response = await fetch(downloadUrl); + + return new Promise((resolve, reject) => { + const gunzip = zlib.createGunzip(); + const extract = tar.extract({ C: savedPath }, ['trivy']); + response.body + .on('error', reject) + .pipe(gunzip) + .on('error', reject) + .pipe(extract) + .on('error', reject) + .on('finish', () => { + if (!this.trivyExists(savedPath)) { + reject('Failed to extract Trivy command file.'); + } + resolve(`${savedPath}/trivy`); + }); + }); + } + + trivyExists(targetDir: string): boolean { + const trivyCmdPaths: string[] = fs + .readdirSync(targetDir) + .filter(f => f === 'trivy'); + return trivyCmdPaths.length === 1; + } +} diff --git a/src/github.ts b/src/github.ts new file mode 100644 index 0000000..e35a465 --- /dev/null +++ b/src/github.ts @@ -0,0 +1,64 @@ +import * as core from '@actions/core'; +import * as github from '@actions/github'; +import { Octokit } from '@octokit/rest'; +import { IssueOption, IssueResponse } from './interface'; + +export class GitHub { + client: Octokit; + + constructor(token: string) { + this.client = new Octokit({ auth: token }); + } + + async getTrivyIssues(image: string, labels: string[] | undefined) { + if (labels == null) { + return []; + } + + let { data: trivyIssues } = await this.client.issues.listForRepo({ + ...github.context.repo, + state: 'open', + labels: labels.join(','), + }); + + return trivyIssues.filter(issue => issue.body.includes(image)); + } + + async createIssue(options: IssueOption): Promise { + const { data: issue } = await this.client.issues.create({ + ...github.context.repo, + ...options, + }); + return { issueNumber: issue.number, htmlUrl: issue.html_url }; + } + + async updateIssue(issueNumber: number, options: IssueOption): Promise { + await this.client.issues.update({ + ...github.context.repo, + issue_number: issueNumber, + body: options.body, + }); + } + + async createOrUpdateIssue( + image: string, + options: IssueOption + ): Promise { + const trivyIssues = await this.getTrivyIssues(image, options.labels); + + if (trivyIssues.length > 0) { + core.info('Found existing issue. Updating existing issue.'); + + const existingIssue = trivyIssues[0]; + await this.updateIssue(existingIssue.number, options); + return { + issueNumber: existingIssue.number, + htmlUrl: existingIssue.html_url, + }; + } else { + core.info('Create new issue'); + + return await this.createIssue(options); + } + } +} diff --git a/src/index.ts b/src/index.ts index ad46d9a..41b9e43 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,85 +1,67 @@ import * as core from '@actions/core'; -import { Trivy, Downloader } from './trivy'; -import { createOrUpdateIssue } from './issue'; -import { - TrivyOption, - IssueOption, - IssueResponse, - Vulnerability, -} from './interface'; +import { Downloader } from './downloader'; +import { GitHub } from './github'; +import { Trivy } from './trivy'; +import { TrivyOption, IssueOption, Vulnerability } from './interface'; async function run() { - try { - const trivyVersion: string = core - .getInput('trivy_version') - .replace(/^v/, ''); - const image: string | undefined = - core.getInput('image') || process.env.IMAGE_NAME; - const issueFlag: boolean = core.getInput('issue').toLowerCase() == 'true'; + const trivyVersion = core.getInput('trivy_version').replace(/^v/, ''); + const image = core.getInput('image') || process.env.IMAGE_NAME; + const issueFlag = core.getInput('issue').toLowerCase() == 'true'; - if (image === undefined || image === '') { - throw new Error('Please specify scan target image name'); - } + if (!image) { + throw new Error('Please specify scan target image name'); + } - const trivyOption: TrivyOption = { - severity: core.getInput('severity').replace(/\s+/g, ''), - vulnType: core.getInput('vuln_type').replace(/\s+/g, ''), - ignoreUnfixed: core.getInput('ignore_unfixed').toLowerCase() === 'true', - format: issueFlag ? 'json' : 'table', - }; + const trivyOption: TrivyOption = { + severity: core.getInput('severity').replace(/\s+/g, ''), + vulnType: core.getInput('vuln_type').replace(/\s+/g, ''), + ignoreUnfixed: core.getInput('ignore_unfixed').toLowerCase() === 'true', + format: issueFlag ? 'json' : 'table', + }; - const downloader = new Downloader(); - const trivyCmdPath: string = await downloader.download(trivyVersion); + const downloader = new Downloader(); + const trivyCmdPath = await downloader.download(trivyVersion); - const trivy = new Trivy(); - const result: Vulnerability[] | string = trivy.scan( - trivyCmdPath, - image, - trivyOption - ); + const trivy = new Trivy(); + const result = trivy.scan(trivyCmdPath, image, trivyOption); - if (!issueFlag) { - core.info( - `Not create a issue because issue parameter is false. - Vulnerabilities: - ${result}` - ); - return; - } + if (!issueFlag) { + core.info(`Not create a issue because issue parameter is false. + Vulnerabilities: ${result}`); + return; + } - const issueContent: string = trivy.parse(image, result as Vulnerability[]); + const issueContent = trivy.parse(image, result as Vulnerability[]); + if (issueContent === '') { + core.info( + 'Vulnerabilities were not found.\nYour maintenance looks good 👍' + ); + return; + } - if (issueContent === '') { - core.info( - 'Vulnerabilities were not found.\nYour maintenance looks good 👍' - ); - return; - } + const issueOption = { + title: core.getInput('issue_title'), + body: issueContent, + labels: core + .getInput('issue_label') + .replace(/\s+/g, '') + .split(','), + assignees: core + .getInput('issue_assignee') + .replace(/\s+/g, '') + .split(','), + }; + const token = core.getInput('token', { required: true }); + const github = new GitHub(token); + const output = await github.createOrUpdateIssue(image, issueOption); - const issueOption: IssueOption = { - title: core.getInput('issue_title'), - body: issueContent, - labels: core - .getInput('issue_label') - .replace(/\s+/g, '') - .split(','), - assignees: core - .getInput('issue_assignee') - .replace(/\s+/g, '') - .split(','), - }; - const token: string = core.getInput('token', { required: true }); - const output: IssueResponse = await createOrUpdateIssue(token, image, issueOption); - core.setOutput('html_url', output.htmlUrl); - core.setOutput('issue_number', output.issueNumber.toString()); + core.setOutput('html_url', output.htmlUrl); + core.setOutput('issue_number', output.issueNumber.toString()); - if (core.getInput("fail_on_vulnerabilities") === 'true') { - core.setFailed(`Vulnerabilities found.\n${issueContent}`) - } - } catch (error) { - core.error(error.stack); - core.setFailed(error.message); + if (core.getInput('fail_on_vulnerabilities') === 'true') { + throw new Error(`Vulnerabilities found.\n${issueContent}`); } } -run(); +run().catch(err => core.setFailed(err.message)); diff --git a/src/issue.ts b/src/issue.ts deleted file mode 100644 index 641b8c6..0000000 --- a/src/issue.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Octokit } from '@octokit/rest'; -import * as core from '@actions/core'; -import * as github from '@actions/github'; -import { IssueOption, IssueResponse } from './interface'; - -async function getTrivyIssues(client: Octokit, image: string, labels: string[] | undefined) { - if (labels == null) { - return [] - } - - let { - data: trivyIssues, - } = await client.issues.listForRepo( - { ...github.context.repo, state: "open", labels: labels.join(",") } - ); - - return trivyIssues.filter(issue => issue.body.includes(image)) -} - -async function createIssue( - client: Octokit, - options: IssueOption -): Promise { - const { - data: issue, - }: Octokit.Response = await client.issues.create( - { - ...github.context.repo, - ...options, - } - ); - return issue -} - -async function updateIssue( - issueNumber: number, - client: Octokit, - options: IssueOption -): Promise { - await client.issues.update( - { - ...github.context.repo, - issue_number: issueNumber, - body: options.body - } - ); -} - -export async function createOrUpdateIssue( - token: string, - image: string, - options: IssueOption -): Promise { - const client: Octokit = new Octokit({ auth: token }); - - const trivyIssues = await getTrivyIssues(client, image, options.labels) - - if (trivyIssues.length > 0) { - core.info("Found existing issue. Updating existing issue.") - - const existingIssue = trivyIssues[0] - await updateIssue(existingIssue.number, client, options) - return { - issueNumber: existingIssue.number, - htmlUrl: existingIssue.html_url, - } - } else { - core.info("Create new issue") - - const newIssue = await createIssue(client, options) - return { - issueNumber: newIssue.number, - htmlUrl: newIssue.html_url, - } - } -} diff --git a/src/trivy.ts b/src/trivy.ts index 4514c62..7eb6fa3 100644 --- a/src/trivy.ts +++ b/src/trivy.ts @@ -1,128 +1,7 @@ -import fs from 'fs'; -import zlib from 'zlib'; -import tar from 'tar'; -import { Octokit } from '@octokit/rest'; -import fetch, { Response } from 'node-fetch'; import { spawnSync, SpawnSyncReturns } from 'child_process'; - import { TrivyOption, Vulnerability } from './interface'; import { isIterable } from './utils'; -export class Downloader { - githubClient: Octokit; - - static readonly trivyRepository = { - owner: 'aquasecurity', - repo: 'trivy', - }; - - constructor() { - this.githubClient = new Octokit(); - } - - public async download( - version: string, - trivyCmdDir: string = __dirname - ): Promise { - const os: string = this.checkPlatform(process.platform); - const downloadUrl: string = await this.getDownloadUrl(version, os); - console.debug(`Download URL: ${downloadUrl}`); - const trivyCmdBaseDir: string = process.env.GITHUB_WORKSPACE || trivyCmdDir; - const trivyCmdPath: string = await this.downloadTrivyCmd( - downloadUrl, - trivyCmdBaseDir - ); - console.debug(`Trivy Command Path: ${trivyCmdPath}`); - return trivyCmdPath; - } - - private checkPlatform(platform: string): string { - switch (platform) { - case 'linux': - return 'Linux'; - case 'darwin': - return 'macOS'; - default: - const errorMsg: string = `Sorry, ${platform} is not supported. - Trivy support Linux, MacOS, FreeBSD and OpenBSD.`; - throw new Error(errorMsg); - } - } - - private async getDownloadUrl(version: string, os: string): Promise { - try { - const response = await this.getAssets(version); - const filename: string = `trivy_${response.version}_${os}-64bit.tar.gz`; - for (const asset of response.assets) { - if (asset.name === filename) { - return asset.browser_download_url; - } - } - throw new Error(); - } catch (error) { - const errorMsg: string = ` - Cloud not be found a Trivy asset that you specified. - Version: ${version} - OS: ${os} - `; - throw new Error(errorMsg); - } - } - - private async getAssets( - version: string - ): Promise<{ - assets: Octokit.ReposGetLatestReleaseResponseAssetsItem[]; - version: string; - }> { - let response: Octokit.Response; - - if (version === 'latest') { - response = await this.githubClient.repos.getLatestRelease({ - ...Downloader.trivyRepository, - }); - version = response.data.tag_name.replace(/v/, ''); - } else { - response = await this.githubClient.repos.getReleaseByTag({ - ...Downloader.trivyRepository, - tag: `v${version}`, - }); - } - return { assets: response.data.assets, version }; - } - - private async downloadTrivyCmd( - downloadUrl: string, - savedPath: string = '.' - ): Promise { - const response: Response = await fetch(downloadUrl); - - return new Promise((resolve, reject) => { - const gunzip = zlib.createGunzip(); - const extract = tar.extract({ C: savedPath }, ['trivy']); - response.body - .on('error', reject) - .pipe(gunzip) - .on('error', reject) - .pipe(extract) - .on('error', reject) - .on('finish', () => { - if (!this.trivyExists(savedPath)) { - reject('Failed to extract Trivy command file.'); - } - resolve(`${savedPath}/trivy`); - }); - }); - } - - public trivyExists(targetDir: string): boolean { - const trivyCmdPaths: string[] = fs - .readdirSync(targetDir) - .filter(f => f === 'trivy'); - return trivyCmdPaths.length === 1; - } -} - export class Trivy { public scan( trivyPath: string, diff --git a/tsconfig.json b/tsconfig.json index 960dc9f..e728077 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -59,5 +59,5 @@ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ }, - "exclude": ["node_modules", "**/*.test.ts"] + "exclude": ["node_modules", "**/*.test.ts", "__tests__/helper.ts"] } diff --git a/yarn.lock b/yarn.lock index 7bc9624..ba30f46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,18 +2,27 @@ # yarn lockfile v1 -"@actions/core@^1.2.6": +"@actions/core@^1.2.7": version "1.3.0" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.3.0.tgz#f5e4b24c889e7f2e58b466cc8c7481292284eba0" integrity sha512-xxtX0Cwdhb8LcgatfJkokqT8KzPvcIbwL9xpLU09nOwBzaStbfm0dNncsP0M4us+EpoPdWy7vbzU5vSOH7K6pg== -"@actions/github@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@actions/github/-/github-1.1.0.tgz#06f34e6b0cf07eb2b3641de3e680dbfae6bcd400" - integrity sha512-cHf6PyoNMdei13jEdGPhKprIMFmjVVW/dnM5/9QmQDJ1ZTaGVyezUSCUIC/ySNLRvDUpeFwPYMdThSEJldSbUw== +"@actions/github@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@actions/github/-/github-4.0.0.tgz#d520483151a2bf5d2dc9cd0f20f9ac3a2e458816" + integrity sha512-Ej/Y2E+VV6sR9X7pWL5F3VgEWrABaT292DRqRU6R4hnQjPtC/zD3nagxVdXWiRQvYDh8kHXo7IDmG42eJ/dOMA== + dependencies: + "@actions/http-client" "^1.0.8" + "@octokit/core" "^3.0.0" + "@octokit/plugin-paginate-rest" "^2.2.3" + "@octokit/plugin-rest-endpoint-methods" "^4.0.0" + +"@actions/http-client@^1.0.8": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-1.0.11.tgz#c58b12e9aa8b159ee39e7dd6cbd0e91d905633c0" + integrity sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg== dependencies: - "@octokit/graphql" "^2.0.1" - "@octokit/rest" "^16.15.0" + tunnel "0.0.6" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13": version "7.12.13" @@ -374,13 +383,26 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@octokit/auth-token@^2.4.0": +"@octokit/auth-token@^2.4.4": version "2.4.5" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.5.tgz#568ccfb8cb46f36441fac094ce34f7a875b197f3" integrity sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA== dependencies: "@octokit/types" "^6.0.3" +"@octokit/core@^3.0.0", "@octokit/core@^3.2.3": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.4.0.tgz#b48aa27d755b339fe7550548b340dcc2b513b742" + integrity sha512-6/vlKPP8NF17cgYXqucdshWqmMZGXkuvtcrWCgU5NOI0Pl2GjlmZyWgBMrU8zJ3v2MJlM6++CiB45VKYmhiWWg== + dependencies: + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.4.12" + "@octokit/request-error" "^2.0.5" + "@octokit/types" "^6.0.3" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + "@octokit/endpoint@^6.0.1": version "6.0.11" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.11.tgz#082adc2aebca6dcefa1fb383f5efb3ed081949d1" @@ -390,49 +412,49 @@ is-plain-object "^5.0.0" universal-user-agent "^6.0.0" -"@octokit/graphql@^2.0.1": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-2.1.3.tgz#60c058a0ed5fa242eca6f938908d95fd1a2f4b92" - integrity sha512-XoXJqL2ondwdnMIW3wtqJWEwcBfKk37jO/rYkoxNPEVeLBDGsGO1TCWggrAlq3keGt/O+C/7VepXnukUxwt5vA== +"@octokit/graphql@^4.5.8": + version "4.6.2" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.6.2.tgz#ec44abdfa87f2b9233282136ae33e4ba446a04e7" + integrity sha512-WmsIR1OzOr/3IqfG9JIczI8gMJUMzzyx5j0XXQ4YihHtKlQc+u35VpVoOXhlKAlaBntvry1WpAzPl/a+s3n89Q== dependencies: - "@octokit/request" "^5.0.0" - universal-user-agent "^2.0.3" + "@octokit/request" "^5.3.0" + "@octokit/types" "^6.0.3" + universal-user-agent "^6.0.0" "@octokit/openapi-types@^7.2.3": version "7.2.3" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-7.2.3.tgz#a7105796db9b85d25d3feba9a1785a124c7803e4" integrity sha512-V1ycxkR19jqbIl3evf2RQiMRBvTNRi+Iy9h20G5OP5dPfEF6GJ1DPlUeiZRxo2HJxRr+UA4i0H1nn4btBDPFrw== -"@octokit/plugin-paginate-rest@^1.1.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc" - integrity sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q== +"@octokit/plugin-paginate-rest@^2.2.3", "@octokit/plugin-paginate-rest@^2.6.2": + version "2.13.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.3.tgz#f0f1792230805108762d87906fb02d573b9e070a" + integrity sha512-46lptzM9lTeSmIBt/sVP/FLSTPGx6DCzAdSX3PfeJ3mTf4h9sGC26WpaQzMEq/Z44cOcmx8VsOhO+uEgE3cjYg== dependencies: - "@octokit/types" "^2.0.1" + "@octokit/types" "^6.11.0" -"@octokit/plugin-request-log@^1.0.0": +"@octokit/plugin-request-log@^1.0.2": version "1.0.3" resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz#70a62be213e1edc04bb8897ee48c311482f9700d" integrity sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ== -"@octokit/plugin-rest-endpoint-methods@2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz#3288ecf5481f68c494dd0602fc15407a59faf61e" - integrity sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ== +"@octokit/plugin-rest-endpoint-methods@5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.3.1.tgz#deddce769b4ec3179170709ab42e4e9e6195aaa9" + integrity sha512-3B2iguGmkh6bQQaVOtCsS0gixrz8Lg0v4JuXPqBcFqLKuJtxAUf3K88RxMEf/naDOI73spD+goJ/o7Ie7Cvdjg== dependencies: - "@octokit/types" "^2.0.1" + "@octokit/types" "^6.16.2" deprecation "^2.3.1" -"@octokit/request-error@^1.0.2": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801" - integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA== +"@octokit/plugin-rest-endpoint-methods@^4.0.0": + version "4.15.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.15.1.tgz#91a064bee99d0ffcef74a04357e1cf15c27d1cd0" + integrity sha512-4gQg4ySoW7ktKB0Mf38fHzcSffVZd6mT5deJQtpqkuPuAqzlED5AJTeW8Uk7dPRn7KaOlWcXB0MedTFJU1j4qA== dependencies: - "@octokit/types" "^2.0.0" - deprecation "^2.0.0" - once "^1.4.0" + "@octokit/types" "^6.13.0" + deprecation "^2.3.1" -"@octokit/request-error@^2.0.0": +"@octokit/request-error@^2.0.0", "@octokit/request-error@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.5.tgz#72cc91edc870281ad583a42619256b380c600143" integrity sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg== @@ -441,7 +463,7 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.0.0", "@octokit/request@^5.2.0": +"@octokit/request@^5.3.0", "@octokit/request@^5.4.12": version "5.4.15" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.15.tgz#829da413dc7dd3aa5e2cdbb1c7d0ebe1f146a128" integrity sha512-6UnZfZzLwNhdLRreOtTkT9n57ZwulCve8q3IT/Z477vThu6snfdkBuhxnChpOKNGxcQ71ow561Qoa6uqLdPtag== @@ -453,36 +475,17 @@ node-fetch "^2.6.1" universal-user-agent "^6.0.0" -"@octokit/rest@^16.15.0": - version "16.43.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.2.tgz#c53426f1e1d1044dee967023e3279c50993dd91b" - integrity sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ== - dependencies: - "@octokit/auth-token" "^2.4.0" - "@octokit/plugin-paginate-rest" "^1.1.1" - "@octokit/plugin-request-log" "^1.0.0" - "@octokit/plugin-rest-endpoint-methods" "2.4.0" - "@octokit/request" "^5.2.0" - "@octokit/request-error" "^1.0.2" - atob-lite "^2.0.0" - before-after-hook "^2.0.0" - btoa-lite "^1.0.0" - deprecation "^2.0.0" - lodash.get "^4.4.2" - lodash.set "^4.3.2" - lodash.uniq "^4.5.0" - octokit-pagination-methods "^1.1.0" - once "^1.4.0" - universal-user-agent "^4.0.0" - -"@octokit/types@^2.0.0", "@octokit/types@^2.0.1": - version "2.16.2" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2" - integrity sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q== +"@octokit/rest@^18.5.6": + version "18.5.6" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.5.6.tgz#8c9a7c9329c7bbf478af20df78ddeab0d21f6d89" + integrity sha512-8HdG6ZjQdZytU6tCt8BQ2XLC7EJ5m4RrbyU/EARSkAM1/HP3ceOzMG/9atEfe17EDMer3IVdHWLedz2wDi73YQ== dependencies: - "@types/node" ">= 8" + "@octokit/core" "^3.2.3" + "@octokit/plugin-paginate-rest" "^2.6.2" + "@octokit/plugin-request-log" "^1.0.2" + "@octokit/plugin-rest-endpoint-methods" "5.3.1" -"@octokit/types@^6.0.3", "@octokit/types@^6.7.1": +"@octokit/types@^6.0.3", "@octokit/types@^6.11.0", "@octokit/types@^6.13.0", "@octokit/types@^6.16.2", "@octokit/types@^6.7.1": version "6.16.2" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.16.2.tgz#62242e0565a3eb99ca2fd376283fe78b4ea057b4" integrity sha512-wWPSynU4oLy3i4KGyk+J1BLwRKyoeW2TwRHgwbDz17WtVFzSK2GOErGliruIx8c+MaYtHSYTx36DSmLNoNbtgA== @@ -564,7 +567,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@>= 8": +"@types/node@*": version "15.9.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-15.9.0.tgz#0b7f6c33ca5618fe329a9d832b478b4964d325a8" integrity sha512-AR1Vq1Ei1GaA5FjKL5PBqblTZsL5M+monvGSZwe6sSIdGiuu7Xr/pNwWJY+0ZQuN8AapD/XMB5IzBAyYRFbocA== @@ -729,11 +732,6 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob-lite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696" - integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY= - atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -812,7 +810,7 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -before-after-hook@^2.0.0: +before-after-hook@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.1.tgz#73540563558687586b52ed217dad6a802ab1549c" integrity sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw== @@ -885,11 +883,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -btoa-lite@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" - integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= - buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2461,31 +2454,16 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.set@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" - integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -2498,11 +2476,6 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -macos-release@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.1.tgz#64033d0ec6a5e6375155a74b1a1eba8e509820ac" - integrity sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg== - make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -2772,11 +2745,6 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -octokit-pagination-methods@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" - integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== - once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2796,14 +2764,6 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" -os-name@^3.0.0, os-name@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" - integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== - dependencies: - macos-release "^2.2.0" - windows-release "^3.1.0" - p-each-series@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" @@ -3533,6 +3493,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -3570,20 +3535,6 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -universal-user-agent@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.1.0.tgz#5abfbcc036a1ba490cb941f8fd68c46d3669e8e4" - integrity sha512-8itiX7G05Tu3mGDTdNY2fB4KJ8MgZLS54RdG6PkkfwMAavrXu1mV/lls/GABx9O3Rw4PnTtasxrvbMQoBYY92Q== - dependencies: - os-name "^3.0.0" - -universal-user-agent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557" - integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg== - dependencies: - os-name "^3.1.0" - universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" @@ -3719,13 +3670,6 @@ which@^1.2.9, which@^1.3.0: dependencies: isexe "^2.0.0" -windows-release@^3.1.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" - integrity sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg== - dependencies: - execa "^1.0.0" - word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"