Skip to content

Commit

Permalink
feat!: update github-releases datasource digest computation to use …
Browse files Browse the repository at this point in the history
…git tag, and preserve existing digest semantics as separate datasource (#20178)

Co-authored-by: RahulGautamSingh <[email protected]>
Co-authored-by: Rhys Arkins <[email protected]>
Co-authored-by: Michael Kriese <[email protected]>
Co-authored-by: HonkingGoose <[email protected]>
  • Loading branch information
5 people committed Feb 23, 2023
1 parent 0592942 commit fd279f0
Show file tree
Hide file tree
Showing 10 changed files with 593 additions and 268 deletions.
5 changes: 5 additions & 0 deletions lib/modules/datasource/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { GalaxyDatasource } from './galaxy';
import { GalaxyCollectionDatasource } from './galaxy-collection';
import { GitRefsDatasource } from './git-refs';
import { GitTagsDatasource } from './git-tags';
import { GithubReleaseAttachmentsDatasource } from './github-release-attachments';
import { GithubReleasesDatasource } from './github-releases';
import { GithubTagsDatasource } from './github-tags';
import { GitlabPackagesDatasource } from './gitlab-packages';
Expand Down Expand Up @@ -76,6 +77,10 @@ api.set(GalaxyDatasource.id, new GalaxyDatasource());
api.set(GalaxyCollectionDatasource.id, new GalaxyCollectionDatasource());
api.set(GitRefsDatasource.id, new GitRefsDatasource());
api.set(GitTagsDatasource.id, new GitTagsDatasource());
api.set(
GithubReleaseAttachmentsDatasource.id,
new GithubReleaseAttachmentsDatasource()
);
api.set(GithubReleasesDatasource.id, new GithubReleasesDatasource());
api.set(GithubTagsDatasource.id, new GithubTagsDatasource());
api.set(GitlabPackagesDatasource.id, new GitlabPackagesDatasource());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import hasha from 'hasha';
import * as httpMock from '../../../../test/http-mock';
import type { GithubDigestFile } from '../../../util/github/types';
import { GitHubReleaseMocker } from './test';
import { GitHubReleaseAttachmentMocker } from './test';

import { GithubReleasesDatasource } from '.';
import { GithubReleaseAttachmentsDatasource } from '.';

describe('modules/datasource/github-releases/digest', () => {
describe('modules/datasource/github-release-attachments/digest', () => {
const packageName = 'some/dep';
const releaseMock = new GitHubReleaseMocker(
const releaseMock = new GitHubReleaseAttachmentMocker(
'https://api.github.com',
packageName
);
const githubReleases = new GithubReleasesDatasource();
const githubReleaseAttachments = new GithubReleaseAttachmentsDatasource();

describe('findDigestAsset', () => {
it('finds SHASUMS.txt file containing digest', async () => {
Expand All @@ -21,7 +21,7 @@ describe('modules/datasource/github-releases/digest', () => {
'another-digest linux-arm64.tar.gz'
);

const digestAsset = await githubReleases.findDigestAsset(
const digestAsset = await githubReleaseAttachments.findDigestAsset(
release,
'test-digest'
);
Expand All @@ -40,7 +40,7 @@ describe('modules/datasource/github-releases/digest', () => {
.get(`/repos/${packageName}/releases/download/v1.0.0/SHASUMS.txt`)
.reply(200, '');

const digestAsset = await githubReleases.findDigestAsset(
const digestAsset = await githubReleaseAttachments.findDigestAsset(
release,
'test-digest'
);
Expand All @@ -57,7 +57,7 @@ describe('modules/datasource/github-releases/digest', () => {
});
const contentDigest = await hasha.async(content, { algorithm: 'sha256' });

const digestAsset = await githubReleases.findDigestAsset(
const digestAsset = await githubReleaseAttachments.findDigestAsset(
release,
contentDigest
);
Expand All @@ -67,7 +67,7 @@ describe('modules/datasource/github-releases/digest', () => {

it('returns null when no assets available', async () => {
const release = releaseMock.release('v1.0.0');
const digestAsset = await githubReleases.findDigestAsset(
const digestAsset = await githubReleaseAttachments.findDigestAsset(
release,
'test-digest'
);
Expand All @@ -89,7 +89,7 @@ describe('modules/datasource/github-releases/digest', () => {
'v1.0.1',
'updated-digest asset.zip'
);
const digest = await githubReleases.mapDigestAssetToRelease(
const digest = await githubReleaseAttachments.mapDigestAssetToRelease(
digestAsset,
release
);
Expand All @@ -106,7 +106,7 @@ describe('modules/datasource/github-releases/digest', () => {
'v1.0.1',
'updated-digest asset-1.0.1.zip'
);
const digest = await githubReleases.mapDigestAssetToRelease(
const digest = await githubReleaseAttachments.mapDigestAssetToRelease(
digestAssetWithVersion,
release
);
Expand All @@ -118,7 +118,7 @@ describe('modules/datasource/github-releases/digest', () => {
'v1.0.1',
'moot-digest asset.tar.gz'
);
const digest = await githubReleases.mapDigestAssetToRelease(
const digest = await githubReleaseAttachments.mapDigestAssetToRelease(
digestAsset,
release
);
Expand All @@ -127,7 +127,7 @@ describe('modules/datasource/github-releases/digest', () => {

it('returns null when digest file not found', async () => {
const release = releaseMock.release('v1.0.1');
const digest = await githubReleases.mapDigestAssetToRelease(
const digest = await githubReleaseAttachments.mapDigestAssetToRelease(
digestAsset,
release
);
Expand All @@ -151,7 +151,7 @@ describe('modules/datasource/github-releases/digest', () => {
algorithm: 'sha256',
});

const digest = await githubReleases.mapDigestAssetToRelease(
const digest = await githubReleaseAttachments.mapDigestAssetToRelease(
digestAsset,
release
);
Expand All @@ -160,7 +160,7 @@ describe('modules/datasource/github-releases/digest', () => {

it('returns null when not found', async () => {
const release = releaseMock.release('v1.0.1');
const digest = await githubReleases.mapDigestAssetToRelease(
const digest = await githubReleaseAttachments.mapDigestAssetToRelease(
digestAsset,
release
);
Expand Down
154 changes: 154 additions & 0 deletions lib/modules/datasource/github-release-attachments/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { getDigest, getPkgReleases } from '..';
import { mocked } from '../../../../test/util';
import * as githubGraphql from '../../../util/github/graphql';
import * as _hostRules from '../../../util/host-rules';
import { GitHubReleaseAttachmentMocker } from './test';
import { GithubReleaseAttachmentsDatasource } from '.';

jest.mock('../../../util/host-rules');
const hostRules = mocked(_hostRules);

const githubApiHost = 'https://api.github.com';

describe('modules/datasource/github-release-attachments/index', () => {
beforeEach(() => {
hostRules.hosts.mockReturnValue([]);
hostRules.find.mockReturnValue({
token: 'some-token',
});
});

describe('getReleases', () => {
it('returns releases', async () => {
jest.spyOn(githubGraphql, 'queryReleases').mockResolvedValueOnce([
{
id: 1,
url: 'https://example.com',
name: 'some/dep2',
description: 'some description',
version: 'a',
releaseTimestamp: '2020-03-09T13:00:00Z',
},
{
id: 2,
url: 'https://example.com',
name: 'some/dep2',
description: 'some description',
version: 'v',
releaseTimestamp: '2020-03-09T12:00:00Z',
},
{
id: 3,
url: 'https://example.com',
name: 'some/dep2',
description: 'some description',
version: '1.0.0',
releaseTimestamp: '2020-03-09T11:00:00Z',
},
{
id: 4,
url: 'https://example.com',
name: 'some/dep2',
description: 'some description',
version: 'v1.1.0',
releaseTimestamp: '2020-03-09T10:00:00Z',
},
{
id: 5,
url: 'https://example.com',
name: 'some/dep2',
description: 'some description',
version: '2.0.0',
releaseTimestamp: '2020-04-09T10:00:00Z',
isStable: false,
},
]);

const res = await getPkgReleases({
datasource: GithubReleaseAttachmentsDatasource.id,
packageName: 'some/dep',
});

expect(res).toMatchObject({
registryUrl: 'https://github.com',
releases: [
{ releaseTimestamp: '2020-03-09T11:00:00.000Z', version: '1.0.0' },
{ version: 'v1.1.0', releaseTimestamp: '2020-03-09T10:00:00.000Z' },
{
version: '2.0.0',
releaseTimestamp: '2020-04-09T10:00:00.000Z',
isStable: false,
},
],
sourceUrl: 'https://github.com/some/dep',
});
});
});

describe('getDigest', () => {
const packageName = 'some/dep';
const currentValue = 'v1.0.0';
const currentDigest = 'v1.0.0-digest';

const releaseMock = new GitHubReleaseAttachmentMocker(
githubApiHost,
packageName
);

it('requires currentDigest', async () => {
const digest = await getDigest(
{ datasource: GithubReleaseAttachmentsDatasource.id, packageName },
currentValue
);
expect(digest).toBeNull();
});

it('defaults to currentDigest when currentVersion is missing', async () => {
const digest = await getDigest(
{
datasource: GithubReleaseAttachmentsDatasource.id,
packageName,
currentDigest,
},
currentValue
);
expect(digest).toEqual(currentDigest);
});

it('returns updated digest in new release', async () => {
releaseMock.withDigestFileAsset(
currentValue,
`${currentDigest} asset.zip`
);
const nextValue = 'v1.0.1';
const nextDigest = 'updated-digest';
releaseMock.withDigestFileAsset(nextValue, `${nextDigest} asset.zip`);
const digest = await getDigest(
{
datasource: GithubReleaseAttachmentsDatasource.id,
packageName,
currentValue,
currentDigest,
},
nextValue
);
expect(digest).toEqual(nextDigest);
});

// This is awkward, but I found returning `null` in this case to not produce an update
// I'd prefer a PR with the old digest (that I can manually patch) to no PR, so I made this decision.
it('ignores failures verifying currentDigest', async () => {
releaseMock.release(currentValue);
const digest = await getDigest(
{
datasource: GithubReleaseAttachmentsDatasource.id,
packageName,
currentValue,
currentDigest,
},
currentValue
);
expect(digest).toEqual(currentDigest);
});
});
});
Loading

0 comments on commit fd279f0

Please sign in to comment.