Merge pull request #3904 from github/mbg/esbuild/split-follow-up

Address review comments for #3899
This commit is contained in:
Michael B. Gale
2026-05-15 12:48:02 +00:00
committed by GitHub
4 changed files with 149 additions and 175 deletions

View File

@@ -66,8 +66,8 @@ const onEndPlugin = {
const SHARED_ENTRYPOINT = "entry-points";
/**
* This plugin finds all source files that contain action entry points.
* It then generates the virtual `entry-points` module which imports all identifies files,
* This plugin finds all source files that contain Action entry points.
* It then generates the virtual `entry-points` module which imports all identified files,
* and re-exports their `runWrapper` functions with suitable aliases.
* A tiny stub file is emitted for each Action entrypoint. Each stub imports the shared bundle
* and calls the respective entry point.
@@ -83,7 +83,7 @@ const entryPointsPlugin = {
const toPascal = (s) =>
s.replace(/(^|-)([a-z0-9])/gi, (_, __, c) => c.toUpperCase());
// Find the source files containing action entry points.
// Find the source files containing Action entry points.
build.onStart(() => {
const actionFiles = globSync("src/*-action{,-post}.ts");
for (const actionFile of actionFiles) {
@@ -112,7 +112,7 @@ const entryPointsPlugin = {
return { path: SHARED_ENTRYPOINT, namespace };
});
// Generate the virtual `entry-points` file based on the actions we discovered.
// Generate the virtual `entry-points` file based on the Actions we discovered.
// Restrict using the namespace. The path filter does not need to discriminate any further.
build.onLoad({ filter: /.*/, namespace }, async () => {
const wrapperTemplatePath = "entry-wrapper.js.tpl";
@@ -127,7 +127,7 @@ const entryPointsPlugin = {
const imports = actionsSorted
.map(
(action) =>
`import * as ${action.pascalCaseName} from "./src/${basename(action.path)}"`,
`import * as ${action.pascalCaseName} from "./src/${basename(action.path)}";`,
)
.join("\n");
const wrappers = actionsSorted
@@ -143,7 +143,7 @@ const entryPointsPlugin = {
};
});
// Emit entry point stubs for each action using the entry template.
// Emit entry point stubs for each Action using the entry template.
build.onEnd(async (result) => {
// Read the entry point template.
const templatePath = "action-entry.js.tpl";
@@ -152,7 +152,7 @@ const entryPointsPlugin = {
const makeHeader = (sourceFile) =>
`// Automatically generated from '${templatePath}' for 'src/${basename(sourceFile)}'.\n\n`;
// Write entry point stubs for each action.
// Write entry point stubs for each Action.
for (const action of actions) {
await writeFile(
join(

View File

@@ -1,85 +0,0 @@
import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client";
import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils";
import * as statusReport from "./status-report";
import {
setupTests,
setupActionsVars,
mockFeatureFlagApiEndpoint,
} from "./testing-utils";
import * as util from "./util";
setupTests(test);
// This test needs to be in its own file so that ava would run it in its own
// nodejs process. The code being tested is in analyze-action.ts, which runs
// immediately on load. So the file needs to be loaded during part of the test,
// and that can happen only once per nodejs process. If multiple such tests are
// in the same test file, ava would run them in the same nodejs process, and all
// but the first test would fail.
test("analyze action with RAM & threads from environment variables", async (t) => {
// This test frequently times out on Windows with the default timeout, so we bump
// it a bit to 20s.
t.timeout(1000 * 20);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
sinon
.stub(statusReport, "createStatusReportBase")
.resolves({} as statusReport.StatusReportBase);
sinon.stub(statusReport, "sendStatusReport").resolves();
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
const gitHubVersion: util.GitHubVersion = {
type: util.GitHubVariant.DOTCOM,
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},
} as unknown as configUtils.Config);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("token").returns("fake-token");
requiredInputStub.withArgs("upload-database").returns("false");
requiredInputStub.withArgs("output").returns("out");
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
optionalInputStub.withArgs("expect-error").returns("false");
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
mockFeatureFlagApiEndpoint(200, {});
// When there are no action inputs for RAM and threads, the action uses
// environment variables (passed down from the init action) to set RAM and
// threads usage.
process.env["CODEQL_THREADS"] = "-1";
process.env["CODEQL_RAM"] = "4992";
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
await runWrapper();
t.assert(
runFinalizeStub.calledOnceWith(
sinon.match.any,
sinon.match.any,
"--threads=-1",
"--ram=4992",
),
);
t.assert(
runQueriesStub.calledOnceWith(
sinon.match.any,
"--ram=4992",
"--threads=-1",
),
);
});
});

View File

@@ -1,83 +0,0 @@
import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client";
import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils";
import * as statusReport from "./status-report";
import {
setupTests,
setupActionsVars,
mockFeatureFlagApiEndpoint,
} from "./testing-utils";
import * as util from "./util";
setupTests(test);
// This test needs to be in its own file so that ava would run it in its own
// nodejs process. The code being tested is in analyze-action.ts, which runs
// immediately on load. So the file needs to be loaded during part of the test,
// and that can happen only once per nodejs process. If multiple such tests are
// in the same test file, ava would run them in the same nodejs process, and all
// but the first test would fail.
test("analyze action with RAM & threads from action inputs", async (t) => {
t.timeout(1000 * 20);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
sinon
.stub(statusReport, "createStatusReportBase")
.resolves({} as statusReport.StatusReportBase);
sinon.stub(statusReport, "sendStatusReport").resolves();
const gitHubVersion: util.GitHubVersion = {
type: util.GitHubVariant.DOTCOM,
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},
} as unknown as configUtils.Config);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("token").returns("fake-token");
requiredInputStub.withArgs("upload-database").returns("false");
requiredInputStub.withArgs("output").returns("out");
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
optionalInputStub.withArgs("expect-error").returns("false");
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
mockFeatureFlagApiEndpoint(200, {});
process.env["CODEQL_THREADS"] = "1";
process.env["CODEQL_RAM"] = "4992";
// Action inputs have precedence over environment variables.
optionalInputStub.withArgs("threads").returns("-1");
optionalInputStub.withArgs("ram").returns("3012");
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
await runWrapper();
t.assert(
runFinalizeStub.calledOnceWith(
sinon.match.any,
sinon.match.any,
"--threads=-1",
"--ram=3012",
),
);
t.assert(
runQueriesStub.calledOnceWith(
sinon.match.any,
"--ram=3012",
"--threads=-1",
),
);
});
});

142
src/analyze-action.test.ts Normal file
View File

@@ -0,0 +1,142 @@
import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as analyze from "./analyze";
import { runWrapper } from "./analyze-action";
import * as api from "./api-client";
import * as configUtils from "./config-utils";
import * as gitUtils from "./git-utils";
import * as statusReport from "./status-report";
import {
setupTests,
setupActionsVars,
mockFeatureFlagApiEndpoint,
} from "./testing-utils";
import * as util from "./util";
setupTests(test);
test.serial(
"analyze action with RAM & threads from environment variables",
async (t) => {
// This test frequently times out on Windows with the default timeout, so we bump
// it a bit to 20s.
t.timeout(1000 * 20);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
sinon
.stub(statusReport, "createStatusReportBase")
.resolves({} as statusReport.StatusReportBase);
sinon.stub(statusReport, "sendStatusReport").resolves();
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
const gitHubVersion: util.GitHubVersion = {
type: util.GitHubVariant.DOTCOM,
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},
} as unknown as configUtils.Config);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("token").returns("fake-token");
requiredInputStub.withArgs("upload-database").returns("false");
requiredInputStub.withArgs("output").returns("out");
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
optionalInputStub.withArgs("expect-error").returns("false");
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
mockFeatureFlagApiEndpoint(200, {});
// When there are no action inputs for RAM and threads, the action uses
// environment variables (passed down from the init action) to set RAM and
// threads usage.
process.env["CODEQL_THREADS"] = "-1";
process.env["CODEQL_RAM"] = "4992";
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
await runWrapper();
t.assert(
runFinalizeStub.calledOnceWith(
sinon.match.any,
sinon.match.any,
"--threads=-1",
"--ram=4992",
),
);
t.assert(
runQueriesStub.calledOnceWith(
sinon.match.any,
"--ram=4992",
"--threads=-1",
),
);
});
},
);
test.serial(
"analyze action with RAM & threads from action inputs",
async (t) => {
t.timeout(1000 * 20);
await util.withTmpDir(async (tmpDir) => {
setupActionsVars(tmpDir, tmpDir);
sinon
.stub(statusReport, "createStatusReportBase")
.resolves({} as statusReport.StatusReportBase);
sinon.stub(statusReport, "sendStatusReport").resolves();
const gitHubVersion: util.GitHubVersion = {
type: util.GitHubVariant.DOTCOM,
};
sinon.stub(configUtils, "getConfig").resolves({
gitHubVersion,
augmentationProperties: {},
languages: [],
packs: [],
trapCaches: {},
} as unknown as configUtils.Config);
const requiredInputStub = sinon.stub(actionsUtil, "getRequiredInput");
requiredInputStub.withArgs("token").returns("fake-token");
requiredInputStub.withArgs("upload-database").returns("false");
requiredInputStub.withArgs("output").returns("out");
const optionalInputStub = sinon.stub(actionsUtil, "getOptionalInput");
optionalInputStub.withArgs("expect-error").returns("false");
sinon.stub(api, "getGitHubVersion").resolves(gitHubVersion);
sinon.stub(gitUtils, "isAnalyzingDefaultBranch").resolves(true);
mockFeatureFlagApiEndpoint(200, {});
process.env["CODEQL_THREADS"] = "1";
process.env["CODEQL_RAM"] = "4992";
// Action inputs have precedence over environment variables.
optionalInputStub.withArgs("threads").returns("-1");
optionalInputStub.withArgs("ram").returns("3012");
const runFinalizeStub = sinon.stub(analyze, "runFinalize");
const runQueriesStub = sinon.stub(analyze, "runQueries");
await runWrapper();
t.assert(
runFinalizeStub.calledOnceWith(
sinon.match.any,
sinon.match.any,
"--threads=-1",
"--ram=3012",
),
);
t.assert(
runQueriesStub.calledOnceWith(
sinon.match.any,
"--ram=3012",
"--threads=-1",
),
);
});
},
);