mirror of
https://github.com/github/codeql-action.git
synced 2026-04-27 17:39:15 +00:00
Type that registries must have either an url or a host
This commit is contained in:
@@ -11,16 +11,16 @@ import { KnownLanguage } from "./languages";
|
||||
import { getActionsLogger, Logger } from "./logging";
|
||||
import { getRepositoryNwo } from "./repository";
|
||||
import {
|
||||
Credential,
|
||||
credentialToStr,
|
||||
getCredentials,
|
||||
getProxyBinaryPath,
|
||||
getSafeErrorMessage,
|
||||
parseLanguage,
|
||||
ProxyInfo,
|
||||
Registry,
|
||||
sendFailedStatusReport,
|
||||
sendSuccessStatusReport,
|
||||
ValidCredential,
|
||||
ValidRegistry,
|
||||
} from "./start-proxy";
|
||||
import { checkConnections } from "./start-proxy/reachability";
|
||||
import { ActionName, sendUnhandledErrorStatusReport } from "./status-report";
|
||||
@@ -40,7 +40,7 @@ type BasicAuthCredentials = {
|
||||
};
|
||||
|
||||
type ProxyConfig = {
|
||||
all_credentials: Credential[];
|
||||
all_credentials: ValidCredential[];
|
||||
ca: CertificateAuthority;
|
||||
proxy_auth?: BasicAuthCredentials;
|
||||
};
|
||||
@@ -243,7 +243,7 @@ async function startProxy(
|
||||
core.setOutput("proxy_port", port.toString());
|
||||
core.setOutput("proxy_ca_certificate", config.ca.cert);
|
||||
|
||||
const registry_urls: Registry[] = config.all_credentials
|
||||
const registry_urls: ValidRegistry[] = config.all_credentials
|
||||
.filter((credential) => credential.url !== undefined)
|
||||
.map((credential) => ({
|
||||
type: credential.type,
|
||||
|
||||
+35
-11
@@ -13,7 +13,12 @@ import { Config } from "./config-utils";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { Logger } from "./logging";
|
||||
import { Credential } from "./start-proxy/types";
|
||||
import {
|
||||
Address,
|
||||
Credential,
|
||||
Registry,
|
||||
ValidCredential,
|
||||
} from "./start-proxy/types";
|
||||
import {
|
||||
ActionName,
|
||||
createStatusReportBase,
|
||||
@@ -223,6 +228,31 @@ const LANGUAGE_TO_REGISTRY_TYPE: Partial<Record<KnownLanguage, string[]>> = {
|
||||
go: ["goproxy_server", "git_source"],
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Extracts an `Address` value from the given `Registry` value by determining whether it has
|
||||
* a `url` value, or no `url` value but a `host` value.
|
||||
*
|
||||
* @throws A `ConfigurationError` if the `Registry` value contains neither a `url` or `host` field.
|
||||
*/
|
||||
function getRegistryAddress(registry: Registry): Address {
|
||||
if (isDefined(registry.url)) {
|
||||
return {
|
||||
url: registry.url,
|
||||
host: registry.host,
|
||||
};
|
||||
} else if (isDefined(registry.host)) {
|
||||
return {
|
||||
url: undefined,
|
||||
host: registry.host,
|
||||
};
|
||||
} else {
|
||||
// The proxy needs one of these to work. If both are defined, the url has the precedence.
|
||||
throw new ConfigurationError(
|
||||
"Invalid credentials - must specify host or url",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// getCredentials returns registry credentials from action inputs.
|
||||
// It prefers `registries_credentials` over `registry_secrets`.
|
||||
// If neither is set, it returns an empty array.
|
||||
@@ -231,7 +261,7 @@ export function getCredentials(
|
||||
registrySecrets: string | undefined,
|
||||
registriesCredentials: string | undefined,
|
||||
language: KnownLanguage | undefined,
|
||||
): Credential[] {
|
||||
): ValidCredential[] {
|
||||
const registryTypeForLanguage = language
|
||||
? LANGUAGE_TO_REGISTRY_TYPE[language]
|
||||
: undefined;
|
||||
@@ -265,7 +295,7 @@ export function getCredentials(
|
||||
);
|
||||
}
|
||||
|
||||
const out: Credential[] = [];
|
||||
const out: ValidCredential[] = [];
|
||||
for (const e of parsed) {
|
||||
if (e === null || typeof e !== "object") {
|
||||
throw new ConfigurationError("Invalid credentials - must be an object");
|
||||
@@ -279,12 +309,7 @@ export function getCredentials(
|
||||
core.setSecret(e.token);
|
||||
}
|
||||
|
||||
if (!isDefined(e.url) && !isDefined(e.host)) {
|
||||
// The proxy needs one of these to work. If both are defined, the url has the precedence.
|
||||
throw new ConfigurationError(
|
||||
"Invalid credentials - must specify host or url",
|
||||
);
|
||||
}
|
||||
const address = getRegistryAddress(e);
|
||||
|
||||
// Filter credentials based on language if specified. `type` is the registry type.
|
||||
// E.g., "maven_feed" for Java/Kotlin, "nuget_repository" for C#.
|
||||
@@ -327,11 +352,10 @@ export function getCredentials(
|
||||
|
||||
out.push({
|
||||
type: e.type,
|
||||
host: e.host,
|
||||
url: e.url,
|
||||
username: e.username,
|
||||
password: e.password,
|
||||
token: e.token,
|
||||
...address,
|
||||
});
|
||||
}
|
||||
return out;
|
||||
|
||||
@@ -11,22 +11,22 @@ import {
|
||||
ReachabilityBackend,
|
||||
ReachabilityError,
|
||||
} from "./reachability";
|
||||
import { ProxyInfo, Registry } from "./types";
|
||||
import { ProxyInfo, ValidRegistry } from "./types";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
class MockReachabilityBackend implements ReachabilityBackend {
|
||||
public async checkConnection(_registry: Registry): Promise<number> {
|
||||
public async checkConnection(_registry: ValidRegistry): Promise<number> {
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
const mavenRegistry: Registry = {
|
||||
const mavenRegistry: ValidRegistry = {
|
||||
type: "maven_registry",
|
||||
url: "https://repo.maven.apache.org/maven2/",
|
||||
};
|
||||
|
||||
const nugetFeed: Registry = {
|
||||
const nugetFeed: ValidRegistry = {
|
||||
type: "nuget_feed",
|
||||
url: "https://api.nuget.org/v3/index.json",
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import { HttpsProxyAgent } from "https-proxy-agent";
|
||||
import { Logger } from "../logging";
|
||||
import { getErrorMessage } from "../util";
|
||||
|
||||
import { ProxyInfo, Registry } from "./types";
|
||||
import { getAddressString, ProxyInfo, Registry, ValidRegistry } from "./types";
|
||||
|
||||
export class ReachabilityError extends Error {
|
||||
constructor(
|
||||
@@ -34,7 +34,7 @@ export interface ReachabilityBackend {
|
||||
* @param registry The registry to try and reach.
|
||||
* @returns The successful status code (in the `<400` range).
|
||||
*/
|
||||
checkConnection: (registry: Registry) => Promise<number>;
|
||||
checkConnection: (registry: ValidRegistry) => Promise<number>;
|
||||
}
|
||||
|
||||
class NetworkReachabilityBackend implements ReachabilityBackend {
|
||||
@@ -47,10 +47,10 @@ class NetworkReachabilityBackend implements ReachabilityBackend {
|
||||
this.agent = new HttpsProxyAgent(`http://${proxy.host}:${proxy.port}`);
|
||||
}
|
||||
|
||||
public async checkConnection(registry: Registry): Promise<number> {
|
||||
public async checkConnection(registry: ValidRegistry): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = https.request(
|
||||
registry.url as string,
|
||||
getAddressString(registry),
|
||||
{ agent: this.agent, method: "HEAD", ca: this.proxy.cert },
|
||||
(res) => {
|
||||
res.destroy();
|
||||
@@ -83,8 +83,8 @@ export async function checkConnections(
|
||||
logger: Logger,
|
||||
proxy: ProxyInfo,
|
||||
backend?: ReachabilityBackend,
|
||||
): Promise<Set<Registry>> {
|
||||
const result: Set<Registry> = new Set();
|
||||
): Promise<Set<ValidRegistry>> {
|
||||
const result: Set<ValidRegistry> = new Set();
|
||||
|
||||
// Don't do anything if there are no registries.
|
||||
if (proxy.registries.length === 0) return result;
|
||||
@@ -96,22 +96,23 @@ export async function checkConnections(
|
||||
}
|
||||
|
||||
for (const registry of proxy.registries) {
|
||||
const address = getAddressString(registry);
|
||||
try {
|
||||
logger.debug(`Testing connection to ${registry.url}...`);
|
||||
logger.debug(`Testing connection to ${address}...`);
|
||||
const statusCode = await backend.checkConnection(registry);
|
||||
|
||||
logger.info(
|
||||
`Successfully tested connection to ${registry.url} (${statusCode})`,
|
||||
`Successfully tested connection to ${address} (${statusCode})`,
|
||||
);
|
||||
result.add(registry);
|
||||
} catch (e) {
|
||||
if (e instanceof ReachabilityError && e.statusCode !== undefined) {
|
||||
logger.error(
|
||||
`Connection test to ${registry.url} failed. (${e.statusCode})`,
|
||||
`Connection test to ${address} failed. (${e.statusCode})`,
|
||||
);
|
||||
} else {
|
||||
logger.error(
|
||||
`Connection test to ${registry.url} failed: ${getErrorMessage(e)}`,
|
||||
`Connection test to ${address} failed: ${getErrorMessage(e)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,41 @@ export interface Registry {
|
||||
url?: string;
|
||||
}
|
||||
|
||||
// If a registry has an `url`, then that takes precedence over the `host` which may or may
|
||||
// not be defined.
|
||||
interface HasUrl {
|
||||
url: string;
|
||||
host?: string;
|
||||
}
|
||||
|
||||
// If a registry does not have an `url`, then it must have a `host`.
|
||||
interface WithoutUrl {
|
||||
url: undefined;
|
||||
host: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A valid `Registry` value must either have a `url` or a `host` value. If it has a `url` value,
|
||||
* then that takes precedence over the `host` value. If there is no `url` value, then it must
|
||||
* have a `host` value.
|
||||
*/
|
||||
export type Address = HasUrl | WithoutUrl;
|
||||
|
||||
/** Gets the address as a string. This will either be the `url` if present, or the `host` if not. */
|
||||
export function getAddressString(address: Address): string {
|
||||
if (address.url === undefined) {
|
||||
return address.host;
|
||||
} else {
|
||||
return address.url;
|
||||
}
|
||||
}
|
||||
|
||||
export type ValidRegistry<T extends Registry = Registry> = T & Address;
|
||||
export type ValidCredential = ValidRegistry<Credential>;
|
||||
|
||||
export interface ProxyInfo {
|
||||
host: string;
|
||||
port: number;
|
||||
cert: string;
|
||||
registries: Registry[];
|
||||
registries: ValidRegistry[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user