mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
feat: add git-refs datasource (#5727)
This commit is contained in:
parent
9498c9726b
commit
fc8a46b6db
5 changed files with 143 additions and 32 deletions
47
lib/datasource/git-refs/index.spec.ts
Normal file
47
lib/datasource/git-refs/index.spec.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import _simpleGit from 'simple-git/promise';
|
||||
import { getPkgReleases } from '.';
|
||||
|
||||
jest.mock('simple-git/promise');
|
||||
const simpleGit: any = _simpleGit;
|
||||
|
||||
const lookupName = 'https://github.com/example/example.git';
|
||||
|
||||
describe('datasource/git-refs', () => {
|
||||
beforeEach(() => global.renovateCache.rmAll());
|
||||
describe('getPkgReleases', () => {
|
||||
it('returns nil if response is wrong', async () => {
|
||||
simpleGit.mockReturnValue({
|
||||
listRemote() {
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
});
|
||||
const versions = await getPkgReleases({ lookupName });
|
||||
expect(versions).toEqual(null);
|
||||
});
|
||||
it('returns nil if remote call throws exception', async () => {
|
||||
simpleGit.mockReturnValue({
|
||||
listRemote() {
|
||||
throw new Error();
|
||||
},
|
||||
});
|
||||
const versions = await getPkgReleases({ lookupName });
|
||||
expect(versions).toEqual(null);
|
||||
});
|
||||
it('returns versions filtered from tags', async () => {
|
||||
simpleGit.mockReturnValue({
|
||||
listRemote() {
|
||||
return Promise.resolve(
|
||||
'commithash1\trefs/tags/0.0.1\ncommithash2\trefs/tags/v0.0.2\ncommithash3\trefs/tags/v0.0.2^{}\ncommithash4\trefs/heads/v0.0.3\ncommithash5\trefs/tags/v0.0.3'
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const versions = await getPkgReleases({
|
||||
lookupName,
|
||||
});
|
||||
|
||||
const result = versions.releases.map(x => x.version).sort();
|
||||
expect(result).toEqual(['0.0.1', 'v0.0.2', 'v0.0.3']);
|
||||
});
|
||||
});
|
||||
});
|
84
lib/datasource/git-refs/index.ts
Normal file
84
lib/datasource/git-refs/index.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import simpleGit from 'simple-git/promise';
|
||||
import * as semver from '../../versioning/semver';
|
||||
import { logger } from '../../logger';
|
||||
import { ReleaseResult, GetReleasesConfig } from '../common';
|
||||
|
||||
export const id = 'git-refs';
|
||||
|
||||
const cacheMinutes = 10;
|
||||
|
||||
// git will prompt for known hosts or passwords, unless we activate BatchMode
|
||||
process.env.GIT_SSH_COMMAND = 'ssh -o BatchMode=yes';
|
||||
|
||||
export interface RawRefs {
|
||||
type: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export async function getRawRefs({
|
||||
lookupName,
|
||||
}: GetReleasesConfig): Promise<RawRefs[] | null> {
|
||||
const git = simpleGit();
|
||||
try {
|
||||
const cacheNamespace = 'git-raw-refs';
|
||||
|
||||
const cachedResult = await renovateCache.get<RawRefs[]>(
|
||||
cacheNamespace,
|
||||
lookupName
|
||||
);
|
||||
/* istanbul ignore next line */
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
// fetch remote tags
|
||||
const lsRemote = await git.listRemote([lookupName, '--sort=-v:refname']);
|
||||
|
||||
if (!lsRemote) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const refs = lsRemote.replace(/^.+?refs\//gm, '').split('\n');
|
||||
|
||||
const result = refs.map(ref => ({
|
||||
type: /(.*?)\//.exec(ref)[1],
|
||||
value: /\/(.*)/.exec(ref)[1],
|
||||
}));
|
||||
|
||||
await renovateCache.set(cacheNamespace, lookupName, result, cacheMinutes);
|
||||
return result;
|
||||
} catch (err) {
|
||||
logger.debug({ err }, `Git-Raw-Refs lookup error in ${lookupName}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function getPkgReleases({
|
||||
lookupName,
|
||||
}: GetReleasesConfig): Promise<ReleaseResult | null> {
|
||||
try {
|
||||
const rawRefs: RawRefs[] = await getRawRefs({ lookupName });
|
||||
|
||||
const refs = rawRefs
|
||||
.filter(ref => ref.type === 'tags' || ref.type === 'heads')
|
||||
.map(ref => ref.value)
|
||||
.filter(ref => semver.isVersion(ref));
|
||||
|
||||
const uniqueRefs = [...new Set(refs)];
|
||||
|
||||
const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, '');
|
||||
|
||||
const result: ReleaseResult = {
|
||||
sourceUrl,
|
||||
releases: uniqueRefs.map(ref => ({
|
||||
version: ref,
|
||||
gitRef: ref,
|
||||
})),
|
||||
};
|
||||
|
||||
return result;
|
||||
} catch (err) {
|
||||
logger.debug({ err }, `Git-Refs lookup error in ${lookupName}`);
|
||||
}
|
||||
return null;
|
||||
}
|
|
@ -44,7 +44,7 @@ export async function getPkgReleases({
|
|||
await renovateCache.set(cacheNamespace, cacheKey, result, cacheMinutes);
|
||||
return result;
|
||||
} catch (err) {
|
||||
logger.debug(`Error looking up tags in ${lookupName}`);
|
||||
logger.debug({ err }, `Git-SubModules lookup error in ${lookupName}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import { getPkgReleases } from '.';
|
|||
jest.mock('simple-git/promise');
|
||||
const simpleGit: any = _simpleGit;
|
||||
|
||||
// const lookupName = 'vapor';
|
||||
const lookupName = 'https://github.com/example/example.git';
|
||||
|
||||
describe('datasource/git-tags', () => {
|
||||
|
|
|
@ -1,42 +1,24 @@
|
|||
import simpleGit from 'simple-git/promise';
|
||||
import { ReleaseResult, GetReleasesConfig } from '../common';
|
||||
import * as semver from '../../versioning/semver';
|
||||
import { logger } from '../../logger';
|
||||
import { ReleaseResult, GetReleasesConfig } from '../common';
|
||||
import * as gitRefs from '../git-refs';
|
||||
|
||||
export const id = 'git-tags';
|
||||
|
||||
const cacheNamespace = 'git-tags';
|
||||
const cacheMinutes = 10;
|
||||
|
||||
// git will prompt for known hosts or passwords, unless we activate BatchMode
|
||||
process.env.GIT_SSH_COMMAND = 'ssh -o BatchMode=yes';
|
||||
|
||||
export async function getPkgReleases({
|
||||
lookupName,
|
||||
}: GetReleasesConfig): Promise<ReleaseResult | null> {
|
||||
const git = simpleGit();
|
||||
try {
|
||||
const cachedResult = await renovateCache.get<ReleaseResult>(
|
||||
cacheNamespace,
|
||||
lookupName
|
||||
);
|
||||
/* istanbul ignore next line */
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
// fetch remote tags
|
||||
const lsRemote = await git.listRemote([
|
||||
'--sort=-v:refname',
|
||||
'--tags',
|
||||
lookupName,
|
||||
]);
|
||||
// extract valid tags from git ls-remote which looks like 'commithash\trefs/tags/1.2.3
|
||||
const tags = lsRemote
|
||||
.replace(/^.+?refs\/tags\//gm, '')
|
||||
.split('\n')
|
||||
const rawRefs: gitRefs.RawRefs[] = await gitRefs.getRawRefs({ lookupName });
|
||||
|
||||
const tags = rawRefs
|
||||
.filter(ref => ref.type === 'tags')
|
||||
.map(ref => ref.value)
|
||||
.filter(tag => semver.isVersion(tag));
|
||||
|
||||
const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, '');
|
||||
|
||||
const result: ReleaseResult = {
|
||||
sourceUrl,
|
||||
releases: tags.map(tag => ({
|
||||
|
@ -45,10 +27,9 @@ export async function getPkgReleases({
|
|||
})),
|
||||
};
|
||||
|
||||
await renovateCache.set(cacheNamespace, lookupName, result, cacheMinutes);
|
||||
return result;
|
||||
} catch (e) {
|
||||
logger.debug(`Error looking up tags in ${lookupName}`);
|
||||
} catch (err) {
|
||||
logger.debug({ err }, `Git-Tags lookup error in ${lookupName}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue