mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 17:41:28 +00:00
Merge pull request #4050 from github/mbg/status/registries
Include `registry_types` in more status reports
This commit is contained in:
337
lib/entry-points.js
generated
337
lib/entry-points.js
generated
@@ -92812,10 +92812,10 @@ var require_util12 = __commonJS({
|
||||
return objectToString(arg) === "[object Array]";
|
||||
}
|
||||
exports2.isArray = isArray2;
|
||||
function isBoolean(arg) {
|
||||
function isBoolean2(arg) {
|
||||
return typeof arg === "boolean";
|
||||
}
|
||||
exports2.isBoolean = isBoolean;
|
||||
exports2.isBoolean = isBoolean2;
|
||||
function isNull(arg) {
|
||||
return arg === null;
|
||||
}
|
||||
@@ -96885,7 +96885,7 @@ var require_validators = __commonJS({
|
||||
throw new ERR_INVALID_ARG_TYPE(name, "a dictionary", value);
|
||||
}
|
||||
});
|
||||
var validateArray = hideStackFrames((value, name, minLength = 0) => {
|
||||
var validateArray2 = hideStackFrames((value, name, minLength = 0) => {
|
||||
if (!ArrayIsArray(value)) {
|
||||
throw new ERR_INVALID_ARG_TYPE(name, "Array", value);
|
||||
}
|
||||
@@ -96895,19 +96895,19 @@ var require_validators = __commonJS({
|
||||
}
|
||||
});
|
||||
function validateStringArray(value, name) {
|
||||
validateArray(value, name);
|
||||
validateArray2(value, name);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
validateString(value[i], `${name}[${i}]`);
|
||||
}
|
||||
}
|
||||
function validateBooleanArray(value, name) {
|
||||
validateArray(value, name);
|
||||
validateArray2(value, name);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
validateBoolean(value[i], `${name}[${i}]`);
|
||||
}
|
||||
}
|
||||
function validateAbortSignalArray(value, name) {
|
||||
validateArray(value, name);
|
||||
validateArray2(value, name);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const signal = value[i];
|
||||
const indexedName = `${name}[${i}]`;
|
||||
@@ -97003,7 +97003,7 @@ var require_validators = __commonJS({
|
||||
isInt32,
|
||||
isUint32,
|
||||
parseFileMode,
|
||||
validateArray,
|
||||
validateArray: validateArray2,
|
||||
validateStringArray,
|
||||
validateBooleanArray,
|
||||
validateAbortSignalArray,
|
||||
@@ -144596,21 +144596,25 @@ function isString(value) {
|
||||
function isNumber(value) {
|
||||
return typeof value === "number";
|
||||
}
|
||||
function isBoolean(value) {
|
||||
return typeof value === "boolean";
|
||||
}
|
||||
function isStringOrUndefined(value) {
|
||||
return value === void 0 || isString(value);
|
||||
}
|
||||
function defaultCheck(validate2) {
|
||||
return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate2(arg) });
|
||||
}
|
||||
function makeValidator(validate2, required = true) {
|
||||
function makeValidator(validate2) {
|
||||
return {
|
||||
validate: validate2,
|
||||
check: defaultCheck(validate2),
|
||||
required
|
||||
required: true
|
||||
};
|
||||
}
|
||||
var string = makeValidator(isString);
|
||||
var number = makeValidator(isNumber);
|
||||
var boolean = makeValidator(isBoolean);
|
||||
function array(validator) {
|
||||
const validate2 = (val) => {
|
||||
return isArray(val) && val.every((e) => validator.validate(e));
|
||||
@@ -144692,6 +144696,10 @@ function validateSchema(schema, obj) {
|
||||
const result = checkSchema(schema, obj, { failFast: true });
|
||||
return result.valid;
|
||||
}
|
||||
function validateArray(elementSchema, arr) {
|
||||
const elementValidator = object(elementSchema);
|
||||
return array(elementValidator).validate(arr);
|
||||
}
|
||||
function successfulCheckSchema() {
|
||||
return {
|
||||
valid: true,
|
||||
@@ -146400,6 +146408,148 @@ async function getGeneratedFiles(workingDirectory) {
|
||||
return generatedFiles;
|
||||
}
|
||||
|
||||
// src/start-proxy/types.ts
|
||||
var usernameSchema = {
|
||||
/** The username needed to authenticate to the package registry, if any. */
|
||||
username: optionalOrNull(string)
|
||||
};
|
||||
function hasUsername(config) {
|
||||
return "username" in config;
|
||||
}
|
||||
var usernamePasswordSchema = {
|
||||
/** The password needed to authenticate to the package registry, if any. */
|
||||
password: optionalOrNull(string),
|
||||
...usernameSchema
|
||||
};
|
||||
function hasUsernameAndPassword(config) {
|
||||
return hasUsername(config) && "password" in config;
|
||||
}
|
||||
var tokenSchema = {
|
||||
/** The token needed to authenticate to the package registry, if any. */
|
||||
token: optionalOrNull(string),
|
||||
...usernameSchema
|
||||
};
|
||||
function hasToken(config) {
|
||||
return "token" in config;
|
||||
}
|
||||
function isToken(config) {
|
||||
return "token" in config && validateSchema(tokenSchema, config);
|
||||
}
|
||||
var azureConfigSchema = {
|
||||
"tenant-id": string,
|
||||
"client-id": string
|
||||
};
|
||||
function isAzureConfig(config) {
|
||||
return validateSchema(azureConfigSchema, config);
|
||||
}
|
||||
var awsConfigSchema = {
|
||||
"aws-region": string,
|
||||
"account-id": string,
|
||||
"role-name": string,
|
||||
domain: string,
|
||||
"domain-owner": string,
|
||||
audience: optionalOrNull(string)
|
||||
};
|
||||
function isAWSConfig(config) {
|
||||
return validateSchema(awsConfigSchema, config);
|
||||
}
|
||||
var jfrogConfigSchema = {
|
||||
"jfrog-oidc-provider-name": string,
|
||||
audience: optionalOrNull(string),
|
||||
"identity-mapping-name": optionalOrNull(string)
|
||||
};
|
||||
function isJFrogConfig(config) {
|
||||
return validateSchema(jfrogConfigSchema, config);
|
||||
}
|
||||
var cloudsmithConfigSchema = {
|
||||
namespace: string,
|
||||
"service-slug": string,
|
||||
"api-host": string
|
||||
};
|
||||
function isCloudsmithConfig(config) {
|
||||
return validateSchema(cloudsmithConfigSchema, config);
|
||||
}
|
||||
var gcpConfigSchema = {
|
||||
"workload-identity-provider": string,
|
||||
"service-account": optionalOrNull(string),
|
||||
audience: optionalOrNull(string)
|
||||
};
|
||||
function isGCPConfig(config) {
|
||||
return validateSchema(gcpConfigSchema, config);
|
||||
}
|
||||
var oidcSchemas = [
|
||||
{ schema: azureConfigSchema, name: "Azure" },
|
||||
{ schema: awsConfigSchema, name: "AWS" },
|
||||
{ schema: jfrogConfigSchema, name: "JFrog" },
|
||||
{ schema: cloudsmithConfigSchema, name: "Cloudsmith" },
|
||||
{ schema: gcpConfigSchema, name: "GCP" }
|
||||
];
|
||||
function credentialToStr(credential) {
|
||||
let result = `Type: ${credential.type};`;
|
||||
const appendIfDefined = (name, val) => {
|
||||
if (isDefined2(val)) {
|
||||
result += ` ${name}: ${val};`;
|
||||
}
|
||||
};
|
||||
appendIfDefined("Url", credential.url);
|
||||
appendIfDefined("Host", credential.host);
|
||||
if (hasUsername(credential)) {
|
||||
appendIfDefined("Username", credential.username);
|
||||
}
|
||||
if ("password" in credential) {
|
||||
appendIfDefined(
|
||||
"Password",
|
||||
isDefined2(credential.password) ? "***" : void 0
|
||||
);
|
||||
}
|
||||
if (hasToken(credential)) {
|
||||
appendIfDefined("Token", isDefined2(credential.token) ? "***" : void 0);
|
||||
}
|
||||
if (isAzureConfig(credential)) {
|
||||
appendIfDefined("Tenant", credential["tenant-id"]);
|
||||
appendIfDefined("Client", credential["client-id"]);
|
||||
} else if (isAWSConfig(credential)) {
|
||||
appendIfDefined("AWS Region", credential["aws-region"]);
|
||||
appendIfDefined("AWS Account", credential["account-id"]);
|
||||
appendIfDefined("AWS Role", credential["role-name"]);
|
||||
appendIfDefined("AWS Domain", credential.domain);
|
||||
appendIfDefined("AWS Domain Owner", credential["domain-owner"]);
|
||||
appendIfDefined("AWS Audience", credential.audience);
|
||||
} else if (isJFrogConfig(credential)) {
|
||||
appendIfDefined("JFrog Provider", credential["jfrog-oidc-provider-name"]);
|
||||
appendIfDefined(
|
||||
"JFrog Identity Mapping",
|
||||
credential["identity-mapping-name"]
|
||||
);
|
||||
appendIfDefined("JFrog Audience", credential.audience);
|
||||
} else if (isCloudsmithConfig(credential)) {
|
||||
appendIfDefined("Cloudsmith Namespace", credential.namespace);
|
||||
appendIfDefined("Cloudsmith Service Slug", credential["service-slug"]);
|
||||
appendIfDefined("Cloudsmith API Host", credential["api-host"]);
|
||||
} else if (isGCPConfig(credential)) {
|
||||
appendIfDefined(
|
||||
"GCP Workload Identity Provider",
|
||||
credential["workload-identity-provider"]
|
||||
);
|
||||
appendIfDefined("GCP Service Account", credential["service-account"]);
|
||||
appendIfDefined("GCP Audience", credential.audience);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
var registryBaseSchema = {
|
||||
/** The type of the package registry. */
|
||||
type: string,
|
||||
/** Whether the registry replaces the base registry for the ecosystem. */
|
||||
"replaces-base": optional(boolean)
|
||||
};
|
||||
function getAddressString(address) {
|
||||
if (address.url === void 0) {
|
||||
return address.host;
|
||||
} else {
|
||||
return address.url;
|
||||
}
|
||||
}
|
||||
|
||||
// src/status-report.ts
|
||||
function getDisplayActionName(actionName) {
|
||||
if (actionName === "finish" /* Analyze */) {
|
||||
@@ -146468,6 +146618,34 @@ function setJobStatusIfUnsuccessful(actionStatus) {
|
||||
);
|
||||
}
|
||||
}
|
||||
function getRegistryTypesFromEnv(logger, env = getEnv()) {
|
||||
const value = env.getOptional("CODEQL_PROXY_URLS" /* PROXY_URLS */);
|
||||
if (value === void 0) {
|
||||
return void 0;
|
||||
}
|
||||
try {
|
||||
const data = JSON.parse(value);
|
||||
if (!isArray(data)) {
|
||||
logger.debug(
|
||||
`Expected '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}' to contain a JSON array, but got '${typeof data}'.`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
if (!validateArray(registryBaseSchema, data)) {
|
||||
logger.debug(
|
||||
`Expected '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}' to contain a JSON array of registry objects, but got something else.`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
const types2 = new Set(data.map((r) => r.type));
|
||||
return Array.from(types2).sort().join(",");
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
`Failed to parse '${"CODEQL_PROXY_URLS" /* PROXY_URLS */}': ${getErrorMessage(err)}.`
|
||||
);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
async function createStatusReportBase(actionName, status, actionStartedAt, config, diskInfo, logger, cause, exception) {
|
||||
try {
|
||||
const commitOid = getOptionalInput("sha") || process.env["GITHUB_SHA"] || "";
|
||||
@@ -146507,6 +146685,7 @@ async function createStatusReportBase(actionName, status, actionStartedAt, confi
|
||||
job_name: jobName,
|
||||
job_run_uuid: jobRunUUID,
|
||||
ref,
|
||||
registry_types: getRegistryTypesFromEnv(logger),
|
||||
runner_os: runnerOs,
|
||||
started_at: workflowStartedAt,
|
||||
status,
|
||||
@@ -157415,7 +157594,7 @@ var import_async = __toESM(require_async(), 1);
|
||||
var import_path6 = require("path");
|
||||
|
||||
// node_modules/archiver/lib/error.js
|
||||
var import_util33 = __toESM(require("util"), 1);
|
||||
var import_util34 = __toESM(require("util"), 1);
|
||||
var ERROR_CODES = {
|
||||
ABORTED: "archive was aborted",
|
||||
DIRECTORYDIRPATHREQUIRED: "diretory dirpath argument must be a non-empty string value",
|
||||
@@ -157440,7 +157619,7 @@ function ArchiverError(code, data) {
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
import_util33.default.inherits(ArchiverError, Error);
|
||||
import_util34.default.inherits(ArchiverError, Error);
|
||||
|
||||
// node_modules/archiver/lib/core.js
|
||||
var import_readable_stream2 = __toESM(require_ours(), 1);
|
||||
@@ -161870,142 +162049,6 @@ var path26 = __toESM(require("path"));
|
||||
var core26 = __toESM(require_core());
|
||||
var toolcache4 = __toESM(require_tool_cache());
|
||||
|
||||
// src/start-proxy/types.ts
|
||||
var usernameSchema = {
|
||||
/** The username needed to authenticate to the package registry, if any. */
|
||||
username: optionalOrNull(string)
|
||||
};
|
||||
function hasUsername(config) {
|
||||
return "username" in config;
|
||||
}
|
||||
var usernamePasswordSchema = {
|
||||
/** The password needed to authenticate to the package registry, if any. */
|
||||
password: optionalOrNull(string),
|
||||
...usernameSchema
|
||||
};
|
||||
function hasUsernameAndPassword(config) {
|
||||
return hasUsername(config) && "password" in config;
|
||||
}
|
||||
var tokenSchema = {
|
||||
/** The token needed to authenticate to the package registry, if any. */
|
||||
token: optionalOrNull(string),
|
||||
...usernameSchema
|
||||
};
|
||||
function hasToken(config) {
|
||||
return "token" in config;
|
||||
}
|
||||
function isToken(config) {
|
||||
return "token" in config && validateSchema(tokenSchema, config);
|
||||
}
|
||||
var azureConfigSchema = {
|
||||
"tenant-id": string,
|
||||
"client-id": string
|
||||
};
|
||||
function isAzureConfig(config) {
|
||||
return validateSchema(azureConfigSchema, config);
|
||||
}
|
||||
var awsConfigSchema = {
|
||||
"aws-region": string,
|
||||
"account-id": string,
|
||||
"role-name": string,
|
||||
domain: string,
|
||||
"domain-owner": string,
|
||||
audience: optionalOrNull(string)
|
||||
};
|
||||
function isAWSConfig(config) {
|
||||
return validateSchema(awsConfigSchema, config);
|
||||
}
|
||||
var jfrogConfigSchema = {
|
||||
"jfrog-oidc-provider-name": string,
|
||||
audience: optionalOrNull(string),
|
||||
"identity-mapping-name": optionalOrNull(string)
|
||||
};
|
||||
function isJFrogConfig(config) {
|
||||
return validateSchema(jfrogConfigSchema, config);
|
||||
}
|
||||
var cloudsmithConfigSchema = {
|
||||
namespace: string,
|
||||
"service-slug": string,
|
||||
"api-host": string
|
||||
};
|
||||
function isCloudsmithConfig(config) {
|
||||
return validateSchema(cloudsmithConfigSchema, config);
|
||||
}
|
||||
var gcpConfigSchema = {
|
||||
"workload-identity-provider": string,
|
||||
"service-account": optionalOrNull(string),
|
||||
audience: optionalOrNull(string)
|
||||
};
|
||||
function isGCPConfig(config) {
|
||||
return validateSchema(gcpConfigSchema, config);
|
||||
}
|
||||
var oidcSchemas = [
|
||||
{ schema: azureConfigSchema, name: "Azure" },
|
||||
{ schema: awsConfigSchema, name: "AWS" },
|
||||
{ schema: jfrogConfigSchema, name: "JFrog" },
|
||||
{ schema: cloudsmithConfigSchema, name: "Cloudsmith" },
|
||||
{ schema: gcpConfigSchema, name: "GCP" }
|
||||
];
|
||||
function credentialToStr(credential) {
|
||||
let result = `Type: ${credential.type};`;
|
||||
const appendIfDefined = (name, val) => {
|
||||
if (isDefined2(val)) {
|
||||
result += ` ${name}: ${val};`;
|
||||
}
|
||||
};
|
||||
appendIfDefined("Url", credential.url);
|
||||
appendIfDefined("Host", credential.host);
|
||||
if (hasUsername(credential)) {
|
||||
appendIfDefined("Username", credential.username);
|
||||
}
|
||||
if ("password" in credential) {
|
||||
appendIfDefined(
|
||||
"Password",
|
||||
isDefined2(credential.password) ? "***" : void 0
|
||||
);
|
||||
}
|
||||
if (hasToken(credential)) {
|
||||
appendIfDefined("Token", isDefined2(credential.token) ? "***" : void 0);
|
||||
}
|
||||
if (isAzureConfig(credential)) {
|
||||
appendIfDefined("Tenant", credential["tenant-id"]);
|
||||
appendIfDefined("Client", credential["client-id"]);
|
||||
} else if (isAWSConfig(credential)) {
|
||||
appendIfDefined("AWS Region", credential["aws-region"]);
|
||||
appendIfDefined("AWS Account", credential["account-id"]);
|
||||
appendIfDefined("AWS Role", credential["role-name"]);
|
||||
appendIfDefined("AWS Domain", credential.domain);
|
||||
appendIfDefined("AWS Domain Owner", credential["domain-owner"]);
|
||||
appendIfDefined("AWS Audience", credential.audience);
|
||||
} else if (isJFrogConfig(credential)) {
|
||||
appendIfDefined("JFrog Provider", credential["jfrog-oidc-provider-name"]);
|
||||
appendIfDefined(
|
||||
"JFrog Identity Mapping",
|
||||
credential["identity-mapping-name"]
|
||||
);
|
||||
appendIfDefined("JFrog Audience", credential.audience);
|
||||
} else if (isCloudsmithConfig(credential)) {
|
||||
appendIfDefined("Cloudsmith Namespace", credential.namespace);
|
||||
appendIfDefined("Cloudsmith Service Slug", credential["service-slug"]);
|
||||
appendIfDefined("Cloudsmith API Host", credential["api-host"]);
|
||||
} else if (isGCPConfig(credential)) {
|
||||
appendIfDefined(
|
||||
"GCP Workload Identity Provider",
|
||||
credential["workload-identity-provider"]
|
||||
);
|
||||
appendIfDefined("GCP Service Account", credential["service-account"]);
|
||||
appendIfDefined("GCP Audience", credential.audience);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function getAddressString(address) {
|
||||
if (address.url === void 0) {
|
||||
return address.host;
|
||||
} else {
|
||||
return address.url;
|
||||
}
|
||||
}
|
||||
|
||||
// src/start-proxy/validation.ts
|
||||
var core25 = __toESM(require_core());
|
||||
function cloneCredential(schema, obj) {
|
||||
|
||||
@@ -35,6 +35,11 @@ export function isNumber(value: unknown): value is number {
|
||||
return typeof value === "number";
|
||||
}
|
||||
|
||||
/** Asserts that `value` is a boolean. */
|
||||
export function isBoolean(value: unknown): value is boolean {
|
||||
return typeof value === "boolean";
|
||||
}
|
||||
|
||||
/** Asserts that `value` is either a string or undefined. */
|
||||
export function isStringOrUndefined(
|
||||
value: unknown,
|
||||
@@ -62,14 +67,11 @@ function defaultCheck(
|
||||
return (arg) => ({ unknownKeys: [], invalidKeys: [], valid: validate(arg) });
|
||||
}
|
||||
|
||||
function makeValidator<T>(
|
||||
validate: (arg: unknown) => arg is T,
|
||||
required: boolean = true,
|
||||
) {
|
||||
function makeValidator<T>(validate: (arg: unknown) => arg is T) {
|
||||
return {
|
||||
validate,
|
||||
check: defaultCheck(validate),
|
||||
required,
|
||||
required: true,
|
||||
} as const satisfies Validator<T>;
|
||||
}
|
||||
|
||||
@@ -82,6 +84,9 @@ export const string = makeValidator(isString);
|
||||
/** A validator for number fields in schemas. */
|
||||
export const number = makeValidator(isNumber);
|
||||
|
||||
/** A validator for boolean fields in schemas. */
|
||||
export const boolean = makeValidator(isBoolean);
|
||||
|
||||
/** A validator for arrays. */
|
||||
export function array<T>(validator: Validator<T>) {
|
||||
const validate = (val: unknown) => {
|
||||
@@ -221,6 +226,23 @@ export function validateSchema<
|
||||
return result.valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that `arr` is an array whose elements satisfy at least `elementSchema`.
|
||||
* Additional keys are accepted in each element.
|
||||
*
|
||||
* @param elementSchema The schema to validate the elements against.
|
||||
* @param arr The array to validate.
|
||||
* @returns Asserts that `arr` has elements of `schema`'s type if validation is successful.
|
||||
*/
|
||||
export function validateArray<
|
||||
S extends Schema,
|
||||
T extends UnvalidatedArray = Array<FromSchema<S>>,
|
||||
>(elementSchema: S, arr: UnvalidatedArray): arr is T {
|
||||
const elementValidator = object(elementSchema);
|
||||
|
||||
return array(elementValidator).validate(arr);
|
||||
}
|
||||
|
||||
export interface CheckSchemaOptions {
|
||||
/** Whether to stop validation after the first error. */
|
||||
failFast?: boolean;
|
||||
|
||||
@@ -83,12 +83,6 @@ export class StartProxyError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
interface StartProxyStatus extends StatusReportBase {
|
||||
// A comma-separated list of registry types which are configured for CodeQL.
|
||||
// This only includes registry types we support, not all that are configured.
|
||||
registry_types: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a status report for the `start-proxy` action indicating a successful outcome.
|
||||
*
|
||||
@@ -112,7 +106,7 @@ export async function sendSuccessStatusReport(
|
||||
logger,
|
||||
);
|
||||
if (statusReportBase !== undefined) {
|
||||
const statusReport: StartProxyStatus = {
|
||||
const statusReport: StatusReportBase = {
|
||||
...statusReportBase,
|
||||
registry_types: registry_types.join(","),
|
||||
};
|
||||
|
||||
@@ -254,13 +254,19 @@ export function credentialToStr(credential: Credential): string {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** A package registry is identified by its type and address. */
|
||||
export type Registry = {
|
||||
/** The schema for `RegistryBase` objects. */
|
||||
export const registryBaseSchema = {
|
||||
/** The type of the package registry. */
|
||||
type: string;
|
||||
type: json.string,
|
||||
/** Whether the registry replaces the base registry for the ecosystem. */
|
||||
"replaces-base"?: boolean;
|
||||
} & Address;
|
||||
"replaces-base": json.optional(json.boolean),
|
||||
} as const satisfies json.Schema;
|
||||
|
||||
/** Information about a registry, other than its address. */
|
||||
export type RegistryBase = json.FromSchema<typeof registryBaseSchema>;
|
||||
|
||||
/** A package registry is identified by its type and address. */
|
||||
export type Registry = RegistryBase & Address;
|
||||
|
||||
// If a registry has an `url`, then that takes precedence over the `host` which may or may
|
||||
// not be defined.
|
||||
|
||||
@@ -4,15 +4,17 @@ import * as uuid from "uuid";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { Config } from "./config-utils";
|
||||
import { EnvVar } from "./environment";
|
||||
import { EnvVar, RegistryProxyVars } from "./environment";
|
||||
import { BuiltInLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { ToolsSource } from "./setup-codeql";
|
||||
import type { Registry } from "./start-proxy";
|
||||
import {
|
||||
ActionName,
|
||||
createInitWithConfigStatusReport,
|
||||
createStatusReportBase,
|
||||
getActionsStatus,
|
||||
getRegistryTypesFromEnv,
|
||||
getJobUUID,
|
||||
InitStatusReport,
|
||||
InitWithConfigStatusReport,
|
||||
@@ -22,12 +24,69 @@ import {
|
||||
setupActionsVars,
|
||||
createTestConfig,
|
||||
makeMacro,
|
||||
getTestEnv,
|
||||
RecordingLogger,
|
||||
callee,
|
||||
} from "./testing-utils";
|
||||
import { BuildMode, ConfigurationError, withTmpDir, wrapError } from "./util";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
test("getRegistryTypesFromEnv - gets unique registry types from environment", async (t) => {
|
||||
const logger = new RecordingLogger(true);
|
||||
const env = getTestEnv({
|
||||
[RegistryProxyVars.PROXY_URLS]: JSON.stringify([
|
||||
{ type: "git_source", url: "https://example.com" },
|
||||
{ type: "git_source", url: "https://github.com" },
|
||||
{ type: "docker_registry", url: "https://registry.example.com" },
|
||||
] satisfies Array<Partial<Registry>>),
|
||||
});
|
||||
|
||||
const result = getRegistryTypesFromEnv(logger, env);
|
||||
t.deepEqual(result, ["git_source", "docker_registry"].sort().join(","));
|
||||
});
|
||||
|
||||
test("getRegistryTypesFromEnv - returns undefined if the env var is not set", async (t) => {
|
||||
const logger = new RecordingLogger(true);
|
||||
const env = getTestEnv({});
|
||||
|
||||
const result = getRegistryTypesFromEnv(logger, env);
|
||||
t.is(result, undefined);
|
||||
});
|
||||
|
||||
test("getRegistryTypesFromEnv - returns undefined if the env var is not valid JSON", async (t) => {
|
||||
const logger = new RecordingLogger(true);
|
||||
const env = getTestEnv({ [RegistryProxyVars.PROXY_URLS]: "[" });
|
||||
|
||||
const result = getRegistryTypesFromEnv(logger, env);
|
||||
t.is(result, undefined);
|
||||
});
|
||||
|
||||
test("getRegistryTypesFromEnv - returns undefined if the env var is unexpected JSON", async (t) => {
|
||||
const logger = new RecordingLogger(true);
|
||||
|
||||
t.is(
|
||||
getRegistryTypesFromEnv(
|
||||
logger,
|
||||
getTestEnv({
|
||||
// Top-level object rather than an array of objects.
|
||||
[RegistryProxyVars.PROXY_URLS]: JSON.stringify({ type: "git_source" }),
|
||||
}),
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
t.is(
|
||||
getRegistryTypesFromEnv(
|
||||
logger,
|
||||
getTestEnv({
|
||||
// Object has no "type" key.
|
||||
[RegistryProxyVars.PROXY_URLS]: JSON.stringify([{}]),
|
||||
}),
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
test("getJobUUID - generates valid UUIDs", async (t) => {
|
||||
await callee(getJobUUID)
|
||||
.withArgs()
|
||||
@@ -74,6 +133,9 @@ function setupEnvironmentAndStub(tmpDir: string) {
|
||||
|
||||
process.env[EnvVar.ANALYSIS_KEY] = "analysis-key";
|
||||
process.env["ImageVersion"] = "2023.05.19.1";
|
||||
process.env[RegistryProxyVars.PROXY_URLS] = JSON.stringify([
|
||||
{ type: "maven_repository" },
|
||||
] satisfies Array<Partial<Registry>>);
|
||||
|
||||
const getRequiredInput = sinon.stub(actionsUtil, "getRequiredInput");
|
||||
getRequiredInput.withArgs("matrix").resolves("input/matrix");
|
||||
@@ -117,6 +179,7 @@ test.serial("createStatusReportBase", async (t) => {
|
||||
t.is(typeof statusReport.job_run_uuid, "string");
|
||||
t.is(statusReport.languages, "java,swift");
|
||||
t.is(statusReport.ref, process.env["GITHUB_REF"]!);
|
||||
t.is(statusReport.registry_types, "maven_repository");
|
||||
t.is(statusReport.runner_available_disk_space_bytes, 100);
|
||||
t.is(statusReport.runner_image_version, process.env["ImageVersion"]);
|
||||
t.is(statusReport.runner_os, process.env["RUNNER_OS"]!);
|
||||
|
||||
@@ -19,12 +19,14 @@ import type { ComputedInput, InputName } from "./config/inputs";
|
||||
import { parseRegistriesWithoutCredentials } from "./config/pack-registries";
|
||||
import type { DependencyCacheRestoreStatusReport } from "./dependency-caching";
|
||||
import { DocUrl } from "./doc-url";
|
||||
import { EnvVar } from "./environment";
|
||||
import { EnvVar, getEnv, ReadOnlyEnv, RegistryProxyVars } from "./environment";
|
||||
import { getRef } from "./git-utils";
|
||||
import * as json from "./json";
|
||||
import type { Logger } from "./logging";
|
||||
import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching";
|
||||
import { getRepositoryNwo } from "./repository";
|
||||
import type { ToolsSource } from "./setup-codeql";
|
||||
import { registryBaseSchema } from "./start-proxy/types";
|
||||
import {
|
||||
ConfigurationError,
|
||||
getRequiredEnvParam,
|
||||
@@ -185,6 +187,12 @@ export interface StatusReportBase {
|
||||
ml_powered_javascript_queries?: string;
|
||||
/** Ref that the workflow was triggered on. */
|
||||
ref: string;
|
||||
/**
|
||||
* A comma-separated list of private registry types which are configured for CodeQL.
|
||||
* This only includes registry types we support (as determined by the `start-proxy` action),
|
||||
* not all that are configured.
|
||||
*/
|
||||
registry_types?: string;
|
||||
/** Action runner hardware architecture (context runner.arch). */
|
||||
runner_arch?: string;
|
||||
/** Available disk space on the runner, in bytes. */
|
||||
@@ -288,6 +296,50 @@ export interface EventReport {
|
||||
started_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to retrieve a list of private registry types from the `CODEQL_PROXY_URLS` environment
|
||||
* variable and returns it as a comma-separated string if successful. Returns `undefined` otherwise.
|
||||
*/
|
||||
export function getRegistryTypesFromEnv(
|
||||
logger: Logger,
|
||||
env: ReadOnlyEnv = getEnv(),
|
||||
): string | undefined {
|
||||
// Try to get the value of the environment variable.
|
||||
const value = env.getOptional(RegistryProxyVars.PROXY_URLS);
|
||||
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Try to parse the JSON we expect to find in it and return the comma-separated list of
|
||||
// (unique) registry types.
|
||||
try {
|
||||
const data = JSON.parse(value) as unknown;
|
||||
|
||||
// Check that the parsed JSON meets our expectations.
|
||||
if (!json.isArray(data)) {
|
||||
logger.debug(
|
||||
`Expected '${RegistryProxyVars.PROXY_URLS}' to contain a JSON array, but got '${typeof data}'.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
if (!json.validateArray(registryBaseSchema, data)) {
|
||||
logger.debug(
|
||||
`Expected '${RegistryProxyVars.PROXY_URLS}' to contain a JSON array of registry objects, but got something else.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const types = new Set(data.map((r) => r.type));
|
||||
return Array.from(types).sort().join(",");
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
`Failed to parse '${RegistryProxyVars.PROXY_URLS}': ${getErrorMessage(err)}.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a StatusReport.
|
||||
*
|
||||
@@ -350,6 +402,7 @@ export async function createStatusReportBase(
|
||||
job_name: jobName,
|
||||
job_run_uuid: jobRunUUID,
|
||||
ref,
|
||||
registry_types: getRegistryTypesFromEnv(logger),
|
||||
runner_os: runnerOs,
|
||||
started_at: workflowStartedAt,
|
||||
status,
|
||||
|
||||
Reference in New Issue
Block a user