diff --git a/.gitignore b/.gitignore index 99e61017..932aad44 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,5 @@ /dist /yarn-error.log .DS_Store -/src/test/private/accessToken.txt /src/test/_tmp_sandbox_ - +/.env diff --git a/.graphqlrc.js b/.graphqlrc.js index 9baa6279..c8be1863 100644 --- a/.graphqlrc.js +++ b/.graphqlrc.js @@ -1,17 +1,6 @@ -const fs = require('fs'); -const path = require('path'); +require('dotenv').config(); -// get credentials from config file -const accessTokenFile = path.resolve( - __dirname, - './src/test/private/accessToken.txt' -); - -const accessToken = fs - .readFileSync(accessTokenFile, { - encoding: 'utf-8', - }) - .trim(); +const accessToken = process.env.ACCESS_TOKEN; module.exports = { schema: 'github-schema.graphql', diff --git a/README.md b/README.md index 96ff8b4a..858b4e39 100644 --- a/README.md +++ b/README.md @@ -201,12 +201,20 @@ console.log(commits); /* [{ - committedDate: '2021-12-20T14:20:16Z', + soureCommit: { + committedDate: '2021-12-20T14:20:16Z', + sha: 'd421ddcf6157150596581c7885afa3690cec6339', + message: '[APM] Add note about synthtrace to APM docs (#121633)', + }, + sourcePullRequest: { + number: 121633, + url: 'https://github.com/elastic/kibana/pull/121633' + mergeCommit: { + sha: 'd421ddcf6157150596581c7885afa3690cec6339', + message: '[APM] Add note about synthtrace to APM docs (#121633)', + } + }, sourceBranch: 'main', - sha: 'd421ddcf6157150596581c7885afa3690cec6339', - originalMessage: '[APM] Add note about synthtrace to APM docs (#121633)', - pullNumber: 121633, - pullUrl: 'https://github.com/elastic/kibana/pull/121633', expectedTargetPullRequests: [ { url: 'https://github.com/elastic/kibana/pull/121643', diff --git a/package.json b/package.json index 8c2cebba..595bbc65 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "branches", "branching" ], - "version": "6.2.1", + "version": "6.3.0-beta-10", "main": "./dist/entrypoint.module.js", "types": "dist/entrypoint.module.d.ts", "bin": { @@ -23,12 +23,12 @@ "license": "MIT", "scripts": { "postinstall": "test -f ./dist/scripts/runPostinstall.js && node ./dist/scripts/runPostinstall.js || echo 'Dist folder missing'", - "postversion": "yarn extractPackageVersion && yarn build", + "version": "echo \"Bumping version\" && yarn extractPackageVersion && git add src/utils/packageVersion.ts && yarn build", "prepare": "husky install", - "prepublishOnly": "yarn build", + "prepublishOnly": "yarn lint", "build": "tsc --project ./tsconfig.prod.json", "extractPackageVersion": "node -p \"'export const PACKAGE_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" | prettier > src/utils/packageVersion.ts", - "lint": "tsc --project ./tsconfig.test.json && eslint './**/*.{ts,js}'", + "lint": "echo \"Running lint\" && tsc --project ./tsconfig.test.json && eslint './**/*.{ts,js}'", "start": "ts-node --transpile-only ./src/entrypoint.cli.ts", "test-all": "yarn lint && jest --config ./jest.config.all.js", "test-mutation": "jest --config ./jest.config.mutation.js", @@ -66,7 +66,9 @@ "axios": "^0.25.0", "dedent": "^0.7.0", "del": "^6.0.0", + "dotenv": "^16.0.0", "find-up": "^5.0.0", + "graphql-tag": "^2.12.6", "inquirer": "^8.2.0", "lodash": "^4.17.21", "make-dir": "^3.1.0", @@ -76,7 +78,8 @@ "terminal-link": "^2.1.1", "utility-types": "^3.10.0", "winston": "^3.5.1", - "yargs": "^17.3.1" + "yargs": "^17.3.1", + "yargs-parser": "^21.0.0" }, "devDependencies": { "@types/core-js": "^2.5.5", @@ -88,25 +91,24 @@ "@types/safe-json-stringify": "^1.1.2", "@types/yargs": "^17.0.8", "@types/yargs-parser": "^20.2.1", - "@typescript-eslint/eslint-plugin": "^5.10.2", - "@typescript-eslint/parser": "^5.10.2", + "@typescript-eslint/eslint-plugin": "^5.11.0", + "@typescript-eslint/parser": "^5.11.0", "eslint": "^8.8.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^26.0.0", + "eslint-plugin-jest": "^26.1.0", "eslint-plugin-prettier": "^4.0.0", "graphql": "^16.3.0", "graphql-config": "^4.1.0", - "graphql-tag": "^2.12.6", "husky": "^7.0.4", - "jest": "^27.4.7", + "jest": "^27.5.1", "jest-snapshot-serializer-ansi": "^1.0.0", "lint-staged": "^12.3.3", "nock": "^13.2.4", "prettier": "^2.5.1", "strip-ansi": "^6.0.1", "ts-jest": "^27.1.3", - "ts-node": "^10.4.0", + "ts-node": "^10.5.0", "typescript": "^4.5.5" } } diff --git a/src/backportRun.ts b/src/backportRun.ts index f45a076e..dd91181e 100755 --- a/src/backportRun.ts +++ b/src/backportRun.ts @@ -47,10 +47,19 @@ export async function backportRun( try { options = await getOptions(processArgs, optionsFromModule); + logger.info('Backporting options', options); + spinner.stop(); + commits = await getCommits(options); + logger.info('Commits', commits); + const targetBranches = await getTargetBranches(options, commits); + logger.info('Target branches', targetBranches); + const results = await runSequentially({ options, commits, targetBranches }); + logger.info('Results', results); + const backportResponse: BackportResponse = { status: 'success', commits, @@ -84,8 +93,7 @@ export async function backportRun( // output consoleLog('\n'); consoleLog(chalk.bold('⚠️ Ouch! An unhandled error occured 😿')); - consoleLog(`Error message: ${e.message}`); - + consoleLog(e.stack ? e.stack : e.message); consoleLog( 'Please open an issue in https://github.com/sqren/backport/issues or contact me directly on https://twitter.com/sorenlouv' ); @@ -97,11 +105,11 @@ export async function backportRun( })}` ) ); - - // write to log - logger.info('Unknown error:', e); } + logger.error('Unhandled exception', e); + process.exitCode = 1; + return backportResponse; } } diff --git a/src/entrypoint.cli.e2e.private.test.ts b/src/entrypoint.cli.e2e.private.test.ts index e01b255b..a7fce453 100644 --- a/src/entrypoint.cli.e2e.private.test.ts +++ b/src/entrypoint.cli.e2e.private.test.ts @@ -4,18 +4,15 @@ import stripAnsi from 'strip-ansi'; import { exec } from './services/child-process-promisified'; import { getDevAccessToken } from './test/private/getDevAccessToken'; import { getSandboxPath, resetSandbox } from './test/sandbox'; +import * as packageVersion from './utils/packageVersion'; const TIMEOUT_IN_SECONDS = 10; jest.setTimeout(15000); -describe('inquirer cli', () => { - let devAccessToken: string; - - beforeAll(async () => { - devAccessToken = await getDevAccessToken(); - }); +const devAccessToken = getDevAccessToken(); +describe('inquirer cli', () => { it('--version', async () => { const res = await runBackportAsync([`--version`]); expect(res).toContain(process.env.npm_package_version); @@ -26,6 +23,13 @@ describe('inquirer cli', () => { expect(res).toContain(process.env.npm_package_version); }); + it('PACKAGE_VERSION should match', async () => { + // @ts-expect-error + expect(packageVersion.UNMOCKED_PACKAGE_VERSION).toBe( + process.env.npm_package_version + ); + }); + it('--help', async () => { const res = await runBackportAsync([`--help`]); expect(res).toMatchInlineSnapshot(` @@ -73,6 +77,7 @@ describe('inquirer cli', () => { --reviewer Add reviewer to the target PR [array] --repoOwner Repository owner [string] --repoName Repository name [string] + --repo Repo owner and name [string] --sha, --commit Commit sha to backport [string] --sourceBranch Specify a non-default branch (normally \\"master\\") to backport from [string] @@ -80,6 +85,8 @@ describe('inquirer cli', () => { -b, --targetBranch, --branch Branch(es) to backport to [array] --targetBranchChoice List branches to backport to [array] -l, --targetPRLabel, --label Add labels to the target (backport) PR [array] + --username User repo that branch will be pushed to. Defaults to the + authenticated user [string] --verbose Show additional debug information [boolean] --verify Opposite of no-verify [boolean] --help Show help [boolean] @@ -126,9 +133,10 @@ describe('inquirer cli', () => { 4. Add family emoji (#2) 7.x 5. Add \`backport\` dep 6. Merge pull request #1 from backport-org/add-heart-emoji - 7. Update .backportrc.json - 8. Bump to 8.0.0 - 9. Add package.json" + 7. Add ❤️ emoji + 8. Update .backportrc.json + 9. Bump to 8.0.0 + 10.Add package.json" `); }); @@ -197,7 +205,7 @@ describe('inquirer cli', () => { `); }); - it(`should limit commits by since and until`, async () => { + it(`should filter commits by "since" and "until"`, async () => { jest.setTimeout(TIMEOUT_IN_SECONDS * 1000 * 1.1); const output = await runBackportAsync( [ @@ -210,24 +218,19 @@ describe('inquirer cli', () => { '--accessToken', devAccessToken, '--since', - '2020-08-15T00:00:00.000Z', + '2020-08-15T10:00:00.000Z', '--until', - '2020-08-15T14:00:00.000Z', + '2020-08-15T10:30:00.000Z', ], { waitForString: 'Select commit' } ); expect(output).toMatchInlineSnapshot(` "? Select commit (Use arrow keys) - ❯ 1. Add 🍏 emoji (#5) 7.x, 7.8 - 2. Add family emoji (#2) 7.x - 3. Add \`backport\` dep - 4. Merge pull request #1 from backport-org/add-heart-emoji - 5. Update .backportrc.json - 6. Bump to 8.0.0 - 7. Add package.json - 8. Update .backportrc.json - 9. Create .backportrc.json" + ❯ 1. Bump to 8.0.0 + 2. Add package.json + 3. Update .backportrc.json + 4. Create .backportrc.json" `); }); @@ -262,6 +265,36 @@ describe('inquirer cli', () => { 6. Bump to 8.0.0" `); }); + + describe('repo: different-merge-strategies', () => { + it('list all commits regardless how they were merged', async () => { + jest.setTimeout(TIMEOUT_IN_SECONDS * 1000 * 1.1); + const output = await runBackportAsync( + [ + '--branch', + 'foo', + '--repo-owner', + 'backport-org', + '--repo-name', + 'different-merge-strategies', + '--accessToken', + devAccessToken, + ], + { waitForString: 'Select commit' } + ); + + expect(output).toMatchInlineSnapshot(` + "? Select commit (Use arrow keys) + ❯ 1. Using squash to merge commits (#3) 7.x + 2. Rebase strategy: Second commit 7.x + 3. Rebase strategy: First commit + 4. Merge pull request #1 from backport-org/merge-strategy + 5. Merge strategy: Second commit + 6. Merge strategy: First commit + 7. Initial commit" + `); + }); + }); }); function runBackportAsync( diff --git a/src/entrypoint.cli.private.test.ts b/src/entrypoint.cli.private.test.ts index e3aca7ad..a0a628a1 100644 --- a/src/entrypoint.cli.private.test.ts +++ b/src/entrypoint.cli.private.test.ts @@ -1,9 +1,9 @@ -import { getCommits } from './entrypoint.module'; +import { Commit, getCommits } from './entrypoint.module'; import { getDevAccessToken } from './test/private/getDevAccessToken'; describe('entrypoint.module', () => { it('getCommits', async () => { - const accessToken = await getDevAccessToken(); + const accessToken = getDevAccessToken(); const commits = await getCommits({ accessToken: accessToken, repoName: 'backport-e2e', @@ -11,9 +11,22 @@ describe('entrypoint.module', () => { pullNumber: 2, }); - expect(commits).toEqual([ + const expectedCommits: Commit[] = [ { - committedDate: '2020-08-15T10:44:04Z', + sourceCommit: { + committedDate: '2020-08-15T10:44:04Z', + message: 'Add family emoji (#2)', + sha: '59d6ff1ca90a4ce210c0a4f0e159214875c19d60', + }, + sourcePullRequest: { + number: 2, + url: 'https://github.com/backport-org/backport-e2e/pull/2', + mergeCommit: { + message: 'Add family emoji (#2)', + sha: '59d6ff1ca90a4ce210c0a4f0e159214875c19d60', + }, + }, + sourceBranch: 'master', expectedTargetPullRequests: [ { branch: '7.x', @@ -26,12 +39,9 @@ describe('entrypoint.module', () => { }, }, ], - originalMessage: 'Add family emoji (#2)', - pullNumber: 2, - pullUrl: 'https://github.com/backport-org/backport-e2e/pull/2', - sha: '59d6ff1ca90a4ce210c0a4f0e159214875c19d60', - sourceBranch: 'master', }, - ]); + ]; + + expect(commits).toEqual(expectedCommits); }); }); diff --git a/src/options/ConfigOptions.ts b/src/options/ConfigOptions.ts index e6dd236d..70b492e9 100644 --- a/src/options/ConfigOptions.ts +++ b/src/options/ConfigOptions.ts @@ -1,4 +1,4 @@ -import { Logger } from '../services/logger'; +import winston from 'winston'; export interface TargetBranchChoice { name: string; @@ -14,7 +14,7 @@ type AutoFixConflictsHandler = ({ }: { files: string[]; directory: string; - logger: Logger; + logger: winston.Logger; targetBranch: string; }) => boolean | Promise; @@ -60,6 +60,7 @@ type Options = Partial<{ targetBranchChoices: TargetBranchChoiceOrString[]; targetBranches: string[]; targetPRLabels: string[]; + username: string; verbose: boolean; }>; diff --git a/src/options/cliArgs.test.ts b/src/options/cliArgs.test.ts index 67195d37..0ef5f991 100644 --- a/src/options/cliArgs.test.ts +++ b/src/options/cliArgs.test.ts @@ -167,6 +167,22 @@ describe('getOptionsFromCliArgs', () => { }); }); + describe('repo', () => { + it('splits into repoOwner and repoName', () => { + const argv = ['--repo', 'elastic/kibana']; + const res = getOptionsFromCliArgs(argv); + expect(res.repoOwner).toEqual('elastic'); + expect(res.repoName).toEqual('kibana'); + }); + + it('throw if both --repo and --repo-name is given', () => { + const argv = ['--repo', 'elastic/kibana', '--repo-name', 'foo']; + expect(() => + getOptionsFromCliArgs(argv, { exitOnError: false }) + ).toThrowError('Arguments repo and repoName are mutually exclusive'); + }); + }); + describe('since/until', () => { it('should always be UTC time (configured globally in jest.config.js)', () => { expect(new Date().getTimezoneOffset()).toBe(0); diff --git a/src/options/cliArgs.ts b/src/options/cliArgs.ts index 4c46518d..1dd71cf0 100644 --- a/src/options/cliArgs.ts +++ b/src/options/cliArgs.ts @@ -55,6 +55,13 @@ export function getOptionsFromCliArgs( choices: ['merge', 'rebase', 'squash'], }) + .option('author', { + description: 'Show commits by a specific user', + alias: 'author', + type: 'string', + conflicts: 'all', + }) + .option('ci', { description: 'Disable interactive prompts', type: 'boolean', @@ -252,11 +259,19 @@ export function getOptionsFromCliArgs( .option('repoOwner', { description: 'Repository owner', type: 'string', + conflicts: ['repo'], }) .option('repoName', { description: 'Repository name', type: 'string', + conflicts: ['repo'], + }) + + .option('repo', { + description: 'Repo owner and name', + type: 'string', + conflicts: ['repoName', 'repoOwner'], }) .option('sha', { @@ -298,11 +313,9 @@ export function getOptionsFromCliArgs( string: true, }) - .option('author', { - description: 'Show commits by a specific user', - alias: 'author', + .option('username', { + description: 'Defaults to the authenticated user ', type: 'string', - conflicts: 'all', }) .option('verbose', { @@ -347,6 +360,9 @@ export function getOptionsFromCliArgs( multipleCommits, all, + // repoName and repoOwner + repo, + // filters author, since, @@ -371,9 +387,18 @@ export function getOptionsFromCliArgs( ...restOptions } = yargsInstance.parseSync(); + const [repoOwner, repoName] = repo?.split('/') ?? [ + restOptions.repoOwner, + restOptions.repoName, + ]; + return excludeUndefined({ ...restOptions, + // repoName and repoOwner + repoOwner, + repoName, + // filters author: all ? null : author, dateSince: since ? new Date(since).toISOString() : undefined, diff --git a/src/options/options.test.ts b/src/options/options.test.ts index 7de69321..4a4c4779 100644 --- a/src/options/options.test.ts +++ b/src/options/options.test.ts @@ -47,11 +47,11 @@ describe('getOptions', () => { await expect(() => getOptions([], { ci: true })).rejects .toThrowErrorMatchingInlineSnapshot(` - "Please update your config file: \\"/myHomeDir/.backport/config.json\\". - It must contain a valid \\"accessToken\\". + "Please update your config file: \\"/myHomeDir/.backport/config.json\\". + It must contain a valid \\"accessToken\\". - Read more: https://github.com/sqren/backport/blob/main/docs/configuration.md#global-config-backportconfigjson" - `); + Read more: https://github.com/sqren/backport/blob/main/docs/configuration.md#global-config-backportconfigjson" + `); }); it('when `targetBranches`, `targetBranchChoices` and `branchLabelMapping` are all empty', async () => { @@ -69,6 +69,34 @@ describe('getOptions', () => { `); }); + describe('whe option is an empty string', () => { + it('throws for "username"', async () => { + await expect(() => + getOptions([], { username: '', author: 'sqren' }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"username\\" cannot be empty!"` + ); + }); + + it('throws for "author"', async () => { + await expect(() => + getOptions([], { author: '' }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"\\"author\\" cannot be empty!"` + ); + }); + + it('throws for "accessToken"', async () => { + await expect(() => getOptions([], { accessToken: '' })).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Please update your config file: \\"/myHomeDir/.backport/config.json\\". + It must contain a valid \\"accessToken\\". + + Read more: https://github.com/sqren/backport/blob/main/docs/configuration.md#global-config-backportconfigjson" + `); + }); + }); + describe('when repoName and repoOwner are missing', () => { beforeEach(() => { mockProjectConfig({ repoName: undefined, repoOwner: undefined }); @@ -79,10 +107,10 @@ describe('getOptions', () => { await expect(() => getOptions([], {})).rejects .toThrowErrorMatchingInlineSnapshot(` - "Please specify a repo name: \\"--repo-name kibana\\". + "Please specify a repo name: \\"--repo-name kibana\\". - Read more: https://github.com/sqren/backport/blob/main/docs/configuration.md#project-config-backportrcjson" - `); + Read more: https://github.com/sqren/backport/blob/main/docs/configuration.md#project-config-backportrcjson" + `); }); it('should get repoName from the remote', async () => { @@ -105,7 +133,7 @@ describe('getOptions', () => { }); it('should ensure that "backport" branch does not exist', async () => { - mockGithubConfigOptions({ refName: 'backport' }); + mockGithubConfigOptions({ hasBackportBranch: true }); await expect(getOptions([], {})).rejects.toThrowError( 'You must delete the branch "backport" to continue. See https://github.com/sqren/backport/issues/155 for details' ); @@ -344,12 +372,12 @@ function mockProjectConfig(projectConfig: ConfigFileOptions) { function mockGithubConfigOptions({ viewerLogin = 'DO_NOT_USE-sqren', defaultBranchRef = 'DO_NOT_USE-default-branch-name', - refName, + hasBackportBranch, historicalMappings = [], }: { viewerLogin?: string; defaultBranchRef?: string; - refName?: string; + hasBackportBranch?: boolean; historicalMappings?: Array<{ committedDate: string; branchLabelMapping: Record; @@ -364,9 +392,7 @@ function mockGithubConfigOptions({ login: viewerLogin, }, repository: { - isFork: false, - parent: null, - ref: refName ? { name: refName } : null, + illegalBackportBranch: hasBackportBranch ? { id: 'foo' } : null, defaultBranchRef: { name: defaultBranchRef, target: { diff --git a/src/options/options.ts b/src/options/options.ts index 00bdd7df..13f62ed6 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -1,7 +1,10 @@ import { isEmpty } from 'lodash'; import { HandledError } from '../services/HandledError'; import { getGlobalConfigPath } from '../services/env'; -import { getOptionsFromGithub } from '../services/github/v4/getOptionsFromGithub/getOptionsFromGithub'; +import { + getOptionsFromGithub, + OptionsFromGithub, +} from '../services/github/v4/getOptionsFromGithub/getOptionsFromGithub'; import { getRepoOwnerAndNameFromGitRemotes } from '../services/github/v4/getRepoOwnerAndNameFromGitRemotes'; import { updateLogger } from './../services/logger'; import { ConfigFileOptions, TargetBranchChoiceOrString } from './ConfigOptions'; @@ -62,7 +65,7 @@ export async function getOptions( }); // combined options from cli and config files - const combined = getCombinedOptions({ + const combined = getMergedOptionsFromConfigAndCli({ optionsFromConfigFiles, optionsFromCliArgs, }); @@ -83,7 +86,7 @@ export async function getOptions( repoOwner, }); - const res = { + const options = { // default author author: optionsFromGithub.authenticatedUsername, @@ -105,12 +108,12 @@ export async function getOptions( repoOwner, }; - requireTargetBranch(res); + throwForRequiredOptions(options); - return res; + return options; } -async function getRequiredOptions(combined: CombinedOptions) { +async function getRequiredOptions(combined: OptionsFromConfigAndCli) { const { accessToken, repoName, repoOwner } = combined; if (accessToken && repoName && repoOwner) { @@ -151,8 +154,58 @@ async function getRequiredOptions(combined: CombinedOptions) { }; } -type CombinedOptions = ReturnType; -function getCombinedOptions({ +function throwForRequiredOptions( + options: OptionsFromConfigAndCli | OptionsFromGithub +) { + // ensure `targetBranches` or `targetBranchChoices` are given + if ( + isEmpty(options.targetBranches) && + isEmpty(options.targetBranchChoices) && + // this is primarily necessary on CI where `targetBranches` and `targetBranchChoices` and not given + isEmpty(options.branchLabelMapping) + ) { + throw new HandledError( + `Please specify a target branch: "--branch 6.1".\n\nRead more: ${PROJECT_CONFIG_DOCS_LINK}` + ); + } + + const optionKeys: Array = [ + 'accessToken', + 'author', + 'autoMergeMethod', + 'backportBinary', + 'configFile', + 'dir', + 'editor', + 'gitHostname', + 'githubApiBaseUrlV3', + 'githubApiBaseUrlV4', + 'logFilePath', + 'prDescription', + 'prFilter', + 'prTitle', + 'repoName', + 'repoOwner', + 'sha', + 'sourceBranch', + 'username', + ]; + + // Disallow empty strings + // this is primarily an issue in Github actions where inputs default to empty strings instead of undefined + // in those cases failing early provides a better UX + optionKeys.forEach((optionName) => { + const option = options[optionName] as string; + if (option === '') { + throw new HandledError(`"${optionName}" cannot be empty!`); + } + }); +} + +type OptionsFromConfigAndCli = ReturnType< + typeof getMergedOptionsFromConfigAndCli +>; +function getMergedOptionsFromConfigAndCli({ optionsFromConfigFiles, optionsFromCliArgs, }: { @@ -165,21 +218,3 @@ function getCombinedOptions({ ...optionsFromCliArgs, }; } - -function requireTargetBranch(config: { - targetBranches: CombinedOptions['targetBranches']; - targetBranchChoices: CombinedOptions['targetBranchChoices']; - branchLabelMapping?: CombinedOptions['branchLabelMapping']; -}) { - // ensure `targetBranches` or `targetBranchChoices` are given - if ( - isEmpty(config.targetBranches) && - isEmpty(config.targetBranchChoices) && - // this is primarily necessary on CI where `targetBranches` and `targetBranchChoices` and not given - isEmpty(config.branchLabelMapping) - ) { - throw new HandledError( - `Please specify a target branch: "--branch 6.1".\n\nRead more: ${PROJECT_CONFIG_DOCS_LINK}` - ); - } -} diff --git a/src/runSequentially.test.ts b/src/runSequentially.test.ts index 7a660dba..ae1895c6 100644 --- a/src/runSequentially.test.ts +++ b/src/runSequentially.test.ts @@ -107,12 +107,21 @@ describe('runSequentially', () => { const commits: Commit[] = [ { - sha: 'abcd', - committedDate: '1', - expectedTargetPullRequests: [], - originalMessage: 'My commit message', + sourceCommit: { + committedDate: '1', + message: 'My commit message', + sha: 'abcd', + }, + sourcePullRequest: { + url: 'foo', + number: 55, + mergeCommit: { + message: 'My commit message', + sha: 'abcd', + }, + }, sourceBranch: 'master', - pullNumber: 55, + expectedTargetPullRequests: [], }, ]; const targetBranches: string[] = ['7.x']; @@ -140,10 +149,10 @@ describe('runSequentially', () => { "base": "7.x", "body": "# Backport - This is an automatic backport to \`7.x\` of: - - #55 + This will backport the following commits from \`master\` to \`7.x\`: + - [My commit message](foo) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", diff --git a/src/runSequentially.ts b/src/runSequentially.ts index 19701412..6e7b7980 100755 --- a/src/runSequentially.ts +++ b/src/runSequentially.ts @@ -58,6 +58,7 @@ export async function runSequentially({ error: e, }); consoleLog(e.message); + logger.error('Could not backport commit', e); } }); diff --git a/src/services/git.test.ts b/src/services/git.test.ts index 853ae00e..2febcac3 100644 --- a/src/services/git.test.ts +++ b/src/services/git.test.ts @@ -514,9 +514,15 @@ describe('commitChanges', () => { repoName: 'kibana', } as ValidConfigOptions; - const commit = { - originalMessage: 'The original commit message', - } as Commit; + const commit: Commit = { + sourceCommit: { + message: 'The original commit message', + committedDate: '2020', + sha: 'abc', + }, + sourceBranch: 'master', + expectedTargetPullRequests: [], + }; it('should return when changes committed successfully', async () => { jest diff --git a/src/services/git.ts b/src/services/git.ts index a2cff908..6da945aa 100644 --- a/src/services/git.ts +++ b/src/services/git.ts @@ -197,7 +197,7 @@ export async function fetchBranch(options: ValidConfigOptions, branch: string) { export async function cherrypick( options: ValidConfigOptions, - sha: Commit['sha'], + sha: string, mergedTargetPullRequest?: ExpectedTargetPullRequest ): Promise<{ conflictingFiles: { @@ -286,9 +286,12 @@ export async function commitChanges( // manually set the commit message if the inferred commit message is empty // this can happen if the user runs `git reset HEAD` and thereby aborts the cherrypick process if (e.stderr?.includes('Aborting commit due to empty commit message')) { - await exec(`git commit -m "${commit.originalMessage}" ${noVerifyFlag}`, { - cwd: getRepoPath(options), - }); + await exec( + `git commit -m "${commit.sourceCommit.message}" ${noVerifyFlag}`, + { + cwd: getRepoPath(options), + } + ); return; } diff --git a/src/services/github/commitFormatters.ts b/src/services/github/commitFormatters.ts index b2e357f7..5e74fa3b 100644 --- a/src/services/github/commitFormatters.ts +++ b/src/services/github/commitFormatters.ts @@ -11,10 +11,3 @@ export function stripPullNumber(message: string) { const messageWithoutPullNumber = firstMessageLine.replace(/( \(#\d+\))$/, ''); return messageWithoutPullNumber; } - -export function extractPullNumber(firstMessageLine: string) { - const matches = firstMessageLine.match(/\(#(\d+)\)/); - if (matches) { - return parseInt(matches[1], 10); - } -} diff --git a/src/services/github/v3/createPullRequest.test.ts b/src/services/github/v3/createPullRequest.test.ts index 9e7d74cb..aeb4970e 100644 --- a/src/services/github/v3/createPullRequest.test.ts +++ b/src/services/github/v3/createPullRequest.test.ts @@ -1,5 +1,4 @@ import { ValidConfigOptions } from '../../../options/options'; -import { Commit } from '../../sourceCommit/parseSourceCommit'; import { getPullRequestBody, getTitle } from './createPullRequest'; describe('getPullRequestBody', () => { @@ -9,10 +8,24 @@ describe('getPullRequestBody', () => { options: {} as ValidConfigOptions, commits: [ { - pullNumber: 55, - sha: 'abcdefghi', - originalMessage: 'My commit message', - } as Commit, + sourcePullRequest: { + number: 55, + url: 'https://github.com/backport-org/different-merge-strategies/pull/55', + mergeCommit: { + sha: 'abcdefghi', + message: 'My commit message (#55)', + }, + }, + + sourceCommit: { + committedDate: '2020', + sha: 'abcdefghi', + message: 'My commit message (#55)', + }, + + expectedTargetPullRequests: [], + sourceBranch: 'master', + }, ], targetBranch: '7.x', @@ -20,10 +33,10 @@ describe('getPullRequestBody', () => { ).toMatchInlineSnapshot(` "# Backport - This is an automatic backport to \`7.x\` of: - - #55 + This will backport the following commits from \`master\` to \`7.x\`: + - [My commit message (#55)](https://github.com/backport-org/different-merge-strategies/pull/55) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)" @@ -36,9 +49,15 @@ describe('getPullRequestBody', () => { options: {} as ValidConfigOptions, commits: [ { - sha: 'abcdefghijklmw', - originalMessage: 'My commit message', - } as Commit, + sourceCommit: { + committedDate: '', + sha: 'abcdefghijklmw', + message: 'My commit message', + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, ], targetBranch: '7.x', @@ -46,10 +65,10 @@ describe('getPullRequestBody', () => { ).toMatchInlineSnapshot(` "# Backport - This is an automatic backport to \`7.x\` of: + This will backport the following commits from \`main\` to \`7.x\`: - My commit message (abcdefgh) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)" @@ -62,14 +81,35 @@ describe('getPullRequestBody', () => { options: {} as ValidConfigOptions, commits: [ { - pullNumber: 55, - sha: 'abcdefghijklm', - originalMessage: 'My commit message', - } as Commit, + sourcePullRequest: { + number: 55, + url: 'https://github.com/backport-org/different-merge-strategies/pull/55', + mergeCommit: { + sha: 'abcdefghijklm', + message: 'My commit message (#55)', + }, + }, + + sourceCommit: { + committedDate: '', + sha: 'abcdefghijklm', + message: 'My commit message (#55)', + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, + { - sha: 'qwertyuiop', - originalMessage: 'Another commit message', - } as Commit, + sourceCommit: { + committedDate: '', + sha: 'qwertyuiop', + message: 'Another commit message', + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, ], targetBranch: '7.x', @@ -77,11 +117,75 @@ describe('getPullRequestBody', () => { ).toMatchInlineSnapshot(` "# Backport - This is an automatic backport to \`7.x\` of: - - #55 + This will backport the following commits from \`main\` to \`7.x\`: + - [My commit message (#55)](https://github.com/backport-org/different-merge-strategies/pull/55) - Another commit message (qwertyui) - + + + ### Questions ? + Please refer to the [Backport tool documentation](https://github.com/sqren/backport)" + `); + }); + + it('when a PR is merged (instead of squashed) and the individual commits are selected', () => { + expect( + getPullRequestBody({ + options: {} as ValidConfigOptions, + commits: [ + { + sourceCommit: { + committedDate: '2022-02-07T23:53:14Z', + message: 'Merge strategy: Second commit', + sha: 'e8df5eaa4db7b94474b48e2320b02d33a830d9fb', + }, + + sourcePullRequest: { + number: 1, + url: 'https://github.com/backport-org/different-merge-strategies/pull/1', + mergeCommit: { + message: + 'Merge pull request #1 from backport-org/merge-strategy\n\nMerge commits to `main`', + sha: '0db7f1ac1233461563d8708511d1c14adbab46da', + }, + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, + + { + sourceCommit: { + committedDate: '2022-02-07T23:51:59Z', + message: 'Merge strategy: First commit', + sha: '5411b1c1144093e422220008f23f2c2b909ed113', + }, + + sourcePullRequest: { + number: 1, + url: 'https://github.com/backport-org/different-merge-strategies/pull/1', + mergeCommit: { + message: + 'Merge pull request #1 from backport-org/merge-strategy\n\nMerge commits to `main`', + sha: '0db7f1ac1233461563d8708511d1c14adbab46da', + }, + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, + ], + + targetBranch: '7.x', + }) + ).toMatchInlineSnapshot(` + "# Backport + + This will backport the following commits from \`main\` to \`7.x\`: + - [Merge strategy: Second commit](https://github.com/backport-org/different-merge-strategies/pull/1) + - [Merge strategy: First commit](https://github.com/backport-org/different-merge-strategies/pull/1) + + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)" @@ -97,21 +201,38 @@ describe('getPullRequestBody', () => { } as ValidConfigOptions, commits: [ { - pullNumber: 55, - sha: 'abcdefghijklm', - originalMessage: 'My commit message', - } as Commit, + sourcePullRequest: { + number: 55, + url: 'https://github.com/backport-org/different-merge-strategies/pull/55', + mergeCommit: { + sha: 'abcdefghijklm', + message: 'My commit message (#55)', + }, + }, + sourceCommit: { + committedDate: '', + sha: 'abcdefghijklm', + message: 'My commit message (#55)', + }, + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, { - sha: 'qwertyuiop', - originalMessage: 'Another commit message', - } as Commit, + sourceCommit: { + committedDate: '', + sha: 'qwertyuiop', + message: 'Another commit message', + }, + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, ], targetBranch: '7.x', }) ).toMatchInlineSnapshot(` "Backporting the following to 7.x: - - #55 + - [My commit message (#55)](https://github.com/backport-org/different-merge-strategies/pull/55) - Another commit message (qwertyui)" `); }); @@ -124,14 +245,35 @@ describe('getPullRequestBody', () => { } as ValidConfigOptions, commits: [ { - pullNumber: 55, - sha: 'abcdefghijklm', - originalMessage: 'My commit message', - } as Commit, + sourcePullRequest: { + number: 55, + url: 'https://github.com/backport-org/different-merge-strategies/pull/55', + mergeCommit: { + sha: 'abcdefghijklm', + message: 'My commit message (#55)', + }, + }, + + sourceCommit: { + committedDate: '', + sha: 'abcdefghijklm', + message: 'My commit message (#55)', + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, + { - sha: 'qwertyuiop', - originalMessage: 'Another commit message', - } as Commit, + sourceCommit: { + committedDate: '', + sha: 'qwertyuiop', + message: 'Another commit message', + }, + + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, ], targetBranch: '7.x', @@ -139,11 +281,11 @@ describe('getPullRequestBody', () => { ).toMatchInlineSnapshot(` "# Backport - This is an automatic backport to \`7.x\` of: - - #55 + This will backport the following commits from \`main\` to \`7.x\`: + - [My commit message (#55)](https://github.com/backport-org/different-merge-strategies/pull/55) - Another commit message (qwertyui) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) @@ -160,19 +302,43 @@ describe('getTitle', () => { options: {} as ValidConfigOptions, commits: [ { - pullNumber: 55, - sha: 'abcdefghi', - originalMessage: 'My commit message', - } as Commit, + sourceBranch: 'main', + sourcePullRequest: { + number: 55, + url: 'https://github.com/backport-org/different-merge-strategies/pull/55', + mergeCommit: { + sha: 'abcdefghi', + message: 'My commit message (#55)', + }, + }, + sourceCommit: { + committedDate: '2020', + sha: 'abcdefghi', + message: 'My commit message (#55)', + }, + expectedTargetPullRequests: [], + }, { - pullNumber: 56, - sha: 'jklmnopqr', - originalMessage: 'Another commit message', - } as Commit, + sourcePullRequest: { + number: 56, + url: 'https://github.com/backport-org/different-merge-strategies/pull/56', + mergeCommit: { + sha: 'jklmnopqr', + message: 'Another commit message (#56)', + }, + }, + sourceCommit: { + committedDate: '2020', + sha: 'jklmnopqr', + message: 'Another commit message (#56)', + }, + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, ], targetBranch: '7.x', }) - ).toEqual('[7.x] My commit message | Another commit message'); + ).toEqual('[7.x] My commit message (#55) | Another commit message (#56)'); }); it('replaces template variables in PR title', () => { @@ -183,14 +349,25 @@ describe('getTitle', () => { } as ValidConfigOptions, commits: [ { - pullNumber: 55, - sha: 'abcdefghi', - originalMessage: 'My commit message', - } as Commit, + sourcePullRequest: { + number: 55, + url: 'https://github.com/backport-org/different-merge-strategies/pull/55', + mergeCommit: { + sha: 'abcdefghi', + message: 'My commit message (#55)', + }, + }, + sourceCommit: { + committedDate: '', + sha: 'abcdefghi', + message: 'My commit message (#55)', + }, + sourceBranch: 'main', + expectedTargetPullRequests: [], + }, ], - targetBranch: '7.x', }) - ).toEqual('Branch: "7.x". Messages: My commit message'); + ).toEqual('Branch: "7.x". Messages: My commit message (#55)'); }); }); diff --git a/src/services/github/v3/createPullRequest.ts b/src/services/github/v3/createPullRequest.ts index da0662fb..670ab2c2 100644 --- a/src/services/github/v3/createPullRequest.ts +++ b/src/services/github/v3/createPullRequest.ts @@ -92,9 +92,13 @@ export function getPullRequestBody({ }) { const commitMessages = commits .map((c) => { - const message = c.pullNumber - ? `#${c.pullNumber}` - : `${getFirstLine(c.originalMessage)} (${getShortSha(c.sha)})`; + const message = c.sourcePullRequest + ? `[${getFirstLine(c.sourceCommit.message)}](${ + c.sourcePullRequest.url + })` + : `${getFirstLine(c.sourceCommit.message)} (${getShortSha( + c.sourceCommit.sha + )})`; return ` - ${message}`; }) @@ -102,7 +106,7 @@ export function getPullRequestBody({ const defaultPrDescription = `# Backport -This is an automatic backport to \`${targetBranch}\` of: +This will backport the following commits from \`${commits[0].sourceBranch}\` to \`${targetBranch}\`: ${commitMessages} @@ -126,7 +130,7 @@ export function getTitle({ targetBranch: string; }) { const commitMessages = commits - .map((commit) => getFirstLine(commit.originalMessage)) + .map((c) => getFirstLine(c.sourceCommit.message)) .join(' | '); const defaultPrTitle = '[{targetBranch}] {commitMessages}'; diff --git a/src/services/github/v3/createStatusComment.test.ts b/src/services/github/v3/createStatusComment.test.ts index c35e58f4..e43023f7 100644 --- a/src/services/github/v3/createStatusComment.test.ts +++ b/src/services/github/v3/createStatusComment.test.ts @@ -28,7 +28,7 @@ describe('createStatusComment', () => { ci: true, } as ValidConfigOptions, backportResponse: { - commits: [{ pullNumber: 100 }], + commits: [{ sourcePullRequest: { number: 100 } }], status: 'failure', error: new Error( `Error message containing very secret access token: ${accessToken}.` @@ -74,7 +74,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); @@ -127,7 +127,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); @@ -145,7 +145,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); }); @@ -196,7 +196,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); @@ -254,7 +254,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); @@ -290,21 +290,43 @@ describe('getCommentBody', () => { error: new HandledError({ code: 'merge-conflict-exception', commitsWithoutBackports: [ + //@ts-expect-error { - //@ts-expect-error commit: { - pullNumber: 5, - pullUrl: 'url-to-pr-5', - originalMessage: 'New Zealand commit message', + sourceBranch: 'master', + sourcePullRequest: { + number: 5, + url: 'url-to-pr-5', + mergeCommit: { + sha: '', + message: 'New Zealand commit message', + }, + }, + sourceCommit: { + committedDate: '', + sha: '', + message: 'New Zealand commit message', + }, + expectedTargetPullRequests: [], }, }, { //@ts-expect-error commit: { - pullNumber: 44, - pullUrl: 'url-to-pr-44', - originalMessage: 'Australia commit', + sourcePullRequest: { + number: 44, + url: 'url-to-pr-44', + mergeCommit: { + sha: '', + message: 'Australia commit', + }, + }, + sourceCommit: { + committedDate: '', + sha: '', + message: 'Australia commit', + }, }, }, ], @@ -343,7 +365,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); @@ -373,8 +395,8 @@ describe('getCommentBody', () => { const params = getParams({ ci: true }); expect(getCommentBody(params)).toMatchInlineSnapshot(` "## ⚪ Backport skipped - The pull request was not backported as there were no branches to backport to. If this is a mistake, please apply the desired version labels or run the backport tool manually. - + The pull request was not backported as there were no branches to backport to. If this is a mistake, please apply the desired version labels or run the backport tool manually. + ### Manual backport To create the backport manually run: \`\`\` @@ -383,7 +405,7 @@ describe('getCommentBody', () => { ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) - " + " `); }); diff --git a/src/services/github/v3/createStatusComment.ts b/src/services/github/v3/createStatusComment.ts index 52e3daf7..02479104 100644 --- a/src/services/github/v3/createStatusComment.ts +++ b/src/services/github/v3/createStatusComment.ts @@ -35,13 +35,13 @@ export async function createStatusComment({ await Promise.all( backportResponse.commits.map((commit) => { - if (!commit.pullNumber) { + if (!commit.sourcePullRequest) { return; } const body = getCommentBody({ options, - pullNumber: commit.pullNumber, + pullNumber: commit.sourcePullRequest.number, backportResponse, }); @@ -54,7 +54,7 @@ export async function createStatusComment({ baseUrl: options.githubApiBaseUrlV3, owner: repoOwner, repo: repoName, - issue_number: commit.pullNumber, + issue_number: commit.sourcePullRequest.number, body: redact(options.accessToken, body), }); }) @@ -103,8 +103,8 @@ export function getCommentBody({ backportResponse.error.errorContext?.code === 'no-branches-exception' ) { return `## ⚪ Backport skipped - The pull request was not backported as there were no branches to backport to. If this is a mistake, please apply the desired version labels or run the backport tool manually. - ${manualBackportCommand}${questionsAndLinkToBackport}${packageVersionSection}`; +The pull request was not backported as there were no branches to backport to. If this is a mistake, please apply the desired version labels or run the backport tool manually. +${manualBackportCommand}${questionsAndLinkToBackport}${packageVersionSection}`; } return `## 💔 Backport failed @@ -130,8 +130,8 @@ ${manualBackportCommand}${questionsAndLinkToBackport}${packageVersionSection}`; if (result.error.errorContext?.code === 'merge-conflict-exception') { const unmergedBackports = result.error.errorContext.commitsWithoutBackports.map((c) => { - return ` - [${getFirstLine(c.commit.originalMessage)}](${ - c.commit.pullUrl + return ` - [${getFirstLine(c.commit.sourceCommit.message)}](${ + c.commit.sourcePullRequest?.url })`; }); diff --git a/src/services/github/v4/apiRequestV4.ts b/src/services/github/v4/apiRequestV4.ts index 271a5200..7fd4904f 100644 --- a/src/services/github/v4/apiRequestV4.ts +++ b/src/services/github/v4/apiRequestV4.ts @@ -1,4 +1,5 @@ import axios, { AxiosResponse } from 'axios'; +import gql from 'graphql-tag'; import { HandledError } from '../../HandledError'; import { logger } from '../../logger'; @@ -91,10 +92,14 @@ function addDebugLogs({ axiosResponse: AxiosResponse; didSucceed: boolean; }) { - logger.info(`POST ${githubApiBaseUrlV4} (status: ${axiosResponse.status})`); + const gqlQueryName = getGqlQueryName(query); + logger.info( + `POST ${githubApiBaseUrlV4} (name:${gqlQueryName}, status: ${axiosResponse.status})` + ); const logMethod = didSucceed ? logger.verbose : logger.info; - logMethod('Query:', query); + logMethod(`Query name ${gqlQueryName}`); + logMethod(`Query: ${query}`); logMethod('Variables:', variables); logMethod('Response headers:', axiosResponse.headers); logMethod('Response data:', axiosResponse.data); @@ -114,3 +119,9 @@ export class GithubV4Exception extends Error { this.name = 'GithubV4Exception'; } } + +function getGqlQueryName(query: string) { + const ast = gql(query); + //@ts-expect-error + return ast.definitions[0].name.value; +} diff --git a/src/services/github/v4/enablePullRequestAutoMerge.private.test.ts b/src/services/github/v4/enablePullRequestAutoMerge.private.test.ts index 3eb8028e..5bdfa2ab 100644 --- a/src/services/github/v4/enablePullRequestAutoMerge.private.test.ts +++ b/src/services/github/v4/enablePullRequestAutoMerge.private.test.ts @@ -69,7 +69,7 @@ describe.skip('enablePullRequestAutoMerge', () => { let options: ValidConfigOptions; beforeAll(async () => { - const accessToken = await getDevAccessToken(); + const accessToken = getDevAccessToken(); const randomString = crypto.randomBytes(4).toString('hex'); branchName = `test-${randomString}`; diff --git a/src/services/github/v4/fetchAuthorId.private.test.ts b/src/services/github/v4/fetchAuthorId.private.test.ts index 03193739..2be115ff 100644 --- a/src/services/github/v4/fetchAuthorId.private.test.ts +++ b/src/services/github/v4/fetchAuthorId.private.test.ts @@ -5,8 +5,8 @@ import { fetchAuthorId } from './fetchAuthorId'; describe('fetchAuthorId', () => { let devAccessToken: string; - beforeAll(async () => { - devAccessToken = await getDevAccessToken(); + beforeAll(() => { + devAccessToken = getDevAccessToken(); }); describe('author = null', () => { diff --git a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitByPullNumber.private.test.ts.snap b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitByPullNumber.private.test.ts.snap index 2edff55c..7f2dd09b 100644 --- a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitByPullNumber.private.test.ts.snap +++ b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitByPullNumber.private.test.ts.snap @@ -25,7 +25,7 @@ exports[`fetchCommitByPullNumber snapshot request/response makes the right queri login } } - oid + sha: oid message committedDate @@ -43,8 +43,8 @@ exports[`fetchCommitByPullNumber snapshot request/response makes the right queri baseRefName # source merge commit (the commit that actually went into the source branch) - sourceMergeCommit: mergeCommit { - oid + mergeCommit { + sha: oid message } @@ -60,7 +60,7 @@ exports[`fetchCommitByPullNumber snapshot request/response makes the right queri ... on PullRequest { # target merge commit: the backport commit that was merged into the target branch targetMergeCommit: mergeCommit { - oid + sha: oid message } repository { @@ -79,7 +79,7 @@ exports[`fetchCommitByPullNumber snapshot request/response makes the right queri node { targetCommit: commit { message - oid + sha: oid } } } @@ -100,7 +100,6 @@ exports[`fetchCommitByPullNumber snapshot request/response makes the right queri exports[`fetchCommitByPullNumber snapshot request/response returns the correct response 1`] = ` Object { - "committedDate": "2021-12-20T14:20:16Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -115,10 +114,19 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/121643", }, ], - "originalMessage": "[APM] Add note about synthtrace to APM docs (#121633)", - "pullNumber": 121633, - "pullUrl": "https://github.com/elastic/kibana/pull/121633", - "sha": "d421ddcf6157150596581c7885afa3690cec6339", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-12-20T14:20:16Z", + "message": "[APM] Add note about synthtrace to APM docs (#121633)", + "sha": "d421ddcf6157150596581c7885afa3690cec6339", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Add note about synthtrace to APM docs (#121633)", + "sha": "d421ddcf6157150596581c7885afa3690cec6339", + }, + "number": 121633, + "url": "https://github.com/elastic/kibana/pull/121633", + }, } `; diff --git a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitBySha.private.test.ts.snap b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitBySha.private.test.ts.snap index 4cfe0f4e..107f614d 100644 --- a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitBySha.private.test.ts.snap +++ b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitBySha.private.test.ts.snap @@ -2,9 +2,9 @@ exports[`fetchCommitBySha snapshot request/response makes the right queries: Query: CommitsBySha 1`] = ` " - query CommitsBySha($repoOwner: String!, $repoName: String!, $oid: String!) { + query CommitsBySha($repoOwner: String!, $repoName: String!, $sha: String!) { repository(owner: $repoOwner, name: $repoName) { - object(expression: $oid) { + object(expression: $sha) { ...SourceCommitWithTargetPullRequest } } @@ -19,7 +19,7 @@ exports[`fetchCommitBySha snapshot request/response makes the right queries: Que login } } - oid + sha: oid message committedDate @@ -37,8 +37,8 @@ exports[`fetchCommitBySha snapshot request/response makes the right queries: Que baseRefName # source merge commit (the commit that actually went into the source branch) - sourceMergeCommit: mergeCommit { - oid + mergeCommit { + sha: oid message } @@ -54,7 +54,7 @@ exports[`fetchCommitBySha snapshot request/response makes the right queries: Que ... on PullRequest { # target merge commit: the backport commit that was merged into the target branch targetMergeCommit: mergeCommit { - oid + sha: oid message } repository { @@ -73,7 +73,7 @@ exports[`fetchCommitBySha snapshot request/response makes the right queries: Que node { targetCommit: commit { message - oid + sha: oid } } } @@ -94,7 +94,6 @@ exports[`fetchCommitBySha snapshot request/response makes the right queries: Que exports[`fetchCommitBySha snapshot request/response returns the correct response 1`] = ` Object { - "committedDate": "2021-12-20T14:20:16Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -109,10 +108,19 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/121643", }, ], - "originalMessage": "[APM] Add note about synthtrace to APM docs (#121633)", - "pullNumber": 121633, - "pullUrl": "https://github.com/elastic/kibana/pull/121633", - "sha": "d421ddcf6157150596581c7885afa3690cec6339", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-12-20T14:20:16Z", + "message": "[APM] Add note about synthtrace to APM docs (#121633)", + "sha": "d421ddcf6157150596581c7885afa3690cec6339", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Add note about synthtrace to APM docs (#121633)", + "sha": "d421ddcf6157150596581c7885afa3690cec6339", + }, + "number": 121633, + "url": "https://github.com/elastic/kibana/pull/121633", + }, } `; diff --git a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.private.test.ts.snap b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.private.test.ts.snap index e98c8d5e..2ce3256f 100644 --- a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.private.test.ts.snap +++ b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.private.test.ts.snap @@ -54,7 +54,7 @@ exports[`fetchCommitsByAuthor snapshot request/response makes the right queries: login } } - oid + sha: oid message committedDate @@ -72,8 +72,8 @@ exports[`fetchCommitsByAuthor snapshot request/response makes the right queries: baseRefName # source merge commit (the commit that actually went into the source branch) - sourceMergeCommit: mergeCommit { - oid + mergeCommit { + sha: oid message } @@ -89,7 +89,7 @@ exports[`fetchCommitsByAuthor snapshot request/response makes the right queries: ... on PullRequest { # target merge commit: the backport commit that was merged into the target branch targetMergeCommit: mergeCommit { - oid + sha: oid message } repository { @@ -108,7 +108,7 @@ exports[`fetchCommitsByAuthor snapshot request/response makes the right queries: node { targetCommit: commit { message - oid + sha: oid } } } @@ -130,7 +130,6 @@ exports[`fetchCommitsByAuthor snapshot request/response makes the right queries: exports[`fetchCommitsByAuthor snapshot request/response returns the correct response 1`] = ` Array [ Object { - "committedDate": "2021-12-20T14:20:16Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -145,23 +144,39 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/121643", }, ], - "originalMessage": "[APM] Add note about synthtrace to APM docs (#121633)", - "pullNumber": 121633, - "pullUrl": "https://github.com/elastic/kibana/pull/121633", - "sha": "d421ddcf6157150596581c7885afa3690cec6339", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-12-20T14:20:16Z", + "message": "[APM] Add note about synthtrace to APM docs (#121633)", + "sha": "d421ddcf6157150596581c7885afa3690cec6339", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Add note about synthtrace to APM docs (#121633)", + "sha": "d421ddcf6157150596581c7885afa3690cec6339", + }, + "number": 121633, + "url": "https://github.com/elastic/kibana/pull/121633", + }, }, Object { - "committedDate": "2021-12-08T20:03:55Z", "expectedTargetPullRequests": Array [], - "originalMessage": "[APM] Prefer service.name for logs correlation (#120694)", - "pullNumber": 120694, - "pullUrl": "https://github.com/elastic/kibana/pull/120694", - "sha": "b1b491959dab47aeb83c88ee2accb2db46d23793", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-12-08T20:03:55Z", + "message": "[APM] Prefer service.name for logs correlation (#120694)", + "sha": "b1b491959dab47aeb83c88ee2accb2db46d23793", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Prefer service.name for logs correlation (#120694)", + "sha": "b1b491959dab47aeb83c88ee2accb2db46d23793", + }, + "number": 120694, + "url": "https://github.com/elastic/kibana/pull/120694", + }, }, Object { - "committedDate": "2021-12-01T23:26:48Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -176,14 +191,22 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/120186", }, ], - "originalMessage": "[APM] Disable telemetry in agent config endpoint (#120106)", - "pullNumber": 120106, - "pullUrl": "https://github.com/elastic/kibana/pull/120106", - "sha": "b1bb4a93959f19a653b9cfb207a5c6acb6559482", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-12-01T23:26:48Z", + "message": "[APM] Disable telemetry in agent config endpoint (#120106)", + "sha": "b1bb4a93959f19a653b9cfb207a5c6acb6559482", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Disable telemetry in agent config endpoint (#120106)", + "sha": "b1bb4a93959f19a653b9cfb207a5c6acb6559482", + }, + "number": 120106, + "url": "https://github.com/elastic/kibana/pull/120106", + }, }, Object { - "committedDate": "2021-11-30T18:47:26Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -206,7 +229,10 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/120012", }, ], - "originalMessage": "[APM] Remove index_pattern.json and add custom field formatters (#119915) + "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-30T18:47:26Z", + "message": "[APM] Remove index_pattern.json and add custom field formatters (#119915) * [APM] Remove index_pattern.json and add custom field formatters @@ -215,13 +241,26 @@ Co-authored-by: Søren Louv-Jansen ", * Fix tests * Fix tutorial", - "pullNumber": 119915, - "pullUrl": "https://github.com/elastic/kibana/pull/119915", - "sha": "434f6e6a88faf24dc1ea41f9f726db78e46355a7", - "sourceBranch": "main", + "sha": "434f6e6a88faf24dc1ea41f9f726db78e46355a7", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Remove index_pattern.json and add custom field formatters (#119915) + +* [APM] Remove index_pattern.json and add custom field formatters + +* Fix tests + +* Fix tests + +* Fix tutorial", + "sha": "434f6e6a88faf24dc1ea41f9f726db78e46355a7", + }, + "number": 119915, + "url": "https://github.com/elastic/kibana/pull/119915", + }, }, Object { - "committedDate": "2021-11-29T15:12:27Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -249,14 +288,22 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/120179", }, ], - "originalMessage": "[APM] Remove log-log descriptions from correlation charts (#119700)", - "pullNumber": 119700, - "pullUrl": "https://github.com/elastic/kibana/pull/119700", - "sha": "ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-29T15:12:27Z", + "message": "[APM] Remove log-log descriptions from correlation charts (#119700)", + "sha": "ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Remove log-log descriptions from correlation charts (#119700)", + "sha": "ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff", + }, + "number": 119700, + "url": "https://github.com/elastic/kibana/pull/119700", + }, }, Object { - "committedDate": "2021-11-29T13:40:01Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -271,14 +318,22 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/119840", }, ], - "originalMessage": "[APM] Fix bug in documentation on \`span.destination\` metrics (#119789)", - "pullNumber": 119789, - "pullUrl": "https://github.com/elastic/kibana/pull/119789", - "sha": "43253ecafa1365eae45d31dd284d0a0bf273bc4d", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-29T13:40:01Z", + "message": "[APM] Fix bug in documentation on \`span.destination\` metrics (#119789)", + "sha": "43253ecafa1365eae45d31dd284d0a0bf273bc4d", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Fix bug in documentation on \`span.destination\` metrics (#119789)", + "sha": "43253ecafa1365eae45d31dd284d0a0bf273bc4d", + }, + "number": 119789, + "url": "https://github.com/elastic/kibana/pull/119789", + }, }, Object { - "committedDate": "2021-11-16T11:44:55Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -303,7 +358,10 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/118675", }, ], - "originalMessage": "[APM] Remove projections (#118327) + "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-16T11:44:55Z", + "message": "[APM] Remove projections (#118327) * Delete errors projection @@ -314,13 +372,28 @@ Co-authored-by: Søren Louv-Jansen ", * Fix tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>", - "pullNumber": 118327, - "pullUrl": "https://github.com/elastic/kibana/pull/118327", - "sha": "b48268dd0c42c9dc1fe310f7c0b3327117d066a5", - "sourceBranch": "main", + "sha": "b48268dd0c42c9dc1fe310f7c0b3327117d066a5", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Remove projections (#118327) + +* Delete errors projection + +* Remove \`getMetricsProjection\` + +* Remove \`getServiceNodesProjection\` + +* Fix tests + +Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>", + "sha": "b48268dd0c42c9dc1fe310f7c0b3327117d066a5", + }, + "number": 118327, + "url": "https://github.com/elastic/kibana/pull/118327", + }, }, Object { - "committedDate": "2021-11-15T22:54:40Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -335,14 +408,22 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/118631", }, ], - "originalMessage": "Update query_debugging_in_development_and_production.md (#118491)", - "pullNumber": 118491, - "pullUrl": "https://github.com/elastic/kibana/pull/118491", - "sha": "e66377790605274d2610f45eed35c9d8febdb7b9", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-15T22:54:40Z", + "message": "Update query_debugging_in_development_and_production.md (#118491)", + "sha": "e66377790605274d2610f45eed35c9d8febdb7b9", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "Update query_debugging_in_development_and_production.md (#118491)", + "sha": "e66377790605274d2610f45eed35c9d8febdb7b9", + }, + "number": 118491, + "url": "https://github.com/elastic/kibana/pull/118491", + }, }, Object { - "committedDate": "2021-11-08T15:12:52Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -357,14 +438,22 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/117872", }, ], - "originalMessage": "[APM] Ignore unavailable indices for ml jobs (#117632)", - "pullNumber": 117632, - "pullUrl": "https://github.com/elastic/kibana/pull/117632", - "sha": "acc7bd9d97a2147f752942dbcf01d7fb2478234b", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-08T15:12:52Z", + "message": "[APM] Ignore unavailable indices for ml jobs (#117632)", + "sha": "acc7bd9d97a2147f752942dbcf01d7fb2478234b", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Ignore unavailable indices for ml jobs (#117632)", + "sha": "acc7bd9d97a2147f752942dbcf01d7fb2478234b", + }, + "number": 117632, + "url": "https://github.com/elastic/kibana/pull/117632", + }, }, Object { - "committedDate": "2021-11-08T11:52:20Z", "expectedTargetPullRequests": Array [ Object { "branch": "8.0", @@ -379,11 +468,20 @@ Co-authored-by: Søren Louv-Jansen ", "url": "https://github.com/elastic/kibana/pull/117831", }, ], - "originalMessage": "[APM] Document \`_inspect\` flag (#117635)", - "pullNumber": 117635, - "pullUrl": "https://github.com/elastic/kibana/pull/117635", - "sha": "d13ee69bdac1deebfea9f02a29cab0f9a87f2f8e", "sourceBranch": "main", + "sourceCommit": Object { + "committedDate": "2021-11-08T11:52:20Z", + "message": "[APM] Document \`_inspect\` flag (#117635)", + "sha": "d13ee69bdac1deebfea9f02a29cab0f9a87f2f8e", + }, + "sourcePullRequest": Object { + "mergeCommit": Object { + "message": "[APM] Document \`_inspect\` flag (#117635)", + "sha": "d13ee69bdac1deebfea9f02a29cab0f9a87f2f8e", + }, + "number": 117635, + "url": "https://github.com/elastic/kibana/pull/117635", + }, }, ] `; diff --git a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.test.ts.snap b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.test.ts.snap index 506dea98..31524018 100644 --- a/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.test.ts.snap +++ b/src/services/github/v4/fetchCommits/__snapshots__/fetchCommitsByAuthor.test.ts.snap @@ -63,7 +63,7 @@ Array [ login } } - oid + sha: oid message committedDate @@ -81,8 +81,8 @@ Array [ baseRefName # source merge commit (the commit that actually went into the source branch) - sourceMergeCommit: mergeCommit { - oid + mergeCommit { + sha: oid message } @@ -98,7 +98,7 @@ Array [ ... on PullRequest { # target merge commit: the backport commit that was merged into the target branch targetMergeCommit: mergeCommit { - oid + sha: oid message } repository { @@ -117,7 +117,7 @@ Array [ node { targetCommit: commit { message - oid + sha: oid } } } diff --git a/src/services/github/v4/fetchCommits/allFetchers.private.test.ts b/src/services/github/v4/fetchCommits/allFetchers.private.test.ts index d6306ce5..beccd472 100644 --- a/src/services/github/v4/fetchCommits/allFetchers.private.test.ts +++ b/src/services/github/v4/fetchCommits/allFetchers.private.test.ts @@ -11,7 +11,7 @@ describe('allFetchers', () => { let commitByAuthor: Commit; beforeEach(async () => { - devAccessToken = await getDevAccessToken(); + devAccessToken = getDevAccessToken(); const commitsByAuthor = await fetchCommitsByAuthor({ accessToken: devAccessToken, @@ -30,7 +30,7 @@ describe('allFetchers', () => { }); it('matches commitByAuthor with commitByPullNumber', async () => { - if (!commitByAuthor.pullNumber) { + if (!commitByAuthor.sourcePullRequest) { throw new Error('Missing pull number!'); } @@ -38,7 +38,7 @@ describe('allFetchers', () => { repoOwner: 'elastic', repoName: 'kibana', accessToken: devAccessToken, - pullNumber: commitByAuthor.pullNumber, + pullNumber: commitByAuthor.sourcePullRequest.number, sourceBranch: 'master', historicalBranchLabelMappings: [], }); @@ -51,7 +51,7 @@ describe('allFetchers', () => { repoOwner: 'elastic', repoName: 'kibana', accessToken: devAccessToken, - sha: commitByAuthor.sha, + sha: commitByAuthor.sourceCommit.sha, sourceBranch: 'main', historicalBranchLabelMappings: [], }); @@ -76,8 +76,21 @@ describe('allFetchers', () => { }); it('returns correct response for commitByAuthor', async () => { - expect(commitByAuthor).toEqual({ - committedDate: '2021-12-20T14:20:16Z', + const expectedCommit: Commit = { + sourceCommit: { + committedDate: '2021-12-20T14:20:16Z', + message: '[APM] Add note about synthtrace to APM docs (#121633)', + sha: 'd421ddcf6157150596581c7885afa3690cec6339', + }, + sourcePullRequest: { + number: 121633, + url: 'https://github.com/elastic/kibana/pull/121633', + mergeCommit: { + message: '[APM] Add note about synthtrace to APM docs (#121633)', + sha: 'd421ddcf6157150596581c7885afa3690cec6339', + }, + }, + sourceBranch: 'main', expectedTargetPullRequests: [ { branch: '8.0', @@ -91,11 +104,7 @@ describe('allFetchers', () => { url: 'https://github.com/elastic/kibana/pull/121643', }, ], - originalMessage: '[APM] Add note about synthtrace to APM docs (#121633)', - pullNumber: 121633, - pullUrl: 'https://github.com/elastic/kibana/pull/121633', - sha: 'd421ddcf6157150596581c7885afa3690cec6339', - sourceBranch: 'main', - }); + }; + expect(commitByAuthor).toEqual(expectedCommit); }); }); diff --git a/src/services/github/v4/fetchCommits/fetchCommitByPullNumber.private.test.ts b/src/services/github/v4/fetchCommits/fetchCommitByPullNumber.private.test.ts index dffdfa79..e7d005f0 100644 --- a/src/services/github/v4/fetchCommits/fetchCommitByPullNumber.private.test.ts +++ b/src/services/github/v4/fetchCommits/fetchCommitByPullNumber.private.test.ts @@ -7,8 +7,8 @@ import { fetchCommitByPullNumber } from './fetchCommitByPullNumber'; describe('fetchCommitByPullNumber', () => { let devAccessToken: string; - beforeAll(async () => { - devAccessToken = await getDevAccessToken(); + beforeAll(() => { + devAccessToken = getDevAccessToken(); }); describe('snapshot request/response', () => { @@ -61,12 +61,20 @@ describe('fetchCommitByPullNumber', () => { historicalBranchLabelMappings: [], }; - expect(await fetchCommitByPullNumber(options)).toEqual({ - committedDate: '2020-08-15T12:40:19Z', - originalMessage: 'Add 🍏 emoji (#5)', - pullNumber: 5, - pullUrl: 'https://github.com/backport-org/backport-e2e/pull/5', - sha: 'ee8c492334cef1ca077a56addb79a26f79821d2f', + const expectedCommit: Commit = { + sourceCommit: { + committedDate: '2020-08-15T12:40:19Z', + message: 'Add 🍏 emoji (#5)', + sha: 'ee8c492334cef1ca077a56addb79a26f79821d2f', + }, + sourcePullRequest: { + number: 5, + url: 'https://github.com/backport-org/backport-e2e/pull/5', + mergeCommit: { + message: 'Add 🍏 emoji (#5)', + sha: 'ee8c492334cef1ca077a56addb79a26f79821d2f', + }, + }, sourceBranch: 'master', expectedTargetPullRequests: [ { @@ -90,7 +98,9 @@ describe('fetchCommitByPullNumber', () => { }, }, ], - }); + }; + + expect(await fetchCommitByPullNumber(options)).toEqual(expectedCommit); }); }); diff --git a/src/services/github/v4/fetchCommits/fetchCommitBySha.private.test.ts b/src/services/github/v4/fetchCommits/fetchCommitBySha.private.test.ts index cfbb8df8..91b8e014 100644 --- a/src/services/github/v4/fetchCommits/fetchCommitBySha.private.test.ts +++ b/src/services/github/v4/fetchCommits/fetchCommitBySha.private.test.ts @@ -7,8 +7,8 @@ import { fetchCommitBySha } from './fetchCommitBySha'; describe('fetchCommitBySha', () => { let devAccessToken: string; - beforeEach(async () => { - devAccessToken = await getDevAccessToken(); + beforeEach(() => { + devAccessToken = getDevAccessToken(); }); describe('snapshot request/response', () => { @@ -50,21 +50,20 @@ describe('fetchCommitBySha', () => { }); it('should return single commit with pull request', async () => { - await expect( - await fetchCommitBySha({ - repoOwner: 'elastic', - repoName: 'kibana', - accessToken: devAccessToken, - sha: 'cb6fbc0', - sourceBranch: 'master', - historicalBranchLabelMappings: [], - }) - ).toEqual({ - committedDate: '2020-07-07T20:40:28Z', - originalMessage: '[APM] Add API tests (#70740)', - pullNumber: 70740, - pullUrl: 'https://github.com/elastic/kibana/pull/70740', - sha: 'cb6fbc0e1b406675724181a3e9f59459b5f8f892', + const expectedCommit: Commit = { + sourceCommit: { + committedDate: '2020-07-07T20:40:28Z', + message: '[APM] Add API tests (#70740)', + sha: 'cb6fbc0e1b406675724181a3e9f59459b5f8f892', + }, + sourcePullRequest: { + number: 70740, + url: 'https://github.com/elastic/kibana/pull/70740', + mergeCommit: { + message: '[APM] Add API tests (#70740)', + sha: 'cb6fbc0e1b406675724181a3e9f59459b5f8f892', + }, + }, sourceBranch: 'master', expectedTargetPullRequests: [ { @@ -78,7 +77,18 @@ describe('fetchCommitBySha', () => { }, }, ], - }); + }; + + await expect( + await fetchCommitBySha({ + repoOwner: 'elastic', + repoName: 'kibana', + accessToken: devAccessToken, + sha: 'cb6fbc0', + sourceBranch: 'master', + historicalBranchLabelMappings: [], + }) + ).toEqual(expectedCommit); }); it('throws if sha does not exist', async () => { diff --git a/src/services/github/v4/fetchCommits/fetchCommitBySha.ts b/src/services/github/v4/fetchCommits/fetchCommitBySha.ts index 819629f1..4747fbba 100644 --- a/src/services/github/v4/fetchCommits/fetchCommitBySha.ts +++ b/src/services/github/v4/fetchCommits/fetchCommitBySha.ts @@ -28,9 +28,9 @@ export async function fetchCommitBySha(options: { } = options; const query = /* GraphQL */ ` - query CommitsBySha($repoOwner: String!, $repoName: String!, $oid: String!) { + query CommitsBySha($repoOwner: String!, $repoName: String!, $sha: String!) { repository(owner: $repoOwner, name: $repoName) { - object(expression: $oid) { + object(expression: $sha) { ...SourceCommitWithTargetPullRequest } } @@ -46,7 +46,7 @@ export async function fetchCommitBySha(options: { variables: { repoOwner, repoName, - oid: sha, + sha, }, }); diff --git a/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.private.test.ts b/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.private.test.ts index 9ecd2004..1ef7772d 100644 --- a/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.private.test.ts +++ b/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.private.test.ts @@ -7,8 +7,8 @@ import { fetchCommitsByAuthor } from './fetchCommitsByAuthor'; describe('fetchCommitsByAuthor', () => { let devAccessToken: string; - beforeAll(async () => { - devAccessToken = await getDevAccessToken(); + beforeAll(() => { + devAccessToken = getDevAccessToken(); }); describe('snapshot request/response', () => { @@ -68,7 +68,7 @@ describe('fetchCommitsByAuthor', () => { const getCommitMessages = (commits: Commit[]) => { return commits.map((c) => - c.originalMessage.replace(/(\r\n|\n|\r)/gm, '') + c.sourceCommit.message.replace(/(\r\n|\n|\r)/gm, '') ); }; @@ -156,7 +156,9 @@ describe('fetchCommitsByAuthor', () => { }); it('returns related OPEN PRs', async () => { - const commitWithOpenPR = res.find((commit) => commit.pullNumber === 9); + const commitWithOpenPR = res.find( + (commit) => commit.sourcePullRequest?.number === 9 + ); expect(commitWithOpenPR?.expectedTargetPullRequests).toEqual([ { branch: '7.8', @@ -168,7 +170,9 @@ describe('fetchCommitsByAuthor', () => { }); it('returns related MERGED PRs', async () => { - const commitWithMergedPRs = res.find((commit) => commit.pullNumber === 5); + const commitWithMergedPRs = res.find( + (commit) => commit.sourcePullRequest?.number === 5 + ); expect(commitWithMergedPRs?.expectedTargetPullRequests).toEqual([ { branch: '7.x', @@ -194,7 +198,9 @@ describe('fetchCommitsByAuthor', () => { }); it('returns empty if there are no related PRs', async () => { - const commitWithoutPRs = res.find((commit) => commit.pullNumber === 8); + const commitWithoutPRs = res.find( + (commit) => commit.sourcePullRequest?.number === 8 + ); expect(commitWithoutPRs?.expectedTargetPullRequests).toEqual([]); }); }); diff --git a/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.test.ts b/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.test.ts index 857db2b8..7a5f805e 100644 --- a/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.test.ts +++ b/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.test.ts @@ -56,28 +56,47 @@ describe('fetchCommitsByAuthor', () => { it('should return a list of commits with pullNumber and existing backports', () => { const expectedCommits: Commit[] = [ { - committedDate: '2021-12-24T00:00:00Z', - sha: '2e63475c483f7844b0f2833bc57fdee32095bacb', - originalMessage: 'Add 👻', + sourceCommit: { + committedDate: '2021-12-24T00:00:00Z', + sha: '2e63475c483f7844b0f2833bc57fdee32095bacb', + message: 'Add 👻', + }, expectedTargetPullRequests: [], sourceBranch: 'source-branch-from-options', }, { - committedDate: '2021-12-23T00:00:00Z', - sha: 'f3b618b9421fdecdb36862f907afbdd6344b361d', - originalMessage: 'Add witch (#85)', - pullNumber: 85, - pullUrl: 'https://github.com/elastic/kibana/pull/85', + sourceCommit: { + committedDate: '2021-12-23T00:00:00Z', + sha: 'f3b618b9421fdecdb36862f907afbdd6344b361d', + message: 'Add witch (#85)', + }, + sourcePullRequest: { + number: 85, + url: 'https://github.com/elastic/kibana/pull/85', + mergeCommit: { + sha: 'f3b618b9421fdecdb36862f907afbdd6344b361d', + message: 'Add witch (#85)', + }, + }, expectedTargetPullRequests: [], sourceBranch: 'master', }, { - committedDate: '2021-12-22T00:00:00Z', - sha: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', - originalMessage: - 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', - pullNumber: 80, - pullUrl: 'https://github.com/elastic/kibana/pull/80', + sourceCommit: { + committedDate: '2021-12-22T00:00:00Z', + sha: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + message: + 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', + }, + sourcePullRequest: { + number: 80, + url: 'https://github.com/elastic/kibana/pull/80', + mergeCommit: { + sha: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + message: + 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', + }, + }, expectedTargetPullRequests: [ { branch: '6.3', @@ -94,16 +113,20 @@ describe('fetchCommitsByAuthor', () => { sourceBranch: 'master', }, { - committedDate: '2021-12-21T00:00:00Z', - sha: '3827bbbaf39914eda4f02f6940189844375fd097', - originalMessage: 'Add backport config', + sourceCommit: { + committedDate: '2021-12-21T00:00:00Z', + sha: '3827bbbaf39914eda4f02f6940189844375fd097', + message: 'Add backport config', + }, expectedTargetPullRequests: [], sourceBranch: 'source-branch-from-options', }, { - committedDate: '2021-12-20T00:00:00Z', - sha: '5ea0da550ac191029459289d67f99ad7d310812b', - originalMessage: 'Initial commit', + sourceCommit: { + committedDate: '2021-12-20T00:00:00Z', + sha: '5ea0da550ac191029459289d67f99ad7d310812b', + message: 'Initial commit', + }, expectedTargetPullRequests: [], sourceBranch: 'source-branch-from-options', }, diff --git a/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.ts b/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.ts index 523ceb46..db400d4b 100644 --- a/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.ts +++ b/src/services/github/v4/fetchCommits/fetchCommitsByAuthor.ts @@ -149,8 +149,12 @@ export async function fetchCommitsByAuthor(options: { throw new HandledError(errorText); } - const commitsUnique = uniqBy(commits, 'sha'); - const commitsSorted = orderBy(commitsUnique, 'committedDate', 'desc'); + const commitsUnique = uniqBy(commits, (c) => c.sourceCommit.sha); + const commitsSorted = orderBy( + commitsUnique, + (c) => c.sourceCommit.committedDate, + 'desc' + ); return commitsSorted; } diff --git a/src/services/github/v4/fetchCommits/fetchPullRequestBySearchQuery.private.test.ts b/src/services/github/v4/fetchCommits/fetchPullRequestBySearchQuery.private.test.ts index d792fe2e..327d390c 100644 --- a/src/services/github/v4/fetchCommits/fetchPullRequestBySearchQuery.private.test.ts +++ b/src/services/github/v4/fetchCommits/fetchPullRequestBySearchQuery.private.test.ts @@ -1,12 +1,13 @@ import { ValidConfigOptions } from '../../../../options/options'; import { getDevAccessToken } from '../../../../test/private/getDevAccessToken'; +import { Commit } from '../../../sourceCommit/parseSourceCommit'; import { fetchPullRequestBySearchQuery } from './fetchPullRequestBySearchQuery'; describe('fetchPullRequestBySearchQuery', () => { let devAccessToken: string; - beforeAll(async () => { - devAccessToken = await getDevAccessToken(); + beforeAll(() => { + devAccessToken = getDevAccessToken(); }); describe('when filter does not match any PRs', () => { @@ -39,9 +40,22 @@ describe('fetchPullRequestBySearchQuery', () => { author: 'sqren', } as ValidConfigOptions; - expect(await fetchPullRequestBySearchQuery(options)).toEqual([ + const expectedCommits: Commit[] = [ { - committedDate: '2020-08-16T21:44:28Z', + sourceCommit: { + committedDate: '2020-08-16T21:44:28Z', + message: 'Add sheep emoji (#9)', + sha: 'eebf165c82a4b718d95c11b3877e365b1949ff28', + }, + sourcePullRequest: { + number: 9, + url: 'https://github.com/backport-org/backport-e2e/pull/9', + mergeCommit: { + message: 'Add sheep emoji (#9)', + sha: 'eebf165c82a4b718d95c11b3877e365b1949ff28', + }, + }, + sourceBranch: 'master', expectedTargetPullRequests: [ { branch: '7.8', @@ -50,14 +64,22 @@ describe('fetchPullRequestBySearchQuery', () => { url: 'https://github.com/backport-org/backport-e2e/pull/10', }, ], - originalMessage: 'Add sheep emoji (#9)', - pullNumber: 9, - pullUrl: 'https://github.com/backport-org/backport-e2e/pull/9', - sha: 'eebf165c82a4b718d95c11b3877e365b1949ff28', - sourceBranch: 'master', }, { - committedDate: '2020-08-15T12:40:19Z', + sourceCommit: { + committedDate: '2020-08-15T12:40:19Z', + message: 'Add 🍏 emoji (#5)', + sha: 'ee8c492334cef1ca077a56addb79a26f79821d2f', + }, + sourcePullRequest: { + number: 5, + url: 'https://github.com/backport-org/backport-e2e/pull/5', + mergeCommit: { + message: 'Add 🍏 emoji (#5)', + sha: 'ee8c492334cef1ca077a56addb79a26f79821d2f', + }, + }, + sourceBranch: 'master', expectedTargetPullRequests: [ { branch: '7.x', @@ -80,13 +102,12 @@ describe('fetchPullRequestBySearchQuery', () => { }, }, ], - originalMessage: 'Add 🍏 emoji (#5)', - pullNumber: 5, - pullUrl: 'https://github.com/backport-org/backport-e2e/pull/5', - sha: 'ee8c492334cef1ca077a56addb79a26f79821d2f', - sourceBranch: 'master', }, - ]); + ]; + + expect(await fetchPullRequestBySearchQuery(options)).toEqual( + expectedCommits + ); }); }); }); diff --git a/src/services/github/v4/fetchExistingPullRequest.private.test.ts b/src/services/github/v4/fetchExistingPullRequest.private.test.ts index 8b860828..74042ff4 100644 --- a/src/services/github/v4/fetchExistingPullRequest.private.test.ts +++ b/src/services/github/v4/fetchExistingPullRequest.private.test.ts @@ -5,8 +5,8 @@ import { fetchExistingPullRequest } from './fetchExistingPullRequest'; describe('fetchExistingPullRequest', () => { let devAccessToken: string; - beforeAll(async () => { - devAccessToken = await getDevAccessToken(); + beforeAll(() => { + devAccessToken = getDevAccessToken(); }); describe('when PR does not exist', () => { diff --git a/src/services/github/v4/fetchRemoteProjectConfig.private.test.ts b/src/services/github/v4/fetchRemoteProjectConfig.private.test.ts index 9624f9bd..a1ac8bcc 100644 --- a/src/services/github/v4/fetchRemoteProjectConfig.private.test.ts +++ b/src/services/github/v4/fetchRemoteProjectConfig.private.test.ts @@ -4,8 +4,8 @@ import { fetchRemoteProjectConfig } from './fetchRemoteProjectConfig'; describe('fetchRemoteProjectConfig', () => { let devAccessToken: string; - beforeEach(async () => { - devAccessToken = await getDevAccessToken(); + beforeEach(() => { + devAccessToken = getDevAccessToken(); }); it('returns the backport config from "main" branch', async () => { diff --git a/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.private.test.ts b/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.private.test.ts index 5b475c51..c98e2368 100644 --- a/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.private.test.ts +++ b/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.private.test.ts @@ -6,7 +6,7 @@ describe('getOptionsFromGithub', () => { let devAccessToken: string; beforeAll(async () => { - devAccessToken = await getDevAccessToken(); + devAccessToken = getDevAccessToken(); jest.spyOn(os, 'homedir').mockReturnValue('/myHomeDir'); }); diff --git a/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.ts b/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.ts index ff5a9df3..620cea0e 100644 --- a/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.ts +++ b/src/services/github/v4/getOptionsFromGithub/getOptionsFromGithub.ts @@ -17,11 +17,15 @@ import { GithubConfigOptionsResponse, query, RemoteConfig } from './query'; // - verify the access token // - ensure no branch named "backport" exists +export type OptionsFromGithub = Awaited< + ReturnType +>; export async function getOptionsFromGithub(options: { accessToken: string; githubApiBaseUrlV4?: string; repoName: string; repoOwner: string; + username?: string; skipRemoteConfig?: boolean; cwd?: string; }) { @@ -46,17 +50,15 @@ export async function getOptionsFromGithub(options: { res = swallowErrorIfConfigFileIsMissing(error); } - // get the original repo (not the fork) - const repo = res.repository.isFork ? res.repository.parent : res.repository; - // it is not possible to have a branch named "backport" - if (repo.ref?.name === 'backport') { + if (res.repository.illegalBackportBranch) { throw new HandledError( 'You must delete the branch "backport" to continue. See https://github.com/sqren/backport/issues/155 for details' ); } - const historicalRemoteConfigs = repo.defaultBranchRef.target.history.edges; + const historicalRemoteConfigs = + res.repository.defaultBranchRef.target.history.edges; const latestRemoteConfig = historicalRemoteConfigs[0]?.remoteConfig; const skipRemoteConfig = await getSkipRemoteConfigFile( options.cwd, @@ -64,10 +66,14 @@ export async function getOptionsFromGithub(options: { latestRemoteConfig ); + const remoteConfig = skipRemoteConfig + ? {} + : parseRemoteConfig(latestRemoteConfig); + return { - authenticatedUsername: res.viewer.login, - sourceBranch: repo.defaultBranchRef.name, - ...(skipRemoteConfig ? {} : parseRemoteConfig(latestRemoteConfig)), + authenticatedUsername: options.username ?? res.viewer.login, + sourceBranch: res.repository.defaultBranchRef.name, + ...remoteConfig, historicalBranchLabelMappings: skipRemoteConfig ? [] : getHistoricalBranchLabelMappings(historicalRemoteConfigs), @@ -169,12 +175,14 @@ function getHistoricalBranchLabelMappings( function swallowErrorIfConfigFileIsMissing(error: GithubV4Exception) { const { data, errors } = error.axiosResponse.data; - const wasMissingConfigError = errors?.some( - (error) => - error.type === 'NOT_FOUND' && - error.path.join('.') === - 'repository.defaultBranchRef.target.history.edges.0.remoteConfig.file' - ); + const wasMissingConfigError = errors?.some((error) => { + const isMatch = + /^repository.defaultBranchRef.target.history.edges.\d+.remoteConfig.file$/.test( + error.path.join('.') + ); + + return isMatch && error.type === 'NOT_FOUND'; + }); // swallow error if it's just the config file that's missing if (wasMissingConfigError && data != null) { diff --git a/src/services/github/v4/getOptionsFromGithub/query.ts b/src/services/github/v4/getOptionsFromGithub/query.ts index 807e5a8f..f65a75d3 100644 --- a/src/services/github/v4/getOptionsFromGithub/query.ts +++ b/src/services/github/v4/getOptionsFromGithub/query.ts @@ -3,30 +3,19 @@ export type RemoteConfig = { file: { object: { text: string } }; }; -type Repository = { - ref: { name: string } | null; - defaultBranchRef: { - name: string; - target: { - history: { edges: Array<{ remoteConfig: RemoteConfig }> }; - }; - }; -}; - export interface GithubConfigOptionsResponse { viewer: { login: string; }; - repository: - | { - isFork: true; - defaultBranchRef: null; - parent: Repository; - } - | ({ - isFork: false; - parent: null; - } & Repository); + repository: { + illegalBackportBranch: { id: string } | null; + defaultBranchRef: { + name: string; + target: { + history: { edges: Array<{ remoteConfig: RemoteConfig }> }; + }; + }; + }; } export const query = /* GraphQL */ ` @@ -35,32 +24,24 @@ export const query = /* GraphQL */ ` login } repository(owner: $repoOwner, name: $repoName) { - isFork - ...Repo - parent { - ...Repo + # check to see if a branch named "backport" exists + illegalBackportBranch: ref(qualifiedName: "refs/heads/backport") { + id } - } - } - - fragment Repo on Repository { - # check to see if a branch named "backport" exists - ref(qualifiedName: "refs/heads/backport") { - name - } - defaultBranchRef { - name - target { - ... on Commit { - history(first: 20, path: ".backportrc.json") { - edges { - remoteConfig: node { - committedDate - file(path: ".backportrc.json") { - ... on TreeEntry { - object { - ... on Blob { - text + defaultBranchRef { + name + target { + ... on Commit { + history(first: 20, path: ".backportrc.json") { + edges { + remoteConfig: node { + committedDate + file(path: ".backportrc.json") { + ... on TreeEntry { + object { + ... on Blob { + text + } } } } diff --git a/src/services/github/v4/getRepoOwnerAndNameFromGitRemotes.private.test.ts b/src/services/github/v4/getRepoOwnerAndNameFromGitRemotes.private.test.ts index 32a80441..33b4c28f 100644 --- a/src/services/github/v4/getRepoOwnerAndNameFromGitRemotes.private.test.ts +++ b/src/services/github/v4/getRepoOwnerAndNameFromGitRemotes.private.test.ts @@ -8,8 +8,8 @@ const sandboxPath = getSandboxPath({ filename: __filename }); describe('fetchRemoteProjectConfig', () => { let devAccessToken: string; - beforeEach(async () => { - devAccessToken = await getDevAccessToken(); + beforeEach(() => { + devAccessToken = getDevAccessToken(); }); describe('when the remote is a fork', () => { diff --git a/src/services/github/v4/mocks/commitsByAuthorMock.ts b/src/services/github/v4/mocks/commitsByAuthorMock.ts index d6a16c20..27aea12c 100644 --- a/src/services/github/v4/mocks/commitsByAuthorMock.ts +++ b/src/services/github/v4/mocks/commitsByAuthorMock.ts @@ -13,7 +13,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { owner: { login: 'elastic' }, }, committedDate: '2021-12-24T00:00:00Z', - oid: '2e63475c483f7844b0f2833bc57fdee32095bacb', + sha: '2e63475c483f7844b0f2833bc57fdee32095bacb', message: 'Add 👻', associatedPullRequests: { edges: [], @@ -27,7 +27,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { owner: { login: 'elastic' }, }, committedDate: '2021-12-23T00:00:00Z', - oid: 'f3b618b9421fdecdb36862f907afbdd6344b361d', + sha: 'f3b618b9421fdecdb36862f907afbdd6344b361d', message: 'Add witch (#85)', associatedPullRequests: { edges: [ @@ -39,8 +39,8 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { nodes: [{ name: 'my-label-b' }], }, number: 85, - sourceMergeCommit: { - oid: 'f3b618b9421fdecdb36862f907afbdd6344b361d', + mergeCommit: { + sha: 'f3b618b9421fdecdb36862f907afbdd6344b361d', message: 'Add witch (#85)', }, timelineItems: { @@ -59,7 +59,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { owner: { login: 'elastic' }, }, committedDate: '2021-12-22T00:00:00Z', - oid: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + sha: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', message: 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', associatedPullRequests: { @@ -72,8 +72,8 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { }, baseRefName: 'master', number: 80, - sourceMergeCommit: { - oid: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + mergeCommit: { + sha: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', message: 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', }, @@ -84,7 +84,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { targetPullRequest: { __typename: 'PullRequest', targetMergeCommit: { - oid: 'target-merge-commit-sha', + sha: 'target-merge-commit-sha', message: 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', }, @@ -102,7 +102,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { { node: { targetCommit: { - oid: 'abc', + sha: 'abc', message: 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', }, @@ -128,7 +128,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { owner: { login: 'elastic' }, }, committedDate: '2021-12-21T00:00:00Z', - oid: '3827bbbaf39914eda4f02f6940189844375fd097', + sha: '3827bbbaf39914eda4f02f6940189844375fd097', message: 'Add backport config', associatedPullRequests: { edges: [], @@ -142,7 +142,7 @@ export const commitsByAuthorMock: CommitByAuthorResponse = { owner: { login: 'elastic' }, }, committedDate: '2021-12-20T00:00:00Z', - oid: '5ea0da550ac191029459289d67f99ad7d310812b', + sha: '5ea0da550ac191029459289d67f99ad7d310812b', message: 'Initial commit', associatedPullRequests: { edges: [], diff --git a/src/services/logger.ts b/src/services/logger.ts index de4882e4..036e08f8 100644 --- a/src/services/logger.ts +++ b/src/services/logger.ts @@ -1,13 +1,8 @@ -import dedent from 'dedent'; -import { isString } from 'lodash'; -import safeJsonStringify from 'safe-json-stringify'; import winston, { format } from 'winston'; import { redact } from '../utils/redact'; import { getLogfilePath } from './env'; -const { combine } = format; - -let winstonInstance: winston.Logger; +export let logger: winston.Logger; // wrapper around console.log export function consoleLog(message: string) { @@ -16,26 +11,6 @@ export function consoleLog(message: string) { //process.stdout.write(message); } -export type Logger = typeof logger; - -export const logger = { - error: (message: string, meta?: unknown) => { - winstonInstance.error(message, null, { meta }); - }, - warn: (message: string, meta?: unknown) => { - winstonInstance.warn(message, null, { meta }); - }, - info: (message: string, meta?: unknown) => { - winstonInstance.info(message, null, { meta }); - }, - verbose: (message: string, meta?: unknown) => { - winstonInstance.verbose(message, null, { meta }); - }, - debug: (message: string, meta?: unknown) => { - winstonInstance.debug(message, null, { meta }); - }, -}; - let _accessToken: string | undefined; export function updateLogger({ @@ -49,7 +24,7 @@ export function updateLogger({ _accessToken = accessToken; // set log level - winstonInstance.level = verbose ? 'debug' : 'info'; + logger.level = verbose ? 'debug' : 'info'; } function redactAccessToken(str: string) { @@ -76,63 +51,27 @@ export function initLogger({ _accessToken = accessToken; } - winstonInstance = winston.createLogger({ + logger = winston.createLogger({ + format: format.combine( + format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), + // Format the metadata object + format.metadata({ + fillExcept: ['message', 'level', 'timestamp', 'label'], + }) + ), transports: ci ? [fileTransport, new winston.transports.Console()] : [fileTransport], }); - // wait exiting until logs have been flushed to disk - winstonInstance.on('finish', () => { - process.exit(1); - }); - return logger; } function getFileTransport({ logFilePath }: { logFilePath?: string }) { return new winston.transports.File({ - level: 'debug', - format: combine( - format.splat(), - format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - winston.format.metadata({ - fillExcept: ['message', 'level', 'timestamp', 'label'], - }), - - format.printf((info) => { - // format without metadata - if (!info.metadata.meta) { - return redactAccessToken(`${info.timestamp}: ${info.message}`); - } - - // format when metadata is a string - if (isString(info.metadata.meta)) { - return redactAccessToken( - `${info.timestamp}: ${info.message}\n${dedent( - info.metadata.meta - )}\n` - ); - } - - if (info.metadata.meta.stack) { - return redactAccessToken( - `${info.timestamp}: ${info.message}\n${info.metadata.meta.stack}\n` - ); - } - - // format when metadata is an object - - return redactAccessToken( - `${info.timestamp}: ${info.message}\n${safeJsonStringify( - info.metadata.meta, - null, - 2 - )}\n` - ); - }) - ), filename: getLogfilePath({ logFilePath }), + level: 'debug', + format: format.combine(format.json()), }); } diff --git a/src/services/prompt.test.ts b/src/services/prompt.test.ts index 32a38035..bac7d78c 100644 --- a/src/services/prompt.test.ts +++ b/src/services/prompt.test.ts @@ -5,12 +5,24 @@ import { Commit } from './sourceCommit/parseSourceCommit'; describe('prompt', () => { describe('getChoicesForCommitPrompt', () => { it('should display status badges via `expectedTargetPullRequests`', () => { - const commits = [ + const commits: Commit[] = [ { - sha: 'ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff', - originalMessage: - '[APM] Remove log-log descriptions from correlation charts (#119700)', - pullNumber: 119700, + sourceBranch: 'master', + sourceCommit: { + committedDate: '1', + sha: 'ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff', + message: + '[APM] Remove log-log descriptions from correlation charts (#119700)', + }, + sourcePullRequest: { + number: 119700, + url: 'foo', + mergeCommit: { + sha: 'ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff', + message: + '[APM] Remove log-log descriptions from correlation charts (#119700)', + }, + }, expectedTargetPullRequests: [ { number: 120178, branch: '8.0', state: 'MERGED' }, { number: 120179, branch: '7.16', state: 'MERGED' }, @@ -34,39 +46,78 @@ describe('prompt', () => { it('should list choices', () => { const commits: Commit[] = [ { - committedDate: '', sourceBranch: 'master', - sha: 'b1b491959dab47aeb83c88ee2accb2db46d23793', - originalMessage: - '[APM] Prefer service.name for logs correlation (#120694)', - pullNumber: 120694, + sourceCommit: { + committedDate: '', + sha: 'b1b491959dab47aeb83c88ee2accb2db46d23793', + message: '[APM] Prefer service.name for logs correlation (#120694)', + }, + sourcePullRequest: { + number: 120694, + url: 'foo', + mergeCommit: { + sha: 'b1b491959dab47aeb83c88ee2accb2db46d23793', + message: + '[APM] Prefer service.name for logs correlation (#120694)', + }, + }, expectedTargetPullRequests: [], }, { - committedDate: '', sourceBranch: 'master', - sha: 'b1bb4a93959f19a653b9cfb207a5c6acb6559482', - originalMessage: - '[APM] Disable telemetry in agent config endpoint (#120106)', - pullNumber: 120106, + sourceCommit: { + committedDate: '', + sha: 'b1bb4a93959f19a653b9cfb207a5c6acb6559482', + message: + '[APM] Disable telemetry in agent config endpoint (#120106)', + }, + sourcePullRequest: { + number: 120106, + url: 'foo', + mergeCommit: { + sha: 'b1bb4a93959f19a653b9cfb207a5c6acb6559482', + message: + '[APM] Disable telemetry in agent config endpoint (#120106)', + }, + }, expectedTargetPullRequests: [], }, { - committedDate: '', sourceBranch: 'master', - sha: '434f6e6a88faf24dc1ea41f9f726db78e46355a7', - originalMessage: - '[APM] Remove index_pattern.json and add custom field formatters (#119915)', - pullNumber: 119915, + sourceCommit: { + committedDate: '', + sha: '434f6e6a88faf24dc1ea41f9f726db78e46355a7', + message: + '[APM] Remove index_pattern.json and add custom field formatters (#119915)', + }, + sourcePullRequest: { + number: 119915, + url: 'foo', + mergeCommit: { + sha: '434f6e6a88faf24dc1ea41f9f726db78e46355a7', + message: + '[APM] Remove index_pattern.json and add custom field formatters (#119915)', + }, + }, expectedTargetPullRequests: [], }, { - committedDate: '', sourceBranch: 'master', - sha: 'ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff', - originalMessage: - '[APM] Remove log-log descriptions from correlation charts (#119700)', - pullNumber: 119700, + sourceCommit: { + committedDate: '', + sha: 'ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff', + message: + '[APM] Remove log-log descriptions from correlation charts (#119700)', + }, + sourcePullRequest: { + number: 119700, + url: 'foo', + mergeCommit: { + sha: 'ae9d51b7fe3ee6f30d0d196c782e0dcabb7ac5ff', + message: + '[APM] Remove log-log descriptions from correlation charts (#119700)', + }, + }, expectedTargetPullRequests: [], }, ]; diff --git a/src/services/prompts.ts b/src/services/prompts.ts index e8feb3dd..4ff67309 100644 --- a/src/services/prompts.ts +++ b/src/services/prompts.ts @@ -107,19 +107,23 @@ export function getChoicesForCommitPrompt( let name; if (showDetails) { - const message = stripPullNumber(c.originalMessage); - const prLink = c.pullUrl ? ` ` + getPrLink(c.pullNumber, c.pullUrl) : ''; + const message = stripPullNumber(c.sourceCommit.message); + const prLink = c.sourcePullRequest + ? ` ` + getPrLink(c.sourcePullRequest.number, c.sourcePullRequest.url) + : ''; const pullStatus = getDetailedPullStatus(c); name = `${position}${message}${prLink}${pullStatus}`; } else { - const message = getFirstLine(c.originalMessage); + const message = getFirstLine(c.sourceCommit.message); const pullStatus = getSimplePullStatus(c); name = `${position}${message} ${pullStatus}`; } - const short = c.pullNumber - ? `#${c.pullNumber} (${getShortSha(c.sha)})` - : getShortSha(c.sha); + const short = c.sourcePullRequest + ? `#${c.sourcePullRequest.number} (${getShortSha( + c.sourcePullRequest.mergeCommit.sha + )})` + : getShortSha(c.sourceCommit.sha); return { name, short, value: c }; }); diff --git a/src/services/sourceCommit/getExpectedTargetPullRequests.ts b/src/services/sourceCommit/getExpectedTargetPullRequests.ts index b758a293..afc1143a 100644 --- a/src/services/sourceCommit/getExpectedTargetPullRequests.ts +++ b/src/services/sourceCommit/getExpectedTargetPullRequests.ts @@ -106,7 +106,7 @@ function getExistingTargetPullRequests( state: targetPullRequest.state, mergeCommit: targetPullRequest.targetMergeCommit ? { - sha: targetPullRequest.targetMergeCommit.oid, + sha: targetPullRequest.targetMergeCommit.sha, message: targetPullRequest.targetMergeCommit.message, } : undefined, diff --git a/src/services/sourceCommit/getMockSourceCommit.ts b/src/services/sourceCommit/getMockSourceCommit.ts index 430f6a08..b26e00db 100644 --- a/src/services/sourceCommit/getMockSourceCommit.ts +++ b/src/services/sourceCommit/getMockSourceCommit.ts @@ -35,7 +35,7 @@ export function getMockSourceCommit({ owner: { login: 'elastic' }, }, committedDate: sourceCommit.commitedDate ?? '2021-12-22T00:00:00Z', - oid: sourceCommit.sha ?? defaultSourceCommitSha, + sha: sourceCommit.sha ?? defaultSourceCommitSha, message: sourceCommit.message, }; @@ -49,19 +49,13 @@ export function getMockSourceCommit({ } return { - repository: { - name: 'kibana', - owner: { login: 'elastic' }, - }, - committedDate: sourceCommit.commitedDate ?? '2021-12-22T00:00:00Z', - oid: sourceCommit.sha ?? defaultSourceCommitSha, - message: sourceCommit.message, + ...baseMockCommit, associatedPullRequests: { edges: [ { node: { - sourceMergeCommit: { - oid: sourceCommit.sha ?? defaultSourceCommitSha, + mergeCommit: { + sha: sourceCommit.sha ?? defaultSourceCommitSha, message: sourceCommit.message, }, url: `https://github.com/elastic/kibana/pull/${sourcePullRequest.number}`, @@ -91,7 +85,7 @@ export function getMockSourceCommit({ timelineItem.state === 'MERGED' ? { message: timelineItem.commitMessages[0], - oid: 'target-merge-commit-sha', + sha: 'target-merge-commit-sha', } : null, @@ -105,7 +99,7 @@ export function getMockSourceCommit({ edges: timelineItem.commitMessages.map((message) => ({ node: { targetCommit: { - oid: 'abc', + sha: 'abc', message: message, }, }, diff --git a/src/services/sourceCommit/parseSourceCommit.test.ts b/src/services/sourceCommit/parseSourceCommit.test.ts index 1833f7b3..4afacd67 100644 --- a/src/services/sourceCommit/parseSourceCommit.test.ts +++ b/src/services/sourceCommit/parseSourceCommit.test.ts @@ -1,6 +1,6 @@ import { ValidConfigOptions } from '../../options/options'; import { getMockSourceCommit } from './getMockSourceCommit'; -import { parseSourceCommit } from './parseSourceCommit'; +import { Commit, parseSourceCommit } from './parseSourceCommit'; describe('parseSourceCommit', () => { describe('pullNumber', () => { @@ -15,21 +15,7 @@ describe('parseSourceCommit', () => { options: {} as unknown as ValidConfigOptions, }); - expect(commit.pullNumber).toBe(55); - }); - - it('extracts `pullNumber` from commit message if it doesnt have any associated PRs', () => { - const mockSourceCommit = getMockSourceCommit({ - sourceCommit: { message: 'My commit message (#66)' }, - sourcePullRequest: null, - }); - - const commit = parseSourceCommit({ - sourceCommit: mockSourceCommit, - options: {} as unknown as ValidConfigOptions, - }); - - expect(commit.pullNumber).toBe(66); + expect(commit.sourcePullRequest?.number).toBe(55); }); }); @@ -223,8 +209,21 @@ describe('parseSourceCommit', () => { } as unknown as ValidConfigOptions, }); - expect(commit).toEqual({ - committedDate: '2021-12-22T00:00:00Z', + const expectedCommit: Commit = { + sourceCommit: { + committedDate: '2021-12-22T00:00:00Z', + message: 'My commit message (#1234)', + sha: 'my-sha', + }, + sourcePullRequest: { + number: 1234, + url: 'https://github.com/elastic/kibana/pull/1234', + mergeCommit: { + message: 'My commit message (#1234)', + sha: 'my-sha', + }, + }, + sourceBranch: 'source-branch-from-associated-pull-request', expectedTargetPullRequests: [ { branch: '6.x', @@ -247,11 +246,8 @@ describe('parseSourceCommit', () => { state: 'MISSING', }, ], - originalMessage: 'My commit message (#1234)', - pullNumber: 1234, - pullUrl: 'https://github.com/elastic/kibana/pull/1234', - sha: 'my-sha', - sourceBranch: 'source-branch-from-associated-pull-request', - }); + }; + + expect(commit).toEqual(expectedCommit); }); }); diff --git a/src/services/sourceCommit/parseSourceCommit.ts b/src/services/sourceCommit/parseSourceCommit.ts index ec7e9b90..5a1076e4 100644 --- a/src/services/sourceCommit/parseSourceCommit.ts +++ b/src/services/sourceCommit/parseSourceCommit.ts @@ -1,21 +1,25 @@ import { isEmpty } from 'lodash'; import { ValidConfigOptions } from '../../options/options'; -import { extractPullNumber } from '../github/commitFormatters'; import { ExpectedTargetPullRequest, getExpectedTargetPullRequests, } from './getExpectedTargetPullRequests'; export interface Commit { - // source commit - committedDate: string; + sourceCommit: { + committedDate: string; + message: string; + sha: string; + }; + sourcePullRequest?: { + number: number; + url: string; + mergeCommit: { + message: string; + sha: string; + }; + }; sourceBranch: string; - sha: string; - originalMessage: string; // TODO: rename to message - pullNumber?: number; - pullUrl?: string; - - // target pull requests expectedTargetPullRequests: ExpectedTargetPullRequest[]; } @@ -28,8 +32,8 @@ export interface SourcePullRequestNode { name: string; }[]; }; - sourceMergeCommit: { - oid: string; + mergeCommit: { + sha: string; message: string; }; timelineItems: { @@ -50,7 +54,7 @@ export interface TimelinePullRequestEdge { number: number; targetMergeCommit: { - oid: string; + sha: string; message: string; } | null; @@ -63,7 +67,7 @@ export interface TimelinePullRequestEdge { commits: { edges: Array<{ - node: { targetCommit: { message: string; oid: string } }; + node: { targetCommit: { message: string; sha: string } }; }>; }; }; @@ -79,7 +83,7 @@ export type SourceCommitWithTargetPullRequest = { name: string; owner: { login: string }; }; - oid: string; + sha: string; message: string; committedDate: string; associatedPullRequests: { @@ -102,12 +106,6 @@ export function parseSourceCommit({ sourceCommit.associatedPullRequests.edges?.[0]?.node; // use info from associated pull request if available. Fall back to commit info - const commitMessage = - sourcePullRequest?.sourceMergeCommit.message ?? sourceCommit.message; - const commitSha = - sourcePullRequest?.sourceMergeCommit.oid ?? sourceCommit.oid; - const pullNumber = - sourcePullRequest?.number ?? extractPullNumber(commitMessage); const sourceBranch = sourcePullRequest?.baseRefName ?? options.sourceBranch; const branchLabelMapping = getBranchLabelMappingForCommit( @@ -122,12 +120,22 @@ export function parseSourceCommit({ ); return { - committedDate: sourceCommit.committedDate, + sourceCommit: { + committedDate: sourceCommit.committedDate, + message: sourceCommit.message, + sha: sourceCommit.sha, + }, + sourcePullRequest: sourcePullRequest + ? { + number: sourcePullRequest.number, + url: sourcePullRequest.url, + mergeCommit: { + message: sourcePullRequest.mergeCommit.message, + sha: sourcePullRequest.mergeCommit.sha, + }, + } + : undefined, sourceBranch, - sha: commitSha, - originalMessage: commitMessage, - pullNumber, - pullUrl: sourcePullRequest?.url, expectedTargetPullRequests, }; } @@ -142,7 +150,7 @@ export const sourceCommitWithTargetPullRequestFragment = { login } } - oid + sha: oid message committedDate @@ -160,8 +168,8 @@ export const sourceCommitWithTargetPullRequestFragment = { baseRefName # source merge commit (the commit that actually went into the source branch) - sourceMergeCommit: mergeCommit { - oid + mergeCommit { + sha: oid message } @@ -177,7 +185,7 @@ export const sourceCommitWithTargetPullRequestFragment = { ... on PullRequest { # target merge commit: the backport commit that was merged into the target branch targetMergeCommit: mergeCommit { - oid + sha: oid message } repository { @@ -196,7 +204,7 @@ export const sourceCommitWithTargetPullRequestFragment = { node { targetCommit: commit { message - oid + sha: oid } } } diff --git a/src/test/backport-e2e.mutation.test.ts b/src/test/backport-e2e.mutation.test.ts index b7740a01..782bdf1d 100644 --- a/src/test/backport-e2e.mutation.test.ts +++ b/src/test/backport-e2e.mutation.test.ts @@ -16,7 +16,7 @@ const sandboxPath = getSandboxPath({ filename: __filename }); const REPO_OWNER = 'backport-org'; const REPO_NAME = 'integration-test'; const BRANCH_WITH_ONE_COMMIT = 'backport/7.x/commit-5bf29b7d'; -const BRANCH_WITH_TWO_COMMITS = 'backport/7.x/commit-5bf29b7d_pr-2'; +const BRANCH_WITH_TWO_COMMITS = 'backport/7.x/commit-5bf29b7d_commit-59d6ff1c'; const AUTHOR = 'sqren'; describe('backport e2e', () => { @@ -28,7 +28,7 @@ describe('backport e2e', () => { beforeAll(async () => { // set alternative homedir jest.spyOn(os, 'homedir').mockReturnValue(`${sandboxPath}/homedir`); - accessToken = await getDevAccessToken(); + accessToken = getDevAccessToken(); mockConfigFiles({ globalConfig: {}, @@ -83,10 +83,10 @@ describe('backport e2e', () => { "base": "7.x", "body": "# Backport - This is an automatic backport to \`7.x\` of: + This will backport the following commits from \`master\` to \`7.x\`: - Add ❤️ emoji (5bf29b7d) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", @@ -162,15 +162,15 @@ describe('backport e2e', () => { "base": "7.x", "body": "# Backport - This is an automatic backport to \`7.x\` of: + This will backport the following commits from \`master\` to \`7.x\`: - Add ❤️ emoji (5bf29b7d) - - #2 + - Add family emoji (#2) (59d6ff1c) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", - "head": "sqren:backport/7.x/commit-5bf29b7d_pr-2", + "head": "sqren:backport/7.x/commit-5bf29b7d_commit-59d6ff1c", "title": "[7.x] Add ❤️ emoji | Add family emoji (#2)", }, ] @@ -247,10 +247,10 @@ describe('backport e2e', () => { "base": "7.x", "body": "# Backport - This is an automatic backport to \`7.x\` of: + This will backport the following commits from \`master\` to \`7.x\`: - Add ❤️ emoji (5bf29b7d) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", @@ -368,26 +368,45 @@ async function deleteBranch({ } async function resetState(accessToken: string) { - await deleteBranch({ + const ownerBranches = await getBranches({ accessToken, repoOwner: REPO_OWNER, repoName: REPO_NAME, - branchName: BRANCH_WITH_ONE_COMMIT, }); - await deleteBranch({ + // delete all branches except master and 7.x + await Promise.all( + ownerBranches + .filter((b) => b.name !== 'master' && b.name !== '7.x') + .map((b) => { + return deleteBranch({ + accessToken, + repoOwner: REPO_OWNER, + repoName: REPO_NAME, + branchName: b.name, + }); + }) + ); + + const forkBranches = await getBranches({ accessToken, repoOwner: AUTHOR, repoName: REPO_NAME, - branchName: BRANCH_WITH_ONE_COMMIT, }); - await deleteBranch({ - accessToken, - repoOwner: AUTHOR, - repoName: REPO_NAME, - branchName: BRANCH_WITH_TWO_COMMITS, - }); + // delete all branches except master and 7.x + await Promise.all( + forkBranches + .filter((b) => b.name !== 'master' && b.name !== '7.x') + .map((b) => { + return deleteBranch({ + accessToken, + repoOwner: AUTHOR, + repoName: REPO_NAME, + branchName: b.name, + }); + }) + ); await resetSandbox(sandboxPath); } diff --git a/src/test/handleUnbackportedPullRequests.private.test.ts b/src/test/handleUnbackportedPullRequests.private.test.ts index 869d7ebb..888c0dae 100644 --- a/src/test/handleUnbackportedPullRequests.private.test.ts +++ b/src/test/handleUnbackportedPullRequests.private.test.ts @@ -1,4 +1,4 @@ -import { getCommits, backportRun } from '../entrypoint.module'; +import { getCommits, backportRun, Commit } from '../entrypoint.module'; import { exec } from '../services/child-process-promisified'; import { getDevAccessToken } from './private/getDevAccessToken'; import { getSandboxPath, resetSandbox } from './sandbox'; @@ -8,7 +8,7 @@ jest.setTimeout(15000); describe('Handle unbackported pull requests', () => { it('shows missing backports for PR number 8', async () => { - const accessToken = await getDevAccessToken(); + const accessToken = getDevAccessToken(); const commits = await getCommits({ accessToken: accessToken, repoOwner: 'backport-org', @@ -16,19 +16,29 @@ describe('Handle unbackported pull requests', () => { pullNumber: 8, }); - expect(commits[0]).toEqual({ - committedDate: '2021-12-16T00:03:34Z', - expectedTargetPullRequests: [{ branch: '7.x', state: 'MISSING' }], - originalMessage: 'Change Barca to Braithwaite (#8)', - pullNumber: 8, - pullUrl: 'https://github.com/backport-org/repo-with-conflicts/pull/8', - sha: '343402a748be2375325b2730fa979bcea5b96ba1', + const expectedCommit: Commit = { + sourceCommit: { + committedDate: '2021-12-16T00:03:34Z', + message: 'Change Barca to Braithwaite (#8)', + sha: '343402a748be2375325b2730fa979bcea5b96ba1', + }, + sourcePullRequest: { + number: 8, + url: 'https://github.com/backport-org/repo-with-conflicts/pull/8', + mergeCommit: { + message: 'Change Barca to Braithwaite (#8)', + sha: '343402a748be2375325b2730fa979bcea5b96ba1', + }, + }, sourceBranch: 'main', - }); + expectedTargetPullRequests: [{ branch: '7.x', state: 'MISSING' }], + }; + + expect(commits[0]).toEqual(expectedCommit); }); it('shows that backport failed because PR number 8 was not backported', async () => { - const accessToken = await getDevAccessToken(); + const accessToken = getDevAccessToken(); const sandboxPath = getSandboxPath({ filename: __filename }); await resetSandbox(sandboxPath); await exec('git init', { cwd: sandboxPath }); @@ -44,10 +54,10 @@ describe('Handle unbackported pull requests', () => { publishStatusComment: false, }); - expect( + const commit: Commit = //@ts-expect-error - result.results[0].error.errorContext?.commitsWithoutBackports[0].commit - .pullNumber - ).toBe(8); + result.results[0].error.errorContext?.commitsWithoutBackports[0].commit; + + expect(commit.sourcePullRequest?.number).toBe(8); }); }); diff --git a/src/test/private/getDevAccessToken.ts b/src/test/private/getDevAccessToken.ts index 36484cd1..31bc02a8 100644 --- a/src/test/private/getDevAccessToken.ts +++ b/src/test/private/getDevAccessToken.ts @@ -1,26 +1,12 @@ -import { readFile } from 'fs/promises'; -import { resolve } from 'path'; +import 'dotenv/config'; -// get global config: either from .backport/config.json or via env variables -export async function getDevAccessToken(): Promise { - const accessToken = process.env.accessToken; - - // get accessToken from env vars - if (accessToken) { - return accessToken; - } - - // get credentials from config file - const accessTokenFile = resolve('./src/test/private/accessToken.txt'); - try { - const accessToken = await readFile(accessTokenFile, { - encoding: 'utf-8', - }); - - return accessToken.trim(); - } catch (e) { +export function getDevAccessToken(): string { + const accessToken = process.env.ACCESS_TOKEN; + if (!accessToken) { throw new Error( - `Missing accessToken in "${accessTokenFile}":\n${e.message}` + 'Please create ".env" file containing: `ACCESS_TOKEN="ghp_very_secret"`' ); } + + return accessToken; } diff --git a/src/test/setupFiles/automatic-mocks.ts b/src/test/setupFiles/automatic-mocks.ts index cf4686a4..80fbea4f 100644 --- a/src/test/setupFiles/automatic-mocks.ts +++ b/src/test/setupFiles/automatic-mocks.ts @@ -14,7 +14,11 @@ jest.mock('find-up', () => { // @ts-expect-error // eslint-disable-next-line no-import-assign -packageVersionModule.PACKAGE_VERSION = '1.2.3'; +packageVersionModule.UNMOCKED_PACKAGE_VERSION = + packageVersionModule.PACKAGE_VERSION; +// @ts-expect-error +// eslint-disable-next-line no-import-assign +packageVersionModule.PACKAGE_VERSION = '1.2.3-mocked'; jest.mock('make-dir', () => { return jest.fn(() => Promise.resolve('/some/path')); diff --git a/src/ui/cherrypickAndCreateTargetPullRequest.test.ts b/src/ui/cherrypickAndCreateTargetPullRequest.test.ts index cd0c0edb..36b0c685 100644 --- a/src/ui/cherrypickAndCreateTargetPullRequest.test.ts +++ b/src/ui/cherrypickAndCreateTargetPullRequest.test.ts @@ -64,19 +64,37 @@ describe('cherrypickAndCreateTargetPullRequest', () => { const commits: Commit[] = [ { - committedDate: 'fff', sourceBranch: '7.x', - sha: 'mySha', - originalMessage: 'My original commit message (#1000)', - pullNumber: 1000, + sourceCommit: { + committedDate: 'fff', + sha: 'mySha', + message: 'My original commit message (#1000)', + }, + sourcePullRequest: { + url: 'foo', + number: 1000, + mergeCommit: { + sha: 'mySha', + message: 'My original commit message (#1000)', + }, + }, expectedTargetPullRequests: [], }, { - committedDate: 'ggg', sourceBranch: '7.x', - sha: 'mySha2', - originalMessage: 'My other commit message (#2000)', - pullNumber: 2000, + sourceCommit: { + committedDate: 'ggg', + sha: 'mySha2', + message: 'My other commit message (#2000)', + }, + sourcePullRequest: { + url: 'foo', + number: 2000, + mergeCommit: { + sha: 'mySha2', + message: 'My other commit message (#2000)', + }, + }, expectedTargetPullRequests: [], }, ]; @@ -104,11 +122,11 @@ describe('cherrypickAndCreateTargetPullRequest', () => { "base": "6.x", "body": "# Backport - This is an automatic backport to \`6.x\` of: - - #1000 - - #2000 + This will backport the following commits from \`7.x\` to \`6.x\`: + - [My original commit message (#1000)](foo) + - [My other commit message (#2000)](foo) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", @@ -172,12 +190,14 @@ describe('cherrypickAndCreateTargetPullRequest', () => { author: 'sqren', } as ValidConfigOptions; - const commits = [ + const commits: Commit[] = [ { - committedDate: 'hhh', + sourceCommit: { + committedDate: 'hhh', + sha: 'mySha', + message: 'My original commit message', + }, sourceBranch: '7.x', - sha: 'mySha', - originalMessage: 'My original commit message', expectedTargetPullRequests: [], }, ]; @@ -204,10 +224,10 @@ describe('cherrypickAndCreateTargetPullRequest', () => { "base": "6.x", "body": "# Backport - This is an automatic backport to \`6.x\` of: + This will backport the following commits from \`7.x\` to \`6.x\`: - My original commit message (mySha) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", @@ -267,10 +287,12 @@ describe('cherrypickAndCreateTargetPullRequest', () => { options, commits: [ { - committedDate: '2021-08-18T16:11:38Z', + sourceCommit: { + committedDate: '2021-08-18T16:11:38Z', + sha: 'mySha', + message: 'My original commit message', + }, sourceBranch: '7.x', - sha: 'mySha', - originalMessage: 'My original commit message', expectedTargetPullRequests: [], }, ], @@ -288,10 +310,10 @@ describe('cherrypickAndCreateTargetPullRequest', () => { "base": "6.x", "body": "# Backport - This is an automatic backport to \`6.x\` of: + This will backport the following commits from \`7.x\` to \`6.x\`: - My original commit message (mySha) - + ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport)", diff --git a/src/ui/cherrypickAndCreateTargetPullRequest.ts b/src/ui/cherrypickAndCreateTargetPullRequest.ts index deb695c3..19c71414 100644 --- a/src/ui/cherrypickAndCreateTargetPullRequest.ts +++ b/src/ui/cherrypickAndCreateTargetPullRequest.ts @@ -108,10 +108,10 @@ export async function cherrypickAndCreateTargetPullRequest({ // add labels to source pull requests if (options.sourcePRLabels.length > 0) { const promises = commits.map((commit) => { - if (commit.pullNumber) { + if (commit.sourcePullRequest) { return addLabelsToPullRequest( options, - commit.pullNumber, + commit.sourcePullRequest.number, options.sourcePRLabels ); } @@ -165,9 +165,9 @@ async function backportViaFilesystem({ function getBackportBranchName(targetBranch: string, commits: Commit[]) { const refValues = commits .map((commit) => - commit.pullNumber - ? `pr-${commit.pullNumber}` - : `commit-${getShortSha(commit.sha)}` + commit.sourcePullRequest + ? `pr-${commit.sourcePullRequest.number}` + : `commit-${getShortSha(commit.sourceCommit.sha)}` ) .join('_') .slice(0, 200); @@ -180,7 +180,7 @@ async function waitForCherrypick( targetBranch: string ) { const spinnerText = `Cherry-picking: ${chalk.greenBright( - getFirstLine(commit.originalMessage) + getFirstLine(commit.sourceCommit.message) )}`; const mergedTargetPullRequest = commit.expectedTargetPullRequests.find( @@ -197,7 +197,7 @@ async function waitForCherrypick( await fetchBranch(options, commit.sourceBranch); ({ conflictingFiles, unstagedFiles, needsResolving } = await cherrypick( options, - commit.sha, + commit.sourceCommit.sha, mergedTargetPullRequest )); diff --git a/src/ui/getCommits.ts b/src/ui/getCommits.ts index bf082722..7c8ff8cb 100644 --- a/src/ui/getCommits.ts +++ b/src/ui/getCommits.ts @@ -24,7 +24,7 @@ export async function getCommits(options: ValidConfigOptions) { spinner.text = `Loading commit "${getShortSha(options.sha)}"`; const commit = await fetchCommitBySha({ ...options, sha: options.sha }); spinner.stopAndPersist( - getOraPersistsOption('Select commit', commit.originalMessage) + getOraPersistsOption('Select commit', commit.sourceCommit.message) ); return [commit]; } @@ -40,7 +40,7 @@ export async function getCommits(options: ValidConfigOptions) { spinner.stopAndPersist( getOraPersistsOption( 'Select pull request', - getFirstLine(commit.originalMessage) + getFirstLine(commit.sourceCommit.message) ) ); diff --git a/src/ui/getCommitsWithoutBackports.test.ts b/src/ui/getCommitsWithoutBackports.test.ts index df97f04c..86415350 100644 --- a/src/ui/getCommitsWithoutBackports.test.ts +++ b/src/ui/getCommitsWithoutBackports.test.ts @@ -21,12 +21,21 @@ describe('getCommitsWithoutBackports', () => { .spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor') .mockResolvedValueOnce([ { - committedDate: '10', + sourceCommit: { + committedDate: '10', + message: 'First commit (#1)', + sha: 'xyz', + }, + sourcePullRequest: { + url: 'https://www.github.com/foo/bar/pull/123', + number: 123, + mergeCommit: { + message: 'First commit (#1)', + sha: 'xyz', + }, + }, expectedTargetPullRequests, - originalMessage: 'First commit (#1)', - sha: 'xyz', sourceBranch: 'main', - pullUrl: 'https://www.github.com/foo/bar/pull/123', }, ]); @@ -36,10 +45,12 @@ describe('getCommitsWithoutBackports', () => { return getCommitsWithoutBackports({ options: {} as ValidConfigOptions, commit: { - committedDate: '100', + sourceCommit: { + committedDate: '100', + message: 'Second commit (#2)', + sha: 'abc', + }, expectedTargetPullRequests: [], - originalMessage: 'Second commit (#2)', - sha: 'abc', sourceBranch: 'main', }, targetBranch: '7.x', @@ -123,7 +134,20 @@ describe('getCommitsWithoutBackports', () => { .spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor') .mockResolvedValueOnce([ { - committedDate: offendingCommitDate, + sourceCommit: { + committedDate: offendingCommitDate, + message: 'First commit (#1)', + sha: 'xyz', + }, + sourcePullRequest: { + number: 123, + url: 'https://www.github.com/foo/bar/pull/123', + mergeCommit: { + message: 'First commit (#1)', + sha: 'xyz', + }, + }, + sourceBranch: 'main', expectedTargetPullRequests: [ { state: 'OPEN', @@ -132,11 +156,6 @@ describe('getCommitsWithoutBackports', () => { url: 'https://www.github.com/foo/bar/pull/456', }, ], - originalMessage: 'First commit (#1)', - sha: 'xyz', - sourceBranch: 'main', - pullNumber: 123, - pullUrl: 'https://www.github.com/foo/bar/pull/123', }, ]); @@ -146,11 +165,21 @@ describe('getCommitsWithoutBackports', () => { return getCommitsWithoutBackports({ options: {} as ValidConfigOptions, commit: { - committedDate: currentCommitDate, - expectedTargetPullRequests: [], - originalMessage: 'Second commit (#2)', - sha: 'abc', + sourceCommit: { + committedDate: currentCommitDate, + message: 'Second commit (#2)', + sha: 'abc', + }, + sourcePullRequest: { + number: 123, + url: 'https://www.github.com/foo/bar/pull/123', + mergeCommit: { + message: 'Second commit (#2)', + sha: 'abc', + }, + }, sourceBranch: 'main', + expectedTargetPullRequests: [], }, targetBranch: '7.x', conflictingFiles: ['/foo/bar/baz.ts'], @@ -189,9 +218,20 @@ describe('getCommitsWithoutBackports', () => { .spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor') .mockResolvedValueOnce([ { - pullUrl: 'https://www.github.com/foo/bar/pull/123', - pullNumber: 123, - committedDate: '10', + sourceCommit: { + committedDate: '10', + message: 'First commit (#1)', + sha: 'xyz', + }, + sourcePullRequest: { + number: 123, + url: 'https://www.github.com/foo/bar/pull/123', + mergeCommit: { + message: 'First commit (#1)', + sha: 'xyz', + }, + }, + sourceBranch: 'main', expectedTargetPullRequests: [ { branch: offendingCommitTargetBranch, @@ -200,9 +240,6 @@ describe('getCommitsWithoutBackports', () => { number: 456, }, ], - originalMessage: 'First commit (#1)', - sha: 'xyz', - sourceBranch: 'main', }, ]); @@ -214,12 +251,20 @@ describe('getCommitsWithoutBackports', () => { // commit that is being backported commit: { - pullUrl: 'https://www.github.com/foo/bar/pull/123', - pullNumber: 123, - committedDate: '100', + sourceCommit: { + committedDate: '100', + message: 'Second commit (#2)', + sha: 'abc', + }, + sourcePullRequest: { + url: 'https://www.github.com/foo/bar/pull/123', + number: 123, + mergeCommit: { + message: 'Second commit (#2)', + sha: 'abc', + }, + }, expectedTargetPullRequests: [], - originalMessage: 'Second commit (#2)', - sha: 'abc', sourceBranch: 'main', }, targetBranch: currentCommitTargetBranch, @@ -252,13 +297,12 @@ describe('getCommitsWithoutBackports', () => { .spyOn(fetchCommitsByAuthorModule, 'fetchCommitsByAuthor') .mockResolvedValueOnce([ { - // intentionally left out: - // pullNumber: 33, - // pullUrl: 'https://www.github.com/foo/bar/pull/123', - committedDate: '10', + sourceCommit: { + committedDate: '10', + sha: 'xyz', + message: 'First commit (#1)', + }, expectedTargetPullRequests: [], - originalMessage: 'First commit (#1)', - sha: 'xyz', sourceBranch: 'main', }, ]); @@ -269,12 +313,20 @@ describe('getCommitsWithoutBackports', () => { const commitsWithoutBackports = await getCommitsWithoutBackports({ options: {} as ValidConfigOptions, commit: { - pullUrl: 'https://www.github.com/foo/bar/pull/123', - pullNumber: 123, - committedDate: '100', + sourceCommit: { + committedDate: '100', + message: 'Second commit (#2)', + sha: 'abc', + }, + sourcePullRequest: { + url: 'https://www.github.com/foo/bar/pull/123', + number: 123, + mergeCommit: { + message: 'Second commit (#2)', + sha: 'abc', + }, + }, expectedTargetPullRequests: [], - originalMessage: 'Second commit (#2)', - sha: 'abc', sourceBranch: 'main', }, targetBranch: '7.x', diff --git a/src/ui/getCommitsWithoutBackports.ts b/src/ui/getCommitsWithoutBackports.ts index 3d68fc51..9c60bd67 100644 --- a/src/ui/getCommitsWithoutBackports.ts +++ b/src/ui/getCommitsWithoutBackports.ts @@ -28,7 +28,7 @@ export async function getCommitsWithoutBackports({ ...options, author: null, // retrieve commits across all authors dateSince: null, - dateUntil: commit.committedDate, + dateUntil: commit.sourceCommit.committedDate, commitPaths: conflictingFiles, }); @@ -36,17 +36,17 @@ export async function getCommitsWithoutBackports({ commitsInConflictingPaths .filter((c) => { // exclude the commit we are currently trying to backport - if (c.sha === commit.sha) { + if (c.sourceCommit.sha === commit.sourceCommit.sha) { return false; } // exclude commits that are newer than the commit we are trying to backport - if (c.committedDate > commit.committedDate) { + if (c.sourceCommit.committedDate > commit.sourceCommit.committedDate) { return false; } // only consider commits that have an associated pull request - if (!c.pullUrl) { + if (!c.sourcePullRequest?.url) { return false; } @@ -83,12 +83,12 @@ export async function getCommitsWithoutBackports({ ); const formatted = pendingBackportPr - ? ` - ${getFirstLine(c.originalMessage)} ${chalk.gray( + ? ` - ${getFirstLine(c.sourceCommit.message)} ${chalk.gray( '(backport pending)' )}\n ${pendingBackportPr.url}` - : ` - ${getFirstLine(c.originalMessage)} ${chalk.red( + : ` - ${getFirstLine(c.sourceCommit.message)} ${chalk.red( '(backport missing)' - )}\n ${c.pullUrl}`; + )}\n ${c.sourcePullRequest?.url}`; return { formatted, commit: c }; }); diff --git a/src/ui/getTargetBranches.test.ts b/src/ui/getTargetBranches.test.ts index 449543c5..214ba4ab 100644 --- a/src/ui/getTargetBranches.test.ts +++ b/src/ui/getTargetBranches.test.ts @@ -28,11 +28,20 @@ describe('getTargetBranches', () => { const commits: Commit[] = [ { - committedDate: 'aaa', - originalMessage: 'hey', - sha: 'abcd', + sourceCommit: { + committedDate: 'aaa', + message: 'hey', + sha: 'abcd', + }, + sourcePullRequest: { + url: 'foo', + number: 1337, + mergeCommit: { + message: 'hey', + sha: 'abcd', + }, + }, sourceBranch: '7.x', - pullNumber: 1337, expectedTargetPullRequests: [], }, ]; @@ -128,11 +137,20 @@ describe('getTargetBranches', () => { const commits: Commit[] = [ { - committedDate: 'bbb', + sourceCommit: { + committedDate: 'bbb', + message: '[backport] Bump to 5.1.3 (#62286)', + sha: 'my-sha', + }, + sourcePullRequest: { + url: 'foo', + number: 62286, + mergeCommit: { + message: '[backport] Bump to 5.1.3 (#62286)', + sha: 'my-sha', + }, + }, sourceBranch: 'master', - sha: 'my-sha', - originalMessage: '[backport] Bump to 5.1.3 (#62286)', - pullNumber: 62286, expectedTargetPullRequests: [{ branch: '7.x', state: 'MISSING' }], }, ]; diff --git a/src/utils/packageVersion.ts b/src/utils/packageVersion.ts index eb5bcc95..25b4a201 100644 --- a/src/utils/packageVersion.ts +++ b/src/utils/packageVersion.ts @@ -1 +1 @@ -export const PACKAGE_VERSION = '6.2.1'; +export const PACKAGE_VERSION = '6.3.0-beta-10'; diff --git a/yarn.lock b/yarn.lock index 9ae13462..86357508 100644 --- a/yarn.lock +++ b/yarn.lock @@ -684,158 +684,158 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.4.6.tgz#0742e6787f682b22bdad56f9db2a8a77f6a86107" - integrity sha512-jauXyacQD33n47A44KrlOVeiXHEXDqapSdfb9kTekOchH/Pd18kBIO1+xxJQRLuG+LUuljFCwTG92ra4NW7SpA== +"@jest/console@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" + integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^27.4.6" - jest-util "^27.4.2" + jest-message-util "^27.5.1" + jest-util "^27.5.1" slash "^3.0.0" -"@jest/core@^27.4.7": - version "27.4.7" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.4.7.tgz#84eabdf42a25f1fa138272ed229bcf0a1b5e6913" - integrity sha512-n181PurSJkVMS+kClIFSX/LLvw9ExSb+4IMtD6YnfxZVerw9ANYtW0bPrm0MJu2pfe9SY9FJ9FtQ+MdZkrZwjg== +"@jest/core@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" + integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== dependencies: - "@jest/console" "^27.4.6" - "@jest/reporters" "^27.4.6" - "@jest/test-result" "^27.4.6" - "@jest/transform" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/console" "^27.5.1" + "@jest/reporters" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.8.1" exit "^0.1.2" - graceful-fs "^4.2.4" - jest-changed-files "^27.4.2" - jest-config "^27.4.7" - jest-haste-map "^27.4.6" - jest-message-util "^27.4.6" - jest-regex-util "^27.4.0" - jest-resolve "^27.4.6" - jest-resolve-dependencies "^27.4.6" - jest-runner "^27.4.6" - jest-runtime "^27.4.6" - jest-snapshot "^27.4.6" - jest-util "^27.4.2" - jest-validate "^27.4.6" - jest-watcher "^27.4.6" + graceful-fs "^4.2.9" + jest-changed-files "^27.5.1" + jest-config "^27.5.1" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-resolve-dependencies "^27.5.1" + jest-runner "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + jest-watcher "^27.5.1" micromatch "^4.0.4" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.4.6.tgz#1e92885d64f48c8454df35ed9779fbcf31c56d8b" - integrity sha512-E6t+RXPfATEEGVidr84WngLNWZ8ffCPky8RqqRK6u1Bn0LK92INe0MDttyPl/JOzaq92BmDzOeuqk09TvM22Sg== +"@jest/environment@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" + integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== dependencies: - "@jest/fake-timers" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" - jest-mock "^27.4.6" + jest-mock "^27.5.1" -"@jest/fake-timers@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.4.6.tgz#e026ae1671316dbd04a56945be2fa251204324e8" - integrity sha512-mfaethuYF8scV8ntPpiVGIHQgS0XIALbpY2jt2l7wb/bvq4Q5pDLk4EP4D7SAvYT1QrPOPVZAtbdGAOOyIgs7A== +"@jest/fake-timers@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" + integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" "@sinonjs/fake-timers" "^8.0.1" "@types/node" "*" - jest-message-util "^27.4.6" - jest-mock "^27.4.6" - jest-util "^27.4.2" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-util "^27.5.1" -"@jest/globals@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.4.6.tgz#3f09bed64b0fd7f5f996920258bd4be8f52f060a" - integrity sha512-kAiwMGZ7UxrgPzu8Yv9uvWmXXxsy0GciNejlHvfPIfWkSxChzv6bgTS3YqBkGuHcis+ouMFI2696n2t+XYIeFw== +"@jest/globals@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" + integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== dependencies: - "@jest/environment" "^27.4.6" - "@jest/types" "^27.4.2" - expect "^27.4.6" + "@jest/environment" "^27.5.1" + "@jest/types" "^27.5.1" + expect "^27.5.1" -"@jest/reporters@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.4.6.tgz#b53dec3a93baf9b00826abf95b932de919d6d8dd" - integrity sha512-+Zo9gV81R14+PSq4wzee4GC2mhAN9i9a7qgJWL90Gpx7fHYkWpTBvwWNZUXvJByYR9tAVBdc8VxDWqfJyIUrIQ== +"@jest/reporters@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" + integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.4.6" - "@jest/test-result" "^27.4.6" - "@jest/transform" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/console" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.2" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" istanbul-lib-coverage "^3.0.0" istanbul-lib-instrument "^5.1.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-haste-map "^27.4.6" - jest-resolve "^27.4.6" - jest-util "^27.4.2" - jest-worker "^27.4.6" + jest-haste-map "^27.5.1" + jest-resolve "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" -"@jest/source-map@^27.4.0": - version "27.4.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.4.0.tgz#2f0385d0d884fb3e2554e8f71f8fa957af9a74b6" - integrity sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ== +"@jest/source-map@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" + integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== dependencies: callsites "^3.0.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" source-map "^0.6.0" -"@jest/test-result@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.4.6.tgz#b3df94c3d899c040f602cea296979844f61bdf69" - integrity sha512-fi9IGj3fkOrlMmhQqa/t9xum8jaJOOAi/lZlm6JXSc55rJMXKHxNDN1oCP39B0/DhNOa2OMupF9BcKZnNtXMOQ== +"@jest/test-result@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" + integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== dependencies: - "@jest/console" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/console" "^27.5.1" + "@jest/types" "^27.5.1" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.4.6.tgz#447339b8a3d7b5436f50934df30854e442a9d904" - integrity sha512-3GL+nsf6E1PsyNsJuvPyIz+DwFuCtBdtvPpm/LMXVkBJbdFvQYCDpccYT56qq5BGniXWlE81n2qk1sdXfZebnw== +"@jest/test-sequencer@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" + integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== dependencies: - "@jest/test-result" "^27.4.6" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.6" - jest-runtime "^27.4.6" + "@jest/test-result" "^27.5.1" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-runtime "^27.5.1" -"@jest/transform@^27.4.6": - version "27.4.6" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.4.6.tgz#153621940b1ed500305eacdb31105d415dc30231" - integrity sha512-9MsufmJC8t5JTpWEQJ0OcOOAXaH5ioaIX6uHVBLBMoCZPfKKQF+EqP8kACAvCZ0Y1h2Zr3uOccg8re+Dr5jxyw== +"@jest/transform@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" + integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.6" - jest-regex-util "^27.4.0" - jest-util "^27.4.2" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-regex-util "^27.5.1" + jest-util "^27.5.1" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" @@ -853,6 +853,17 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + "@n1ru4l/graphql-live-query@^0.9.0": version "0.9.0" resolved "https://registry.yarnpkg.com/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz#defaebdd31f625bee49e6745934f36312532b2bc" @@ -1189,14 +1200,14 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz#f8c1d59fc37bd6d9d11c97267fdfe722c4777152" - integrity sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q== +"@typescript-eslint/eslint-plugin@^5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.11.0.tgz#3b866371d8d75c70f9b81535e7f7d3aa26527c7a" + integrity sha512-HJh33bgzXe6jGRocOj4FmefD7hRY4itgjzOrSs3JPrTNXsX7j5+nQPciAUj/1nZtwo2kAc3C75jZO+T23gzSGw== dependencies: - "@typescript-eslint/scope-manager" "5.10.2" - "@typescript-eslint/type-utils" "5.10.2" - "@typescript-eslint/utils" "5.10.2" + "@typescript-eslint/scope-manager" "5.11.0" + "@typescript-eslint/type-utils" "5.11.0" + "@typescript-eslint/utils" "5.11.0" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -1204,14 +1215,14 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.2.tgz#b6076d27cc5499ce3f2c625f5ccde946ecb7db9a" - integrity sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg== +"@typescript-eslint/parser@^5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.11.0.tgz#b4fcaf65513f9b34bdcbffdda055724a5efb7e04" + integrity sha512-x0DCjetHZYBRovJdr3U0zG9OOdNXUaFLJ82ehr1AlkArljJuwEsgnud+Q7umlGDFLFrs8tU8ybQDFocp/eX8mQ== dependencies: - "@typescript-eslint/scope-manager" "5.10.2" - "@typescript-eslint/types" "5.10.2" - "@typescript-eslint/typescript-estree" "5.10.2" + "@typescript-eslint/scope-manager" "5.11.0" + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/typescript-estree" "5.11.0" debug "^4.3.2" "@typescript-eslint/scope-manager@5.10.2": @@ -1222,12 +1233,20 @@ "@typescript-eslint/types" "5.10.2" "@typescript-eslint/visitor-keys" "5.10.2" -"@typescript-eslint/type-utils@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz#ad5acdf98a7d2ab030bea81f17da457519101ceb" - integrity sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw== +"@typescript-eslint/scope-manager@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz#f5aef83ff253f457ecbee5f46f762298f0101e4b" + integrity sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA== + dependencies: + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/visitor-keys" "5.11.0" + +"@typescript-eslint/type-utils@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.11.0.tgz#58be0ba73d1f6ef8983d79f7f0bc2209b253fefe" + integrity sha512-wDqdsYO6ofLaD4DsGZ0jGwxp4HrzD2YKulpEZXmgN3xo4BHJwf7kq49JTRpV0Gx6bxkSUmc9s0EIK1xPbFFpIA== dependencies: - "@typescript-eslint/utils" "5.10.2" + "@typescript-eslint/utils" "5.11.0" debug "^4.3.2" tsutils "^3.21.0" @@ -1236,6 +1255,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.2.tgz#604d15d795c4601fffba6ecb4587ff9fdec68ce8" integrity sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w== +"@typescript-eslint/types@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.11.0.tgz#ba345818a2540fdf2755c804dc2158517ab61188" + integrity sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ== + "@typescript-eslint/typescript-estree@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz#810906056cd3ddcb35aa333fdbbef3713b0fe4a7" @@ -1249,7 +1273,32 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.10.2", "@typescript-eslint/utils@^5.10.0": +"@typescript-eslint/typescript-estree@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz#53f9e09b88368191e52020af77c312a4777ffa43" + integrity sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg== + dependencies: + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/visitor-keys" "5.11.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.11.0.tgz#d91548ef180d74c95d417950336d9260fdbe1dc5" + integrity sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.11.0" + "@typescript-eslint/types" "5.11.0" + "@typescript-eslint/typescript-estree" "5.11.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/utils@^5.10.0": version "5.10.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.2.tgz#1fcd37547c32c648ab11aea7173ec30060ee87a8" integrity sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg== @@ -1269,6 +1318,14 @@ "@typescript-eslint/types" "5.10.2" eslint-visitor-keys "^3.0.0" +"@typescript-eslint/visitor-keys@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.11.0.tgz#888542381f1a2ac745b06d110c83c0b261487ebb" + integrity sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA== + dependencies: + "@typescript-eslint/types" "5.11.0" + eslint-visitor-keys "^3.0.0" + abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -1462,18 +1519,18 @@ axios@^0.25.0: dependencies: follow-redirects "^1.14.7" -babel-jest@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.4.6.tgz#4d024e69e241cdf4f396e453a07100f44f7ce314" - integrity sha512-qZL0JT0HS1L+lOuH+xC2DVASR3nunZi/ozGhpgauJHgmI7f8rudxf6hUjEHympdQ/J64CdKmPkgfJ+A3U6QCrg== +babel-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" + integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== dependencies: - "@jest/transform" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^27.4.0" + babel-preset-jest "^27.5.1" chalk "^4.0.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" slash "^3.0.0" babel-plugin-istanbul@^6.1.1: @@ -1487,10 +1544,10 @@ babel-plugin-istanbul@^6.1.1: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz#d7831fc0f93573788d80dee7e682482da4c730d6" - integrity sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw== +babel-plugin-jest-hoist@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" + integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -1515,12 +1572,12 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz#70d0e676a282ccb200fbabd7f415db5fdf393bca" - integrity sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg== +babel-preset-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" + integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== dependencies: - babel-plugin-jest-hoist "^27.4.0" + babel-plugin-jest-hoist "^27.5.1" babel-preset-current-node-syntax "^1.0.0" backo2@^1.0.2: @@ -1982,6 +2039,11 @@ diff-sequences@^27.4.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -2015,6 +2077,11 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" +dotenv@^16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" + integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== + dset@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.1.tgz#07de5af7a8d03eab337ad1a8ba77fe17bba61a8c" @@ -2159,10 +2226,10 @@ eslint-plugin-import@^2.25.4: resolve "^1.20.0" tsconfig-paths "^3.12.0" -eslint-plugin-jest@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.0.0.tgz#f83a25a23ab90ce5b375b1d44389b8c391be5ce8" - integrity sha512-Fvs0YgJ/nw9FTrnqTuMGVrkozkd07jkQzWm0ajqyHlfcsdkxGfAuv30fgfWHOnHiCr9+1YQ365CcDX7vrNhqQg== +eslint-plugin-jest@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.1.0.tgz#9f6c33e66f3cef3f2832c3a4d2caa21a75792dee" + integrity sha512-vjF6RvcKm4xZSJgCmXb9fXmhzTva+I9jtj9Qv5JeZQTRocU7WT1g3Kx0cZ+00SekPe2DtSWDawHtSj4RaxFhXQ== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -2334,15 +2401,15 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expect@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.4.6.tgz#f335e128b0335b6ceb4fcab67ece7cbd14c942e6" - integrity sha512-1M/0kAALIaj5LaG66sFJTbRsWTADnylly82cu4bspI0nl+pgP4E6Bh/aqdHlTUjul06K7xQnnrAoqfxVU0+/ag== +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== dependencies: - "@jest/types" "^27.4.2" - jest-get-type "^27.4.0" - jest-matcher-utils "^27.4.6" - jest-message-util "^27.4.6" + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" external-editor@^3.0.3: version "3.1.0" @@ -2609,6 +2676,11 @@ graceful-fs@^4.2.4: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + graphql-config@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.1.0.tgz#a3b28d3fb537952ebeb69c75e4430605a10695e3" @@ -3042,85 +3114,87 @@ iterall@^1.2.1: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== -jest-changed-files@^27.4.2: - version "27.4.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.4.2.tgz#da2547ea47c6e6a5f6ed336151bd2075736eb4a5" - integrity sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A== +jest-changed-files@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" + integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" execa "^5.0.0" throat "^6.0.1" -jest-circus@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.4.6.tgz#d3af34c0eb742a967b1919fbb351430727bcea6c" - integrity sha512-UA7AI5HZrW4wRM72Ro80uRR2Fg+7nR0GESbSI/2M+ambbzVuA63mn5T1p3Z/wlhntzGpIG1xx78GP2YIkf6PhQ== +jest-circus@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" + integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== dependencies: - "@jest/environment" "^27.4.6" - "@jest/test-result" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" - expect "^27.4.6" + expect "^27.5.1" is-generator-fn "^2.0.0" - jest-each "^27.4.6" - jest-matcher-utils "^27.4.6" - jest-message-util "^27.4.6" - jest-runtime "^27.4.6" - jest-snapshot "^27.4.6" - jest-util "^27.4.2" - pretty-format "^27.4.6" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^27.4.7: - version "27.4.7" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.4.7.tgz#d00e759e55d77b3bcfea0715f527c394ca314e5a" - integrity sha512-zREYhvjjqe1KsGV15mdnxjThKNDgza1fhDT+iUsXWLCq3sxe9w5xnvyctcYVT5PcdLSjv7Y5dCwTS3FCF1tiuw== +jest-cli@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" + integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== dependencies: - "@jest/core" "^27.4.7" - "@jest/test-result" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/core" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" chalk "^4.0.0" exit "^0.1.2" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^27.4.7" - jest-util "^27.4.2" - jest-validate "^27.4.6" + jest-config "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" prompts "^2.0.1" yargs "^16.2.0" -jest-config@^27.4.7: - version "27.4.7" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.4.7.tgz#4f084b2acbd172c8b43aa4cdffe75d89378d3972" - integrity sha512-xz/o/KJJEedHMrIY9v2ParIoYSrSVY6IVeE4z5Z3i101GoA5XgfbJz+1C8EYPsv7u7f39dS8F9v46BHDhn0vlw== +jest-config@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" + integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== dependencies: "@babel/core" "^7.8.0" - "@jest/test-sequencer" "^27.4.6" - "@jest/types" "^27.4.2" - babel-jest "^27.4.6" + "@jest/test-sequencer" "^27.5.1" + "@jest/types" "^27.5.1" + babel-jest "^27.5.1" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.1" - graceful-fs "^4.2.4" - jest-circus "^27.4.6" - jest-environment-jsdom "^27.4.6" - jest-environment-node "^27.4.6" - jest-get-type "^27.4.0" - jest-jasmine2 "^27.4.6" - jest-regex-util "^27.4.0" - jest-resolve "^27.4.6" - jest-runner "^27.4.6" - jest-util "^27.4.2" - jest-validate "^27.4.6" + graceful-fs "^4.2.9" + jest-circus "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-get-type "^27.5.1" + jest-jasmine2 "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runner "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" micromatch "^4.0.4" - pretty-format "^27.4.6" + parse-json "^5.2.0" + pretty-format "^27.5.1" slash "^3.0.0" + strip-json-comments "^3.1.1" jest-diff@^27.0.0: version "27.4.2" @@ -3132,146 +3206,151 @@ jest-diff@^27.0.0: jest-get-type "^27.4.0" pretty-format "^27.4.2" -jest-diff@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d" - integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w== +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== dependencies: chalk "^4.0.0" - diff-sequences "^27.4.0" - jest-get-type "^27.4.0" - pretty-format "^27.4.6" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-docblock@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.4.0.tgz#06c78035ca93cbbb84faf8fce64deae79a59f69f" - integrity sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg== +jest-docblock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" + integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== dependencies: detect-newline "^3.0.0" -jest-each@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.4.6.tgz#e7e8561be61d8cc6dbf04296688747ab186c40ff" - integrity sha512-n6QDq8y2Hsmn22tRkgAk+z6MCX7MeVlAzxmZDshfS2jLcaBlyhpF3tZSJLR+kXmh23GEvS0ojMR8i6ZeRvpQcA== +jest-each@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" + integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" chalk "^4.0.0" - jest-get-type "^27.4.0" - jest-util "^27.4.2" - pretty-format "^27.4.6" - -jest-environment-jsdom@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.4.6.tgz#c23a394eb445b33621dfae9c09e4c8021dea7b36" - integrity sha512-o3dx5p/kHPbUlRvSNjypEcEtgs6LmvESMzgRFQE6c+Prwl2JLA4RZ7qAnxc5VM8kutsGRTB15jXeeSbJsKN9iA== - dependencies: - "@jest/environment" "^27.4.6" - "@jest/fake-timers" "^27.4.6" - "@jest/types" "^27.4.2" + jest-get-type "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + +jest-environment-jsdom@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" + integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" - jest-mock "^27.4.6" - jest-util "^27.4.2" + jest-mock "^27.5.1" + jest-util "^27.5.1" jsdom "^16.6.0" -jest-environment-node@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.4.6.tgz#ee8cd4ef458a0ef09d087c8cd52ca5856df90242" - integrity sha512-yfHlZ9m+kzTKZV0hVfhVu6GuDxKAYeFHrfulmy7Jxwsq4V7+ZK7f+c0XP/tbVDMQW7E4neG2u147hFkuVz0MlQ== +jest-environment-node@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" + integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== dependencies: - "@jest/environment" "^27.4.6" - "@jest/fake-timers" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" - jest-mock "^27.4.6" - jest-util "^27.4.2" + jest-mock "^27.5.1" + jest-util "^27.5.1" jest-get-type@^27.4.0: version "27.4.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== -jest-haste-map@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.4.6.tgz#c60b5233a34ca0520f325b7e2cc0a0140ad0862a" - integrity sha512-0tNpgxg7BKurZeFkIOvGCkbmOHbLFf4LUQOxrQSMjvrQaQe3l6E8x6jYC1NuWkGo5WDdbr8FEzUxV2+LWNawKQ== +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +jest-haste-map@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" + integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" - graceful-fs "^4.2.4" - jest-regex-util "^27.4.0" - jest-serializer "^27.4.0" - jest-util "^27.4.2" - jest-worker "^27.4.6" + graceful-fs "^4.2.9" + jest-regex-util "^27.5.1" + jest-serializer "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" micromatch "^4.0.4" walker "^1.0.7" optionalDependencies: fsevents "^2.3.2" -jest-jasmine2@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.4.6.tgz#109e8bc036cb455950ae28a018f983f2abe50127" - integrity sha512-uAGNXF644I/whzhsf7/qf74gqy9OuhvJ0XYp8SDecX2ooGeaPnmJMjXjKt0mqh1Rl5dtRGxJgNrHlBQIBfS5Nw== +jest-jasmine2@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" + integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== dependencies: - "@jest/environment" "^27.4.6" - "@jest/source-map" "^27.4.0" - "@jest/test-result" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/environment" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^27.4.6" + expect "^27.5.1" is-generator-fn "^2.0.0" - jest-each "^27.4.6" - jest-matcher-utils "^27.4.6" - jest-message-util "^27.4.6" - jest-runtime "^27.4.6" - jest-snapshot "^27.4.6" - jest-util "^27.4.2" - pretty-format "^27.4.6" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" throat "^6.0.1" -jest-leak-detector@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.4.6.tgz#ed9bc3ce514b4c582637088d9faf58a33bd59bf4" - integrity sha512-kkaGixDf9R7CjHm2pOzfTxZTQQQ2gHTIWKY/JZSiYTc90bZp8kSZnUMS3uLAfwTZwc0tcMRoEX74e14LG1WapA== +jest-leak-detector@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" + integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== dependencies: - jest-get-type "^27.4.0" - pretty-format "^27.4.6" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-matcher-utils@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.6.tgz#53ca7f7b58170638590e946f5363b988775509b8" - integrity sha512-XD4PKT3Wn1LQnRAq7ZsTI0VRuEc9OrCPFiO1XL7bftTGmfNF0DcEwMHRgqiu7NGf8ZoZDREpGrCniDkjt79WbA== +jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== dependencies: chalk "^4.0.0" - jest-diff "^27.4.6" - jest-get-type "^27.4.0" - pretty-format "^27.4.6" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-message-util@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.4.6.tgz#9fdde41a33820ded3127465e1a5896061524da31" - integrity sha512-0p5szriFU0U74czRSFjH6RyS7UYIAkn/ntwMuOwTGWrQIOh5NzXXrq72LOqIkJKKvFbPq+byZKuBz78fjBERBA== +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^27.4.6" + pretty-format "^27.5.1" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.4.6.tgz#77d1ba87fbd33ccb8ef1f061697e7341b7635195" - integrity sha512-kvojdYRkst8iVSZ1EJ+vc1RRD9llueBjKzXzeCytH3dMM7zvPV/ULcfI2nr0v0VUgm3Bjt3hBCQvOeaBz+ZTHw== +jest-mock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -3279,99 +3358,98 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== -jest-regex-util@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" - integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== +jest-regex-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== -jest-resolve-dependencies@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.6.tgz#fc50ee56a67d2c2183063f6a500cc4042b5e2327" - integrity sha512-W85uJZcFXEVZ7+MZqIPCscdjuctruNGXUZ3OHSXOfXR9ITgbUKeHj+uGcies+0SsvI5GtUfTw4dY7u9qjTvQOw== +jest-resolve-dependencies@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" + integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== dependencies: - "@jest/types" "^27.4.2" - jest-regex-util "^27.4.0" - jest-snapshot "^27.4.6" + "@jest/types" "^27.5.1" + jest-regex-util "^27.5.1" + jest-snapshot "^27.5.1" -jest-resolve@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.4.6.tgz#2ec3110655e86d5bfcfa992e404e22f96b0b5977" - integrity sha512-SFfITVApqtirbITKFAO7jOVN45UgFzcRdQanOFzjnbd+CACDoyeX7206JyU92l4cRr73+Qy/TlW51+4vHGt+zw== +jest-resolve@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" + integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" chalk "^4.0.0" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.6" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" jest-pnp-resolver "^1.2.2" - jest-util "^27.4.2" - jest-validate "^27.4.6" + jest-util "^27.5.1" + jest-validate "^27.5.1" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.4.6.tgz#1d390d276ec417e9b4d0d081783584cbc3e24773" - integrity sha512-IDeFt2SG4DzqalYBZRgbbPmpwV3X0DcntjezPBERvnhwKGWTW7C5pbbA5lVkmvgteeNfdd/23gwqv3aiilpYPg== +jest-runner@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" + integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== dependencies: - "@jest/console" "^27.4.6" - "@jest/environment" "^27.4.6" - "@jest/test-result" "^27.4.6" - "@jest/transform" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/console" "^27.5.1" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" chalk "^4.0.0" emittery "^0.8.1" - exit "^0.1.2" - graceful-fs "^4.2.4" - jest-docblock "^27.4.0" - jest-environment-jsdom "^27.4.6" - jest-environment-node "^27.4.6" - jest-haste-map "^27.4.6" - jest-leak-detector "^27.4.6" - jest-message-util "^27.4.6" - jest-resolve "^27.4.6" - jest-runtime "^27.4.6" - jest-util "^27.4.2" - jest-worker "^27.4.6" + graceful-fs "^4.2.9" + jest-docblock "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-haste-map "^27.5.1" + jest-leak-detector "^27.5.1" + jest-message-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runtime "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" source-map-support "^0.5.6" throat "^6.0.1" -jest-runtime@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.4.6.tgz#83ae923818e3ea04463b22f3597f017bb5a1cffa" - integrity sha512-eXYeoR/MbIpVDrjqy5d6cGCFOYBFFDeKaNWqTp0h6E74dK0zLHzASQXJpl5a2/40euBmKnprNLJ0Kh0LCndnWQ== - dependencies: - "@jest/environment" "^27.4.6" - "@jest/fake-timers" "^27.4.6" - "@jest/globals" "^27.4.6" - "@jest/source-map" "^27.4.0" - "@jest/test-result" "^27.4.6" - "@jest/transform" "^27.4.6" - "@jest/types" "^27.4.2" +jest-runtime@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" + integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/globals" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" execa "^5.0.0" glob "^7.1.3" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.6" - jest-message-util "^27.4.6" - jest-mock "^27.4.6" - jest-regex-util "^27.4.0" - jest-resolve "^27.4.6" - jest-snapshot "^27.4.6" - jest-util "^27.4.2" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" slash "^3.0.0" strip-bom "^4.0.0" -jest-serializer@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.4.0.tgz#34866586e1cae2388b7d12ffa2c7819edef5958a" - integrity sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ== +jest-serializer@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== dependencies: "@types/node" "*" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" jest-snapshot-serializer-ansi@^1.0.0: version "1.0.0" @@ -3381,35 +3459,35 @@ jest-snapshot-serializer-ansi@^1.0.0: has-ansi "^3.0.0" strip-ansi "^4.0.0" -jest-snapshot@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.4.6.tgz#e2a3b4fff8bdce3033f2373b2e525d8b6871f616" - integrity sha512-fafUCDLQfzuNP9IRcEqaFAMzEe7u5BF7mude51wyWv7VRex60WznZIC7DfKTgSIlJa8aFzYmXclmN328aqSDmQ== +jest-snapshot@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" + integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== dependencies: "@babel/core" "^7.7.2" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.0.0" - "@jest/transform" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^27.4.6" - graceful-fs "^4.2.4" - jest-diff "^27.4.6" - jest-get-type "^27.4.0" - jest-haste-map "^27.4.6" - jest-matcher-utils "^27.4.6" - jest-message-util "^27.4.6" - jest-util "^27.4.2" + expect "^27.5.1" + graceful-fs "^4.2.9" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + jest-haste-map "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-util "^27.5.1" natural-compare "^1.4.0" - pretty-format "^27.4.6" + pretty-format "^27.5.1" semver "^7.3.2" -jest-util@^27.0.0, jest-util@^27.4.2: +jest-util@^27.0.0: version "27.4.2" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.4.2.tgz#ed95b05b1adfd761e2cda47e0144c6a58e05a621" integrity sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA== @@ -3421,48 +3499,60 @@ jest-util@^27.0.0, jest-util@^27.4.2: graceful-fs "^4.2.4" picomatch "^2.2.3" -jest-validate@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.4.6.tgz#efc000acc4697b6cf4fa68c7f3f324c92d0c4f1f" - integrity sha512-872mEmCPVlBqbA5dToC57vA3yJaMRfIdpCoD3cyHWJOMx+SJwLNw0I71EkWs41oza/Er9Zno9XuTkRYCPDUJXQ== +jest-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" + integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== + dependencies: + "@jest/types" "^27.5.1" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^27.4.0" + jest-get-type "^27.5.1" leven "^3.1.0" - pretty-format "^27.4.6" + pretty-format "^27.5.1" -jest-watcher@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.4.6.tgz#673679ebeffdd3f94338c24f399b85efc932272d" - integrity sha512-yKQ20OMBiCDigbD0quhQKLkBO+ObGN79MO4nT7YaCuQ5SM+dkBNWE8cZX0FjU6czwMvWw6StWbe+Wv4jJPJ+fw== +jest-watcher@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" + integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== dependencies: - "@jest/test-result" "^27.4.6" - "@jest/types" "^27.4.2" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^27.4.2" + jest-util "^27.5.1" string-length "^4.0.1" -jest-worker@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" - integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== +jest-worker@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^27.4.7: - version "27.4.7" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.4.7.tgz#87f74b9026a1592f2da05b4d258e57505f28eca4" - integrity sha512-8heYvsx7nV/m8m24Vk26Y87g73Ba6ueUd0MWed/NXMhSZIm62U/llVbS0PJe1SHunbyXjJ/BqG1z9bFjGUIvTg== +jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" + integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== dependencies: - "@jest/core" "^27.4.7" + "@jest/core" "^27.5.1" import-local "^3.0.2" - jest-cli "^27.4.7" + jest-cli "^27.5.1" js-tokens@^4.0.0: version "4.0.0" @@ -4030,7 +4120,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.0.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -4129,10 +4219,10 @@ pretty-format@^27.0.0, pretty-format@^27.4.2: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-format@^27.4.6: - version "27.4.6" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7" - integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g== +pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== dependencies: ansi-regex "^5.0.1" ansi-styles "^5.0.0" @@ -4698,10 +4788,10 @@ ts-jest@^27.1.3: semver "7.x" yargs-parser "20.x" -ts-node@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" - integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== +ts-node@^10.5.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.5.0.tgz#618bef5854c1fbbedf5e31465cbb224a1d524ef9" + integrity sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw== dependencies: "@cspotcode/source-map-support" "0.7.0" "@tsconfig/node10" "^1.0.7" @@ -4714,6 +4804,7 @@ ts-node@^10.4.0: create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" yn "3.1.1" ts-node@^9: @@ -4850,6 +4941,11 @@ utility-types@^3.10.0: resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"