Files
Sebastian Poxhofer 03baf6ee4a test(noNewURL): add new rule enforcing parseUrl() from 'lib/util/url.ts' (#43247)
* test(noNewURL): add new rule enforcing parseUrl() from 'lib/util/url.ts'

* replace newURL with parseUrl

* remove non-null assertions marks if appropiate

* test: add additional tests

* test: add additional tests and ignore where it makes sense

* implement suggestions

* test: further improve coverage

* apply suggestion
2026-05-13 16:23:10 +00:00

122 lines
3.8 KiB
TypeScript

import url from 'node:url';
import { isNonEmptyArray, isNonEmptyString } from '@sindresorhus/is';
import { CONFIG_GIT_URL_UNAVAILABLE } from '../../../constants/error-messages.ts';
import { logger } from '../../../logger/index.ts';
import { getEnv } from '../../../util/env.ts';
import * as hostRules from '../../../util/host-rules.ts';
import type { HttpResponse } from '../../../util/http/types.ts';
import { parseUrl } from '../../../util/url.ts';
import { getPrBodyStruct } from '../pr-body.ts';
import type { GitUrlOption } from '../types.ts';
import type { GitLabMergeRequest } from './schema.ts';
import type { GitlabPr, RepoResponse } from './types.ts';
export const DRAFT_PREFIX = 'Draft: ';
export const DRAFT_PREFIX_DEPRECATED = 'WIP: ';
export const defaults = {
hostType: 'gitlab',
endpoint: 'https://gitlab.com/api/v4/',
version: '0.0.0',
};
export function prInfo(mr: GitLabMergeRequest): GitlabPr {
const pr: GitlabPr = {
sourceBranch: mr.source_branch,
targetBranch: mr.target_branch,
state: mr.state === 'opened' ? 'open' : mr.state,
number: mr.iid,
title: mr.title,
createdAt: mr.created_at,
hasAssignees: !!(mr.assignee?.id ?? mr.assignees?.[0]?.id),
bodyStruct: getPrBodyStruct(mr.description),
...(mr.target_branch && { targetBranch: mr.target_branch }),
...(mr.head_pipeline?.status && {
headPipelineStatus: mr.head_pipeline?.status,
}),
...(mr.head_pipeline?.sha && { headPipelineSha: mr.head_pipeline?.sha }),
...(isNonEmptyArray(mr.reviewers) && {
reviewers: mr.reviewers?.map(({ username }) => username),
}),
...(mr.labels && { labels: mr.labels }),
...(mr.sha && { sha: mr.sha }),
};
if (pr.title.startsWith(DRAFT_PREFIX)) {
pr.title = pr.title.substring(DRAFT_PREFIX.length);
pr.isDraft = true;
} else if (pr.title.startsWith(DRAFT_PREFIX_DEPRECATED)) {
pr.title = pr.title.substring(DRAFT_PREFIX_DEPRECATED.length);
pr.isDraft = true;
}
return pr;
}
export function getRepoUrl(
repository: string,
gitUrl: GitUrlOption | undefined,
res: HttpResponse<RepoResponse>,
): string {
if (gitUrl === 'ssh') {
if (!res.body.ssh_url_to_repo) {
throw new Error(CONFIG_GIT_URL_UNAVAILABLE);
}
logger.debug(`Using ssh URL: ${res.body.ssh_url_to_repo}`);
return res.body.ssh_url_to_repo;
}
const opts = hostRules.find({
hostType: defaults.hostType,
url: defaults.endpoint,
});
const env = getEnv();
if (
gitUrl === 'endpoint' ||
isNonEmptyString(env.GITLAB_IGNORE_REPO_URL) ||
res.body.http_url_to_repo === null
) {
if (res.body.http_url_to_repo === null) {
logger.debug('no http_url_to_repo found. Falling back to old behavior.');
}
if (env.GITLAB_IGNORE_REPO_URL) {
logger.warn(
'GITLAB_IGNORE_REPO_URL environment variable is deprecated. Please use "gitUrl" option.',
);
}
const parsedEndpoint = parseUrl(defaults.endpoint);
if (!parsedEndpoint) {
throw new Error(`Invalid GitLab endpoint: ${defaults.endpoint}`);
}
const { protocol, host, pathname } = parsedEndpoint;
const newPathname = pathname.slice(0, pathname.indexOf('/api'));
const uri = url.format({
/* v8 ignore start: should never happen (#40625) */
protocol: protocol.slice(0, -1) || 'https',
/* v8 ignore stop */
// TODO: types (#22198)
auth: `oauth2:${opts.token!}`,
host,
pathname: `${newPathname}/${repository}.git`,
});
logger.debug(`Using URL based on configured endpoint, url:${uri}`);
return uri;
}
logger.debug(`Using http URL: ${res.body.http_url_to_repo}`);
const repoUrl = parseUrl(res.body.http_url_to_repo);
// should never happen, but bad tests are causing that
if (!repoUrl) {
return '';
}
repoUrl.username = 'oauth2';
repoUrl.password = opts.token!;
return repoUrl.toString();
}