fix(core/changelogs): pass though known project info (#11515)

This commit is contained in:
Michael Kriese 2021-09-01 13:07:55 +02:00 committed by GitHub
parent 28793a3900
commit 0eb5c6d2cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 510 additions and 418 deletions

View file

@ -20,7 +20,7 @@ export class GitHubReleaseMocker {
published_at: '2020-03-09T11:00:00Z', published_at: '2020-03-09T11:00:00Z',
prerelease: false, prerelease: false,
assets: [], assets: [],
}; } as GithubRelease;
for (const assetFn of Object.keys(assets)) { for (const assetFn of Object.keys(assets)) {
const assetPath = `/repos/${this.lookupName}/releases/download/${version}/${assetFn}`; const assetPath = `/repos/${this.lookupName}/releases/download/${version}/${assetFn}`;
const assetData = assets[assetFn]; const assetData = assets[assetFn];

View file

@ -1,8 +1,13 @@
export type GithubRelease = { export type GithubRelease = {
id: number;
tag_name: string; tag_name: string;
published_at: string; published_at: string;
prerelease: boolean; prerelease: boolean;
assets: GithubReleaseAsset[]; assets: GithubReleaseAsset[];
html_url: string;
name: string;
body: string;
}; };
export interface GithubReleaseAsset { export interface GithubReleaseAsset {

View file

@ -4,7 +4,7 @@ import { GithubHttp } from '../../util/http/github';
import { ensureTrailingSlash } from '../../util/url'; import { ensureTrailingSlash } from '../../util/url';
import * as githubReleases from '../github-releases'; import * as githubReleases from '../github-releases';
import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types'; import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types';
import type { TagResponse } from './types'; import type { GitHubTag, TagResponse } from './types';
export const id = 'github-tags'; export const id = 'github-tags';
export const customRegistrySupport = true; export const customRegistrySupport = true;
@ -148,12 +148,9 @@ async function getTags({
: `${sourceUrlBase}api/v3/`; : `${sourceUrlBase}api/v3/`;
// tag // tag
const url = `${apiBaseUrl}repos/${repo}/tags?per_page=100`; const url = `${apiBaseUrl}repos/${repo}/tags?per_page=100`;
type GitHubTag = {
name: string;
}[];
const versions = ( const versions = (
await http.getJson<GitHubTag>(url, { await http.getJson<GitHubTag[]>(url, {
paginate: true, paginate: true,
}) })
).body.map((o) => o.name); ).body.map((o) => o.name);

View file

@ -5,3 +5,7 @@ export interface TagResponse {
sha: string; sha: string;
}; };
} }
export interface GitHubTag {
name: string;
}

View file

@ -1,4 +1,5 @@
export interface GitlabRelease { export interface GitlabRelease {
description: string;
name: string; name: string;
tag_name: string; tag_name: string;
released_at: string; released_at: string;

View file

@ -60,6 +60,7 @@ Object {
"accept-encoding": "gzip, deflate, br", "accept-encoding": "gzip, deflate, br",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)", "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
}, },
"hostType": "any",
"http2": false, "http2": false,
"method": "POST", "method": "POST",
"password": "***********", "password": "***********",

View file

@ -66,6 +66,7 @@ export default function prepareError(err: Error): Record<string, unknown> {
const options: Record<string, unknown> = { const options: Record<string, unknown> = {
headers: clone(err.options.headers), headers: clone(err.options.headers),
url: err.options.url?.toString(), url: err.options.url?.toString(),
hostType: err.options.context.hostType,
}; };
response.options = options; response.options = options;

View file

@ -105,7 +105,11 @@ async function gotRoutine<T>(
} }
export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> { export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> {
constructor(private hostType: string, private options?: HttpOptions) {} private options?: GotOptions;
constructor(private hostType: string, options?: HttpOptions) {
this.options = merge<GotOptions>(options, { context: { hostType } });
}
protected async request<T>( protected async request<T>(
requestUrl: string | URL, requestUrl: string | URL,

View file

@ -7,9 +7,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "@renovate/no", "depName": "@renovate/no",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -59,9 +60,10 @@ Object {
"apiBaseUrl": "https://github-enterprise.example.com/api/v3/", "apiBaseUrl": "https://github-enterprise.example.com/api/v3/",
"baseUrl": "https://github-enterprise.example.com/", "baseUrl": "https://github-enterprise.example.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github-enterprise.example.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github-enterprise.example.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -111,9 +113,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -163,9 +166,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -215,9 +219,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -267,9 +272,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {

View file

@ -7,8 +7,9 @@ Object {
"apiBaseUrl": "https://gitlab.com/api/v4/", "apiBaseUrl": "https://gitlab.com/api/v4/",
"baseUrl": "https://gitlab.com/", "baseUrl": "https://gitlab.com/",
"depName": "renovate", "depName": "renovate",
"gitlab": "meno/dropzone", "repository": "meno/dropzone",
"repository": "https://gitlab.com/meno/dropzone/", "sourceUrl": "https://gitlab.com/meno/dropzone/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -154,8 +155,9 @@ Object {
"apiBaseUrl": "https://gitlab-enterprise.example.com/api/v4/", "apiBaseUrl": "https://gitlab-enterprise.example.com/api/v4/",
"baseUrl": "https://gitlab-enterprise.example.com/", "baseUrl": "https://gitlab-enterprise.example.com/",
"depName": "renovate", "depName": "renovate",
"gitlab": "meno/dropzone", "repository": "meno/dropzone",
"repository": "https://gitlab-enterprise.example.com/meno/dropzone/", "sourceUrl": "https://gitlab-enterprise.example.com/meno/dropzone/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -197,8 +199,9 @@ Object {
"apiBaseUrl": "https://git.test.com/api/v4/", "apiBaseUrl": "https://git.test.com/api/v4/",
"baseUrl": "https://git.test.com/", "baseUrl": "https://git.test.com/",
"depName": "renovate", "depName": "renovate",
"gitlab": "meno/dropzone", "repository": "meno/dropzone",
"repository": "https://git.test.com/meno/dropzone/", "sourceUrl": "https://git.test.com/meno/dropzone/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -240,8 +243,9 @@ Object {
"apiBaseUrl": "https://gitlab.com/api/v4/", "apiBaseUrl": "https://gitlab.com/api/v4/",
"baseUrl": "https://gitlab.com/", "baseUrl": "https://gitlab.com/",
"depName": "renovate", "depName": "renovate",
"gitlab": "meno/dropzone", "repository": "meno/dropzone",
"repository": "https://gitlab.com/meno/dropzone/", "sourceUrl": "https://gitlab.com/meno/dropzone/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -403,8 +407,9 @@ Object {
"apiBaseUrl": "https://gitlab.com/api/v4/", "apiBaseUrl": "https://gitlab.com/api/v4/",
"baseUrl": "https://gitlab.com/", "baseUrl": "https://gitlab.com/",
"depName": "renovate", "depName": "renovate",
"gitlab": "meno/dropzone", "repository": "meno/dropzone",
"repository": "https://gitlab.com/meno/dropzone/", "sourceUrl": "https://gitlab.com/meno/dropzone/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -550,8 +555,9 @@ Object {
"apiBaseUrl": "https://gitlab.com/api/v4/", "apiBaseUrl": "https://gitlab.com/api/v4/",
"baseUrl": "https://gitlab.com/", "baseUrl": "https://gitlab.com/",
"depName": "renovate", "depName": "renovate",
"gitlab": "meno/dropzone", "repository": "meno/dropzone",
"repository": "https://gitlab.com/meno/dropzone/", "sourceUrl": "https://gitlab.com/meno/dropzone/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {

View file

@ -7,9 +7,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "@renovate/no", "depName": "@renovate/no",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -163,9 +164,10 @@ Object {
"apiBaseUrl": "https://github-enterprise.example.com/api/v3/", "apiBaseUrl": "https://github-enterprise.example.com/api/v3/",
"baseUrl": "https://github-enterprise.example.com/", "baseUrl": "https://github-enterprise.example.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github-enterprise.example.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github-enterprise.example.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -363,9 +365,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -563,9 +566,10 @@ Object {
"apiBaseUrl": "https://github-enterprise.example.com/api/v3/", "apiBaseUrl": "https://github-enterprise.example.com/api/v3/",
"baseUrl": "https://github-enterprise.example.com/", "baseUrl": "https://github-enterprise.example.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github-enterprise.example.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github-enterprise.example.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -763,9 +767,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -815,9 +820,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -1019,9 +1025,10 @@ Object {
"apiBaseUrl": "https://api.github.com/", "apiBaseUrl": "https://api.github.com/",
"baseUrl": "https://github.com/", "baseUrl": "https://github.com/",
"depName": "renovate", "depName": "renovate",
"github": "chalk/chalk", "repository": "chalk/chalk",
"repository": "https://github.com/chalk/chalk",
"sourceDirectory": undefined, "sourceDirectory": undefined,
"sourceUrl": "https://github.com/chalk/chalk",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {

View file

@ -5,7 +5,8 @@ Object {
"a": 1, "a": 1,
"hasReleaseNotes": false, "hasReleaseNotes": false,
"project": Object { "project": Object {
"github": "https://github.com/nodeca/js-yaml", "repository": "https://github.com/nodeca/js-yaml",
"type": "github",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -24,7 +25,8 @@ Object {
"a": 1, "a": 1,
"hasReleaseNotes": false, "hasReleaseNotes": false,
"project": Object { "project": Object {
"gitlab": "https://gitlab.com/gitlab-org/gitter/webapp/", "repository": "https://gitlab.com/gitlab-org/gitter/webapp/",
"type": "gitlab",
}, },
"versions": Array [ "versions": Array [
Object { Object {
@ -137,7 +139,7 @@ Array [
] ]
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 1`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "" 1`] = `
Object { Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124) "body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
", ",
@ -148,7 +150,7 @@ Object {
} }
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 2`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "" 2`] = `
Array [ Array [
Object { Object {
"headers": Object { "headers": Object {
@ -163,85 +165,7 @@ Array [
] ]
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 3`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "other@" 1`] = `
Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
",
"id": undefined,
"name": undefined,
"tag": "v1.0.1",
"url": "https://github.com/some/other-repository/releases/v1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 4`] = `
Array [
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate, br",
"host": "api.github.com",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
},
"method": "GET",
"url": "https://api.github.com/repos/some/other-repository/releases?per_page=100",
},
]
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 5`] = `
Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
",
"id": undefined,
"name": undefined,
"tag": "other-1.0.1",
"url": "https://github.com/some/other-repository/releases/other-1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 6`] = `
Array [
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate, br",
"host": "api.github.com",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
},
"method": "GET",
"url": "https://api.github.com/repos/some/other-repository/releases?per_page=100",
},
]
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 7`] = `
Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
",
"id": undefined,
"name": undefined,
"tag": "other_v1.0.1",
"url": "https://github.com/some/other-repository/releases/other_v1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 8`] = `
Array [
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate, br",
"host": "api.github.com",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
},
"method": "GET",
"url": "https://api.github.com/repos/some/other-repository/releases?per_page=100",
},
]
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 9`] = `
Object { Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124) "body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
", ",
@ -252,7 +176,7 @@ Object {
} }
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body 10`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "other@" 2`] = `
Array [ Array [
Object { Object {
"headers": Object { "headers": Object {
@ -267,9 +191,94 @@ Array [
] ]
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo 1`] = `null`; exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "other_v" 1`] = `
Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
",
"id": undefined,
"name": undefined,
"tag": "other_v1.0.1",
"url": "https://github.com/some/other-repository/releases/other_v1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo 2`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "other_v" 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate, br",
"host": "api.github.com",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
},
"method": "GET",
"url": "https://api.github.com/repos/some/other-repository/releases?per_page=100",
},
]
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "other-" 1`] = `
Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
",
"id": undefined,
"name": undefined,
"tag": "other-1.0.1",
"url": "https://github.com/some/other-repository/releases/other-1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "other-" 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate, br",
"host": "api.github.com",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
},
"method": "GET",
"url": "https://api.github.com/repos/some/other-repository/releases?per_page=100",
},
]
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "v" 1`] = `
Object {
"body": "some body [#123](https://github.com/some/other-repository/issues/123), [#124](https://github.com/some/yet-other-repository/issues/124)
",
"id": undefined,
"name": undefined,
"tag": "v1.0.1",
"url": "https://github.com/some/other-repository/releases/v1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body "v" 2`] = `
Array [
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate, br",
"host": "api.github.com",
"user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
},
"method": "GET",
"url": "https://api.github.com/repos/some/other-repository/releases?per_page=100",
},
]
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo "" 1`] = `
Object {
"body": "some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)",
"name": undefined,
"tag": "1.0.1",
"url": "https://gitlab.com/some/other-repository/tags/1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo "" 2`] = `
Array [ Array [
Object { Object {
"headers": Object { "headers": Object {
@ -284,9 +293,16 @@ Array [
] ]
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo other- 1`] = `null`; exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo "other-" 1`] = `
Object {
"body": "some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)",
"name": undefined,
"tag": "other-1.0.1",
"url": "https://gitlab.com/some/other-repository/tags/other-1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo other- 2`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo "other-" 2`] = `
Array [ Array [
Object { Object {
"headers": Object { "headers": Object {
@ -301,9 +317,16 @@ Array [
] ]
`; `;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo v 1`] = `null`; exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo "v" 1`] = `
Object {
"body": "some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)",
"name": undefined,
"tag": "v1.0.1",
"url": "https://gitlab.com/some/other-repository/tags/v1.0.1",
}
`;
exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo v 2`] = ` exports[`workers/pr/changelog/release-notes getReleaseNotes() gets release notes with body from gitlab repo "v" 2`] = `
Array [ Array [
Object { Object {
"headers": Object { "headers": Object {

View file

@ -1,4 +1,6 @@
import changelogFilenameRegex from 'changelog-filename-regex'; import changelogFilenameRegex from 'changelog-filename-regex';
import type { GithubRelease } from '../../../../datasource/github-releases/types';
import type { GitHubTag } from '../../../../datasource/github-tags/types';
import { logger } from '../../../../logger'; import { logger } from '../../../../logger';
import type { import type {
GithubGitBlob, GithubGitBlob,
@ -18,7 +20,7 @@ export async function getTags(
logger.trace('github.getTags()'); logger.trace('github.getTags()');
const url = `${endpoint}repos/${repository}/tags?per_page=100`; const url = `${endpoint}repos/${repository}/tags?per_page=100`;
try { try {
const res = await http.getJson<{ name: string }[]>(url, { const res = await http.getJson<GitHubTag[]>(url, {
paginate: true, paginate: true,
}); });
@ -30,8 +32,10 @@ export async function getTags(
return tags.map((tag) => tag.name).filter(Boolean); return tags.map((tag) => tag.name).filter(Boolean);
} catch (err) { } catch (err) {
logger.debug({ sourceRepo: repository }, 'Failed to fetch Github tags'); logger.debug(
logger.debug({ err }); { sourceRepo: repository, err },
'Failed to fetch Github tags'
);
// istanbul ignore if // istanbul ignore if
if (err.message?.includes('Bad credentials')) { if (err.message?.includes('Bad credentials')) {
logger.warn('Bad credentials triggering tag fail lookup in changelog'); logger.warn('Bad credentials triggering tag fail lookup in changelog');
@ -108,15 +112,7 @@ export async function getReleaseList(
const url = `${ensureTrailingSlash( const url = `${ensureTrailingSlash(
apiBaseUrl apiBaseUrl
)}repos/${repository}/releases?per_page=100`; )}repos/${repository}/releases?per_page=100`;
const res = await http.getJson< const res = await http.getJson<GithubRelease[]>(url, { paginate: true });
{
html_url: string;
id: number;
tag_name: string;
name: string;
body: string;
}[]
>(url, { paginate: true });
return res.body.map((release) => ({ return res.body.map((release) => ({
url: release.html_url, url: release.html_url,
id: release.id, id: release.id,

View file

@ -1,4 +1,6 @@
import changelogFilenameRegex from 'changelog-filename-regex'; import changelogFilenameRegex from 'changelog-filename-regex';
import type { GitlabRelease } from '../../../../datasource/gitlab-releases/types';
import type { GitlabTag } from '../../../../datasource/gitlab-tags/types';
import { logger } from '../../../../logger'; import { logger } from '../../../../logger';
import type { GitlabTreeNode } from '../../../../types/platform/gitlab'; import type { GitlabTreeNode } from '../../../../types/platform/gitlab';
import { GitlabHttp } from '../../../../util/http/gitlab'; import { GitlabHttp } from '../../../../util/http/gitlab';
@ -20,7 +22,7 @@ export async function getTags(
repository repository
)}/repository/tags?per_page=100`; )}/repository/tags?per_page=100`;
try { try {
const res = await http.getJson<{ name: string }[]>(url, { const res = await http.getJson<GitlabTag[]>(url, {
paginate: true, paginate: true,
}); });
@ -32,7 +34,10 @@ export async function getTags(
return tags.map((tag) => tag.name).filter(Boolean); return tags.map((tag) => tag.name).filter(Boolean);
} catch (err) { } catch (err) {
logger.info({ sourceRepo: repository }, 'Failed to fetch Gitlab tags'); logger.debug(
{ sourceRepo: repository, err },
'Failed to fetch Gitlab tags'
);
// istanbul ignore if // istanbul ignore if
if (err.message?.includes('Bad credentials')) { if (err.message?.includes('Bad credentials')) {
logger.warn('Bad credentials triggering tag fail lookup in changelog'); logger.warn('Bad credentials triggering tag fail lookup in changelog');
@ -101,14 +106,8 @@ export async function getReleaseList(
const apiUrl = `${ensureTrailingSlash( const apiUrl = `${ensureTrailingSlash(
apiBaseUrl apiBaseUrl
)}projects/${repoId}/releases`; )}projects/${repoId}/releases`;
const res = await http.getJson<
{ const res = await http.getJson<GitlabRelease[]>(`${apiUrl}?per_page=100`, {
name: string;
release: string;
description: string;
tag_name: string;
}[]
>(`${apiUrl}?per_page=100`, {
paginate: true, paginate: true,
}); });
return res.body.map((release) => ({ return res.body.map((release) => ({

View file

@ -10,7 +10,12 @@ import {
getReleaseNotesMd, getReleaseNotesMd,
releaseNotesCacheMinutes, releaseNotesCacheMinutes,
} from './release-notes'; } from './release-notes';
import type { ChangeLogNotes } from './types'; import type {
ChangeLogNotes,
ChangeLogProject,
ChangeLogRelease,
ChangeLogResult,
} from './types';
jest.mock('../../../util/host-rules'); jest.mock('../../../util/host-rules');
@ -37,6 +42,18 @@ const gitlabTreeResponse = [
{ path: 'README.md', type: 'blob' }, { path: 'README.md', type: 'blob' },
]; ];
const githubProject = {
type: 'github',
apiBaseUrl: 'https://api.github.com/',
baseUrl: 'https://github.com/',
} as ChangeLogProject;
const gitlabProject = {
type: 'gitlab',
apiBaseUrl: 'https://gitlab.com/api/v4/',
baseUrl: 'https://gitlab.com/',
} as ChangeLogProject;
describe('workers/pr/changelog/release-notes', () => { describe('workers/pr/changelog/release-notes', () => {
beforeEach(() => { beforeEach(() => {
hostRules.find.mockReturnValue({}); hostRules.find.mockReturnValue({});
@ -60,6 +77,7 @@ describe('workers/pr/changelog/release-notes', () => {
it('handles date object', () => { it('handles date object', () => {
expect(releaseNotesCacheMinutes(new Date())).toEqual(55); expect(releaseNotesCacheMinutes(new Date())).toEqual(55);
}); });
it.each([null, undefined, 'fake', 123])('handles invalid: %s', (date) => { it.each([null, undefined, 'fake', 123])('handles invalid: %s', (date) => {
expect(releaseNotesCacheMinutes(date as never)).toEqual(55); expect(releaseNotesCacheMinutes(date as never)).toEqual(55);
}); });
@ -69,31 +87,47 @@ describe('workers/pr/changelog/release-notes', () => {
it('returns input if invalid', async () => { it('returns input if invalid', async () => {
const input = { a: 1 }; const input = { a: 1 };
expect(await addReleaseNotes(input as never)).toEqual(input); expect(await addReleaseNotes(input as never)).toEqual(input);
expect(await addReleaseNotes(null)).toBeNull();
expect(await addReleaseNotes({ versions: [] } as never)).toStrictEqual({
versions: [],
});
}); });
it('returns ChangeLogResult', async () => { it('returns ChangeLogResult', async () => {
const input = { const input = {
a: 1, a: 1,
project: { github: 'https://github.com/nodeca/js-yaml' }, project: {
type: 'github',
repository: 'https://github.com/nodeca/js-yaml',
},
versions: [{ version: '3.10.0', compare: { url: '' } }], versions: [{ version: '3.10.0', compare: { url: '' } }],
}; };
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(await addReleaseNotes(input as never)).toMatchSnapshot(); expect(await addReleaseNotes(input as never)).toMatchSnapshot();
}); });
it('returns ChangeLogResult without release notes', async () => { it('returns ChangeLogResult without release notes', async () => {
const input = { const input = {
a: 1, a: 1,
project: { gitlab: 'https://gitlab.com/gitlab-org/gitter/webapp/' }, project: {
versions: [{ version: '20.26.0', compare: { url: '' } }], type: 'gitlab',
}; repository: 'https://gitlab.com/gitlab-org/gitter/webapp/',
} as ChangeLogProject,
versions: [
{ version: '20.26.0', compare: { url: '' } } as ChangeLogRelease,
],
} as ChangeLogResult;
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(await addReleaseNotes(input as never)).toMatchSnapshot(); expect(await addReleaseNotes(input)).toMatchSnapshot();
}); });
}); });
describe('getReleaseList()', () => { describe('getReleaseList()', () => {
it('should return empty array if no apiBaseUrl', async () => { it('should return empty array if no apiBaseUrl', async () => {
const res = await getReleaseList('', 'some/yet-other-repository'); const res = await getReleaseList({} as ChangeLogProject);
expect(res).toEqual([]); expect(res).toEqual([]);
}); });
it('should return release list for github repo', async () => { it('should return release list for github repo', async () => {
httpMock httpMock
.scope('https://api.github.com/') .scope('https://api.github.com/')
@ -106,14 +140,15 @@ describe('workers/pr/changelog/release-notes', () => {
}, },
]); ]);
const res = await getReleaseList( const res = await getReleaseList({
'https://api.github.com/', ...githubProject,
'some/yet-other-repository' repository: 'some/yet-other-repository',
); });
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it('should return release list for gitlab.com project', async () => { it('should return release list for gitlab.com project', async () => {
httpMock httpMock
.scope('https://gitlab.com/') .scope('https://gitlab.com/')
@ -127,14 +162,15 @@ describe('workers/pr/changelog/release-notes', () => {
body: 'some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)', body: 'some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)',
}, },
]); ]);
const res = await getReleaseList( const res = await getReleaseList({
'https://gitlab.com/api/v4/', ...gitlabProject,
'some/yet-other-repository' repository: 'some/yet-other-repository',
); });
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it('should return release list for self hosted gitlab project', async () => { it('should return release list for self hosted gitlab project', async () => {
hostRules.find.mockReturnValue({ token: 'some-token' }); hostRules.find.mockReturnValue({ token: 'some-token' });
httpMock httpMock
@ -149,15 +185,18 @@ describe('workers/pr/changelog/release-notes', () => {
body: 'some body #123, [#124](https://my.custom.domain/some/yet-other-repository/issues/124)', body: 'some body #123, [#124](https://my.custom.domain/some/yet-other-repository/issues/124)',
}, },
]); ]);
const res = await getReleaseList( const res = await getReleaseList({
'https://my.custom.domain/api/v4/', ...gitlabProject,
'some/yet-other-repository' repository: 'some/yet-other-repository',
); apiBaseUrl: 'https://my.custom.domain/api/v4/',
baseUrl: 'https://my.custom.domain/',
});
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
}); });
describe('getReleaseNotes()', () => { describe('getReleaseNotes()', () => {
it('should return null for release notes without body', async () => { it('should return null for release notes without body', async () => {
httpMock httpMock
@ -165,17 +204,19 @@ describe('workers/pr/changelog/release-notes', () => {
.get('/repos/some/repository/releases?per_page=100') .get('/repos/some/repository/releases?per_page=100')
.reply(200, [{ tag_name: 'v1.0.0' }, { tag_name: 'v1.0.1' }]); .reply(200, [{ tag_name: 'v1.0.0' }, { tag_name: 'v1.0.1' }]);
const res = await getReleaseNotes( const res = await getReleaseNotes(
'some/repository', {
'1.0.0', ...githubProject,
'some', repository: 'some/repository',
'https://github.com/', depName: 'some',
'https://api.github.com/' },
'1.0.0'
); );
expect(res).toBeNull(); expect(res).toBeNull();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it.each([[''], ['v'], ['other-'], ['other_v'], ['other@']])( it.each([[''], ['v'], ['other-'], ['other_v'], ['other@']])(
'gets release notes with body', 'gets release notes with body "%s"',
async (prefix) => { async (prefix) => {
httpMock httpMock
.scope('https://api.github.com/') .scope('https://api.github.com/')
@ -188,19 +229,21 @@ describe('workers/pr/changelog/release-notes', () => {
}, },
]); ]);
const res = await getReleaseNotes( const res = await getReleaseNotes(
'some/other-repository', {
'1.0.1', ...githubProject,
'other', repository: 'some/other-repository',
'https://github.com/', depName: 'other',
'https://api.github.com/' },
'1.0.1'
); );
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
} }
); );
it.each([[''], ['v'], ['other-']])( it.each([[''], ['v'], ['other-']])(
'gets release notes with body from gitlab repo %s', 'gets release notes with body from gitlab repo "%s"',
async (prefix) => { async (prefix) => {
httpMock httpMock
.scope('https://api.gitlab.com/') .scope('https://api.gitlab.com/')
@ -209,52 +252,53 @@ describe('workers/pr/changelog/release-notes', () => {
{ tag_name: `${prefix}1.0.0` }, { tag_name: `${prefix}1.0.0` },
{ {
tag_name: `${prefix}1.0.1`, tag_name: `${prefix}1.0.1`,
body: 'some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)', description:
'some body #123, [#124](https://gitlab.com/some/yet-other-repository/issues/124)',
}, },
]); ]);
const res = await getReleaseNotes( const res = await getReleaseNotes(
'some/other-repository', {
'1.0.1', ...gitlabProject,
'other', repository: 'some/other-repository',
'https://gitlab.com/', depName: 'other',
'https://api.gitlab.com/' apiBaseUrl: 'https://api.gitlab.com/',
},
'1.0.1'
); );
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
} }
); );
it.each([[''], ['v'], ['other-']])(
'gets null from repository without gitlab/github in domain %s', it('gets null from repository without gitlab/github in domain', async () => {
async (prefix) => { const res = await getReleaseNotes(
// FIXME: Should not call `api.lol.lol` ? {
httpMock repository: 'some/repository',
.scope('https://api.lol.lol') depName: 'other',
.get('/repos/some/other-repository/releases?per_page=100') apiBaseUrl: 'https://api.lol.lol/',
.reply(404); baseUrl: 'https://lol.lol/',
const res = await getReleaseNotes( } as ChangeLogProject,
'some/other-repository', '1.0.1'
'1.0.1', );
'other', expect(res).toBeNull();
'https://lol.lol/', });
'https://api.lol.lol/'
);
expect(res).toBeNull();
}
);
}); });
describe('getReleaseNotesMd()', () => { describe('getReleaseNotesMd()', () => {
it('handles not found', async () => { it('handles not found', async () => {
httpMock.scope('https://api.github.com').get('/repos/chalk').reply(404); httpMock.scope('https://api.github.com').get('/repos/chalk').reply(404);
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'chalk', {
'2.0.0', ...githubProject,
'https://github.com/', repository: 'chalk',
'https://api.github.com/' },
'2.0.0'
); );
expect(res).toBeNull(); expect(res).toBeNull();
}); });
it('handles files mismatch', async () => { it('handles files mismatch', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -268,14 +312,16 @@ describe('workers/pr/changelog/release-notes', () => {
], ],
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'chalk', {
'2.0.0', ...githubProject,
'https://github.com/', repository: 'chalk',
'https://api.github.com/' },
'2.0.0'
); );
expect(res).toBeNull(); expect(res).toBeNull();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it('handles wrong format', async () => { it('handles wrong format', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -288,14 +334,16 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from('not really markdown').toString('base64'), content: Buffer.from('not really markdown').toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'some/repository1', {
'1.0.0', ...githubProject,
'https://github.com/', repository: 'some/repository1',
'https://api.github.com/' },
'1.0.0'
); );
expect(res).toBeNull(); expect(res).toBeNull();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it('handles bad markdown', async () => { it('handles bad markdown', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -308,14 +356,16 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(`#\nha\nha\n#\nha\nha`).toString('base64'), content: Buffer.from(`#\nha\nha\n#\nha\nha`).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'some/repository2', {
'1.0.0', ...githubProject,
'https://github.com/', repository: 'some/repository2',
'https://api.github.com/' },
'1.0.0'
); );
expect(res).toBeNull(); expect(res).toBeNull();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it('parses angular.js', async () => { it('parses angular.js', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -328,16 +378,18 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(angularJsChangelogMd).toString('base64'), content: Buffer.from(angularJsChangelogMd).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'angular/angular.js', {
'1.6.9', ...githubProject,
'https://github.com/', repository: 'angular/angular.js',
'https://api.github.com/' },
'1.6.9'
); );
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
}); });
it('parses gitlab.com/gitlab-org/gitter/webapp', async () => { it('parses gitlab.com/gitlab-org/gitter/webapp', async () => {
jest.setTimeout(0); jest.setTimeout(0);
httpMock httpMock
@ -349,16 +401,19 @@ describe('workers/pr/changelog/release-notes', () => {
.get('/projects/gitlab-org%2fgitter%2fwebapp/repository/blobs/abcd/raw') .get('/projects/gitlab-org%2fgitter%2fwebapp/repository/blobs/abcd/raw')
.reply(200, gitterWebappChangelogMd); .reply(200, gitterWebappChangelogMd);
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'gitlab-org/gitter/webapp', {
'20.26.0', ...gitlabProject,
'https://gitlab.com/', repository: 'gitlab-org/gitter/webapp',
'https://api.gitlab.com/' apiBaseUrl: 'https://api.gitlab.com/',
},
'20.26.0'
); );
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('parses self hosted gitlab', async () => { it('parses self hosted gitlab', async () => {
hostRules.find.mockReturnValue({ token: 'some-token' }); hostRules.find.mockReturnValue({ token: 'some-token' });
jest.setTimeout(0); jest.setTimeout(0);
@ -371,16 +426,20 @@ describe('workers/pr/changelog/release-notes', () => {
.get('/projects/gitlab-org%2fgitter%2fwebapp/repository/blobs/abcd/raw') .get('/projects/gitlab-org%2fgitter%2fwebapp/repository/blobs/abcd/raw')
.reply(200, gitterWebappChangelogMd); .reply(200, gitterWebappChangelogMd);
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'gitlab-org/gitter/webapp', {
'20.26.0', ...gitlabProject,
'https://my.custom.domain/', repository: 'gitlab-org/gitter/webapp',
'https://my.custom.domain/' apiBaseUrl: 'https://my.custom.domain/',
baseUrl: 'https://my.custom.domain/',
},
'20.26.0'
); );
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('parses jest', async () => { it('parses jest', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -393,16 +452,18 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(jestChangelogMd).toString('base64'), content: Buffer.from(jestChangelogMd).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'facebook/jest', {
'22.0.0', ...githubProject,
'https://github.com/', repository: 'facebook/jest',
'https://api.github.com/' },
'22.0.0'
); );
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('handles github sourceDirectory', async () => { it('handles github sourceDirectory', async () => {
const sourceDirectory = 'packages/foo'; const sourceDirectory = 'packages/foo';
const subdirTree = clone(githubTreeResponse); const subdirTree = clone(githubTreeResponse);
@ -420,17 +481,19 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(jsYamlChangelogMd).toString('base64'), content: Buffer.from(jsYamlChangelogMd).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'nodeca/js-yaml', {
'3.10.0', ...githubProject,
'https://github.com/', repository: 'nodeca/js-yaml',
'https://api.github.com/', sourceDirectory,
sourceDirectory },
'3.10.0'
); );
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('parses js-yaml', async () => { it('parses js-yaml', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -443,16 +506,28 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(jsYamlChangelogMd).toString('base64'), content: Buffer.from(jsYamlChangelogMd).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'nodeca/js-yaml', {
'3.10.0', ...githubProject,
'https://github.com/', repository: 'nodeca/js-yaml',
'https://api.github.com/' },
'3.10.0'
); );
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
// FIXME: explicit assert condition // FIXME: explicit assert condition
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('ignores invalid', async () => {
const res = await getReleaseNotesMd(
{
repository: 'nodeca/js-yaml',
} as ChangeLogProject,
'3.10.0'
);
expect(res).toBeNull();
});
describe('ReleaseNotes Correctness', () => { describe('ReleaseNotes Correctness', () => {
let versionOneNotes: ChangeLogNotes; let versionOneNotes: ChangeLogNotes;
let versionTwoNotes: ChangeLogNotes; let versionTwoNotes: ChangeLogNotes;
@ -468,10 +543,11 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(yargsChangelogMd).toString('base64'), content: Buffer.from(yargsChangelogMd).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'yargs/yargs', {
'15.3.0', ...githubProject,
'https://github.com/', repository: 'yargs/yargs',
'https://api.github.com/' },
'15.3.0'
); );
versionOneNotes = res; versionOneNotes = res;
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
@ -479,6 +555,7 @@ describe('workers/pr/changelog/release-notes', () => {
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('parses yargs 15.2.0', async () => { it('parses yargs 15.2.0', async () => {
httpMock httpMock
.scope('https://api.github.com') .scope('https://api.github.com')
@ -491,10 +568,11 @@ describe('workers/pr/changelog/release-notes', () => {
content: Buffer.from(yargsChangelogMd).toString('base64'), content: Buffer.from(yargsChangelogMd).toString('base64'),
}); });
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'yargs/yargs', {
'15.2.0', ...githubProject,
'https://github.com/', repository: 'yargs/yargs',
'https://api.github.com/' },
'15.2.0'
); );
versionTwoNotes = res; versionTwoNotes = res;
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
@ -502,6 +580,7 @@ describe('workers/pr/changelog/release-notes', () => {
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('parses adapter-utils 4.33.0', async () => { it('parses adapter-utils 4.33.0', async () => {
httpMock httpMock
.scope('https://gitlab.com/') .scope('https://gitlab.com/')
@ -514,10 +593,11 @@ describe('workers/pr/changelog/release-notes', () => {
) )
.reply(200, adapterutilsChangelogMd); .reply(200, adapterutilsChangelogMd);
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'itentialopensource/adapter-utils', {
'4.33.0', ...gitlabProject,
'https://gitlab.com/', repository: 'itentialopensource/adapter-utils',
'https://gitlab.com/api/v4/' },
'4.33.0'
); );
versionTwoNotes = res; versionTwoNotes = res;
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
@ -525,6 +605,7 @@ describe('workers/pr/changelog/release-notes', () => {
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('handles gitlab sourceDirectory', async () => { it('handles gitlab sourceDirectory', async () => {
const sourceDirectory = 'packages/foo'; const sourceDirectory = 'packages/foo';
const response = clone(gitlabTreeResponse).map((file) => ({ const response = clone(gitlabTreeResponse).map((file) => ({
@ -542,11 +623,12 @@ describe('workers/pr/changelog/release-notes', () => {
) )
.reply(200, adapterutilsChangelogMd); .reply(200, adapterutilsChangelogMd);
const res = await getReleaseNotesMd( const res = await getReleaseNotesMd(
'itentialopensource/adapter-utils', {
'4.33.0', ...gitlabProject,
'https://gitlab.com/', repository: 'itentialopensource/adapter-utils',
'https://gitlab.com/api/v4/', sourceDirectory,
sourceDirectory },
'4.33.0'
); );
versionTwoNotes = res; versionTwoNotes = res;
expect(httpMock.getTrace()).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot();
@ -554,9 +636,11 @@ describe('workers/pr/changelog/release-notes', () => {
expect(res).not.toBeNull(); expect(res).not.toBeNull();
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
}); });
it('isUrl', () => { it('isUrl', () => {
expect(versionOneNotes).not.toMatchObject(versionTwoNotes); expect(versionOneNotes).not.toMatchObject(versionTwoNotes);
}); });
it('15.3.0 is not equal to 15.2.0', () => { it('15.3.0 is not equal to 15.2.0', () => {
expect(versionOneNotes).not.toMatchObject(versionTwoNotes); expect(versionOneNotes).not.toMatchObject(versionTwoNotes);
}); });

View file

@ -2,64 +2,61 @@ import * as URL from 'url';
import is from '@sindresorhus/is'; import is from '@sindresorhus/is';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import MarkdownIt from 'markdown-it'; import MarkdownIt from 'markdown-it';
import { PLATFORM_TYPE_GITLAB } from '../../../constants/platforms';
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import * as memCache from '../../../util/cache/memory'; import * as memCache from '../../../util/cache/memory';
import * as packageCache from '../../../util/cache/package'; import * as packageCache from '../../../util/cache/package';
import * as hostRules from '../../../util/host-rules';
import { linkify } from '../../../util/markdown'; import { linkify } from '../../../util/markdown';
import * as github from './github'; import * as github from './github';
import * as gitlab from './gitlab'; import * as gitlab from './gitlab';
import type { ChangeLogFile, ChangeLogNotes, ChangeLogResult } from './types'; import type {
ChangeLogFile,
ChangeLogNotes,
ChangeLogProject,
ChangeLogResult,
} from './types';
const markdown = new MarkdownIt('zero'); const markdown = new MarkdownIt('zero');
markdown.enable(['heading', 'lheading']); markdown.enable(['heading', 'lheading']);
export async function getReleaseList( export async function getReleaseList(
apiBaseUrl: string, project: ChangeLogProject
repository: string
): Promise<ChangeLogNotes[]> { ): Promise<ChangeLogNotes[]> {
logger.trace('getReleaseList()'); logger.trace('getReleaseList()');
// istanbul ignore if const { apiBaseUrl, repository, type } = project;
if (!apiBaseUrl) {
logger.debug('No apiBaseUrl');
return [];
}
try { try {
if (apiBaseUrl.includes('gitlab')) { switch (type) {
return await gitlab.getReleaseList(apiBaseUrl, repository); case 'gitlab':
} return await gitlab.getReleaseList(apiBaseUrl, repository);
case 'github':
return await github.getReleaseList(apiBaseUrl, repository);
const opts = hostRules.find({ default:
hostType: PLATFORM_TYPE_GITLAB, logger.warn({ apiBaseUrl, repository, type }, 'Invalid project type');
url: apiBaseUrl, return [];
});
if (opts.token) {
return await gitlab.getReleaseList(apiBaseUrl, repository);
} }
return await github.getReleaseList(apiBaseUrl, repository);
} catch (err) /* istanbul ignore next */ { } catch (err) /* istanbul ignore next */ {
if (err.statusCode === 404) { if (err.statusCode === 404) {
logger.debug({ repository }, 'getReleaseList 404'); logger.debug({ repository, type, apiBaseUrl }, 'getReleaseList 404');
} else { } else {
logger.info({ repository, err }, 'getReleaseList error'); logger.debug(
{ repository, type, apiBaseUrl, err },
'getReleaseList error'
);
} }
return [];
} }
return [];
} }
export function getCachedReleaseList( export function getCachedReleaseList(
apiBaseUrl: string, project: ChangeLogProject
repository: string
): Promise<ChangeLogNotes[]> { ): Promise<ChangeLogNotes[]> {
const cacheKey = `getReleaseList-${apiBaseUrl}-${repository}`; const cacheKey = `getReleaseList-${project.apiBaseUrl}-${project.repository}`;
const cachedResult = memCache.get<Promise<ChangeLogNotes[]>>(cacheKey); const cachedResult = memCache.get<Promise<ChangeLogNotes[]>>(cacheKey);
// istanbul ignore if // istanbul ignore if
if (cachedResult !== undefined) { if (cachedResult !== undefined) {
return cachedResult; return cachedResult;
} }
const promisedRes = getReleaseList(apiBaseUrl, repository); const promisedRes = getReleaseList(project);
memCache.set(cacheKey, promisedRes); memCache.set(cacheKey, promisedRes);
return promisedRes; return promisedRes;
} }
@ -94,14 +91,12 @@ export function massageBody(
} }
export async function getReleaseNotes( export async function getReleaseNotes(
repository: string, project: ChangeLogProject,
version: string, version: string
depName: string,
baseUrl: string,
apiBaseUrl: string
): Promise<ChangeLogNotes | null> { ): Promise<ChangeLogNotes | null> {
const { baseUrl, depName, repository } = project;
logger.trace(`getReleaseNotes(${repository}, ${version}, ${depName})`); logger.trace(`getReleaseNotes(${repository}, ${version}, ${depName})`);
const releaseList = await getCachedReleaseList(apiBaseUrl, repository); const releaseList = await getCachedReleaseList(project);
logger.trace({ releaseList }, 'Release list from getReleaseList'); logger.trace({ releaseList }, 'Release list from getReleaseList');
let releaseNotes: ChangeLogNotes | null = null; let releaseNotes: ChangeLogNotes | null = null;
for (const release of releaseList) { for (const release of releaseList) {
@ -172,84 +167,70 @@ function isUrl(url: string): boolean {
} }
export async function getReleaseNotesMdFileInner( export async function getReleaseNotesMdFileInner(
repository: string, project: ChangeLogProject
apiBaseUrl: string,
sourceDirectory?: string
): Promise<ChangeLogFile> | null { ): Promise<ChangeLogFile> | null {
const { apiBaseUrl, repository, sourceDirectory, type } = project;
try { try {
if (apiBaseUrl.includes('gitlab')) { switch (type) {
return await gitlab.getReleaseNotesMd( case 'gitlab':
repository, return await gitlab.getReleaseNotesMd(
apiBaseUrl, repository,
sourceDirectory apiBaseUrl,
); sourceDirectory
} );
case 'github':
return await github.getReleaseNotesMd(
repository,
apiBaseUrl,
sourceDirectory
);
const opts = hostRules.find({ default:
hostType: PLATFORM_TYPE_GITLAB, logger.warn({ apiBaseUrl, repository, type }, 'Invalid project type');
url: apiBaseUrl, return null;
});
if (opts.token) {
return await gitlab.getReleaseNotesMd(
repository,
apiBaseUrl,
sourceDirectory
);
} }
return await github.getReleaseNotesMd(
repository,
apiBaseUrl,
sourceDirectory
);
} catch (err) /* istanbul ignore next */ { } catch (err) /* istanbul ignore next */ {
if (err.statusCode === 404) { if (err.statusCode === 404) {
logger.debug('Error 404 getting changelog md'); logger.debug(
{ repository, type, apiBaseUrl },
'Error 404 getting changelog md'
);
} else { } else {
logger.debug({ err, repository }, 'Error getting changelog md'); logger.debug(
{ err, repository, type, apiBaseUrl },
'Error getting changelog md'
);
} }
return null;
} }
return null;
} }
export function getReleaseNotesMdFile( export function getReleaseNotesMdFile(
repository: string, project: ChangeLogProject
apiBaseUrl: string,
sourceDirectory?: string
): Promise<ChangeLogFile | null> { ): Promise<ChangeLogFile | null> {
const cacheKey = `getReleaseNotesMdFile-${repository}-${apiBaseUrl}`; const cacheKey = `getReleaseNotesMdFile-${project.repository}-${project.apiBaseUrl}`;
const cachedResult = memCache.get<Promise<ChangeLogFile | null>>(cacheKey); const cachedResult = memCache.get<Promise<ChangeLogFile | null>>(cacheKey);
// istanbul ignore if // istanbul ignore if
if (cachedResult !== undefined) { if (cachedResult !== undefined) {
return cachedResult; return cachedResult;
} }
const promisedRes = getReleaseNotesMdFileInner( const promisedRes = getReleaseNotesMdFileInner(project);
repository,
apiBaseUrl,
sourceDirectory
);
memCache.set(cacheKey, promisedRes); memCache.set(cacheKey, promisedRes);
return promisedRes; return promisedRes;
} }
export async function getReleaseNotesMd( export async function getReleaseNotesMd(
repository: string, project: ChangeLogProject,
version: string, version: string
baseUrl: string,
apiBaseUrl: string,
sourceDirectory?: string
): Promise<ChangeLogNotes | null> { ): Promise<ChangeLogNotes | null> {
const { baseUrl, repository } = project;
logger.trace(`getReleaseNotesMd(${repository}, ${version})`); logger.trace(`getReleaseNotesMd(${repository}, ${version})`);
const skippedRepos = ['facebook/react-native']; const skippedRepos = ['facebook/react-native'];
// istanbul ignore if // istanbul ignore if
if (skippedRepos.includes(repository)) { if (skippedRepos.includes(repository)) {
return null; return null;
} }
const changelog = await getReleaseNotesMdFile( const changelog = await getReleaseNotesMdFile(project);
repository,
apiBaseUrl,
sourceDirectory
);
if (!changelog) { if (!changelog) {
return null; return null;
} }
@ -332,20 +313,13 @@ export function releaseNotesCacheMinutes(releaseDate?: string | Date): number {
export async function addReleaseNotes( export async function addReleaseNotes(
input: ChangeLogResult input: ChangeLogResult
): Promise<ChangeLogResult> { ): Promise<ChangeLogResult> {
if ( if (!input?.versions || !input.project?.type) {
!input?.versions ||
(!input?.project?.github && !input?.project?.gitlab)
) {
logger.debug('Missing project or versions'); logger.debug('Missing project or versions');
return input; return input;
} }
const output: ChangeLogResult = { ...input, versions: [] }; const output: ChangeLogResult = { ...input, versions: [] };
const repository = input.project.github const repository = input.project.repository;
? input.project.github.replace(/\.git$/, '') const cacheNamespace = `changelog-${input.project.type}-notes`;
: input.project.gitlab;
const cacheNamespace = input.project.github
? 'changelog-github-notes'
: 'changelog-gitlab-notes';
function getCacheKey(version: string): string { function getCacheKey(version: string): string {
return `${repository}:${version}`; return `${repository}:${version}`;
} }
@ -355,23 +329,10 @@ export async function addReleaseNotes(
releaseNotes = await packageCache.get(cacheNamespace, cacheKey); releaseNotes = await packageCache.get(cacheNamespace, cacheKey);
// istanbul ignore else: no cache tests // istanbul ignore else: no cache tests
if (!releaseNotes) { if (!releaseNotes) {
const { sourceDirectory } = input.project; releaseNotes = await getReleaseNotesMd(input.project, v.version);
releaseNotes = await getReleaseNotesMd(
repository,
v.version,
input.project.baseUrl,
input.project.apiBaseUrl,
sourceDirectory
);
// istanbul ignore else: should be tested // istanbul ignore else: should be tested
if (!releaseNotes) { if (!releaseNotes) {
releaseNotes = await getReleaseNotes( releaseNotes = await getReleaseNotes(input.project, v.version);
repository,
v.version,
input.project.depName,
input.project.baseUrl,
input.project.apiBaseUrl
);
} }
// Small hack to force display of release notes when there is a compare url // Small hack to force display of release notes when there is a compare url
if (!releaseNotes && v.compare.url) { if (!releaseNotes && v.compare.url) {

View file

@ -68,7 +68,10 @@ export async function getChangeLogJSON({
const apiBaseUrl = sourceUrl.startsWith('https://github.com/') const apiBaseUrl = sourceUrl.startsWith('https://github.com/')
? 'https://api.github.com/' ? 'https://api.github.com/'
: baseUrl + 'api/v3/'; : baseUrl + 'api/v3/';
const repository = pathname.slice(1).replace(/\/$/, ''); const repository = pathname
.slice(1)
.replace(/\/$/, '')
.replace(/\.git$/, '');
if (repository.split('/').length !== 2) { if (repository.split('/').length !== 2) {
logger.debug({ sourceUrl }, 'Invalid github URL found'); logger.debug({ sourceUrl }, 'Invalid github URL found');
return null; return null;
@ -154,8 +157,9 @@ export async function getChangeLogJSON({
project: { project: {
apiBaseUrl, apiBaseUrl,
baseUrl, baseUrl,
github: repository, type: 'github',
repository: sourceUrl, repository,
sourceUrl,
sourceDirectory, sourceDirectory,
depName, depName,
}, },

View file

@ -130,8 +130,9 @@ export async function getChangeLogJSON({
project: { project: {
apiBaseUrl, apiBaseUrl,
baseUrl, baseUrl,
gitlab: repository, type: 'gitlab',
repository: sourceUrl, repository,
sourceUrl,
depName, depName,
}, },
versions: changelogReleases, versions: changelogReleases,

View file

@ -22,11 +22,11 @@ export interface ChangeLogRelease {
export interface ChangeLogProject { export interface ChangeLogProject {
depName?: string; depName?: string;
github?: string; type: 'github' | 'gitlab';
gitlab?: string;
apiBaseUrl?: string; apiBaseUrl?: string;
baseUrl: string; baseUrl: string;
repository: string; repository: string;
sourceUrl: string;
sourceDirectory?: string; sourceDirectory?: string;
} }

View file

@ -1,21 +1,18 @@
import { git, mocked, partial } from '../../../test/util'; import { getConfig, git, mocked, partial, platform } from '../../../test/util';
import { getConfig } from '../../config/defaults';
import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms'; import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
import { Pr, platform as _platform } from '../../platform'; import type { Pr } from '../../platform/types';
import { BranchStatus } from '../../types'; import { BranchStatus } from '../../types';
import * as _limits from '../global/limits'; import * as _limits from '../global/limits';
import type { BranchConfig } from '../types'; import type { BranchConfig } from '../types';
import * as prAutomerge from './automerge'; import * as prAutomerge from './automerge';
import * as _changelogHelper from './changelog'; import * as _changelogHelper from './changelog';
import { getChangeLogJSON } from './changelog'; import type { ChangeLogResult } from './changelog';
import * as codeOwners from './code-owners'; import * as codeOwners from './code-owners';
import * as prWorker from '.'; import * as prWorker from '.';
const codeOwnersMock = mocked(codeOwners); const codeOwnersMock = mocked(codeOwners);
const changelogHelper = mocked(_changelogHelper); const changelogHelper = mocked(_changelogHelper);
const gitlabChangelogHelper = mocked(_changelogHelper); const gitlabChangelogHelper = mocked(_changelogHelper);
const platform = mocked(_platform);
const defaultConfig = getConfig();
const limits = mocked(_limits); const limits = mocked(_limits);
jest.mock('../../util/git'); jest.mock('../../util/git');
@ -24,12 +21,12 @@ jest.mock('./code-owners');
jest.mock('../global/limits'); jest.mock('../global/limits');
function setupChangelogMock() { function setupChangelogMock() {
changelogHelper.getChangeLogJSON = jest.fn();
const resultValue = { const resultValue = {
project: { project: {
type: 'github',
baseUrl: 'https://github.com/', baseUrl: 'https://github.com/',
github: 'renovateapp/dummy', repository: 'renovateapp/dummy',
repository: 'https://github.com/renovateapp/dummy', sourceUrl: 'https://github.com/renovateapp/dummy',
}, },
hasReleaseNotes: true, hasReleaseNotes: true,
versions: [ versions: [
@ -51,7 +48,7 @@ function setupChangelogMock() {
}, },
}, },
], ],
}; } as ChangeLogResult;
const errorValue = { const errorValue = {
error: _changelogHelper.ChangeLogError.MissingGithubToken, error: _changelogHelper.ChangeLogError.MissingGithubToken,
}; };
@ -61,12 +58,12 @@ function setupChangelogMock() {
} }
function setupGitlabChangelogMock() { function setupGitlabChangelogMock() {
gitlabChangelogHelper.getChangeLogJSON = jest.fn();
const resultValue = { const resultValue = {
project: { project: {
type: 'gitlab',
baseUrl: 'https://gitlab.com/', baseUrl: 'https://gitlab.com/',
gitlab: 'renovateapp/gitlabdummy', repository: 'renovateapp/gitlabdummy',
repository: 'https://gitlab.com/renovateapp/gitlabdummy', sourceUrl: 'https://gitlab.com/renovateapp/gitlabdummy',
}, },
hasReleaseNotes: true, hasReleaseNotes: true,
versions: [ versions: [
@ -88,7 +85,7 @@ function setupGitlabChangelogMock() {
}, },
}, },
], ],
}; } as ChangeLogResult;
const errorValue = { const errorValue = {
error: _changelogHelper.ChangeLogError.MissingGithubToken, error: _changelogHelper.ChangeLogError.MissingGithubToken,
}; };
@ -103,7 +100,7 @@ describe('workers/pr/index', () => {
let pr: Pr; let pr: Pr;
beforeEach(() => { beforeEach(() => {
config = partial<BranchConfig>({ config = partial<BranchConfig>({
...defaultConfig, ...getConfig(),
}); });
pr = partial<Pr>({ pr = partial<Pr>({
canMerge: true, canMerge: true,
@ -180,7 +177,7 @@ describe('workers/pr/index', () => {
jest.resetAllMocks(); jest.resetAllMocks();
setupChangelogMock(); setupChangelogMock();
config = partial<BranchConfig>({ config = partial<BranchConfig>({
...defaultConfig, ...getConfig(),
}); });
config.branchName = 'renovate/dummy-1.x'; config.branchName = 'renovate/dummy-1.x';
config.prTitle = 'Update dependency dummy to v1.1.0'; config.prTitle = 'Update dependency dummy to v1.1.0';
@ -199,9 +196,7 @@ describe('workers/pr/index', () => {
displayNumber: 'New Pull Request', displayNumber: 'New Pull Request',
} as never); } as never);
config.upgrades = [config]; config.upgrades = [config];
platform.massageMarkdown = jest.fn((input) => input); platform.massageMarkdown.mockImplementation((input) => input);
platform.getBranchPr = jest.fn();
platform.getBranchStatus = jest.fn();
}); });
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
@ -252,7 +247,7 @@ describe('workers/pr/index', () => {
}); });
it('should create PR if success', async () => { it('should create PR if success', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.automerge = true; config.automerge = true;
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
@ -264,7 +259,7 @@ describe('workers/pr/index', () => {
}); });
it('should not create PR if limit is reached', async () => { it('should not create PR if limit is reached', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.automerge = true; config.automerge = true;
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
@ -275,7 +270,7 @@ describe('workers/pr/index', () => {
}); });
it('should create PR if limit is reached but dashboard checked', async () => { it('should create PR if limit is reached but dashboard checked', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.automerge = true; config.automerge = true;
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
@ -315,7 +310,7 @@ describe('workers/pr/index', () => {
config.recreateClosed = true; config.recreateClosed = true;
config.rebaseWhen = 'never'; config.rebaseWhen = 'never';
for (const upgrade of config.upgrades) { for (const upgrade of config.upgrades) {
upgrade.logJSON = await getChangeLogJSON(upgrade); upgrade.logJSON = await changelogHelper.getChangeLogJSON(upgrade);
} }
const { pr } = await prWorker.ensurePr(config); const { pr } = await prWorker.ensurePr(config);
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
@ -330,7 +325,7 @@ describe('workers/pr/index', () => {
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
config.timezone = 'some timezone'; config.timezone = 'some timezone';
config.rebaseWhen = 'behind-base-branch'; config.rebaseWhen = 'behind-base-branch';
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
const { pr } = await prWorker.ensurePr(config); const { pr } = await prWorker.ensurePr(config);
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
// FIXME: explicit assert condition // FIXME: explicit assert condition
@ -341,7 +336,6 @@ describe('workers/pr/index', () => {
}); });
it('should return null if creating PR fails', async () => { it('should return null if creating PR fails', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
platform.createPr = jest.fn();
platform.createPr.mockImplementationOnce(() => { platform.createPr.mockImplementationOnce(() => {
throw new Error('Validation Failed (422)'); throw new Error('Validation Failed (422)');
}); });
@ -405,6 +399,7 @@ describe('workers/pr/index', () => {
config.assignees = ['@foo', 'bar']; config.assignees = ['@foo', 'bar'];
config.reviewers = ['foo', '@bar', 'foo@bar.com']; config.reviewers = ['foo', '@bar', 'foo@bar.com'];
config.filterUnavailableUsers = true; config.filterUnavailableUsers = true;
// optional function is undefined by jest
platform.filterUnavailableUsers = jest.fn(); platform.filterUnavailableUsers = jest.fn();
platform.filterUnavailableUsers.mockResolvedValue(['foo']); platform.filterUnavailableUsers.mockResolvedValue(['foo']);
await prWorker.ensurePr(config); await prWorker.ensurePr(config);
@ -523,7 +518,7 @@ describe('workers/pr/index', () => {
config.semanticCommitScope = null; config.semanticCommitScope = null;
config.automerge = true; config.automerge = true;
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
const { pr } = await prWorker.ensurePr(config); const { pr } = await prWorker.ensurePr(config);
expect(platform.updatePr.mock.calls).toMatchSnapshot(); expect(platform.updatePr.mock.calls).toMatchSnapshot();
expect(platform.updatePr).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0);
@ -537,7 +532,7 @@ describe('workers/pr/index', () => {
config.semanticCommitScope = null; config.semanticCommitScope = null;
config.automerge = true; config.automerge = true;
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
const { pr } = await prWorker.ensurePr(config); const { pr } = await prWorker.ensurePr(config);
expect(platform.updatePr).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0);
expect(pr).toMatchObject(modifiedPr); expect(pr).toMatchObject(modifiedPr);
@ -546,7 +541,7 @@ describe('workers/pr/index', () => {
config.newValue = '1.2.0'; config.newValue = '1.2.0';
config.automerge = true; config.automerge = true;
config.schedule = ['before 5am']; config.schedule = ['before 5am'];
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
platform.getBranchPr.mockResolvedValueOnce(existingPr); platform.getBranchPr.mockResolvedValueOnce(existingPr);
const { pr } = await prWorker.ensurePr(config); const { pr } = await prWorker.ensurePr(config);
// FIXME: explicit assert condition // FIXME: explicit assert condition
@ -614,9 +609,8 @@ describe('workers/pr/index', () => {
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.privateRepo = false; config.privateRepo = false;
config.logJSON = await getChangeLogJSON(config); config.logJSON = await changelogHelper.getChangeLogJSON(config);
config.logJSON.project.gitlab = 'someproject'; config.logJSON.project.repository = 'someproject';
delete config.logJSON.project.github;
const { pr } = await prWorker.ensurePr(config); const { pr } = await prWorker.ensurePr(config);
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
expect(platform.createPr.mock.calls[0]).toMatchSnapshot(); expect(platform.createPr.mock.calls[0]).toMatchSnapshot();

View file

@ -278,9 +278,7 @@ export async function ensurePr(
if (logJSON) { if (logJSON) {
if (typeof logJSON.error === 'undefined') { if (typeof logJSON.error === 'undefined') {
if (logJSON.project) { if (logJSON.project) {
upgrade.repoName = logJSON.project.github upgrade.repoName = logJSON.project.repository;
? logJSON.project.github
: logJSON.project.gitlab;
} }
upgrade.hasReleaseNotes = logJSON.hasReleaseNotes; upgrade.hasReleaseNotes = logJSON.hasReleaseNotes;
upgrade.releases = []; upgrade.releases = [];