From e1328c0c0f785370690f617e5a57a7ec46247aa0 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Wed, 19 Jul 2023 19:00:40 +0700 Subject: [PATCH 01/12] add test for App class --- Dockerfile | 2 +- src/CodeCoachError.ts | 7 ++ src/Config/Config.spec.ts | 19 ++--- src/Config/Config.ts | 6 +- src/Config/index.ts | 2 +- src/Provider/GitLab/GitLabMRService.ts | 56 +++++++++----- src/app.spec.ts | 101 +++++++++++++++++++++++++ src/app.ts | 73 +++++++++--------- src/index.ts | 23 ++++++ 9 files changed, 218 insertions(+), 71 deletions(-) create mode 100644 src/CodeCoachError.ts create mode 100644 src/app.spec.ts create mode 100644 src/index.ts diff --git a/Dockerfile b/Dockerfile index de134d5..f385516 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,4 +13,4 @@ RUN yarn install --production COPY --from=build /app/dist ./dist RUN npm link -ENTRYPOINT ["/app/dist/app.js"] \ No newline at end of file +ENTRYPOINT ["/app/dist/index.js"] diff --git a/src/CodeCoachError.ts b/src/CodeCoachError.ts new file mode 100644 index 0000000..eee3ecb --- /dev/null +++ b/src/CodeCoachError.ts @@ -0,0 +1,7 @@ +export default class CodeCoachError extends Error { + constructor(message: string) { + super(message); + Object.setPrototypeOf(this, CodeCoachError.prototype); + this.name = 'CodeCoachError'; + } +} diff --git a/src/Config/Config.spec.ts b/src/Config/Config.spec.ts index d0c6e3e..6ad9f12 100644 --- a/src/Config/Config.spec.ts +++ b/src/Config/Config.spec.ts @@ -1,4 +1,5 @@ import { BuildLogFile } from './@types'; +import { ConfigParser } from './Config'; const mockGitHubRepo = 'https://github.com/codeleague/codecoach.git'; const mockGitHubPr = 42; @@ -70,8 +71,7 @@ describe('Config parsing Test', () => { }; it('should be able to parse GitHub config provided by environment variables', async () => { - process.argv = GITHUB_ENV_ARGS; - const config = (await import('./Config')).configs; + const config = ConfigParser(GITHUB_ENV_ARGS); expect(config.vcs).toBe('github'); expect(config.githubRepoUrl).toBe(mockGitHubRepo); expect(config.githubPr).toBe(mockGitHubPr); @@ -84,8 +84,7 @@ describe('Config parsing Test', () => { }); it('should be able to parse GitHub config provided by file', async () => { - process.argv = GITHUB_FILE_ARGS; - const config = (await import('./Config')).configs; + const config = ConfigParser(GITHUB_FILE_ARGS); expect(config.vcs).toBe('github'); expect(config.githubRepoUrl).toBe(mockGitHubRepo); expect(config.githubPr).toBe(mockGitHubPr); @@ -98,8 +97,7 @@ describe('Config parsing Test', () => { }); it('should be able to parse GitLab config provided by environment variables', async () => { - process.argv = GITLAB_ENV_ARGS; - const config = (await import('./Config')).configs; + const config = ConfigParser(GITLAB_ENV_ARGS); expect(config.vcs).toBe('gitlab'); expect(config.gitlabHost).toBe(mockGitLabHost); expect(config.gitlabProjectId).toBe(mockGitLabProjectId); @@ -113,8 +111,7 @@ describe('Config parsing Test', () => { }); it('should be able to parse GitLab config provided by file', async () => { - process.argv = GITLAB_FILE_ARGS; - const config = (await import('./Config')).configs; + const config = ConfigParser(GITLAB_FILE_ARGS); expect(config.vcs).toBe('gitlab'); expect(config.gitlabHost).toBe(mockGitLabHost); expect(config.gitlabProjectId).toBe(mockGitLabProjectId); @@ -128,16 +125,14 @@ describe('Config parsing Test', () => { }); it('should be able to parse dryRun config provided by environment variables', async () => { - process.argv = DRYRUN_ENV_ARGS; - const config = (await import('./Config')).configs; + const config = ConfigParser(DRYRUN_ENV_ARGS); expect(config.dryRun).toBe(true); validateBuildLog(config.buildLogFile); }); it('should be able to parse dryRun config provided by file', async () => { - process.argv = DRYRUN_FILE_ARGS; - const config = (await import('./Config')).configs; + const config = ConfigParser(DRYRUN_FILE_ARGS); expect(config.dryRun).toBe(true); validateBuildLog(config.buildLogFile); diff --git a/src/Config/Config.ts b/src/Config/Config.ts index 8473540..0b73937 100644 --- a/src/Config/Config.ts +++ b/src/Config/Config.ts @@ -123,7 +123,7 @@ and is build root directory (optional (Will use current context as cwd)). }) .strict() .help() - .wrap(120) - .parse(process.argv.slice(1)) as ConfigArgument; + .wrap(120); -export const configs = args; +export const ConfigParser = (argv: string[]): ConfigArgument => + args.parse(argv) as ConfigArgument; diff --git a/src/Config/index.ts b/src/Config/index.ts index 2062f95..313ab95 100644 --- a/src/Config/index.ts +++ b/src/Config/index.ts @@ -1,3 +1,3 @@ -export { configs } from './Config'; +export { ConfigParser } from './Config'; export * from './@types'; export * from './@enums'; diff --git a/src/Provider/GitLab/GitLabMRService.ts b/src/Provider/GitLab/GitLabMRService.ts index 1bedb3c..ecdbd1e 100644 --- a/src/Provider/GitLab/GitLabMRService.ts +++ b/src/Provider/GitLab/GitLabMRService.ts @@ -9,20 +9,27 @@ import { import * as Resource from '@gitbeaker/core/dist/types/resources'; import { Gitlab } from '@gitbeaker/node'; -import { configs } from '../../Config'; - export class GitLabMRService implements IGitLabMRService { - private readonly projectId: number; - private readonly mrIid: number; + private readonly gitlabHost: string; + private readonly gitlabProjectId: number; + private readonly gitlabMrIid: number; + private readonly gitlabToken: string; private readonly api: Resource.Gitlab; - constructor() { - this.projectId = configs.gitlabProjectId; - this.mrIid = configs.gitlabMrIid; + constructor( + gitlabHost: string, + gitlabProjectId: number, + gitlabMrIid: number, + gitlabToken: string, + ) { + this.gitlabHost = gitlabHost; + this.gitlabProjectId = gitlabProjectId; + this.gitlabMrIid = gitlabMrIid; + this.gitlabToken = gitlabToken; this.api = new Gitlab({ - host: configs.gitlabHost, - token: configs.gitlabToken, + host: this.gitlabHost, + token: this.gitlabToken, }); } @@ -43,9 +50,14 @@ export class GitLabMRService implements IGitLabMRService { new_line: line, }; - await this.api.MergeRequestDiscussions.create(this.projectId, this.mrIid, body, { - position, - }); + await this.api.MergeRequestDiscussions.create( + this.gitlabProjectId, + this.gitlabMrIid, + body, + { + position, + }, + ); } async getCurrentUserId(): Promise { @@ -54,21 +66,26 @@ export class GitLabMRService implements IGitLabMRService { } async listAllNotes(): Promise { - return await this.api.MergeRequestNotes.all(this.projectId, this.mrIid); + return await this.api.MergeRequestNotes.all(this.gitlabProjectId, this.gitlabMrIid); } async deleteNote(noteId: number): Promise { - await this.api.MergeRequestNotes.remove(this.projectId, this.mrIid, noteId); + await this.api.MergeRequestNotes.remove( + this.gitlabProjectId, + this.gitlabMrIid, + noteId, + ); } // github can do someone fancy shit here we cant async createNote(note: string): Promise { - await this.api.MergeRequestNotes.create(this.projectId, this.mrIid, note); + await this.api.MergeRequestNotes.create(this.gitlabProjectId, this.gitlabMrIid, note); } async diff(): Promise { - const changes = (await this.api.MergeRequests.changes(this.projectId, this.mrIid)) - .changes; + const changes = ( + await this.api.MergeRequests.changes(this.gitlabProjectId, this.gitlabMrIid) + ).changes; if (!changes) { return []; @@ -81,7 +98,10 @@ export class GitLabMRService implements IGitLabMRService { } async getLatestVersion(): Promise { - const versions = await this.api.MergeRequests.versions(this.projectId, this.mrIid); + const versions = await this.api.MergeRequests.versions( + this.gitlabProjectId, + this.gitlabMrIid, + ); const collected = versions.filter((v) => v.state === 'collected'); if (collected.length === 0) throw new Error('No collected version in MR'); diff --git a/src/app.spec.ts b/src/app.spec.ts new file mode 100644 index 0000000..0c490ce --- /dev/null +++ b/src/app.spec.ts @@ -0,0 +1,101 @@ +import { App } from './app'; +import CodeCoachError from './CodeCoachError'; +import { ConfigArgument } from './Config'; +import { File } from './File'; +import { VCSEngine } from './Provider/CommonVCS/VCSEngine'; +import { GitLabAdapter } from './Provider/GitLab/GitLabAdapter'; +import { GitLabMRService } from './Provider/GitLab/GitLabMRService'; +import { GitHubAdapter } from './Provider/GitHub/GitHubAdapter'; +import { GitHubPRService } from './Provider/GitHub/GitHubPRService'; + +jest.mock('./File'); +jest.mock('./Provider/CommonVCS/VCSEngine'); +jest.mock('./Provider/GitLab/GitLabAdapter'); +jest.mock('./Provider/GitLab/GitLabMRService'); +jest.mock('./Provider/GitHub/GitHubAdapter'); +jest.mock('./Provider/GitHub/GitHubPRService'); + +const mockedVCSEngine = VCSEngine as jest.MockedClass; +const mockedGitLabAdapter = GitLabAdapter as jest.MockedClass; +const mockedGitLabMRService = GitLabMRService as jest.MockedClass; +const mockedGitHubAdapter = GitHubAdapter as jest.MockedClass; +const mockedGitHubPRService = GitHubPRService as jest.MockedClass; + +describe('App', () => { + it('should not require VCS when dry-run', async () => { + const mockedWriteFileHelper = jest.fn(); + File.writeFileHelper = mockedWriteFileHelper; + + const configs = ({ buildLogFile: [], dryRun: true } as unknown) as ConfigArgument; + const app = new App(configs); + await app.start(); + + expect(mockedWriteFileHelper).toBeCalled(); + }); + + it('should throw "VCS adapter is not found" error when run without VCS', async () => { + const app = new App(({ buildLogFile: [] } as unknown) as ConfigArgument); + const fn = async () => await app.start(); + + await expect(fn).rejects.toThrowError(CodeCoachError); + await expect(fn).rejects.toThrowError('VCS adapter is not found'); + }); + + it('should initialize GitLabAdapter and GitLabMRService correctly', async () => { + const vcsReportFn = jest.fn().mockResolvedValue(true); + mockedVCSEngine.mockImplementationOnce(() => { + return ({ + report: vcsReportFn, + } as unknown) as VCSEngine; + }); + + const configs = ({ + vcs: 'gitlab', + gitlabHost: 'https://gitlab.com', + gitlabProjectId: 1234, + gitlabMrIid: 99, + gitlabToken: 'fakegitlabtoken', + buildLogFile: [], + } as unknown) as ConfigArgument; + + const app = new App(configs); + await app.start(); + + expect(vcsReportFn).toBeCalledTimes(1); + expect(mockedGitLabMRService).toBeCalledWith( + configs.gitlabHost, + configs.gitlabProjectId, + configs.gitlabMrIid, + configs.gitlabToken, + ); + expect(mockedGitLabAdapter).toBeCalledTimes(1); + }); + + it('should initialize GitHubAdapter and GitHubPRService correctly', async () => { + const vcsReportFn = jest.fn().mockResolvedValue(true); + mockedVCSEngine.mockImplementationOnce(() => { + return ({ + report: vcsReportFn, + } as unknown) as VCSEngine; + }); + + const configs = ({ + vcs: 'github', + githubRepoUrl: 'https://github.com/codeleague/codecoach', + githubPr: 1234, + githubToken: 'fakegithubtoken', + buildLogFile: [], + } as unknown) as ConfigArgument; + + const app = new App(configs); + await app.start(); + + expect(vcsReportFn).toBeCalledTimes(1); + expect(mockedGitHubPRService).toBeCalledWith( + configs.githubToken, + configs.githubRepoUrl, + configs.githubPr, + ); + expect(mockedGitHubAdapter).toBeCalledTimes(1); + }); +}); diff --git a/src/app.ts b/src/app.ts index 7f00611..3f49c10 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,4 @@ -#!/usr/bin/env node - -import { BuildLogFile, configs, ProjectType } from './Config'; +import { BuildLogFile, ConfigArgument, ProjectType } from './Config'; import { File } from './File'; import { Log } from './Logger'; import { @@ -22,47 +20,59 @@ import { VCSEngine } from './Provider/CommonVCS/VCSEngine'; import { GitLabAdapter } from './Provider/GitLab/GitLabAdapter'; import { VCSAdapter } from './Provider/@interfaces/VCSAdapter'; import { AnalyzerBot } from './AnalyzerBot/AnalyzerBot'; +import CodeCoachError from './CodeCoachError'; + +export class App { + private vcs: VCS; + private readonly configs: ConfigArgument; -class App { - private vcs: VCS | null = null; + constructor(configs: ConfigArgument) { + this.configs = configs; + } async start(): Promise { - if (!configs.dryRun) { - const adapter = App.getAdapter(); + if (!this.configs.dryRun) { + const adapter = this.getAdapter(); if (!adapter) { - Log.error('VCS adapter is not found'); - process.exit(1); + throw new CodeCoachError('VCS adapter is not found'); } - const analyzer = new AnalyzerBot(configs); - this.vcs = new VCSEngine(configs, analyzer, adapter); + const analyzer = new AnalyzerBot(this.configs); + this.vcs = new VCSEngine(this.configs, analyzer, adapter); } - const logs = await this.parseBuildData(configs.buildLogFile); + const logs = await this.parseBuildData(this.configs.buildLogFile); Log.info('Build data parsing completed'); const reportToVcs = this.reportToVcs(logs); - const logToFile = App.writeLogToFile(logs); + const logToFile = this.writeLogToFile(logs); const [passed] = await Promise.all([reportToVcs, logToFile]); if (!passed) { - Log.error('There are some linting error and exit code reporting is enabled'); - process.exit(1); + throw new CodeCoachError( + 'There are some linting error and exit code reporting is enabled', + ); } } - private static getAdapter(): VCSAdapter | undefined { - if (configs.vcs === 'github') { + private getAdapter(): VCSAdapter | undefined { + if (this.configs.vcs === 'github') { const githubPRService = new GitHubPRService( - configs.githubToken, - configs.githubRepoUrl, - configs.githubPr, + this.configs.githubToken, + this.configs.githubRepoUrl, + this.configs.githubPr, ); return new GitHubAdapter(githubPRService); - } else if (configs.vcs === 'gitlab') { - return new GitLabAdapter(new GitLabMRService()); + } else if (this.configs.vcs === 'gitlab') { + const gitlabMRService = new GitLabMRService( + this.configs.gitlabHost, + this.configs.gitlabProjectId, + this.configs.gitlabMrIid, + this.configs.gitlabToken, + ); + return new GitLabAdapter(gitlabMRService); } } - private static getParser(type: ProjectType, cwd: string): Parser { + private getParser(type: ProjectType, cwd: string): Parser { switch (type) { case ProjectType.dotnetbuild: return new DotnetBuildParser(cwd); @@ -87,7 +97,7 @@ class App { const logsTasks = files.map(async ({ type, path, cwd }) => { Log.debug('Parsing', { type, path, cwd }); const content = await File.readFileHelper(path); - const parser = App.getParser(type, cwd); + const parser = this.getParser(type, cwd); return parser.parse(content); }); @@ -95,7 +105,7 @@ class App { } private async reportToVcs(logs: LogType[]): Promise { - if (!this.vcs) { + if (this.configs.dryRun) { Log.info('Dry run enabled, skip reporting'); return true; } @@ -110,9 +120,9 @@ class App { } } - private static async writeLogToFile(logs: LogType[]): Promise { + private async writeLogToFile(logs: LogType[]): Promise { try { - await File.writeFileHelper(configs.output, JSON.stringify(logs, null, 2)); + await File.writeFileHelper(this.configs.output, JSON.stringify(logs, null, 2)); Log.info('Write output completed'); } catch (error) { Log.error('Write output failed', { error }); @@ -120,12 +130,3 @@ class App { } } } - -new App().start().catch((error) => { - if (error instanceof Error) { - const { stack, message } = error; - Log.error('Unexpected error', { stack, message }); - } - Log.error('Unexpected error', { error }); - process.exit(2); -}); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..307f633 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,23 @@ +#!/usr/bin/env node + +import CodeCoachError from './CodeCoachError'; +import { ConfigParser } from './Config'; +import { Log } from './Logger'; +import { App } from './app'; + +const cliOptions = ConfigParser(process.argv); + +new App(cliOptions).start().catch((error) => { + if (error instanceof CodeCoachError) { + Log.error(error.message); + process.exit(1); + } + + if (error instanceof Error) { + const { stack, message } = error; + Log.error('Unexpected error', { stack, message }); + } + + Log.error('Unexpected error', { error }); + process.exit(2); +}); From de9e77b45fa7052267ed37788b240fcaff121b52 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Wed, 19 Jul 2023 19:48:28 +0700 Subject: [PATCH 02/12] change entrypoint path --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 213c550..581f329 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "prepublishOnly": "yarn build" }, "bin": { - "codecoach": "dist/app.js" + "codecoach": "dist/index.js" }, "files": [ "dist/**/*" From 367aa7d10be2e802ef83ddbb55b7dd55d59f63ce Mon Sep 17 00:00:00 2001 From: jeeyo Date: Mon, 24 Jul 2023 17:06:19 +0700 Subject: [PATCH 03/12] add sample smocker gitlab mock --- tests/gitlabmock.yml | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 tests/gitlabmock.yml diff --git a/tests/gitlabmock.yml b/tests/gitlabmock.yml new file mode 100755 index 0000000..7499917 --- /dev/null +++ b/tests/gitlabmock.yml @@ -0,0 +1,71 @@ +# getCurrentUserId +- request: + path: /user + method: GET + response: + status: 200 + headers: + Content-Type: application/json + body: |- + { + "id": 1, + "name": "John Smith", + "username": "john_smith", + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", + "web_url": "http://localhost:3000/john_smith", + "created_at": "2012-05-23T08:00:58Z" + } + +# listAllNotes +- request: + path: + matcher: ShouldMatch + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/notes + method: GET + response: + status: 200 + headers: + Content-Type: application/json + body: |- + [ + { + "id": 301, + "body": "Comment for MR", + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z" + }, + "created_at": "2013-10-02T08:57:14Z", + "updated_at": "2013-10-02T08:57:14Z", + "confidential": false, + }, + { + "id": 302, + "body": "LGTM", + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z" + }, + "created_at": "2013-10-02T09:22:45Z", + "updated_at": "2013-10-02T10:22:45Z", + "confidential": false + } + ] + +# deleteNote +- request: + path: + matcher: ShouldMatch + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/notes\/[^\/]+ + method: DELETE + response: + status: 200 From 01d923032b193bc23413f928215ebe475167a858 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Wed, 26 Jul 2023 15:52:58 +0700 Subject: [PATCH 04/12] add GitLab integration test --- jest.config.js | 6 +- package.json | 2 + tests/eslint-report.json | 25 ++ tests/gitlab.ts | 68 ++++++ tests/gitlabmock.yml | 139 ++++++++--- tests/utils.ts | 49 ++++ yarn.lock | 497 ++++++++++++++++++++++++++++++++++++++- 7 files changed, 749 insertions(+), 37 deletions(-) create mode 100644 tests/eslint-report.json create mode 100644 tests/gitlab.ts create mode 100644 tests/utils.ts diff --git a/jest.config.js b/jest.config.js index 5e50958..c97e887 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,11 @@ module.exports = { - roots: ['/src'], + testEnvironment: 'node', + roots: ['/src', '/tests'], testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'], transform: { '^.+\\.(ts|tsx)$': 'ts-jest', }, + moduleNameMapper: { + axios: 'axios/dist/node/axios.cjs', + }, }; diff --git a/package.json b/package.json index 581f329..937259a 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@types/rimraf": "^3.0.0", "@typescript-eslint/eslint-plugin": "^4.9.1", "@typescript-eslint/parser": "^4.9.1", + "axios": "^1.4.0", "eslint": "^7.15.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-prettier": "^3.1.4", @@ -40,6 +41,7 @@ "jest": "^26.4.0", "nodemon": "^2.0.6", "prettier": "^2.2.1", + "testcontainers": "^9.12.0", "ts-jest": "^26.4.4", "ts-node": "^9.1.1", "typescript": "^4.1.2" diff --git a/tests/eslint-report.json b/tests/eslint-report.json new file mode 100644 index 0000000..f915911 --- /dev/null +++ b/tests/eslint-report.json @@ -0,0 +1,25 @@ +[ + { + "filePath": "/Users/codeleague/example/src/App.tsx", + "messages": [ + { + "ruleId": "react-hooks/rules-of-hooks", + "severity": 2, + "message": "React Hook \"useEffect\" is called conditionally. React Hooks must be called in the exact same order in every component render.", + "line": 11, + "column": 5, + "nodeType": "Identifier", + "endLine": 11, + "endColumn": 14 + } + ], + "suppressedMessages": [], + "errorCount": 1, + "fatalErrorCount": 0, + "warningCount": 0, + "fixableErrorCount": 0, + "fixableWarningCount": 0, + "source": "import { useEffect, useState } from \"react\";\nimport reactLogo from \"./assets/react.svg\";\nimport viteLogo from \"/vite.svg\";\nimport \"./App.css\";\n\nfunction App() {\n const [count, setCount] = useState(0)\n\n const name = '';\n if (name !== '') {\n useEffect(function persistForm() {\n localStorage.setItem('formData',name);\n });\n }\n\n return (\n <>\n
\n \n \"Vite\n \n \n \"React\n \n
\n

Vite + React

\n
\n \n

\n Edit src/App.tsx and save to test HMR\n

\n
\n

\n Click on the Vite and React logos to learn more\n

\n \n );\n}\n\nexport default App;\n", + "usedDeprecatedRules": [] + } +] diff --git a/tests/gitlab.ts b/tests/gitlab.ts new file mode 100644 index 0000000..baa509c --- /dev/null +++ b/tests/gitlab.ts @@ -0,0 +1,68 @@ +import { StartedTestContainer } from 'testcontainers'; +import { ConfigParser } from '../src/Config'; +import { App } from '../src/app'; +import { + configHttpMockServerWithYaml, + getHttpMockServerHistory, + startHttpMockServer, + stopHttpMockServer, +} from './utils'; +import CodeCoachError from '../src/CodeCoachError'; + +jest.setTimeout(60000); + +describe('GitLab', () => { + let gitlab: StartedTestContainer; + + beforeEach(async () => { + gitlab = await startHttpMockServer(); + await configHttpMockServerWithYaml(gitlab, './tests/gitlabmock.yml'); + }); + + afterEach(async () => { + stopHttpMockServer(gitlab); + }); + + it('should correctly report to GitLab', async () => { + const configs = ConfigParser([ + 'node', + 'app.ts', + '--vcs="gitlab"', + `--gitlabHost=http://${gitlab.getHost()}:${gitlab.getMappedPort(8080)}`, + `--gitlabProjectId=1`, + `--gitlabMrIid=1`, + `--gitlabToken=privatetoken`, + `-f=eslint;./tests/eslint-report.json;/Users/codeleague/example`, + `-o=output.log`, + '--failOnWarnings', + ]); + const app = new App(configs); + const undertest = () => app.start(); + await expect(undertest).rejects.toThrow( + new CodeCoachError( + 'There are some linting error and exit code reporting is enabled', + ), + ); + + // assertions + const history = await getHttpMockServerHistory(gitlab); + + expect(history).toHaveLength(4); + expect(history[0].request).toMatchObject({ + path: '/api/v4/projects/1/merge_requests/1/versions', + method: 'GET', + }); + expect(history[1].request).toMatchObject({ + path: '/api/v4/projects/1/merge_requests/1/changes', + method: 'GET', + }); + expect(history[2].request).toMatchObject({ + path: '/api/v4/projects/1/merge_requests/1/discussions', + method: 'POST', + }); + expect(history[3].request).toMatchObject({ + path: '/api/v4/projects/1/merge_requests/1/notes', + method: 'POST', + }); + }); +}); diff --git a/tests/gitlabmock.yml b/tests/gitlabmock.yml index 7499917..c66ae62 100755 --- a/tests/gitlabmock.yml +++ b/tests/gitlabmock.yml @@ -1,28 +1,43 @@ +# createMRDiscussion +- request: + path: + matcher: ShouldMatch + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/discussions\/?$ + method: POST + headers: + Private-Token: privatetoken + response: + status: 200 + # getCurrentUserId - request: path: /user method: GET + headers: + Private-Token: privatetoken response: status: 200 headers: Content-Type: application/json body: |- { - "id": 1, + "id": 99, "name": "John Smith", "username": "john_smith", "state": "active", "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", "web_url": "http://localhost:3000/john_smith", - "created_at": "2012-05-23T08:00:58Z" + "created_at": "2022-05-23T08:00:58Z" } # listAllNotes - request: path: matcher: ShouldMatch - value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/notes + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/notes\/?$ method: GET + headers: + Private-Token: privatetoken response: status: 200 headers: @@ -30,34 +45,29 @@ body: |- [ { - "id": 301, - "body": "Comment for MR", - "author": { - "id": 1, - "username": "pipin", - "email": "admin@example.com", - "name": "Pip", - "state": "active", - "created_at": "2013-09-30T13:46:01Z" - }, - "created_at": "2013-10-02T08:57:14Z", - "updated_at": "2013-10-02T08:57:14Z", - "confidential": false, - }, - { - "id": 302, - "body": "LGTM", - "author": { - "id": 1, - "username": "pipin", - "email": "admin@example.com", - "name": "Pip", - "state": "active", - "created_at": "2013-09-30T13:46:01Z" - }, - "created_at": "2013-10-02T09:22:45Z", - "updated_at": "2013-10-02T10:22:45Z", - "confidential": false + "id": 6273413, + "type": null, + "body": "added 1 commit\n\n
  • 3b1c0654 - fix CI
\n\n[Compare with previous version](/full-stack/tooling/codecoach-game-poc/-/merge_requests/20/diffs?diff_id=3712228&start_sha=3a01be0ebd483c7fa5d1fa166d27956cd5becc9b)", + "attachment": null, + "author": { + "id": 99, + "username": "john_smith", + "name": "John Smith", + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", + "web_url": "http://localhost:3000/john_smith" + }, + "created_at": "2023-07-25T08:34:51.384Z", + "updated_at": "2023-07-25T08:34:51.385Z", + "system": true, + "noteable_id": 859214, + "noteable_type": "MergeRequest", + "project_id": 37985, + "resolvable": false, + "confidential": false, + "internal": false, + "noteable_iid": 20, + "commands_changes": {} } ] @@ -67,5 +77,72 @@ matcher: ShouldMatch value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/notes\/[^\/]+ method: DELETE + headers: + Private-Token: privatetoken + response: + status: 200 + +# createNote +- request: + path: + matcher: ShouldMatch + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/notes\/?$ + method: POST + headers: + Private-Token: privatetoken + response: + status: 200 + +# diff +- request: + path: + matcher: ShouldMatch + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/changes\/?$ + method: GET + headers: + Private-Token: privatetoken response: status: 200 + headers: + Content-Type: application/json + body: |- + { + "changes": [ + { + "diff": "@@ -4,12 +4,14 @@ import viteLogo from \"/vite.svg\";\n import \"./App.css\";\n \n function App() {\n- const [count, setCount] = useState(0);\n- const name = '';\n- useEffect(function persistForm() {\n- localStorage.setItem('formData',name);\n- });\n+ const [count, setCount] = useState(0)\n \n+ const name = '';\n+ if (name !== '') {\n+ useEffect(function persistForm() {\n+ localStorage.setItem('formData',name);\n+ });\n+ }\n \n return (\n <>\n", + "new_path": "src/App.tsx", + "old_path": "src/App.tsx", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false + } + ] + } + +# getLatestVersion +- request: + path: + matcher: ShouldMatch + value: \/projects\/[^\/]+\/merge_requests\/[^\/]+\/versions\/?$ + method: GET + headers: + Private-Token: privatetoken + response: + status: 200 + headers: + Content-Type: application/json + body: |- + [ + { + "id": 3712211, + "head_commit_sha": "3a01be0ebd483c7fa5d1fa166d27956cd5becc9b", + "base_commit_sha": "28ab14718546dc00d20b8f56b2732ac4281fc1ab", + "start_commit_sha": "28ab14718546dc00d20b8f56b2732ac4281fc1ab", + "created_at": "2023-07-25T08:33:48.665Z", + "merge_request_id": 859214, + "state": "collected", + "real_size": "1" + } + ] diff --git a/tests/utils.ts b/tests/utils.ts new file mode 100644 index 0000000..09655fa --- /dev/null +++ b/tests/utils.ts @@ -0,0 +1,49 @@ +import { GenericContainer, StartedTestContainer } from 'testcontainers'; +import fs from 'fs'; +import axios from 'axios'; + +interface HttpServerMockHistory { + request: { + path: string; + method: string; + origin: string; + body: string | Record | undefined; + headers: Record; + date: string; + }; + response: { + status: number; + body: string | Record | undefined; + date: string; + }; +} + +export const startHttpMockServer = async (): Promise => { + return await new GenericContainer('thiht/smocker').withExposedPorts(8080, 8081).start(); +}; + +export const configHttpMockServerWithYaml = async ( + mock: StartedTestContainer, + yml: string, +): Promise => { + await axios.post( + `http://${mock.getHost()}:${mock.getMappedPort(8081)}/mocks`, + fs.readFileSync(yml), + { + headers: { + 'Content-Type': 'application/x-yaml', + }, + }, + ); +}; + +export const getHttpMockServerHistory = async ( + mock: StartedTestContainer, +): Promise => { + return (await axios.get(`http://${mock.getHost()}:${mock.getMappedPort(8081)}/history`)) + .data; +}; + +export const stopHttpMockServer = async (mock: StartedTestContainer): Promise => { + await mock.stop(); +}; diff --git a/yarn.lock b/yarn.lock index e871886..accca54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -258,6 +258,11 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -734,6 +739,13 @@ dependencies: defer-to-connect "^2.0.0" +"@types/archiver@^5.3.2": + version "5.3.2" + resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-5.3.2.tgz#a9f0bcb0f0b991400e7766d35f6e19d163bdadcc" + integrity sha512-IctHreBuWE5dvBDz/0WeKtyVKVRs4h75IblxOACL92wU66v+HGAfEYAOyXkOFphvRJMhuXdI9huDXpX0FC6lCw== + dependencies: + "@types/readdir-glob" "*" + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" @@ -782,6 +794,22 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/docker-modem@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/docker-modem/-/docker-modem-3.0.2.tgz#c49c902e17364fc724e050db5c1d2b298c6379d4" + integrity sha512-qC7prjoEYR2QEe6SmCVfB1x3rfcQtUr1n4x89+3e0wSTMQ/KYCyf+/RAA9n2tllkkNc6//JMUZePdFRiGIWfaQ== + dependencies: + "@types/node" "*" + "@types/ssh2" "*" + +"@types/dockerode@^3.3.19": + version "3.3.19" + resolved "https://registry.yarnpkg.com/@types/dockerode/-/dockerode-3.3.19.tgz#59eb07550a102b397a9504083a6c50d811eed04c" + integrity sha512-7CC5yIpQi+bHXwDK43b/deYXteP3Lem9gdocVVHJPSRJJLMfbiOchQV3rDmAPkMw+n3GIVj7m1six3JW+VcwwA== + dependencies: + "@types/docker-modem" "*" + "@types/node" "*" + "@types/glob@*": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -856,11 +884,21 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499" integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA== -"@types/node@>= 8", "@types/node@^14.14.11": +"@types/node@>= 8": version "14.14.11" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.11.tgz#fc25a4248a5e8d0837019b1d170146d07334abe0" integrity sha512-BJ97wAUuU3NUiUCp44xzUFquQEvnk1wu7q4CMEUYKJWjdkr0YWYDsm4RFtAvxYsNjLsKcrFt6RvK8r+mnzMbEQ== +"@types/node@^14.14.11": + version "14.18.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.54.tgz#fc304bd66419030141fa997dc5a9e0e374029ae8" + integrity sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw== + +"@types/node@^18.11.18": + version "18.17.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.0.tgz#35d44267a33dd46b49ee0f73d31b05fd7407e290" + integrity sha512-GXZxEtOxYGFchyUzxvKI14iff9KZ2DI+A6a37o6EQevtg6uO9t+aUZKcaC1Te5Ng1OnLM7K9NVVj+FbecD9cJg== + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -871,6 +909,13 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3" integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== +"@types/readdir-glob@*": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/readdir-glob/-/readdir-glob-1.1.1.tgz#27ac2db283e6aa3d110b14ff9da44fcd1a5c38b1" + integrity sha512-ImM6TmoF8bgOwvehGviEj3tRdRBbQujr1N+0ypaln/GWjaerOB26jb93vsRHmdMtvVQZQebOlqt2HROark87mQ== + dependencies: + "@types/node" "*" + "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -886,6 +931,28 @@ "@types/glob" "*" "@types/node" "*" +"@types/ssh2-streams@*": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.9.tgz#8ca51b26f08750a780f82ee75ff18d7160c07a87" + integrity sha512-I2J9jKqfmvXLR5GomDiCoHrEJ58hAOmFrekfFqmCFd+A6gaEStvWnPykoWUwld1PNg4G5ag1LwdA+Lz1doRJqg== + dependencies: + "@types/node" "*" + +"@types/ssh2@*": + version "1.11.13" + resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-1.11.13.tgz#e6224da936abec0541bf26aa826b1cc37ea70d69" + integrity sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ== + dependencies: + "@types/node" "^18.11.18" + +"@types/ssh2@^0.5.48": + version "0.5.52" + resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.52.tgz#9dbd8084e2a976e551d5e5e70b978ed8b5965741" + integrity sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg== + dependencies: + "@types/node" "*" + "@types/ssh2-streams" "*" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -1091,6 +1158,35 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +archiver-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" + integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw== + dependencies: + glob "^7.1.4" + graceful-fs "^4.2.0" + lazystream "^1.0.0" + lodash.defaults "^4.2.0" + lodash.difference "^4.5.0" + lodash.flatten "^4.4.0" + lodash.isplainobject "^4.0.6" + lodash.union "^4.6.0" + normalize-path "^3.0.0" + readable-stream "^2.0.0" + +archiver@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6" + integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w== + dependencies: + archiver-utils "^2.1.0" + async "^3.2.3" + buffer-crc32 "^0.2.1" + readable-stream "^3.6.0" + readdir-glob "^1.0.0" + tar-stream "^2.2.0" + zip-stream "^4.1.0" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -1128,6 +1224,13 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +asn1@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -1150,11 +1253,21 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +async-lock@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.0.tgz#c8b6630eff68fbbdd8a5b6eb763dac3bfbb8bf02" + integrity sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ== + async@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== +async@^3.2.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1175,6 +1288,15 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== +axios@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-jest@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.3.0.tgz#10d0ca4b529ca3e7d1417855ef7d7bd6fc0c3463" @@ -1240,6 +1362,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -1253,7 +1380,7 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -bcrypt-pbkdf@^1.0.0: +bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= @@ -1275,6 +1402,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + boxen@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" @@ -1297,6 +1433,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -1339,11 +1482,34 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buffer-crc32@^0.2.1, buffer-crc32@^0.2.13: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + 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" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buildcheck@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" + integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q== + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -1470,6 +1636,11 @@ chokidar@^3.2.2: optionalDependencies: fsevents "~2.1.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -1598,6 +1769,16 @@ component-emitter@^1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== +compress-commons@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d" + integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ== + dependencies: + buffer-crc32 "^0.2.13" + crc32-stream "^4.0.2" + normalize-path "^3.0.0" + readable-stream "^3.6.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1632,6 +1813,27 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cpu-features@~0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.8.tgz#a2d464b023b8ad09004c8cdca23b33f192f63546" + integrity sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg== + dependencies: + buildcheck "~0.0.6" + nan "^2.17.0" + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +crc32-stream@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007" + integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w== + dependencies: + crc-32 "^1.2.0" + readable-stream "^3.4.0" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1723,6 +1925,13 @@ debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1841,6 +2050,32 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +docker-compose@^0.24.1: + version "0.24.1" + resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.24.1.tgz#09f9a2408395b8adf80feaacf65f6e2a4b119866" + integrity sha512-CVphzCi0Hmw/0CHlAzgiwhLsJjFRqnvpBYMYbf63bz6MON69ElgrfrgQTmgPtEjbifjgaptu3+Gea62vI+9jiA== + dependencies: + yaml "^2.2.2" + +docker-modem@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" + integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== + dependencies: + debug "^4.1.1" + readable-stream "^3.5.0" + split-ca "^1.0.1" + ssh2 "^1.11.0" + +dockerode@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" + integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== + dependencies: + "@balena/dockerignore" "^1.0.2" + docker-modem "^3.0.0" + tar-fs "~2.0.1" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1895,7 +2130,7 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -2296,6 +2531,11 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2331,6 +2571,11 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2375,6 +2620,11 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-port@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" @@ -2495,6 +2745,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.2.4: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -2622,6 +2877,11 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -2671,7 +2931,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3511,6 +3771,13 @@ latest-version@^5.0.0: dependencies: package-json "^6.3.0" +lazystream@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" + integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== + dependencies: + readable-stream "^2.0.5" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -3549,6 +3816,26 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.difference@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" + integrity sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA== + +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -3559,6 +3846,11 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash.union@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" + integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw== + lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" @@ -3699,6 +3991,13 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" +minimatch@^5.1.0: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -3712,7 +4011,12 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@1.x: +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@1.x, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -3727,6 +4031,11 @@ ms@2.1.2, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nan@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -3759,6 +4068,13 @@ node-fetch@^2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@^2.6.12: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4133,6 +4449,27 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" +proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + +properties-reader@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/properties-reader/-/properties-reader-2.2.0.tgz#41d837fe143d8d5f2386b6a869a1975c0b2c595c" + integrity sha512-CgVcr8MwGoBKK24r9TwHfZkLLaNFHQ6y4wgT9w/XzdpacOOi5ciH4hcuLechSDAwXsfrGQtI2JTutY2djOx2Ow== + dependencies: + mkdirp "^1.0.4" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -4229,6 +4566,19 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" +readable-stream@^2.0.0, readable-stream@^2.0.5: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@^2.3.7: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -4242,6 +4592,15 @@ readable-stream@^2.3.7: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.1.1, readable-stream@^3.5.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -4251,6 +4610,13 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readdir-glob@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" + integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== + dependencies: + minimatch "^5.1.0" + readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -4405,6 +4771,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -4684,6 +5055,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== +split-ca@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -4701,6 +5077,25 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +ssh-remote-port-forward@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz#72b0c5df8ec27ca300c75805cc6b266dee07e298" + integrity sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ== + dependencies: + "@types/ssh2" "^0.5.48" + ssh2 "^1.4.0" + +ssh2@^1.11.0, ssh2@^1.4.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb" + integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA== + dependencies: + asn1 "^0.2.6" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.8" + nan "^2.17.0" + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -4862,6 +5257,37 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" +tar-fs@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-fs@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + +tar-stream@^2.0.0, tar-stream@^2.1.4, tar-stream@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + term-size@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" @@ -4884,6 +5310,28 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +testcontainers@^9.12.0: + version "9.12.0" + resolved "https://registry.yarnpkg.com/testcontainers/-/testcontainers-9.12.0.tgz#f9f2492af4317f649611005b60fa0bbf6fdd7639" + integrity sha512-zmjLTAUqCiDvhDq7TCwcyhI3m/cXXKGnhyLLJ9pgh53VgG9O+P+opX1pIx28aYTUQ7Yu6b5sJf0xoIuxoiclWg== + dependencies: + "@balena/dockerignore" "^1.0.2" + "@types/archiver" "^5.3.2" + "@types/dockerode" "^3.3.19" + archiver "^5.3.1" + async-lock "^1.4.0" + byline "^5.0.0" + debug "^4.3.4" + docker-compose "^0.24.1" + dockerode "^3.3.5" + get-port "^5.1.1" + node-fetch "^2.6.12" + proper-lockfile "^4.1.2" + properties-reader "^2.2.0" + ssh-remote-port-forward "^1.0.4" + tar-fs "^2.1.1" + tmp "^0.2.1" + text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" @@ -4899,6 +5347,13 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -4977,6 +5432,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + triple-beam@^1.2.0, triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" @@ -5228,6 +5688,11 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -5250,6 +5715,14 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.0.0: version "8.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.1.0.tgz#c628acdcf45b82274ce7281ee31dd3c839791771" @@ -5393,6 +5866,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^2.2.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== + yargs-parser@20.x, yargs-parser@^20.2.2: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" @@ -5440,3 +5918,12 @@ yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +zip-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79" + integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A== + dependencies: + archiver-utils "^2.1.0" + compress-commons "^4.1.0" + readable-stream "^3.6.0" From 694421ca51ded78db8f215544e95bdf63e9e67f1 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Wed, 26 Jul 2023 16:21:26 +0700 Subject: [PATCH 05/12] refactor --- tests/{gitlab.ts => gitlab.spec.ts} | 15 +++++++++------ tests/utils.ts | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) rename tests/{gitlab.ts => gitlab.spec.ts} (84%) diff --git a/tests/gitlab.ts b/tests/gitlab.spec.ts similarity index 84% rename from tests/gitlab.ts rename to tests/gitlab.spec.ts index baa509c..a8f3961 100644 --- a/tests/gitlab.ts +++ b/tests/gitlab.spec.ts @@ -1,22 +1,22 @@ -import { StartedTestContainer } from 'testcontainers'; +import type { StartedTestContainer } from 'testcontainers'; import { ConfigParser } from '../src/Config'; import { App } from '../src/app'; import { - configHttpMockServerWithYaml, + configureHttpMockServerWithYaml, getHttpMockServerHistory, startHttpMockServer, stopHttpMockServer, } from './utils'; import CodeCoachError from '../src/CodeCoachError'; -jest.setTimeout(60000); +jest.setTimeout(15000); describe('GitLab', () => { let gitlab: StartedTestContainer; beforeEach(async () => { gitlab = await startHttpMockServer(); - await configHttpMockServerWithYaml(gitlab, './tests/gitlabmock.yml'); + await configureHttpMockServerWithYaml(gitlab, './tests/gitlabmock.yml'); }); afterEach(async () => { @@ -38,15 +38,14 @@ describe('GitLab', () => { ]); const app = new App(configs); const undertest = () => app.start(); + await expect(undertest).rejects.toThrow( new CodeCoachError( 'There are some linting error and exit code reporting is enabled', ), ); - // assertions const history = await getHttpMockServerHistory(gitlab); - expect(history).toHaveLength(4); expect(history[0].request).toMatchObject({ path: '/api/v4/projects/1/merge_requests/1/versions', @@ -63,6 +62,10 @@ describe('GitLab', () => { expect(history[3].request).toMatchObject({ path: '/api/v4/projects/1/merge_requests/1/notes', method: 'POST', + body: { + body: + '## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning', + }, }); }); }); diff --git a/tests/utils.ts b/tests/utils.ts index 09655fa..1382cd1 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -22,7 +22,7 @@ export const startHttpMockServer = async (): Promise => { return await new GenericContainer('thiht/smocker').withExposedPorts(8080, 8081).start(); }; -export const configHttpMockServerWithYaml = async ( +export const configureHttpMockServerWithYaml = async ( mock: StartedTestContainer, yml: string, ): Promise => { From c76f357cea0e1e855a6e8d4b2cb76095ddd60209 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Thu, 27 Jul 2023 01:29:54 +0700 Subject: [PATCH 06/12] add dryrun test --- tests/dryrun.spec.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/dryrun.spec.ts diff --git a/tests/dryrun.spec.ts b/tests/dryrun.spec.ts new file mode 100644 index 0000000..29be5bd --- /dev/null +++ b/tests/dryrun.spec.ts @@ -0,0 +1,34 @@ +import { ConfigParser } from '../src/Config'; +import { App } from '../src/app'; +import fs from 'fs'; + +describe('Dry Run', () => { + it('should correctly write output to file', async () => { + const configs = ConfigParser([ + 'node', + 'app.ts', + '--dryRun', + `-f=eslint;./tests/eslint-report.json;/Users/codeleague/example`, + `-o=./tests/output.log`, + '--failOnWarnings', + ]); + const app = new App(configs); + await app.start(); + + const outputFile = JSON.parse(fs.readFileSync('./tests/output.log', 'utf8')); + expect(outputFile).toHaveLength(1); + expect(outputFile[0]).toMatchObject({ + ruleId: 'react-hooks/rules-of-hooks', + log: + '{"ruleId":"react-hooks/rules-of-hooks","severity":2,"message":"React Hook \\"useEffect\\" is called conditionally. React Hooks must be called in the exact same order in every component render.","line":11,"column":5,"nodeType":"Identifier","endLine":11,"endColumn":14}', + line: 11, + lineOffset: 5, + msg: + 'React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.', + source: 'src/App.tsx', + severity: 'error', + valid: true, + type: 'eslint', + }); + }); +}); From 271ad524c282f3848e6bbf4eaf216ba05c00b652 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Thu, 27 Jul 2023 16:02:50 +0700 Subject: [PATCH 07/12] add removeOldComment test --- tests/gitlab.spec.ts | 78 ++++++++++++++++++++++++++++++++------------ tests/gitlabmock.yml | 72 ++++++++++++++++++++++++---------------- 2 files changed, 101 insertions(+), 49 deletions(-) diff --git a/tests/gitlab.spec.ts b/tests/gitlab.spec.ts index a8f3961..2e405c5 100644 --- a/tests/gitlab.spec.ts +++ b/tests/gitlab.spec.ts @@ -29,11 +29,13 @@ describe('GitLab', () => { 'app.ts', '--vcs="gitlab"', `--gitlabHost=http://${gitlab.getHost()}:${gitlab.getMappedPort(8080)}`, + // `--gitlabHost=http://localhost:8080`, `--gitlabProjectId=1`, `--gitlabMrIid=1`, `--gitlabToken=privatetoken`, `-f=eslint;./tests/eslint-report.json;/Users/codeleague/example`, `-o=output.log`, + '--removeOldComment', '--failOnWarnings', ]); const app = new App(configs); @@ -45,27 +47,61 @@ describe('GitLab', () => { ), ); - const history = await getHttpMockServerHistory(gitlab); - expect(history).toHaveLength(4); - expect(history[0].request).toMatchObject({ - path: '/api/v4/projects/1/merge_requests/1/versions', - method: 'GET', - }); - expect(history[1].request).toMatchObject({ - path: '/api/v4/projects/1/merge_requests/1/changes', - method: 'GET', - }); - expect(history[2].request).toMatchObject({ - path: '/api/v4/projects/1/merge_requests/1/discussions', - method: 'POST', - }); - expect(history[3].request).toMatchObject({ - path: '/api/v4/projects/1/merge_requests/1/notes', - method: 'POST', - body: { - body: - '## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning', + const history = await getHttpMockServerHistory(gitlab as StartedTestContainer); + expect(history).toHaveLength(8); + expect(history).toMatchObject([ + { + request: { + path: '/api/v4/projects/1/merge_requests/1/versions', + method: 'GET', + }, }, - }); + { + request: { + path: '/api/v4/projects/1/merge_requests/1/changes', + method: 'GET', + }, + }, + { + request: { + path: '/api/v4/user', + method: 'GET', + }, + }, + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes', + method: 'GET', + }, + }, + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes/987654', + method: 'DELETE', + }, + }, + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes/987655', + method: 'DELETE', + }, + }, + { + request: { + path: '/api/v4/projects/1/merge_requests/1/discussions', + method: 'POST', + }, + }, + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes', + method: 'POST', + body: { + body: + '## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning', + }, + }, + }, + ]); }); }); diff --git a/tests/gitlabmock.yml b/tests/gitlabmock.yml index c66ae62..4a8e35d 100755 --- a/tests/gitlabmock.yml +++ b/tests/gitlabmock.yml @@ -11,7 +11,9 @@ # getCurrentUserId - request: - path: /user + path: + matcher: ShouldMatch + value: /user method: GET headers: Private-Token: privatetoken @@ -22,11 +24,11 @@ body: |- { "id": 99, - "name": "John Smith", - "username": "john_smith", + "username": "codecoach-bro", + "name": "codecoach-bro", "state": "active", - "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", - "web_url": "http://localhost:3000/john_smith", + "avatar_url": "http://localhost:3000/uploads/user/avatar/2656/avatar.png", + "web_url": "https://gitlab.agodadev.io/codecoach-bro", "created_at": "2022-05-23T08:00:58Z" } @@ -45,29 +47,43 @@ body: |- [ { - "id": 6273413, - "type": null, - "body": "added 1 commit\n\n
  • 3b1c0654 - fix CI
\n\n[Compare with previous version](/full-stack/tooling/codecoach-game-poc/-/merge_requests/20/diffs?diff_id=3712228&start_sha=3a01be0ebd483c7fa5d1fa166d27956cd5becc9b)", - "attachment": null, - "author": { - "id": 99, - "username": "john_smith", - "name": "John Smith", - "state": "active", - "avatar_url": "http://localhost:3000/uploads/user/avatar/1/index.jpg", - "web_url": "http://localhost:3000/john_smith" - }, - "created_at": "2023-07-25T08:34:51.384Z", - "updated_at": "2023-07-25T08:34:51.385Z", - "system": true, - "noteable_id": 859214, - "noteable_type": "MergeRequest", - "project_id": 37985, - "resolvable": false, - "confidential": false, - "internal": false, - "noteable_iid": 20, - "commands_changes": {} + "id": 987655, + "body": "## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning", + "attachment": null, + "author": { + "id": 99, + "username": "codecoach-bro", + "name": "codecoach-bro", + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/2656/avatar.png", + "web_url": "https://gitlab.agodadev.io/codecoach-bro" + }, + "created_at": "2023-07-25T08:35:38.675Z", + "updated_at": "2023-07-25T08:35:38.675Z", + "system": false, + "noteable_id": 859214, + "noteable_type": "MergeRequest", + "project_id": 37985, + "resolvable": false + }, + { + "id": 987654, + "body": ":rotating_light: React Hook \"useEffect\" is called conditionally. React Hooks must be called in the exact same order in every component render.", + "attachment": null, + "author": { + "id": 99, + "username": "codecoach-bro", + "name": "codecoach-bro", + "state": "active", + "avatar_url": "http://localhost:3000/uploads/user/avatar/2656/avatar.png", + "web_url": "https://gitlab.agodadev.io/codecoach-bro" + }, + "created_at": "2023-07-25T08:35:38.418Z", + "updated_at": "2023-07-25T08:35:38.418Z", + "system": false, + "noteable_id": 859214, + "noteable_type": "MergeRequest", + "resolvable": true } ] From e51abbb202cb107bd06763fcdadf134464ab3385 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Thu, 27 Jul 2023 16:56:34 +0700 Subject: [PATCH 08/12] assert unordered requests --- tests/gitlab.spec.ts | 100 +++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/tests/gitlab.spec.ts b/tests/gitlab.spec.ts index 2e405c5..5706ee8 100644 --- a/tests/gitlab.spec.ts +++ b/tests/gitlab.spec.ts @@ -29,7 +29,6 @@ describe('GitLab', () => { 'app.ts', '--vcs="gitlab"', `--gitlabHost=http://${gitlab.getHost()}:${gitlab.getMappedPort(8080)}`, - // `--gitlabHost=http://localhost:8080`, `--gitlabProjectId=1`, `--gitlabMrIid=1`, `--gitlabToken=privatetoken`, @@ -48,60 +47,69 @@ describe('GitLab', () => { ); const history = await getHttpMockServerHistory(gitlab as StartedTestContainer); + + // for matching unordered array + const sortByRequestPath = ( + a: { request: { path: string } }, + b: { request: { path: string } }, + ) => a.request?.path.localeCompare(b.request.path); + expect(history).toHaveLength(8); - expect(history).toMatchObject([ - { - request: { - path: '/api/v4/projects/1/merge_requests/1/versions', - method: 'GET', + expect(history.sort(sortByRequestPath)).toMatchObject( + [ + { + request: { + path: '/api/v4/projects/1/merge_requests/1/changes', + method: 'GET', + }, }, - }, - { - request: { - path: '/api/v4/projects/1/merge_requests/1/changes', - method: 'GET', + { + request: { + path: '/api/v4/projects/1/merge_requests/1/versions', + method: 'GET', + }, }, - }, - { - request: { - path: '/api/v4/user', - method: 'GET', + { + request: { + path: '/api/v4/user', + method: 'GET', + }, }, - }, - { - request: { - path: '/api/v4/projects/1/merge_requests/1/notes', - method: 'GET', + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes', + method: 'GET', + }, }, - }, - { - request: { - path: '/api/v4/projects/1/merge_requests/1/notes/987654', - method: 'DELETE', + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes/987654', + method: 'DELETE', + }, }, - }, - { - request: { - path: '/api/v4/projects/1/merge_requests/1/notes/987655', - method: 'DELETE', + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes/987655', + method: 'DELETE', + }, }, - }, - { - request: { - path: '/api/v4/projects/1/merge_requests/1/discussions', - method: 'POST', + { + request: { + path: '/api/v4/projects/1/merge_requests/1/discussions', + method: 'POST', + }, }, - }, - { - request: { - path: '/api/v4/projects/1/merge_requests/1/notes', - method: 'POST', - body: { - body: - '## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning', + { + request: { + path: '/api/v4/projects/1/merge_requests/1/notes', + method: 'POST', + body: { + body: + '## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning', + }, }, }, - }, - ]); + ].sort(sortByRequestPath), + ); }); }); From ceff32e2ae8660796d4eafef2c3b2d854a8e22d5 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Mon, 31 Jul 2023 10:35:29 +0700 Subject: [PATCH 09/12] add GitHub --- tests/github.spec.ts | 117 ++++++++++++++++++++++++++++++++ tests/githubmock.yml | 154 +++++++++++++++++++++++++++++++++++++++++++ tests/gitlab.spec.ts | 7 +- tests/utils.ts | 6 ++ 4 files changed, 278 insertions(+), 6 deletions(-) create mode 100644 tests/github.spec.ts create mode 100755 tests/githubmock.yml diff --git a/tests/github.spec.ts b/tests/github.spec.ts new file mode 100644 index 0000000..b2624b7 --- /dev/null +++ b/tests/github.spec.ts @@ -0,0 +1,117 @@ +import type { StartedTestContainer } from 'testcontainers'; +import { ConfigParser } from '../src/Config'; +import { App } from '../src/app'; +import { + configureHttpMockServerWithYaml, + getHttpMockServerHistory, + sortByRequestPath, + startHttpMockServer, + stopHttpMockServer, +} from './utils'; + +jest.setTimeout(15000); + +describe('GitHub', () => { + let github: StartedTestContainer; + + beforeEach(async () => { + github = await startHttpMockServer(); + await configureHttpMockServerWithYaml(github, './tests/githubmock.yml'); + }); + + afterEach(async () => { + stopHttpMockServer(github); + }); + + it('should correctly report to github', async () => { + const host = github.getHost(); + const port = github.getMappedPort(8080); + const configs = ConfigParser([ + 'node', + 'app.ts', + '--vcs="github"', + `--githubRepoUrl=http://${host}:${port}/codecoach-bro/testproject`, + `--githubPr=1`, + `--githubToken=privatetoken`, + `-f=eslint;./tests/eslint-report.json;/Users/codeleague/example`, + `-o=output.log`, + '--removeOldComment', + '--failOnWarnings', + ]); + const app = new App(configs); + await app.start(); + + const history = await getHttpMockServerHistory(github as StartedTestContainer); + + expect(history).toHaveLength(10); + expect(history.sort(sortByRequestPath)).toMatchObject( + [ + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/pulls/1', + method: 'GET', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/pulls/1/files', + method: 'GET', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/pulls/1/comments', + method: 'GET', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/issues/1/comments', + method: 'GET', + }, + }, + { + request: { + path: '/api/v3/user', + method: 'GET', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/issues/comments/1653381079', + method: 'DELETE', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/pulls/comments/1276113835', + method: 'DELETE', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/pulls/1/comments', + method: 'POST', + }, + }, + { + request: { + path: '/api/v3/repos/codecoach-bro/testproject/issues/1/comments', + method: 'POST', + body: { + body: + '## CodeCoach reports 1 issue\n:rotating_light: 1 error\n:warning: 0 warning', + }, + }, + }, + { + request: { + path: + '/api/v3/repos/codecoach-bro/testproject/statuses/92e39f6e1ebb55485234a5531402bb14ad4fbf2c', + method: 'POST', + }, + }, + ].sort(sortByRequestPath), + ); + }); +}); diff --git a/tests/githubmock.yml b/tests/githubmock.yml new file mode 100755 index 0000000..84a8c2d --- /dev/null +++ b/tests/githubmock.yml @@ -0,0 +1,154 @@ +# getLatestCommitSha +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/pulls\/[^\/]+\/?$ + method: GET + headers: + Authorization: token privatetoken + response: + status: 200 + headers: + Content-Type: application/json + body: |- + { + "head": { + "sha": "92e39f6e1ebb55485234a5531402bb14ad4fbf2c" + } + } + +# diff +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/pulls/[^\/]+\/files\/?$ + method: GET + headers: + Authorization: token privatetoken + response: + status: 200 + headers: + Content-Type: application/json + body: |- + [ + { + "filename": "src/App.tsx", + "patch": "@@ -7,11 +7,10 @@ function App() {\n const [count, setCount] = useState(0)\n \n const name = '';\n- if (name !== '') {\n- useEffect(function persistForm() {\n- localStorage.setItem('formData',name);\n- });\n- }\n+ useEffect(function persistForm() {\n+ localStorage.setItem('formData',name);\n+ });\n+\n \n return (\n <>" + } + ] + +# getCurrentUserId +- request: + path: + matcher: ShouldMatch + value: \/user\/?$ + method: GET + headers: + Authorization: token privatetoken + response: + status: 200 + headers: + Content-Type: application/json + body: |- + { + "id": 1765881 + } + +# listAllReviewComments +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/pulls/[^\/]+\/comments\/?$ + method: GET + headers: + Authorization: token privatetoken + response: + status: 200 + headers: + Content-Type: application/json + body: |- + [ + { + "id": 1276113835, + "user": { + "id": 1765881 + } + } + ] + +# createReviewComment +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/pulls/[^\/]+\/comments\/?$ + method: POST + headers: + Authorization: token privatetoken + response: + status: 201 + +# deleteReviewComment +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/pulls\/comments\/[^\/]+ + method: DELETE + headers: + Authorization: token privatetoken + response: + status: 204 + +# listAllComments +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/issues/[^\/]+\/comments\/?$ + method: GET + headers: + Authorization: token privatetoken + response: + status: 200 + headers: + Content-Type: application/json + body: |- + [ + { + "id": 1653381079, + "user": { + "id": 1765881 + } + } + ] + +# createComment +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/issues/[^\/]+\/comments\/?$ + method: POST + headers: + Authorization: token privatetoken + response: + status: 201 + +# deleteComment +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/issues\/comments\/[^\/]+ + method: DELETE + headers: + Authorization: token privatetoken + response: + status: 204 + +# setCommitStatus +- request: + path: + matcher: ShouldMatch + value: \/repos\/[^\/]+\/[^\/]+\/statuses\/[^\/]+ + method: POST + headers: + Authorization: token privatetoken + response: + status: 201 diff --git a/tests/gitlab.spec.ts b/tests/gitlab.spec.ts index 5706ee8..07dc4b8 100644 --- a/tests/gitlab.spec.ts +++ b/tests/gitlab.spec.ts @@ -4,6 +4,7 @@ import { App } from '../src/app'; import { configureHttpMockServerWithYaml, getHttpMockServerHistory, + sortByRequestPath, startHttpMockServer, stopHttpMockServer, } from './utils'; @@ -48,12 +49,6 @@ describe('GitLab', () => { const history = await getHttpMockServerHistory(gitlab as StartedTestContainer); - // for matching unordered array - const sortByRequestPath = ( - a: { request: { path: string } }, - b: { request: { path: string } }, - ) => a.request?.path.localeCompare(b.request.path); - expect(history).toHaveLength(8); expect(history.sort(sortByRequestPath)).toMatchObject( [ diff --git a/tests/utils.ts b/tests/utils.ts index 1382cd1..690f6d8 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -47,3 +47,9 @@ export const getHttpMockServerHistory = async ( export const stopHttpMockServer = async (mock: StartedTestContainer): Promise => { await mock.stop(); }; + +// for matching unordered array +export const sortByRequestPath = ( + a: { request: { path: string } }, + b: { request: { path: string } }, +): number => a.request?.path.localeCompare(b.request.path); From 1017708d60ae15de83e4193bc6bf6ff002a2533c Mon Sep 17 00:00:00 2001 From: jeeyo Date: Mon, 31 Jul 2023 10:41:00 +0700 Subject: [PATCH 10/12] change ID --- tests/github.spec.ts | 4 ++-- tests/githubmock.yml | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/github.spec.ts b/tests/github.spec.ts index b2624b7..8322332 100644 --- a/tests/github.spec.ts +++ b/tests/github.spec.ts @@ -78,13 +78,13 @@ describe('GitHub', () => { }, { request: { - path: '/api/v3/repos/codecoach-bro/testproject/issues/comments/1653381079', + path: '/api/v3/repos/codecoach-bro/testproject/issues/comments/3848497', method: 'DELETE', }, }, { request: { - path: '/api/v3/repos/codecoach-bro/testproject/pulls/comments/1276113835', + path: '/api/v3/repos/codecoach-bro/testproject/pulls/comments/99881235', method: 'DELETE', }, }, diff --git a/tests/githubmock.yml b/tests/githubmock.yml index 84a8c2d..3c580c3 100755 --- a/tests/githubmock.yml +++ b/tests/githubmock.yml @@ -13,7 +13,7 @@ body: |- { "head": { - "sha": "92e39f6e1ebb55485234a5531402bb14ad4fbf2c" + "sha": "403926033d001b5279df37cbbe5287b7c7c267fa" } } @@ -51,7 +51,7 @@ Content-Type: application/json body: |- { - "id": 1765881 + "id": 12123 } # listAllReviewComments @@ -69,9 +69,9 @@ body: |- [ { - "id": 1276113835, + "id": 99881235, "user": { - "id": 1765881 + "id": 12123 } } ] @@ -113,9 +113,9 @@ body: |- [ { - "id": 1653381079, + "id": 3848497, "user": { - "id": 1765881 + "id": 12123 } } ] From 7483a28d7884e15b7d30a9353c0aadf2ad59b11d Mon Sep 17 00:00:00 2001 From: jeeyo Date: Mon, 31 Jul 2023 11:00:59 +0700 Subject: [PATCH 11/12] Fix GitHub assertion --- tests/github.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/github.spec.ts b/tests/github.spec.ts index 8322332..4b98a31 100644 --- a/tests/github.spec.ts +++ b/tests/github.spec.ts @@ -107,7 +107,7 @@ describe('GitHub', () => { { request: { path: - '/api/v3/repos/codecoach-bro/testproject/statuses/92e39f6e1ebb55485234a5531402bb14ad4fbf2c', + '/api/v3/repos/codecoach-bro/testproject/statuses/403926033d001b5279df37cbbe5287b7c7c267fa', method: 'POST', }, }, From 10f86d58e3b8840223baad3251ff1cb8c4f21091 Mon Sep 17 00:00:00 2001 From: jeeyo Date: Wed, 9 Aug 2023 16:30:25 +0700 Subject: [PATCH 12/12] recreate yarn.lock file --- yarn.lock | 50 ++++++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0d87d1f..839730f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -273,11 +273,6 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@balena/dockerignore@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" - integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== - "@babel/types@^7.6.1", "@babel/types@^7.9.6": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" @@ -287,6 +282,11 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -781,13 +781,6 @@ dependencies: defer-to-connect "^1.0.1" -"@szmarczak/http-timer@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" - integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== - dependencies: - defer-to-connect "^2.0.0" - "@types/archiver@^5.3.2": version "5.3.2" resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-5.3.2.tgz#a9f0bcb0f0b991400e7766d35f6e19d163bdadcc" @@ -943,13 +936,6 @@ dependencies: "@types/node" "*" -"@types/responselike@*", "@types/responselike@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" - integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== - dependencies: - "@types/node" "*" - "@types/rimraf@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.0.tgz#b9d03f090ece263671898d57bb7bb007023ac19f" @@ -1251,6 +1237,11 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + asn1@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -1258,11 +1249,6 @@ asn1@^0.2.6: dependencies: safer-buffer "~2.1.0" -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -1817,7 +1803,7 @@ colorspace@1.1.x: color "3.0.x" text-hex "1.0.x" -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -2613,6 +2599,15 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -5262,11 +5257,6 @@ split-ca@^1.0.1: resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== - split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"