Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(jenkins-plugins): convert to class-based datasource #12702

Merged
merged 6 commits into from Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/datasource/api.ts
Expand Up @@ -19,7 +19,7 @@ import * as go from './go';
import { GradleVersionDatasource } from './gradle-version';
import { HelmDatasource } from './helm';
import { HexDatasource } from './hex';
import * as jenkinsPlugins from './jenkins-plugins';
import { JenkinsPluginsDatasource } from './jenkins-plugins';
import * as maven from './maven';
import { NodeDatasource } from './node';
import * as npm from './npm';
Expand Down Expand Up @@ -61,7 +61,7 @@ api.set('go', go);
api.set('gradle-version', new GradleVersionDatasource());
api.set('helm', new HelmDatasource());
api.set('hex', new HexDatasource());
api.set('jenkins-plugins', jenkinsPlugins);
api.set('jenkins-plugins', new JenkinsPluginsDatasource());
api.set('maven', maven);
api.set('npm', npm);
api.set(NodeDatasource.id, new NodeDatasource());
Expand Down
1 change: 0 additions & 1 deletion lib/datasource/jenkins-plugins/common.ts

This file was deleted.

176 changes: 0 additions & 176 deletions lib/datasource/jenkins-plugins/get.ts

This file was deleted.

30 changes: 3 additions & 27 deletions lib/datasource/jenkins-plugins/index.spec.ts
Expand Up @@ -2,34 +2,24 @@ import { getPkgReleases } from '..';
import * as httpMock from '../../../test/http-mock';
import { loadJsonFixture } from '../../../test/util';
import * as versioning from '../../versioning/docker';
import { resetCache } from './get';
import * as jenkins from '.';
import { JenkinsPluginsDatasource } from '.';

const jenkinsPluginsVersions = loadJsonFixture('plugin-versions.json');
const jenkinsPluginsInfo = loadJsonFixture('update-center.actual.json');

describe('datasource/jenkins-plugins/index', () => {
describe('getReleases', () => {
const SKIP_CACHE = process.env.RENOVATE_SKIP_CACHE;

const params = {
versioning: versioning.id,
datasource: jenkins.id,
datasource: JenkinsPluginsDatasource.id,
depName: 'email-ext',
registryUrls: ['https://updates.jenkins.io/'],
};

beforeEach(() => {
resetCache();
process.env.RENOVATE_SKIP_CACHE = 'true';
jest.resetAllMocks();
});

afterEach(() => {
if (!httpMock.allUsed()) {
throw new Error('Not all http mocks have been used!');
}
process.env.RENOVATE_SKIP_CACHE = SKIP_CACHE;
});

it('returns null for a package miss', async () => {
Expand All @@ -41,11 +31,6 @@ describe('datasource/jenkins-plugins/index', () => {
.get('/current/update-center.actual.json')
.reply(200, jenkinsPluginsInfo);

httpMock
.scope('https://updates.jenkins.io')
.get('/current/plugin-versions.json')
.reply(200, jenkinsPluginsVersions);

expect(await getPkgReleases(newparams)).toBeNull();
});

Expand All @@ -60,7 +45,7 @@ describe('datasource/jenkins-plugins/index', () => {
.get('/current/plugin-versions.json')
.reply(200, jenkinsPluginsVersions);

let res = await getPkgReleases(params);
const res = await getPkgReleases(params);
expect(res.releases).toHaveLength(75);
expect(res).toMatchSnapshot();

Expand All @@ -74,10 +59,6 @@ describe('datasource/jenkins-plugins/index', () => {
expect(
res.releases.find((release) => release.version === '12.98')
).toBeUndefined();

// check that caching is working and no http requests are done after the first call to getPkgReleases
res = await getPkgReleases(params);
expect(res.releases).toHaveLength(75);
});

it('returns package releases for a hit for info and miss for releases', async () => {
Expand Down Expand Up @@ -106,11 +87,6 @@ describe('datasource/jenkins-plugins/index', () => {
.get('/current/update-center.actual.json')
.reply(200, '{}');

httpMock
.scope('https://updates.jenkins.io')
.get('/current/plugin-versions.json')
.reply(200, '{}');

expect(await getPkgReleases(params)).toBeNull();
});
});
Expand Down
107 changes: 102 additions & 5 deletions lib/datasource/jenkins-plugins/index.ts
@@ -1,5 +1,102 @@
export { id } from './common';
export { getReleases } from './get';
export const customRegistrySupport = true;
export const defaultRegistryUrls = ['https://updates.jenkins.io'];
export const registryStrategy = 'hunt';
import { logger } from '../../logger';
import { cache } from '../../util/cache/package/decorator';
import { clone } from '../../util/clone';
import { Datasource } from '../datasource';
import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
import type {
JenkinsPluginsInfoResponse,
JenkinsPluginsVersionsResponse,
} from './types';

export class JenkinsPluginsDatasource extends Datasource {
static readonly id = 'jenkins-plugins';

constructor() {
super(JenkinsPluginsDatasource.id);
}

override readonly defaultRegistryUrls = ['https://updates.jenkins.io'];

override readonly registryStrategy = 'hunt';

private static readonly packageInfoUrl =
'https://updates.jenkins.io/current/update-center.actual.json';
private static readonly packageVersionsUrl =
'https://updates.jenkins.io/current/plugin-versions.json';

async getReleases({
lookupName,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const plugins = await this.getJenkinsPluginInfo();
const plugin = plugins[lookupName];
if (!plugin) {
return null;
}

const result = clone(plugin);
const versions = await this.getJenkinsPluginVersions();
const releases = versions[lookupName];
result.releases = releases ? clone(releases) : [];
return result;
}

@cache({
namespace: JenkinsPluginsDatasource.id,
key: 'info',
ttlMinutes: 1440,
})
async getJenkinsPluginInfo(): Promise<Record<string, ReleaseResult>> {
const { plugins } =
await this.getJenkinsUpdateCenterResponse<JenkinsPluginsInfoResponse>(
JenkinsPluginsDatasource.packageInfoUrl
);

const info: Record<string, ReleaseResult> = {};
for (const name of Object.keys(plugins ?? [])) {
info[name] = {
releases: [], // releases
sourceUrl: plugins[name]?.scm,
};
}
return info;
}

@cache({ namespace: JenkinsPluginsDatasource.id, key: 'versions' })
async getJenkinsPluginVersions(): Promise<Record<string, Release[]>> {
const { plugins } =
await this.getJenkinsUpdateCenterResponse<JenkinsPluginsVersionsResponse>(
JenkinsPluginsDatasource.packageVersionsUrl
);

const versions: Record<string, Release[]> = {};
for (const name of Object.keys(plugins ?? [])) {
versions[name] = Object.keys(plugins[name]).map((version) => ({
version,
downloadUrl: plugins[name][version]?.url,
releaseTimestamp: plugins[name][version]?.buildDate
? new Date(`${plugins[name][version].buildDate} UTC`)
: null,
}));
}
return versions;
}

private async getJenkinsUpdateCenterResponse<T>(url: string): Promise<T> {
let response: T;

try {
logger.debug(`jenkins-plugins: Fetching Jenkins plugins from ${url}`);
const startTime = Date.now();
response = (await this.http.getJson<T>(url)).body;
const durationMs = Math.round(Date.now() - startTime);
logger.debug(
{ durationMs },
`jenkins-plugins: Fetched Jenkins plugins from ${url}`
);
} catch (err) /* istanbul ignore next */ {
this.handleGenericErrors(err);
}

return response;
}
}