Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions lib/entry-points.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"long": "^5.3.2",
"node-forge": "^1.4.0",
"semver": "^7.8.5",
"uuid": "^14.0.1"
"uuid": "^14.0.1",
"undici": "^6.24.0"
},
"devDependencies": {
"@ava/typescript": "6.0.0",
Expand Down
36 changes: 34 additions & 2 deletions src/api-client.test.ts
Comment thread
mario-campos marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import { DO_NOT_RETRY_STATUSES } from "./api-client";
import { ActionsEnvVars } from "./environment";
import { ActionsEnvVars, RegistryProxyVars } from "./environment";
import { getTestEnv, setupTests } from "./testing-utils";
import * as util from "./util";

Expand All @@ -27,14 +27,17 @@ test.serial("getApiClient", async (t) => {

sinon.stub(actionsUtil, "getRequiredInput").withArgs("token").returns("xyz");

api.getApiClient(env);
const apiClient = api.getApiClient(env);
t.truthy(apiClient);

t.true(githubStub.calledOnce);
t.assert(
githubStub.calledOnceWithExactly({
auth: "token xyz",
baseUrl: "http://api.github.localhost",
log: sinon.match.any,
userAgent: `CodeQL-Action/${actionsUtil.getActionVersion()}`,
request: sinon.match.any,
retry: {
doNotRetry: DO_NOT_RETRY_STATUSES,
},
Expand Down Expand Up @@ -204,3 +207,32 @@ test.serial(
}
},
);

test("getRegistryProxy - returns undefined if the proxy is not configured", async (t) => {
// Empty environment.
t.is(api.getRegistryProxy(getTestEnv()), undefined);
// Only the host.
t.is(
api.getRegistryProxy(
getTestEnv({ [RegistryProxyVars.PROXY_HOST]: "localhost" }),
),
undefined,
);
// Only the port.
t.is(
api.getRegistryProxy(
getTestEnv({ [RegistryProxyVars.PROXY_PORT]: "1234" }),
),
undefined,
);
});

test("getRegistryProxy - returns value when both vars are set", async (t) => {
const proxy = api.getRegistryProxy(
getTestEnv({
[RegistryProxyVars.PROXY_HOST]: "localhost",
[RegistryProxyVars.PROXY_PORT]: "1234",
}),
);
t.truthy(proxy);
});
56 changes: 55 additions & 1 deletion src/api-client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import * as core from "@actions/core";
import * as githubUtils from "@actions/github/lib/utils";
import * as retry from "@octokit/plugin-retry";
import {
ProxyAgent,
RequestInfo,
RequestInit,
fetch as undiciFetch,
} from "undici";

import { getActionVersion, getRequiredInput } from "./actions-util";
import { EnvVar, ReadOnlyEnv, ActionsEnvVars, getEnv } from "./environment";
import {
ActionsEnvVars,
EnvVar,
ReadOnlyEnv,
RegistryProxyVars,
getEnv,
} from "./environment";
import { Logger } from "./logging";
import { getRepositoryNwo, RepositoryNwo } from "./repository";
import {
Expand Down Expand Up @@ -43,6 +55,47 @@ export interface GitHubApiExternalRepoDetails {
apiURL: string | undefined;
}

/**
* Gets the configuration for the private registry authentication proxy,
* if it is available in the environment.
*
* @param env The environment to query for the proxy host and port.
* @returns A `ProxyAgent` corresponding to the private registry proxy,
* or `undefined` if we couldn't retrieve the host and port.
*/
export function getRegistryProxy(env: ReadOnlyEnv): ProxyAgent | undefined {
const host = env.getOptional(RegistryProxyVars.PROXY_HOST);
const port = env.getOptional(RegistryProxyVars.PROXY_PORT);
const cert = env.getOptional(RegistryProxyVars.PROXY_CA_CERTIFICATE);

if (host && port) {
return new ProxyAgent({
uri: `http://${host}:${port}`,
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10,
requestTls: cert ? { ca: cert } : undefined,
});
}

return undefined;
}

/**
* Returns an implementation of `fetch` to use for API requests.
* This will run API requests through the private registry authentication proxy
* if it is configured.
*
* @param env The environment to query for the proxy host and port.
*/
export function getApiFetch(env: ReadOnlyEnv): typeof undiciFetch {
const dispatcher = getRegistryProxy(env);

const proxiedFetch = (req: RequestInfo, init?: RequestInit) => {
return undiciFetch(req, { ...init, dispatcher });
};
return proxiedFetch;
}

function createApiClientWithDetails(
apiDetails: GitHubApiCombinedDetails,
{ allowExternal = false } = {},
Expand All @@ -60,6 +113,7 @@ function createApiClientWithDetails(
warn: core.warning,
error: core.error,
},
request: { fetch: getApiFetch(getEnv()) },
retry: {
doNotRetry: DO_NOT_RETRY_STATUSES,
},
Expand Down
12 changes: 11 additions & 1 deletion src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/**
* Environment variables used by Default Setup to communicate the private registry proxy configuration.
*/
export enum RegistryProxyVars {
PROXY_HOST = "CODEQL_PROXY_HOST",
PROXY_PORT = "CODEQL_PROXY_PORT",
PROXY_CA_CERTIFICATE = "CODEQL_PROXY_CA_CERTIFICATE",
PROXY_URLS = "CODEQL_PROXY_URLS",
}

/**
* Environment variables used by the CodeQL Action.
*
Expand Down Expand Up @@ -202,7 +212,7 @@ export enum ActionsEnvVars {
}

/** A type representing all known environment variables. */
export type KnownEnvVar = EnvVar | ActionsEnvVars;
export type KnownEnvVar = EnvVar | ActionsEnvVars | RegistryProxyVars;

/**
* Gets an environment variable, but throws an error if it is not set.
Expand Down
3 changes: 1 addition & 2 deletions src/testing-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@ export function makeMacro<Args extends unknown[]>(
return wrapper;
}

export function getTestEnv(): Env {
const testEnv: NodeJS.ProcessEnv = {};
export function getTestEnv(testEnv: NodeJS.ProcessEnv = {}): Env {
return getEnv(testEnv);
}

Expand Down