Skip to content

Commit

Permalink
refactor(bazel): Prepare for non-GitHub url parsing (#20390)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov authored Feb 14, 2023
1 parent ad68c4d commit da69c4b
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 42 deletions.
115 changes: 83 additions & 32 deletions lib/modules/manager/bazel/rules/http.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,94 @@
import is from '@sindresorhus/is';
import { z } from 'zod';
import { regEx } from '../../../../util/regex';
import { escapeRegExp, regEx } from '../../../../util/regex';
import { parseUrl } from '../../../../util/url';
import { GithubReleasesDatasource } from '../../../datasource/github-releases';
import { GithubTagsDatasource } from '../../../datasource/github-tags';
import type { PackageDependency } from '../../types';
import type { UrlParsedResult } from '../types';

export function parseArchiveUrl(
urlString: string | undefined | null
): UrlParsedResult | null {
if (!urlString) {
return null;
}
const url = parseUrl(urlString);
if (!url || url.host !== 'github.com' || !url.pathname) {
return null;
}
const [p0, p1, p2, p3, p4, p5] = url.pathname.split('/').slice(1);
const repo = p0 + '/' + p1;
// Source: https://bazel.build/rules/lib/repo/http
const archives = [
'.zip',
'.tar',
'.jar',
'.war',
'.aar',
'.ar',
'.deb',

'.gz',
'.tar.gz',
'.tgz',

'.bz2',
'.tar.bz2',
'.tbz2',

'.xz',
'.tar.xz',
'.txz',

'.zst',
'.tar.zst',
'.tzst',
];

const archiveSuffixRegex = regEx(
`(?:${archives.map(escapeRegExp).join('|')})$`
);

function stripArchiveSuffix(value: string): string {
return value.replace(archiveSuffixRegex, '');
}

function isHash(value: unknown): value is string {
return is.string(value) && regEx(/[0-9a-z]{40}/i).test(value);
}

export function parseGithubPath(
pathname: string
): Partial<PackageDependency> | null {
const [p0, p1, p2, p3, p4, p5] = pathname.split('/').slice(1);
const packageName = p0 + '/' + p1;
let datasource = '';
let currentValue: string | null = null;
let value: string | null = null;
if (p2 === 'releases' && p3 === 'download') {
// https://github.com/foo/bar/releases/download/1.2.3/bar-1.2.3.tar.gz
datasource = GithubReleasesDatasource.id;
currentValue = p4;
value = p4;
} else if (p2 === 'archive' && p3 === 'refs' && p4 === 'tags') {
// https://github.com/foo/bar/archive/refs/tags/v1.2.3.tar.gz
datasource = GithubTagsDatasource.id;
currentValue = p5;
value = p5;
} else if (p2 === 'archive') {
// https://github.com/foo/bar/archive/1.2.3.tar.gz
datasource = GithubTagsDatasource.id;
currentValue = p3;
value = p3;
}

if (currentValue) {
// Strip archive extension to get hash or tag.
// Tolerates formats produced by Git(Hub|Lab) and allowed by http_archive
// Note: Order matters in suffix list to strip, e.g. .tar.gz.
for (const extension of ['.gz', '.bz2', '.xz', '.tar', '.tgz', '.zip']) {
if (currentValue.endsWith(extension)) {
currentValue = currentValue.slice(0, -extension.length);
}
}
if (!value) {
return null;
}

value = stripArchiveSuffix(value);
return isHash(value)
? { datasource, packageName, currentDigest: value }
: { datasource, packageName, currentValue: value };
}

export function parseArchiveUrl(
urlString: string | undefined | null
): Partial<PackageDependency> | null {
if (!urlString) {
return null;
}

const url = parseUrl(urlString);

return { datasource, repo, currentValue };
if (url?.host === 'github.com') {
return parseGithubPath(url.pathname);
}

return null;
}

Expand All @@ -71,13 +113,22 @@ export const HttpTarget = z
datasource: parsedUrl.datasource,
depType: rule,
depName: name,
packageName: parsedUrl.repo,
packageName: parsedUrl.packageName,
};

if (regEx(/^[a-f0-9]{40}$/i).test(parsedUrl.currentValue)) {
dep.currentDigest = parsedUrl.currentValue;
} else {
// We don't want to set both `currentValue` and `currentDigest`.
//
// What we want is to provide the first occurrence of `currentValue`,
// or, if it's not available, `currentDigest`.
//
// Auto-replace mechanism will replace this first occurrence,
// and artifact update function will do the rest.
//
// Hence, `if-else-if` is being used here.
if (parsedUrl.currentValue) {
dep.currentValue = parsedUrl.currentValue;
} else if (parsedUrl.currentDigest) {
dep.currentDigest = parsedUrl.currentDigest;
}

return [dep];
Expand Down
8 changes: 4 additions & 4 deletions lib/modules/manager/bazel/rules/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ describe('modules/manager/bazel/rules/index', () => {
)
).toEqual({
datasource: 'github-tags',
repo: 'foo/bar',
currentValue: 'abcdef0123abcdef0123abcdef0123abcdef0123',
packageName: 'foo/bar',
currentDigest: 'abcdef0123abcdef0123abcdef0123abcdef0123',
});

// Archive of a release
Expand All @@ -27,7 +27,7 @@ describe('modules/manager/bazel/rules/index', () => {
)
).toEqual({
datasource: 'github-releases',
repo: 'foo/bar',
packageName: 'foo/bar',
currentValue: '1.2.3',
});

Expand All @@ -38,7 +38,7 @@ describe('modules/manager/bazel/rules/index', () => {
)
).toEqual({
datasource: 'github-tags',
repo: 'aspect-build/rules_js',
packageName: 'aspect-build/rules_js',
currentValue: 'v1.1.2',
});
});
Expand Down
6 changes: 0 additions & 6 deletions lib/modules/manager/bazel/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
export interface UrlParsedResult {
datasource: string;
repo: string;
currentValue: string;
}

export interface BazelManagerData {
idx: number;
}
Expand Down

0 comments on commit da69c4b

Please sign in to comment.