Move some definitions out of util.ts into a new github.ts module

This commit is contained in:
Michael B. Gale
2026-10-13 14:42:12 +01:00
parent 752e8025e9
commit 7538fa2081
9 changed files with 184 additions and 158 deletions

90
lib/entry-points.js generated
View File

@@ -42967,11 +42967,11 @@ var require_tracingPolicy = __commonJS({
var import_log = require_log3();
var import_core_util = require_commonjs4();
var import_restError = require_restError3();
var import_util58 = require_internal3();
var import_util59 = require_internal3();
var tracingPolicyName2 = "tracingPolicy";
function tracingPolicy2(options = {}) {
const userAgentPromise = (0, import_userAgent.getUserAgentValue)(options.userAgentPrefix);
const sanitizer = new import_util58.Sanitizer({
const sanitizer = new import_util59.Sanitizer({
additionalAllowedQueryParameters: options.additionalAllowedQueryParameters
});
const tracingClient = tryCreateTracingClient();
@@ -46597,11 +46597,11 @@ var require_response2 = __commonJS({
});
module2.exports = __toCommonJS2(response_exports);
var import_core_rest_pipeline = require_commonjs6();
var import_util58 = require_util9();
var import_util59 = require_util9();
var originalResponse = /* @__PURE__ */ Symbol("Original FullOperationResponse");
function toCompatResponse2(response, options) {
let request3 = (0, import_util58.toWebResourceLike)(response.request);
let headers = (0, import_util58.toHttpHeadersLike)(response.headers);
let request3 = (0, import_util59.toWebResourceLike)(response.request);
let headers = (0, import_util59.toHttpHeadersLike)(response.headers);
if (options?.createProxy) {
return new Proxy(response, {
get(target, prop, receiver) {
@@ -46642,7 +46642,7 @@ var require_response2 = __commonJS({
return {
...compatResponse,
headers,
request: (0, import_util58.toPipelineRequest)(compatResponse.request)
request: (0, import_util59.toPipelineRequest)(compatResponse.request)
};
}
}
@@ -46749,7 +46749,7 @@ var require_requestPolicyFactoryPolicy = __commonJS({
requestPolicyFactoryPolicyName: () => requestPolicyFactoryPolicyName2
});
module2.exports = __toCommonJS2(requestPolicyFactoryPolicy_exports);
var import_util58 = require_util9();
var import_util59 = require_util9();
var import_response = require_response2();
var HttpPipelineLogLevel2 = /* @__PURE__ */ ((HttpPipelineLogLevel22) => {
HttpPipelineLogLevel22[HttpPipelineLogLevel22["ERROR"] = 1] = "ERROR";
@@ -46773,14 +46773,14 @@ var require_requestPolicyFactoryPolicy = __commonJS({
async sendRequest(request3, next) {
let httpPipeline = {
async sendRequest(httpRequest) {
const response2 = await next((0, import_util58.toPipelineRequest)(httpRequest));
const response2 = await next((0, import_util59.toPipelineRequest)(httpRequest));
return (0, import_response.toCompatResponse)(response2, { createProxy: true });
}
};
for (const factory of orderedFactories) {
httpPipeline = factory.create(httpPipeline, mockRequestPolicyOptions);
}
const webResourceLike = (0, import_util58.toWebResourceLike)(request3, { createProxy: true });
const webResourceLike = (0, import_util59.toWebResourceLike)(request3, { createProxy: true });
const response = await httpPipeline.sendRequest(webResourceLike);
return (0, import_response.toPipelineResponse)(response);
}
@@ -46815,12 +46815,12 @@ var require_httpClientAdapter = __commonJS({
});
module2.exports = __toCommonJS2(httpClientAdapter_exports);
var import_response = require_response2();
var import_util58 = require_util9();
var import_util59 = require_util9();
function convertHttpClient2(requestPolicyClient) {
return {
sendRequest: async (request3) => {
const response = await requestPolicyClient.sendRequest(
(0, import_util58.toWebResourceLike)(request3, { createProxy: true })
(0, import_util59.toWebResourceLike)(request3, { createProxy: true })
);
return (0, import_response.toPipelineResponse)(response);
}
@@ -46858,7 +46858,7 @@ var require_commonjs9 = __commonJS({
disableKeepAlivePolicyName: () => import_disableKeepAlivePolicy.disableKeepAlivePolicyName,
requestPolicyFactoryPolicyName: () => import_requestPolicyFactoryPolicy.requestPolicyFactoryPolicyName,
toCompatResponse: () => import_response.toCompatResponse,
toHttpHeadersLike: () => import_util58.toHttpHeadersLike
toHttpHeadersLike: () => import_util59.toHttpHeadersLike
});
module2.exports = __toCommonJS2(src_exports);
var import_extendedClient = require_extendedClient();
@@ -46866,7 +46866,7 @@ var require_commonjs9 = __commonJS({
var import_requestPolicyFactoryPolicy = require_requestPolicyFactoryPolicy();
var import_disableKeepAlivePolicy = require_disableKeepAlivePolicy();
var import_httpClientAdapter = require_httpClientAdapter();
var import_util58 = require_util9();
var import_util59 = require_util9();
}
});
@@ -169587,7 +169587,6 @@ function checkSchema(schema, obj, options = {}, path30 = "") {
// src/util.ts
var BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json";
var BROKEN_VERSIONS = ["0.0.0-20211207"];
var GITHUB_DOTCOM_URL = "https://github.com";
var DEFAULT_DEBUG_ARTIFACT_NAME = "debug-artifacts";
var DEFAULT_DEBUG_DATABASE_NAME = "db";
var DEFAULT_RESERVED_RAM_SCALING_FACTOR = 0.05;
@@ -169803,34 +169802,6 @@ function getGeneratedSuitePath(config, language) {
"config-queries.qls"
);
}
function parseGitHubUrl(inputUrl) {
const originalUrl = inputUrl;
if (inputUrl.indexOf("://") === -1) {
inputUrl = `https://${inputUrl}`;
}
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
}
let url2;
try {
url2 = new URL(inputUrl);
} catch {
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
}
if (url2.hostname === "github.com" || url2.hostname === "api.github.com") {
return GITHUB_DOTCOM_URL;
}
if (url2.pathname.indexOf("/api/v3") !== -1) {
url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3"));
}
if (url2.hostname.startsWith("api.")) {
url2.hostname = url2.hostname.substring(4);
}
if (!url2.pathname.endsWith("/")) {
url2.pathname = `${url2.pathname}/`;
}
return url2.toString();
}
var CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR = "CODEQL_ACTION_WARNED_ABOUT_VERSION";
var hasBeenWarnedAboutVersion = false;
function checkGitHubVersionInRange(version, logger2) {
@@ -170688,6 +170659,37 @@ retry.VERSION = VERSION7;
// src/api-client.ts
var import_undici = __toESM(require_undici());
// src/github.ts
var GITHUB_DOTCOM_URL = "https://github.com";
function parseGitHubUrl(inputUrl) {
const originalUrl = inputUrl;
if (inputUrl.indexOf("://") === -1) {
inputUrl = `https://${inputUrl}`;
}
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
}
let url2;
try {
url2 = new URL(inputUrl);
} catch {
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
}
if (url2.hostname === "github.com" || url2.hostname === "api.github.com") {
return GITHUB_DOTCOM_URL;
}
if (url2.pathname.indexOf("/api/v3") !== -1) {
url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3"));
}
if (url2.hostname.startsWith("api.")) {
url2.hostname = url2.hostname.substring(4);
}
if (!url2.pathname.endsWith("/")) {
url2.pathname = `${url2.pathname}/`;
}
return url2.toString();
}
// src/repository.ts
function getRepositoryNwo() {
return getRepositoryNwoFromEnv("GITHUB_REPOSITORY");
@@ -183046,7 +183048,7 @@ var import_async = __toESM(require_async(), 1);
var import_path7 = require("path");
// node_modules/archiver/lib/error.js
var import_util36 = __toESM(require("util"), 1);
var import_util37 = __toESM(require("util"), 1);
var ERROR_CODES = {
ABORTED: "archive was aborted",
DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value",
@@ -183071,7 +183073,7 @@ function ArchiverError(code, data) {
this.code = code;
this.data = data;
}
import_util36.default.inherits(ArchiverError, Error);
import_util37.default.inherits(ArchiverError, Error);
// node_modules/archiver/lib/core.js
var import_readable_stream2 = __toESM(require_ours(), 1);

View File

@@ -19,16 +19,15 @@ import {
getEnv,
exportEnvVar,
} from "./environment";
import { GITHUB_DOTCOM_URL, parseGitHubUrl } from "./github";
import { Logger } from "./logging";
import { getRepositoryNwo, RepositoryNwo } from "./repository";
import {
asHTTPError,
ConfigurationError,
getRequiredEnvParam,
GITHUB_DOTCOM_URL,
GitHubVariant,
GitHubVersion,
parseGitHubUrl,
parseMatrixInput,
} from "./util";

View File

@@ -12,11 +12,12 @@ import { type CodeQL } from "./codeql";
import { Config } from "./config-utils";
import { Feature } from "./feature-flags";
import * as gitUtils from "./git-utils";
import { parseGitHubUrl } from "./github";
import { Logger, withGroupAsync } from "./logging";
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
import { RepositoryNwo } from "./repository";
import * as util from "./util";
import { asHTTPError, bundleDb, CleanupLevel, parseGitHubUrl } from "./util";
import { asHTTPError, bundleDb, CleanupLevel } from "./util";
/** Information about a database upload. */
export interface DatabaseUploadResult {

69
src/github.test.ts Normal file
View File

@@ -0,0 +1,69 @@
import test from "ava";
import * as github from "./github";
import { setupTests } from "./testing-utils";
setupTests(test);
test("parseGitHubUrl", (t) => {
t.deepEqual(github.parseGitHubUrl("github.com"), "https://github.com");
t.deepEqual(
github.parseGitHubUrl("https://github.com"),
"https://github.com",
);
t.deepEqual(
github.parseGitHubUrl("https://api.github.com"),
"https://github.com",
);
t.deepEqual(
github.parseGitHubUrl("https://github.com/foo/bar"),
"https://github.com",
);
t.deepEqual(
github.parseGitHubUrl("github.example.com"),
"https://github.example.com/",
);
t.deepEqual(
github.parseGitHubUrl("https://github.example.com"),
"https://github.example.com/",
);
t.deepEqual(
github.parseGitHubUrl("https://api.github.example.com"),
"https://github.example.com/",
);
t.deepEqual(
github.parseGitHubUrl("https://github.example.com/api/v3"),
"https://github.example.com/",
);
t.deepEqual(
github.parseGitHubUrl("https://github.example.com:1234"),
"https://github.example.com:1234/",
);
t.deepEqual(
github.parseGitHubUrl("https://api.github.example.com:1234"),
"https://github.example.com:1234/",
);
t.deepEqual(
github.parseGitHubUrl("https://github.example.com:1234/api/v3"),
"https://github.example.com:1234/",
);
t.deepEqual(
github.parseGitHubUrl("https://github.example.com/base/path"),
"https://github.example.com/base/path/",
);
t.deepEqual(
github.parseGitHubUrl("https://github.example.com/base/path/api/v3"),
"https://github.example.com/base/path/",
);
t.throws(() => github.parseGitHubUrl(""), {
message: '"" is not a valid URL',
});
t.throws(() => github.parseGitHubUrl("ssh://github.com"), {
message: '"ssh://github.com" is not a http or https URL',
});
t.throws(() => github.parseGitHubUrl("http:///::::433"), {
message: '"http:///::::433" is not a valid URL',
});
});

62
src/github.ts Normal file
View File

@@ -0,0 +1,62 @@
import type { GitHubInstance } from "./api-client";
import { ActionsEnvVars, type ReadOnlyEnv } from "./environment";
import { ConfigurationError } from "./util";
/** A string representing a GitHub instance address. */
export type InstanceURL = string;
/**
* The URL for github.com.
*/
export const GITHUB_DOTCOM_URL: InstanceURL = "https://github.com";
/** A string representing a GitHub API instance address. */
export type InstanceApiURL = string;
/**
* The URL for api.github.com.
*/
export const GITHUB_DOTCOM_API_URL: InstanceApiURL = "https://api.github.com";
/**
* Parses user input of a github.com or GHES URL to a canonical form.
* Removes any API prefix or suffix if one is present.
*/
export function parseGitHubUrl(inputUrl: string): string {
const originalUrl = inputUrl;
if (inputUrl.indexOf("://") === -1) {
inputUrl = `https://${inputUrl}`;
}
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
}
let url: URL;
try {
url = new URL(inputUrl);
} catch {
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
}
// If we detect this is trying to be to github.com
// then return with a fixed canonical URL.
if (url.hostname === "github.com" || url.hostname === "api.github.com") {
return GITHUB_DOTCOM_URL;
}
// Remove the API prefix if it's present
if (url.pathname.indexOf("/api/v3") !== -1) {
url.pathname = url.pathname.substring(0, url.pathname.indexOf("/api/v3"));
}
// Also consider subdomain isolation on GHES
if (url.hostname.startsWith("api.")) {
url.hostname = url.hostname.substring(4);
}
// Normalise path to having a trailing slash for consistency
if (!url.pathname.endsWith("/")) {
url.pathname = `${url.pathname}/`;
}
return url.toString();
}

View File

@@ -36,6 +36,7 @@ import {
Feature,
FeatureEnablement,
} from "./feature-flags";
import { GITHUB_DOTCOM_URL } from "./github";
import { BuiltInLanguage } from "./languages";
import { Logger } from "./logging";
import { getCodeQlVersionsForOverlayBaseDatabases } from "./overlay/caching";
@@ -100,7 +101,7 @@ async function getCodeQLBundleDownloadURL(
// This GitHub instance, and the canonical Action.
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
// GitHub.com, and the canonical Action.
[util.GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY],
[GITHUB_DOTCOM_URL, CODEQL_DEFAULT_ACTION_REPOSITORY],
];
// We now filter out any duplicates.
// Duplicates will happen either because the GitHub instance is GitHub.com, or because the Action is not a fork.
@@ -113,7 +114,7 @@ async function getCodeQLBundleDownloadURL(
const [apiURL, repository] = downloadSource;
// If we've reached the final case, short-circuit the API check since we know the bundle exists and is public.
if (
apiURL === util.GITHUB_DOTCOM_URL &&
apiURL === GITHUB_DOTCOM_URL &&
repository === CODEQL_DEFAULT_ACTION_REPOSITORY
) {
break;

View File

@@ -31,6 +31,7 @@ import {
exportEnvVar,
} from "./environment";
import { getRef } from "./git-utils";
import { GITHUB_DOTCOM_URL } from "./github";
import * as json from "./json";
import type { Logger } from "./logging";
import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching";
@@ -41,7 +42,6 @@ import {
ConfigurationError,
getRequiredEnvParam,
isInTestMode,
GITHUB_DOTCOM_URL,
DiskUsage,
assertNever,
BuildMode,

View File

@@ -164,66 +164,6 @@ test.serial("getExtraOptionsEnvParam() fails on invalid JSON", (t) => {
process.env.CODEQL_ACTION_EXTRA_OPTIONS = origExtraOptions;
});
test("parseGitHubUrl", (t) => {
t.deepEqual(util.parseGitHubUrl("github.com"), "https://github.com");
t.deepEqual(util.parseGitHubUrl("https://github.com"), "https://github.com");
t.deepEqual(
util.parseGitHubUrl("https://api.github.com"),
"https://github.com",
);
t.deepEqual(
util.parseGitHubUrl("https://github.com/foo/bar"),
"https://github.com",
);
t.deepEqual(
util.parseGitHubUrl("github.example.com"),
"https://github.example.com/",
);
t.deepEqual(
util.parseGitHubUrl("https://github.example.com"),
"https://github.example.com/",
);
t.deepEqual(
util.parseGitHubUrl("https://api.github.example.com"),
"https://github.example.com/",
);
t.deepEqual(
util.parseGitHubUrl("https://github.example.com/api/v3"),
"https://github.example.com/",
);
t.deepEqual(
util.parseGitHubUrl("https://github.example.com:1234"),
"https://github.example.com:1234/",
);
t.deepEqual(
util.parseGitHubUrl("https://api.github.example.com:1234"),
"https://github.example.com:1234/",
);
t.deepEqual(
util.parseGitHubUrl("https://github.example.com:1234/api/v3"),
"https://github.example.com:1234/",
);
t.deepEqual(
util.parseGitHubUrl("https://github.example.com/base/path"),
"https://github.example.com/base/path/",
);
t.deepEqual(
util.parseGitHubUrl("https://github.example.com/base/path/api/v3"),
"https://github.example.com/base/path/",
);
t.throws(() => util.parseGitHubUrl(""), {
message: '"" is not a valid URL',
});
t.throws(() => util.parseGitHubUrl("ssh://github.com"), {
message: '"ssh://github.com" is not a http or https URL',
});
t.throws(() => util.parseGitHubUrl("http:///::::433"), {
message: '"http:///::::433" is not a valid URL',
});
});
test("allowed API versions", async (t) => {
t.is(util.apiVersionInRange("1.33.0", "1.33", "2.0"), undefined);
t.is(util.apiVersionInRange("1.33.1", "1.33", "2.0"), undefined);

View File

@@ -45,11 +45,6 @@ const BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json";
*/
const BROKEN_VERSIONS = ["0.0.0-20211207"];
/**
* The URL for github.com.
*/
export const GITHUB_DOTCOM_URL = "https://github.com";
/**
* Default name of the debugging artifact.
*/
@@ -465,49 +460,6 @@ export function getGeneratedSuitePath(config: Config, language: Language) {
);
}
/**
* Parses user input of a github.com or GHES URL to a canonical form.
* Removes any API prefix or suffix if one is present.
*/
export function parseGitHubUrl(inputUrl: string): string {
const originalUrl = inputUrl;
if (inputUrl.indexOf("://") === -1) {
inputUrl = `https://${inputUrl}`;
}
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
}
let url: URL;
try {
url = new URL(inputUrl);
} catch {
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
}
// If we detect this is trying to be to github.com
// then return with a fixed canonical URL.
if (url.hostname === "github.com" || url.hostname === "api.github.com") {
return GITHUB_DOTCOM_URL;
}
// Remove the API prefix if it's present
if (url.pathname.indexOf("/api/v3") !== -1) {
url.pathname = url.pathname.substring(0, url.pathname.indexOf("/api/v3"));
}
// Also consider subdomain isolation on GHES
if (url.hostname.startsWith("api.")) {
url.hostname = url.hostname.substring(4);
}
// Normalise path to having a trailing slash for consistency
if (!url.pathname.endsWith("/")) {
url.pathname = `${url.pathname}/`;
}
return url.toString();
}
const CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR =
"CODEQL_ACTION_WARNED_ABOUT_VERSION";