From 3cbc3364e55e3b492b835bd292bfc3a50a656074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Sat, 28 Mar 2020 12:45:17 +0100 Subject: [PATCH] Add options `githubApiBaseUrlV3` and `githubApiBaseUrlV4` and remove `apiHostname` --- README.md | 49 +++++----- docs/configuration.md | 77 +++++++++++---- src/options/cliArgs.test.ts | 10 +- src/options/cliArgs.ts | 15 ++- src/options/config/config.test.ts | 3 +- src/options/config/config.ts | 3 +- src/options/options.test.ts | 6 +- src/runWithOptions.test.ts | 7 +- .../fetchCommitsByAuthor.test.ts.snap | 18 +++- src/services/github/addLabelsToPullRequest.ts | 10 +- src/services/github/createPullRequest.ts | 10 +- src/services/github/fetchAuthorId.ts | 4 +- .../github/fetchCommitByPullNumber.ts | 10 +- src/services/github/fetchCommitBySha.test.ts | 2 +- src/services/github/fetchCommitBySha.ts | 4 +- .../github/fetchCommitsByAuthor.test.ts | 93 ++++--------------- src/services/github/fetchCommitsByAuthor.ts | 4 +- src/services/github/getDefaultRepoBranch.ts | 4 +- src/services/github/gqlRequest.test.ts | 27 +++--- src/services/github/gqlRequest.ts | 6 +- .../mocks/getExistingBackportPRsMock.ts | 59 ++++++++++++ src/services/github/verifyAccessToken.test.ts | 2 +- src/services/github/verifyAccessToken.ts | 4 +- src/test/getDefaultOptions.ts | 3 +- src/types/Config.ts | 3 +- src/ui/cherrypickAndCreatePullRequest.test.ts | 5 +- src/ui/getCommitBySha.test.ts | 4 +- 27 files changed, 263 insertions(+), 179 deletions(-) create mode 100644 src/services/github/mocks/getExistingBackportPRsMock.ts diff --git a/README.md b/README.md index 95b539ed..7ed34d98 100644 --- a/README.md +++ b/README.md @@ -91,30 +91,31 @@ The above commands will start an interactive prompt. You can use the `arrow keys ### CLI arguments -| Option | Description | Default | Type | -| ---------------- | ------------------------------------------------------ | -------------- | ------- | -| --accesstoken | Github access token | | string | -| --all | Show commits from other than me | false | boolean | -| --api-hostname | Hostname for the Github API | api.github.com | string | -| --author | Filter commits by author | _Current user_ | string | -| --branch | Branch to backport to | | string | -| --commits-count | Number of commits to choose from | 10 | number | -| --editor | Editor (eg. `code`) to open and solve conflicts | | string | -| --fork | Create backports in fork (true) or origin repo (false) | true | boolean | -| --git-hostname | Hostname for Git remotes | github.com | string | -| --labels | Pull request labels | | string | -| --multiple | Select multiple commits/branches | false | boolean | -| --path | Only list commits touching files under a specific path | | string | -| --pr-description | Pull request description suffix | | string | -| --pr-title | Pull request title pattern | | string | -| --pr | Pull request to backport | | number | -| --reset-author | Set yourself as commit author | | boolean | -| --sha | Sha of commit to backport | | string | -| --sourceBranch | Backport commits from a non-default branch | | string | -| --upstream | Name of organization and repository | | string | -| --username | Github username | | string | -| --help | Show help | | | -| -v, --version | Show version number | | | +| Option | Description | Default | Type | +| ------------------------ | ------------------------------------------------------ | ------------------------------ | ------- | +| --accesstoken | Github access token | | string | +| --all | Show commits from other than me | false | boolean | +| --author | Filter commits by author | _Current user_ | string | +| --branch | Branch to backport to | | string | +| --commits-count | Number of commits to choose from | 10 | number | +| --editor | Editor (eg. `code`) to open and solve conflicts | | string | +| --fork | Create backports in fork (true) or origin repo (false) | true | boolean | +| --git-hostname | Hostname for Git remotes | github.com | string | +| --github-api-base-url-v3 | Base url for Github's Rest (v3) API | https://api.github.com | string | +| --github-api-base-url-v4 | Base url for Github's GraphQL (v4) API | https://api.github.com/graphql | string | +| --labels | Pull request labels | | string | +| --multiple | Select multiple commits/branches | false | boolean | +| --path | Only list commits touching files under a specific path | | string | +| --pr-description | Pull request description suffix | | string | +| --pr-title | Pull request title pattern | | string | +| --pr | Pull request to backport | | number | +| --reset-author | Set yourself as commit author | | boolean | +| --sha | Sha of commit to backport | | string | +| --sourceBranch | Backport commits from a non-default branch | | string | +| --upstream | Name of organization and repository | | string | +| --username | Github username | | string | +| --help | Show help | | | +| -v, --version | Show version number | | | All of the CLI arguments can also be configured via the [configuration options](https://github.com/sqren/backport/blob/master/docs/configuration.md) in the config files. diff --git a/docs/configuration.md b/docs/configuration.md index 54d0aba0..5ebb9ad3 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -30,7 +30,6 @@ Please select the necessary access scopes: **For public and private repos (recommended)** ![image](https://user-images.githubusercontent.com/209966/67081197-fe93d380-f196-11e9-8891-c6ba8c4686a4.png) - **For public repos only** ![image](https://user-images.githubusercontent.com/209966/67081207-018ec400-f197-11e9-86aa-4ae4a003fcbd.png) @@ -66,18 +65,30 @@ Example: Github organization/user and repository name separated with forward slash. -Example: "elastic/kibana" - CLI: `--upstream elastic/kibana` +Config: + +```json +{ + "upsteam": "elastic/kibana" +} +``` + #### `branches` **required** List of branches that will be available to backport to. The array can contain branch names as strings or objects that also contains the field `checked` which indicates whether the branch should be pre-selected. It is useful to pre-select branches you often backport to. -Example: `[{ "name": "6.x", "checked": true }, "6.3", "6.2", "6.1", "6.0"]` - CLI: `--branches 6.1 --branches 6.0` +Config: + +```json +{ + "branches": [{ "name": "6.x", "checked": true }, "6.3", "6.2", "6.1", "6.0"] +} +``` + #### `all` `true`: list all commits @@ -98,6 +109,14 @@ Default: `true` CLI: `--fork=false` +Config: + +```json +{ + "fork": false +} +``` + #### `multipleCommits` `true`: you will be able to select multiple commits to backport. You will use `` to select, and `` to confirm you selection. @@ -118,20 +137,24 @@ Default: `true` Labels that will be added to the backport pull request. These are often useful if you want to filter for backport PRs. -Example: `["backport", "apm-team"]` +CLI: `--labels backport --labels apm-team` + +Config: -CLI: `--labels myLabel --labels myOtherLabel` +```json +{ + "labels": ["backport", "apm-team"] +} +``` #### `prTitle` Pull request title pattern. You can access the base branch (`{baseBranch}`) and commit message (`{commitMessages}`) via the special accessors in quotes. Multiple commits will be concatenated and separated by pipes. -Example: `"{commitMessages} backport for {baseBranch}"` - Default: `"[{baseBranch}] {commitMessages}"` -CLI: `--prTitle "My PR Title"` +CLI: `--pr-title "{commitMessages} backport for {baseBranch}"` #### `prDescription` @@ -144,30 +167,44 @@ For people who often need to add the same description to PRs they can create a b alias backport-skip-ci='backport --prDescription "[skip-ci]"' ``` -CLI: `--prDescription "skip-ci"` +CLI: `--pr-description "skip-ci"` #### `sourceBranch` By default the list of commits will be sourced from the repository's default branch (mostly "master"). Use `sourceBranch` to list and backport commits from other branches than the default. -CLI: `--sourceBranch 7.x` +Default: master (unless the default branch on Github is changed) + +CLI: `--source-branch 7.x` + +Config: + +```json +{ + "sourceBranch": "7.x" +} +``` #### `gitHostname` Hostname for Github. -Example: `github.my-private-company.com` - Default: `github.com` -CLI: `--gitHostname "github.my-private-company.com"` +CLI: `--git-hostname "github.my-private-company.com"` + +#### `githubApiBaseUrlV3` + +Base url for Github's Rest (v3) API + +Default: `https://api.github.com` -#### `apiHostname` +CLI: `--github-api-base-url-v3 "https://api.github.my-private-company.com"` -Hostname for the Github API. +#### `githubApiBaseUrlV4` -Example: `api.github.my-private-company.com` +Base url for Github's Rest (v3) API -Default: `api.github.com` +Default: `https://api.github.com/graphql` -CLI: `--apiHostname "api.github.my-private-company.com"` +CLI: `--github-api-base-url-v4 "https://github-enterprise.acme-inc.com/api"` diff --git a/src/options/cliArgs.test.ts b/src/options/cliArgs.test.ts index 05722ffb..39cf60e0 100644 --- a/src/options/cliArgs.test.ts +++ b/src/options/cliArgs.test.ts @@ -6,7 +6,8 @@ describe('getOptionsFromCliArgs', () => { const configOptions = { accessToken: 'myAccessToken', all: false, - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', backportCreatedLabels: [], branchChoices: [], fork: true, @@ -37,7 +38,8 @@ describe('getOptionsFromCliArgs', () => { expect(res).toEqual({ accessToken: 'myAccessToken', all: true, - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', backportCreatedLabels: [], branches: ['6.0', '6.1'], branchChoices: [], @@ -61,7 +63,7 @@ describe('getOptionsFromCliArgs', () => { const argv = [ '--access-token', 'my access token', - '--apiHostname', + '--githubApiBaseUrlV3', 'my api hostname', ]; @@ -69,7 +71,7 @@ describe('getOptionsFromCliArgs', () => { expect(res.accessToken).toEqual('my access token'); expect('access-token' in res).toEqual(false); - expect(res.apiHostname).toEqual('my api hostname'); + expect(res.githubApiBaseUrlV3).toEqual('my api hostname'); expect('api-hostname' in res).toEqual(false); }); diff --git a/src/options/cliArgs.ts b/src/options/cliArgs.ts index 83893e9a..310d8f32 100644 --- a/src/options/cliArgs.ts +++ b/src/options/cliArgs.ts @@ -23,11 +23,6 @@ export function getOptionsFromCliArgs( description: 'List all commits', type: 'boolean', }) - .option('apiHostname', { - default: configOptions.apiHostname, - description: 'Hostname for the Github API', - type: 'string', - }) .option('author', { default: configOptions.author, description: 'Show commits by specific author', @@ -65,6 +60,16 @@ export function getOptionsFromCliArgs( description: 'Hostname for Github', type: 'string', }) + .option('githubApiBaseUrlV3', { + default: configOptions.githubApiBaseUrlV3, + description: `Base url for Github's REST (v3) API`, + type: 'string', + }) + .option('githubApiBaseUrlV4', { + default: configOptions.githubApiBaseUrlV4, + description: `Base url for Github's GraphQL (v4) API`, + type: 'string', + }) .option('labels', { default: configOptions.labels, description: 'Pull request labels for the resulting backport PRs', diff --git a/src/options/config/config.test.ts b/src/options/config/config.test.ts index ecbb48ed..f08dc03e 100644 --- a/src/options/config/config.test.ts +++ b/src/options/config/config.test.ts @@ -12,7 +12,8 @@ describe('getOptionsFromConfigFiles', () => { expect(res).toEqual({ accessToken: 'myAccessToken', all: false, - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', backportCreatedLabels: [], branchChoices: [ { checked: false, name: '6.0' }, diff --git a/src/options/config/config.ts b/src/options/config/config.ts index ce48d8da..abff09c4 100644 --- a/src/options/config/config.ts +++ b/src/options/config/config.ts @@ -29,7 +29,8 @@ export async function getOptionsFromConfigFiles() { labels: [] as string[], prTitle: '[{baseBranch}] {commitMessages}', gitHostname: 'github.com', - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', branchChoices: getBranchesAsObjects(branches), ...combinedConfig, }; diff --git a/src/options/options.test.ts b/src/options/options.test.ts index f9ecc058..658e7cdd 100644 --- a/src/options/options.test.ts +++ b/src/options/options.test.ts @@ -50,7 +50,8 @@ describe('getOptions', () => { expect(options).toEqual({ accessToken: 'myAccessToken', all: false, - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', author: 'sqren', backportCreatedLabels: [], branchChoices: [ @@ -79,7 +80,8 @@ describe('validateRequiredOptions', () => { const validOptions: OptionsFromCliArgs = { accessToken: 'myAccessToken', all: false, - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', author: undefined, backportCreatedLabels: [], branchChoices: [], diff --git a/src/runWithOptions.test.ts b/src/runWithOptions.test.ts index a21f1e15..5f8f0736 100644 --- a/src/runWithOptions.test.ts +++ b/src/runWithOptions.test.ts @@ -21,7 +21,8 @@ describe('runWithOptions', () => { const options: BackportOptions = { accessToken: 'myAccessToken', all: false, - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', author: 'sqren', backportCreatedLabels: [], branches: [], @@ -109,7 +110,7 @@ describe('runWithOptions', () => { repoName: 'kibana', repoOwner: 'elastic', username: 'sqren', - apiHostname: 'api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', }) ); }); @@ -119,7 +120,7 @@ describe('runWithOptions', () => { expect.objectContaining({ repoName: 'kibana', repoOwner: 'elastic', - apiHostname: 'api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', }), { base: '6.x', diff --git a/src/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap b/src/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap index 5140be9d..1a3a2ee5 100644 --- a/src/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap +++ b/src/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap @@ -2,9 +2,8 @@ exports[`fetchCommitsByAuthor when commit has an associated pull request should call with correct args to fetch author id 1`] = ` Array [ + "https://api.github.com/graphql", Object { - "accessToken": "myAccessToken", - "apiHostname": "api.github.com", "query": " query getIdByLogin($login: String!) { user(login: $login) { @@ -16,14 +15,19 @@ Array [ "login": "sqren", }, }, + Object { + "headers": Object { + "Authorization": "bearer myAccessToken", + "Content-Type": "application/json", + }, + }, ] `; exports[`fetchCommitsByAuthor when commit has an associated pull request should call with correct args to fetch commits 1`] = ` Array [ + "https://api.github.com/graphql", Object { - "accessToken": "myAccessToken", - "apiHostname": "api.github.com", "query": " query getCommitsByAuthorQuery( $repoOwner: String! @@ -104,5 +108,11 @@ Array [ "sourceBranch": undefined, }, }, + Object { + "headers": Object { + "Authorization": "bearer myAccessToken", + "Content-Type": "application/json", + }, + }, ] `; diff --git a/src/services/github/addLabelsToPullRequest.ts b/src/services/github/addLabelsToPullRequest.ts index e3c7f269..30ebe45a 100644 --- a/src/services/github/addLabelsToPullRequest.ts +++ b/src/services/github/addLabelsToPullRequest.ts @@ -4,7 +4,13 @@ import { handleGithubError } from './handleGithubError'; import { logger } from '../logger'; export async function addLabelsToPullRequest( - { apiHostname, repoName, repoOwner, accessToken, username }: BackportOptions, + { + githubApiBaseUrlV3, + repoName, + repoOwner, + accessToken, + username, + }: BackportOptions, pullNumber: number, labels: string[] ) { @@ -12,7 +18,7 @@ export async function addLabelsToPullRequest( try { return await axios.post( - `https://${apiHostname}/repos/${repoOwner}/${repoName}/issues/${pullNumber}/labels`, + `${githubApiBaseUrlV3}/repos/${repoOwner}/${repoName}/issues/${pullNumber}/labels`, labels, { auth: { diff --git a/src/services/github/createPullRequest.ts b/src/services/github/createPullRequest.ts index 798e5213..5200dc33 100644 --- a/src/services/github/createPullRequest.ts +++ b/src/services/github/createPullRequest.ts @@ -5,7 +5,13 @@ import { handleGithubError } from './handleGithubError'; import { logger } from '../logger'; export async function createPullRequest( - { apiHostname, repoName, repoOwner, accessToken, username }: BackportOptions, + { + githubApiBaseUrlV3, + repoName, + repoOwner, + accessToken, + username, + }: BackportOptions, payload: { title: string; body: string; @@ -19,7 +25,7 @@ export async function createPullRequest( try { const res: AxiosResponse = await axios.post( - `https://${apiHostname}/repos/${repoOwner}/${repoName}/pulls`, + `${githubApiBaseUrlV3}/repos/${repoOwner}/${repoName}/pulls`, payload, { auth: { diff --git a/src/services/github/fetchAuthorId.ts b/src/services/github/fetchAuthorId.ts index 6f6c2a50..4c7443ce 100644 --- a/src/services/github/fetchAuthorId.ts +++ b/src/services/github/fetchAuthorId.ts @@ -6,7 +6,7 @@ interface DataResponse { } export async function fetchAuthorId(options: BackportOptions) { - const { all, author, accessToken, apiHostname } = options; + const { all, author, accessToken, githubApiBaseUrlV4 } = options; if (all) { return null; } @@ -20,7 +20,7 @@ export async function fetchAuthorId(options: BackportOptions) { `; const res = await gqlRequest({ - apiHostname, + githubApiBaseUrlV4, accessToken, query, variables: { login: author }, diff --git a/src/services/github/fetchCommitByPullNumber.ts b/src/services/github/fetchCommitByPullNumber.ts index 5e7e8de6..c79f3767 100644 --- a/src/services/github/fetchCommitByPullNumber.ts +++ b/src/services/github/fetchCommitByPullNumber.ts @@ -7,7 +7,13 @@ import { HandledError } from '../HandledError'; export async function fetchCommitByPullNumber( options: BackportOptions & { pullNumber: number } ): Promise { - const { apiHostname, repoName, repoOwner, pullNumber, accessToken } = options; + const { + githubApiBaseUrlV4, + repoName, + repoOwner, + pullNumber, + accessToken, + } = options; const query = /* GraphQL */ ` query getCommitbyPullNumber( $repoOwner: String! @@ -29,7 +35,7 @@ export async function fetchCommitByPullNumber( `; const res = await gqlRequest({ - apiHostname, + githubApiBaseUrlV4, accessToken, query, variables: { diff --git a/src/services/github/fetchCommitBySha.test.ts b/src/services/github/fetchCommitBySha.test.ts index 22cb8890..f8db1e29 100644 --- a/src/services/github/fetchCommitBySha.test.ts +++ b/src/services/github/fetchCommitBySha.test.ts @@ -11,7 +11,7 @@ describe('fetchCommitBySha', () => { accessToken: 'myAccessToken', username: 'sqren', author: 'sqren', - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', } as BackportOptions; const axiosSpy = jest diff --git a/src/services/github/fetchCommitBySha.ts b/src/services/github/fetchCommitBySha.ts index e2d88f66..054974f8 100644 --- a/src/services/github/fetchCommitBySha.ts +++ b/src/services/github/fetchCommitBySha.ts @@ -11,7 +11,7 @@ export async function fetchCommitBySha( options: BackportOptions & { sha: string } ): Promise { const { - apiHostname, + githubApiBaseUrlV3, repoName, repoOwner, sha, @@ -20,7 +20,7 @@ export async function fetchCommitBySha( } = options; try { const res = await axios.get>( - `https://${apiHostname}/search/commits?q=hash:${sha}%20repo:${repoOwner}/${repoName}&per_page=1`, + `${githubApiBaseUrlV3}/search/commits?q=hash:${sha}%20repo:${repoOwner}/${repoName}&per_page=1`, { auth: { username: username, diff --git a/src/services/github/fetchCommitsByAuthor.test.ts b/src/services/github/fetchCommitsByAuthor.test.ts index 3ebeb0ed..98cda73d 100644 --- a/src/services/github/fetchCommitsByAuthor.test.ts +++ b/src/services/github/fetchCommitsByAuthor.test.ts @@ -1,4 +1,3 @@ -import * as gqlRequest from './gqlRequest'; import { CommitSelected } from './Commit'; import { PullRequestEdge, @@ -7,16 +6,20 @@ import { TimelineItemEdge, } from './fetchCommitsByAuthor'; import { commitsWithPullRequestsMock } from './mocks/commitsByAuthorMock'; +import { getExistingBackportPRsMock } from './mocks/getExistingBackportPRsMock'; import { getDefaultOptions } from '../../test/getDefaultOptions'; +import axios from 'axios'; + +const currentUserMock = { user: { id: 'myUserId' } } as const; describe('fetchCommitsByAuthor', () => { describe('when commit has an associated pull request', () => { let requestSpy: jasmine.Spy; let res: CommitSelected[]; beforeEach(async () => { - requestSpy = spyOn(gqlRequest, 'gqlRequest').and.returnValues( - { user: { id: 'myUserId' } }, - commitsWithPullRequestsMock + requestSpy = spyOn(axios, 'post').and.returnValues( + { data: { data: currentUserMock } }, + { data: { data: commitsWithPullRequestsMock } } ); const options = getDefaultOptions(); @@ -92,21 +95,21 @@ describe('fetchCommitsByAuthor', () => { describe('when a custom github api hostname is supplied', () => { it('should be used in gql requests', async () => { - const requestSpy = spyOn(gqlRequest, 'gqlRequest').and.returnValues( - { user: { id: 'myUserId' } }, - commitsWithPullRequestsMock + const requestSpy = spyOn(axios, 'post').and.returnValues( + { data: { data: currentUserMock } }, + { data: { data: commitsWithPullRequestsMock } } ); const options = getDefaultOptions({ - apiHostname: 'api.github.my-company.com', + githubApiBaseUrlV4: 'https://api.github.my-company.com', }); await fetchCommitsByAuthor(options); - expect(requestSpy.calls.argsFor(0)[0].apiHostname).toBe( - 'api.github.my-company.com' + expect(requestSpy.calls.argsFor(0)[0]).toBe( + 'https://api.github.my-company.com' ); - expect(requestSpy.calls.argsFor(1)[0].apiHostname).toBe( - 'api.github.my-company.com' + expect(requestSpy.calls.argsFor(1)[0]).toBe( + 'https://api.github.my-company.com' ); }); }); @@ -174,69 +177,11 @@ async function getExistingBackportsByRepoName( repoName1: string, repoName2: string ) { - const mock = { - repository: { - ref: { - target: { - history: { - edges: [ - { - node: { - oid: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', - message: - 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', - associatedPullRequests: { - edges: [ - { - node: { - repository: { - name: repoName1, - owner: { - login: 'elastic', - }, - }, - number: 80, - timelineItems: { - edges: [ - { - node: { - source: { - __typename: 'PullRequest', - state: 'MERGED', - baseRefName: '6.3', - commits: { - edges: [ - { - node: { - commit: { - message: - 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', - }, - }, - }, - ], - }, - }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - }, - }; + const existingPrsMock = getExistingBackportPRsMock(repoName1); - spyOn(gqlRequest, 'gqlRequest').and.returnValues( - { user: { id: 'myUserId' } }, - mock + spyOn(axios, 'post').and.returnValues( + { data: { data: currentUserMock } }, + { data: { data: existingPrsMock } } ); const options = getDefaultOptions({ diff --git a/src/services/github/fetchCommitsByAuthor.ts b/src/services/github/fetchCommitsByAuthor.ts index 330a6d53..fcdf846e 100644 --- a/src/services/github/fetchCommitsByAuthor.ts +++ b/src/services/github/fetchCommitsByAuthor.ts @@ -13,7 +13,7 @@ export async function fetchCommitsByAuthor( ): Promise { const { accessToken, - apiHostname, + githubApiBaseUrlV4, commitsCount, path, repoName, @@ -95,7 +95,7 @@ export async function fetchCommitsByAuthor( const authorId = await fetchAuthorId(options); const res = await gqlRequest({ - apiHostname, + githubApiBaseUrlV4, accessToken, query, variables: { diff --git a/src/services/github/getDefaultRepoBranch.ts b/src/services/github/getDefaultRepoBranch.ts index b5ce96a7..57343069 100644 --- a/src/services/github/getDefaultRepoBranch.ts +++ b/src/services/github/getDefaultRepoBranch.ts @@ -11,7 +11,7 @@ export interface DataResponse { export async function getDefaultRepoBranch({ accessToken, - apiHostname, + githubApiBaseUrlV4, repoName, repoOwner, }: ReturnType) { @@ -26,7 +26,7 @@ export async function getDefaultRepoBranch({ `; const res = await gqlRequest({ - apiHostname, + githubApiBaseUrlV4, accessToken, query, variables: { diff --git a/src/services/github/gqlRequest.test.ts b/src/services/github/gqlRequest.test.ts index f359f11e..4d57072d 100644 --- a/src/services/github/gqlRequest.test.ts +++ b/src/services/github/gqlRequest.test.ts @@ -6,30 +6,31 @@ import dedent from 'dedent'; describe('gqlRequest', () => { describe('when request succeeds', () => { let spy: jest.SpyInstance; - beforeEach(() => { + let res: unknown; + beforeEach(async () => { spy = jest.spyOn(axios, 'post').mockResolvedValue({ data: { data: 'some data', }, } as any); + + res = await gqlRequest({ + accessToken: 'myAccessToken', + githubApiBaseUrlV4: 'https://my-custom-api.com/graphql', + query: 'myQuery', + variables: { + foo: 'bar', + }, + }); }); it('should return correct response', async () => { - expect( - await gqlRequest({ - accessToken: 'myAccessToken', - apiHostname: 'myApiHostname', - query: 'myQuery', - variables: { - foo: 'bar', - }, - }) - ).toEqual('some data'); + expect(res).toEqual('some data'); }); it('should call with correct args', async () => { expect(spy).toHaveBeenCalledWith( - 'https://myApiHostname/graphql', + 'https://my-custom-api.com/graphql', { query: 'myQuery', variables: { foo: 'bar' }, @@ -62,7 +63,7 @@ describe('gqlRequest', () => { return expect( gqlRequest({ accessToken: 'myAccessToken', - apiHostname: 'myApiHostname', + githubApiBaseUrlV4: 'myApiHostname', query: 'myQuery', variables: { foo: 'bar', diff --git a/src/services/github/gqlRequest.ts b/src/services/github/gqlRequest.ts index a19eaeca..b5eecfa9 100644 --- a/src/services/github/gqlRequest.ts +++ b/src/services/github/gqlRequest.ts @@ -17,12 +17,12 @@ interface GithubResponse { } export async function gqlRequest({ - apiHostname, + githubApiBaseUrlV4, query, variables, accessToken, }: { - apiHostname: string; + githubApiBaseUrlV4: string; query: string; variables?: { [key: string]: string | number | null; @@ -33,7 +33,7 @@ export async function gqlRequest({ logger.verbose(query); logger.verbose(variables as any); const response = await axios.post>( - `https://${apiHostname}/graphql`, + githubApiBaseUrlV4, { query, variables }, { headers: { diff --git a/src/services/github/mocks/getExistingBackportPRsMock.ts b/src/services/github/mocks/getExistingBackportPRsMock.ts new file mode 100644 index 00000000..d4b8941c --- /dev/null +++ b/src/services/github/mocks/getExistingBackportPRsMock.ts @@ -0,0 +1,59 @@ +export const getExistingBackportPRsMock = (repoName: string) => ({ + repository: { + ref: { + target: { + history: { + edges: [ + { + node: { + oid: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + message: + 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', + associatedPullRequests: { + edges: [ + { + node: { + repository: { + name: repoName, + owner: { + login: 'elastic', + }, + }, + number: 80, + timelineItems: { + edges: [ + { + node: { + source: { + __typename: 'PullRequest', + state: 'MERGED', + baseRefName: '6.3', + commits: { + edges: [ + { + node: { + commit: { + message: + 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', + }, + }, + }, + ], + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + }, +}); diff --git a/src/services/github/verifyAccessToken.test.ts b/src/services/github/verifyAccessToken.test.ts index d1b71e2f..30094519 100644 --- a/src/services/github/verifyAccessToken.test.ts +++ b/src/services/github/verifyAccessToken.test.ts @@ -8,7 +8,7 @@ describe('verifyAccessToken', () => { beforeEach(() => { options = { accessToken: 'myAccessToken', - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', repoName: 'kibana', repoOwner: 'elastic', } as BackportOptions; diff --git a/src/services/github/verifyAccessToken.ts b/src/services/github/verifyAccessToken.ts index ec86180a..fafde192 100644 --- a/src/services/github/verifyAccessToken.ts +++ b/src/services/github/verifyAccessToken.ts @@ -15,13 +15,13 @@ function getSSOAuthUrl(ssoHeader?: string) { export async function verifyAccessToken({ username, accessToken, - apiHostname, + githubApiBaseUrlV3, repoName, repoOwner, }: ReturnType) { try { return await axios.head( - `https://${apiHostname}/repos/${repoOwner}/${repoName}`, + `${githubApiBaseUrlV3}/repos/${repoOwner}/${repoName}`, { auth: { username: username, diff --git a/src/test/getDefaultOptions.ts b/src/test/getDefaultOptions.ts index 9d1dfc9f..b7657d07 100644 --- a/src/test/getDefaultOptions.ts +++ b/src/test/getDefaultOptions.ts @@ -7,7 +7,8 @@ export function getDefaultOptions(options: Partial = {}) { accessToken: 'myAccessToken', username: 'sqren', author: 'sqren', - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', + githubApiBaseUrlV4: 'https://api.github.com/graphql', ...options, } as BackportOptions; } diff --git a/src/types/Config.ts b/src/types/Config.ts index a9f8aa5e..461c0a9a 100644 --- a/src/types/Config.ts +++ b/src/types/Config.ts @@ -18,10 +18,11 @@ export interface Config { // both all?: boolean; author?: string; - apiHostname?: string; backportCreatedLabels?: string[]; commitsCount?: number; gitHostname?: string; + githubApiBaseUrlV3?: string; + githubApiBaseUrlV4?: string; labels?: string[]; multiple?: boolean; multipleBranches?: boolean; diff --git a/src/ui/cherrypickAndCreatePullRequest.test.ts b/src/ui/cherrypickAndCreatePullRequest.test.ts index 1867d0fc..fed65299 100644 --- a/src/ui/cherrypickAndCreatePullRequest.test.ts +++ b/src/ui/cherrypickAndCreatePullRequest.test.ts @@ -34,7 +34,7 @@ describe('cherrypickAndCreatePullRequest', () => { execSpy = (exec as any) as jest.SpyInstance; const options = { - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', fork: true, labels: ['backport'], prDescription: 'myPrSuffix', @@ -104,7 +104,7 @@ myPrSuffix` describe('when commit does not have a pull request reference', () => { beforeEach(async () => { const options = { - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', fork: true, labels: ['backport'], prTitle: '[{baseBranch}] {commitMessages}', @@ -166,7 +166,6 @@ myPrSuffix` spyOn(prompts, 'confirmPrompt').and.returnValue(didResolve); const options = { - apiHostname: 'api.github.com', fork: true, labels: ['backport'], prTitle: '[{baseBranch}] {commitMessages}', diff --git a/src/ui/getCommitBySha.test.ts b/src/ui/getCommitBySha.test.ts index e0c96bb3..a2039cbf 100644 --- a/src/ui/getCommitBySha.test.ts +++ b/src/ui/getCommitBySha.test.ts @@ -15,7 +15,7 @@ describe('getCommitBySha', () => { repoOwner: 'elastic', repoName: 'kibana', sha: 'myCommitSha', - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', } as BackportOptions & { sha: string }); expect(commit).toEqual({ @@ -42,7 +42,7 @@ describe('getCommitBySha', () => { repoOwner: 'elastic', repoName: 'kibana', sha: 'myCommitSha', - apiHostname: 'api.github.com', + githubApiBaseUrlV3: 'https://api.github.com', } as BackportOptions & { sha: string }) ).rejects.toThrowError('No commit found on master with sha "myCommitSha"'); });