mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-02 02:29:51 +00:00
e5ef25bbba
* fix(datasource/gitlab-tags): replace getJsonUnchecked with validated getJson The go datasource embeds GitlabTagsDatasource, so its test mocks are updated to satisfy the stricter GitlabTag schema (commit.id/created_at). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: fixup tests --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
450 lines
14 KiB
TypeScript
450 lines
14 KiB
TypeScript
import { hostRules } from '~test/host-rules.ts';
|
|
import * as httpMock from '~test/http-mock.ts';
|
|
import { GitTagsDatasource } from '../git-tags/index.ts';
|
|
import { GithubTagsDatasource } from '../github-tags/index.ts';
|
|
import { BaseGoDatasource } from './base.ts';
|
|
import { GoDirectDatasource } from './releases-direct.ts';
|
|
|
|
vi.mock('./base.ts');
|
|
|
|
const datasource = new GoDirectDatasource();
|
|
const getDatasourceSpy = vi.spyOn(BaseGoDatasource, 'getDatasource');
|
|
|
|
describe('modules/datasource/go/releases-direct', () => {
|
|
const gitGetTags = vi.spyOn(GitTagsDatasource.prototype, 'getReleases');
|
|
const githubGetTags = vi.spyOn(GithubTagsDatasource.prototype, 'getReleases');
|
|
|
|
describe('getReleases', () => {
|
|
it('returns null for null getDatasource result', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce(null);
|
|
const res = await datasource.getReleases({
|
|
packageName: 'golang.org/foo/something',
|
|
});
|
|
expect(res).toBeNull();
|
|
});
|
|
|
|
it('throws for getDatasource error', async () => {
|
|
getDatasourceSpy.mockRejectedValueOnce(new Error('unknown'));
|
|
await expect(
|
|
datasource.getReleases({
|
|
packageName: 'golang.org/foo/something',
|
|
}),
|
|
).rejects.toThrow('unknown');
|
|
});
|
|
|
|
it('processes real data', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'golang/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
githubGetTags.mockResolvedValueOnce({
|
|
releases: [
|
|
{ gitRef: 'v1.0.0', version: 'v1.0.0' },
|
|
{ gitRef: 'v2.0.0', version: 'v2.0.0' },
|
|
],
|
|
});
|
|
|
|
const res = await datasource.getReleases({
|
|
packageName: 'golang.org/x/text',
|
|
});
|
|
|
|
expect(res).toEqual({
|
|
releases: [
|
|
{ gitRef: 'v1.0.0', version: 'v1.0.0' },
|
|
{ gitRef: 'v2.0.0', version: 'v2.0.0' },
|
|
],
|
|
sourceUrl: 'https://github.com/golang/text',
|
|
});
|
|
});
|
|
|
|
it('support forgejo', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'forgejo-tags',
|
|
registryUrl: 'https://code.forgejo.org',
|
|
packageName: 'go-chi/cache',
|
|
});
|
|
httpMock
|
|
.scope('https://code.forgejo.org/')
|
|
.get('/api/v1/repos/go-chi/cache/tags')
|
|
.reply(200, [
|
|
{
|
|
name: 'v0.1.0',
|
|
commit: {
|
|
sha: 'd73d815ec22c421e7192a414594ac798c73c89e5',
|
|
created: '2022-05-15T16:29:42Z',
|
|
},
|
|
},
|
|
{
|
|
name: 'v0.2.0',
|
|
commit: {
|
|
sha: '3976707232cb68751ff2ddf42547ff95c6878a97',
|
|
created: '2022-05-15T17:23:28Z',
|
|
},
|
|
},
|
|
{
|
|
name: 'v0.2.1',
|
|
commit: {
|
|
sha: '2963b104773ead7ed28c00181c03318885d909dc',
|
|
created: '2024-09-06T23:44:34Z',
|
|
},
|
|
},
|
|
]);
|
|
const res = await datasource.getReleases({
|
|
packageName: 'code.forgejo.org/go-chi/cache',
|
|
});
|
|
expect(res).toEqual({
|
|
registryUrl: 'https://code.forgejo.org',
|
|
releases: [
|
|
{
|
|
gitRef: 'v0.1.0',
|
|
newDigest: 'd73d815ec22c421e7192a414594ac798c73c89e5',
|
|
releaseTimestamp: '2022-05-15T16:29:42.000Z',
|
|
version: 'v0.1.0',
|
|
},
|
|
{
|
|
gitRef: 'v0.2.0',
|
|
newDigest: '3976707232cb68751ff2ddf42547ff95c6878a97',
|
|
releaseTimestamp: '2022-05-15T17:23:28.000Z',
|
|
version: 'v0.2.0',
|
|
},
|
|
{
|
|
gitRef: 'v0.2.1',
|
|
newDigest: '2963b104773ead7ed28c00181c03318885d909dc',
|
|
releaseTimestamp: '2024-09-06T23:44:34.000Z',
|
|
version: 'v0.2.1',
|
|
},
|
|
],
|
|
sourceUrl: 'https://code.forgejo.org/go-chi/cache',
|
|
});
|
|
});
|
|
|
|
it('support gitlab', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'gitlab-tags',
|
|
registryUrl: 'https://gitlab.com',
|
|
packageName: 'golang/text',
|
|
});
|
|
httpMock
|
|
.scope('https://gitlab.com/')
|
|
.get('/api/v4/projects/golang%2Ftext/repository/tags?per_page=100')
|
|
.reply(200, [
|
|
{ name: 'v1.0.0', commit: { id: 'aaa100', created_at: '' } },
|
|
{ name: 'v2.0.0', commit: { id: 'aaa200', created_at: '' } },
|
|
]);
|
|
const res = await datasource.getReleases({
|
|
packageName: 'golang.org/x/text',
|
|
});
|
|
expect(res).toMatchObject({
|
|
releases: [{ version: 'v1.0.0' }, { version: 'v2.0.0' }],
|
|
sourceUrl: 'https://gitlab.com/golang/text',
|
|
});
|
|
});
|
|
|
|
it('support gitea', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'gitea-tags',
|
|
registryUrl: 'https://gitea.com',
|
|
packageName: 'go-chi/cache',
|
|
});
|
|
httpMock
|
|
.scope('https://gitea.com/')
|
|
.get('/api/v1/repos/go-chi/cache/tags')
|
|
.reply(200, [
|
|
{
|
|
name: 'v0.1.0',
|
|
commit: {
|
|
sha: 'd73d815ec22c421e7192a414594ac798c73c89e5',
|
|
created: '2022-05-15T16:29:42Z',
|
|
},
|
|
},
|
|
{
|
|
name: 'v0.2.0',
|
|
commit: {
|
|
sha: '3976707232cb68751ff2ddf42547ff95c6878a97',
|
|
created: '2022-05-15T17:23:28Z',
|
|
},
|
|
},
|
|
{
|
|
name: 'v0.2.1',
|
|
commit: {
|
|
sha: '2963b104773ead7ed28c00181c03318885d909dc',
|
|
created: '2024-09-06T23:44:34Z',
|
|
},
|
|
},
|
|
]);
|
|
const res = await datasource.getReleases({
|
|
packageName: 'gitea.com/go-chi/cache',
|
|
});
|
|
expect(res).toEqual({
|
|
registryUrl: 'https://gitea.com',
|
|
releases: [
|
|
{
|
|
gitRef: 'v0.1.0',
|
|
newDigest: 'd73d815ec22c421e7192a414594ac798c73c89e5',
|
|
releaseTimestamp: '2022-05-15T16:29:42.000Z',
|
|
version: 'v0.1.0',
|
|
},
|
|
{
|
|
gitRef: 'v0.2.0',
|
|
newDigest: '3976707232cb68751ff2ddf42547ff95c6878a97',
|
|
releaseTimestamp: '2022-05-15T17:23:28.000Z',
|
|
version: 'v0.2.0',
|
|
},
|
|
{
|
|
gitRef: 'v0.2.1',
|
|
newDigest: '2963b104773ead7ed28c00181c03318885d909dc',
|
|
releaseTimestamp: '2024-09-06T23:44:34.000Z',
|
|
version: 'v0.2.1',
|
|
},
|
|
],
|
|
sourceUrl: 'https://gitea.com/go-chi/cache',
|
|
});
|
|
});
|
|
|
|
it('support git', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'git-tags',
|
|
packageName: 'renovatebot.com/abc/def',
|
|
});
|
|
gitGetTags.mockResolvedValueOnce({
|
|
releases: [
|
|
{ gitRef: 'v1.0.0', version: 'v1.0.0' },
|
|
{ gitRef: 'v2.0.0', version: 'v2.0.0' },
|
|
],
|
|
});
|
|
const res = await datasource.getReleases({
|
|
packageName: 'renovatebot.com/abc/def',
|
|
});
|
|
expect(res).toEqual({
|
|
releases: [
|
|
{
|
|
gitRef: 'v1.0.0',
|
|
version: 'v1.0.0',
|
|
},
|
|
{
|
|
gitRef: 'v2.0.0',
|
|
version: 'v2.0.0',
|
|
},
|
|
],
|
|
sourceUrl: null,
|
|
});
|
|
});
|
|
|
|
it('support self hosted gitlab private repositories', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'gitlab-tags',
|
|
registryUrl: 'https://my.custom.domain',
|
|
packageName: 'golang/myrepo',
|
|
});
|
|
hostRules.add({ token: 'some-token' });
|
|
httpMock
|
|
.scope('https://my.custom.domain/')
|
|
.get('/api/v4/projects/golang%2Fmyrepo/repository/tags?per_page=100')
|
|
.reply(200, [
|
|
{ name: 'v1.0.0', commit: { id: 'aaa100', created_at: '' } },
|
|
{ name: 'v2.0.0', commit: { id: 'aaa200', created_at: '' } },
|
|
]);
|
|
const res = await datasource.getReleases({
|
|
packageName: 'my.custom.domain/golang/myrepo',
|
|
});
|
|
expect(res).toMatchObject({
|
|
releases: [{ version: 'v1.0.0' }, { version: 'v2.0.0' }],
|
|
sourceUrl: 'https://my.custom.domain/golang/myrepo',
|
|
});
|
|
});
|
|
|
|
it('support bitbucket tags', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'bitbucket-tags',
|
|
packageName: 'golang/text',
|
|
registryUrl: 'https://bitbucket.org',
|
|
});
|
|
httpMock
|
|
.scope('https://api.bitbucket.org/')
|
|
.get('/2.0/repositories/golang/text/refs/tags?pagelen=100')
|
|
.reply(200, {
|
|
pagelen: 2,
|
|
page: 1,
|
|
values: [{ name: 'v1.0.0' }, { name: 'v2.0.0' }],
|
|
});
|
|
const res = await datasource.getReleases({
|
|
packageName: 'bitbucket.org/golang/text',
|
|
});
|
|
expect(res).toMatchObject({
|
|
releases: [{ version: 'v1.0.0' }, { version: 'v2.0.0' }],
|
|
sourceUrl: 'https://bitbucket.org/golang/text',
|
|
});
|
|
});
|
|
|
|
it('support ghe', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
registryUrl: 'https://git.enterprise.com',
|
|
packageName: 'example/module',
|
|
});
|
|
githubGetTags.mockResolvedValueOnce({
|
|
releases: [
|
|
{ gitRef: 'v1.0.0', version: 'v1.0.0' },
|
|
{ gitRef: 'v2.0.0', version: 'v2.0.0' },
|
|
],
|
|
});
|
|
|
|
const res = await datasource.getReleases({
|
|
packageName: 'git.enterprise.com/example/module',
|
|
});
|
|
|
|
expect(res).toEqual({
|
|
releases: [
|
|
{ gitRef: 'v1.0.0', version: 'v1.0.0' },
|
|
{ gitRef: 'v2.0.0', version: 'v2.0.0' },
|
|
],
|
|
sourceUrl: 'https://git.enterprise.com/example/module',
|
|
});
|
|
expect(githubGetTags.mock.calls).toMatchObject([
|
|
[{ registryUrl: 'https://git.enterprise.com' }],
|
|
]);
|
|
});
|
|
|
|
it('works for known servers', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'go-x/x',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
githubGetTags.mockResolvedValue({ releases: [] });
|
|
const packages = [
|
|
{ packageName: 'github.com/x/text' },
|
|
{ packageName: 'gopkg.in/x/text' },
|
|
{ packageName: 'gopkg.in/x' },
|
|
];
|
|
for (const pkg of packages) {
|
|
const res = await datasource.getReleases(pkg);
|
|
expect(res?.releases).toBeEmpty();
|
|
}
|
|
expect(githubGetTags).toHaveBeenCalledTimes(3);
|
|
});
|
|
|
|
it('support gitlab subgroups', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'gitlab-tags',
|
|
registryUrl: 'https://gitlab.com',
|
|
packageName: 'group/subgroup/repo',
|
|
});
|
|
httpMock
|
|
.scope('https://gitlab.com/')
|
|
.get(
|
|
'/api/v4/projects/group%2Fsubgroup%2Frepo/repository/tags?per_page=100',
|
|
)
|
|
.reply(200, [
|
|
{ name: 'v1.0.0', commit: { id: 'aaa100', created_at: '' } },
|
|
{ name: 'v2.0.0', commit: { id: 'aaa200', created_at: '' } },
|
|
]);
|
|
const res = await datasource.getReleases({
|
|
packageName: 'gitlab.com/group/subgroup/repo',
|
|
});
|
|
expect(res).toMatchObject({
|
|
releases: [{ version: 'v1.0.0' }, { version: 'v2.0.0' }],
|
|
sourceUrl: 'https://gitlab.com/group/subgroup/repo',
|
|
});
|
|
});
|
|
|
|
it('works for nested modules on github', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
const packages = [
|
|
{ packageName: 'github.com/x/text/a' },
|
|
{ packageName: 'github.com/x/text/b' },
|
|
];
|
|
|
|
githubGetTags.mockResolvedValue({
|
|
releases: [
|
|
{ version: 'a/v1.0.0', gitRef: 'a/v1.0.0' },
|
|
{ version: 'b/v2.0.0', gitRef: 'b/v2.0.0' },
|
|
],
|
|
});
|
|
|
|
for (const pkg of packages) {
|
|
const prefix = pkg.packageName.split('/')[3];
|
|
const result = await datasource.getReleases(pkg);
|
|
expect(result?.releases).toHaveLength(1);
|
|
expect(result?.releases[0].version.startsWith(prefix)).toBeFalse();
|
|
}
|
|
});
|
|
|
|
it('falls back to unprefixed tags', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
|
|
const releases = [
|
|
{ version: 'v1.0.0', gitRef: 'v1.0.0' },
|
|
{ version: 'v2.0.0', gitRef: 'v2.0.0' },
|
|
];
|
|
githubGetTags.mockResolvedValue({ releases });
|
|
|
|
await expect(
|
|
datasource.getReleases({ packageName: 'github.com/x/text/a' }),
|
|
).resolves.toEqual({ releases, sourceUrl: 'https://github.com/x/text' });
|
|
await expect(
|
|
datasource.getReleases({ packageName: 'github.com/x/text/b' }),
|
|
).resolves.toEqual({ releases, sourceUrl: 'https://github.com/x/text' });
|
|
});
|
|
|
|
it('works for nested modules on github v2+ major upgrades', async () => {
|
|
getDatasourceSpy.mockResolvedValueOnce({
|
|
datasource: 'github-tags',
|
|
packageName: 'x/text',
|
|
registryUrl: 'https://github.com',
|
|
});
|
|
const pkg = { packageName: 'github.com/x/text/b/v2' };
|
|
|
|
githubGetTags.mockResolvedValue({
|
|
releases: [
|
|
{ version: 'a/v1.0.0', gitRef: 'a/v1.0.0' },
|
|
{ version: 'v5.0.0', gitRef: 'v5.0.0' },
|
|
{ version: 'b/v2.0.0', gitRef: 'b/v2.0.0' },
|
|
{ version: 'b/v3.0.0', gitRef: 'b/v3.0.0' },
|
|
{ version: 'b/vuw/xyz', gitRef: 'b/vuw/xyz' },
|
|
],
|
|
});
|
|
|
|
const result = await datasource.getReleases(pkg);
|
|
expect(result?.releases).toEqual([
|
|
{ version: 'v2.0.0', gitRef: 'b/v2.0.0' },
|
|
{ version: 'v3.0.0', gitRef: 'b/v3.0.0' },
|
|
]);
|
|
});
|
|
});
|
|
});
|