-
Notifications
You must be signed in to change notification settings - Fork 355
/
Copy pathinit.ts
258 lines (244 loc) · 7.83 KB
/
init.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
import * as fs from "fs";
import * as path from "path";
import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as io from "@actions/io";
import * as semver from "semver";
import { getOptionalInput, isSelfHostedRunner } from "./actions-util";
import { GitHubApiCombinedDetails, GitHubApiDetails } from "./api-client";
import { CodeQL, setupCodeQL } from "./codeql";
import * as configUtils from "./config-utils";
import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags";
import { getGitRoot } from "./git-utils";
import { Language, isScannedLanguage } from "./languages";
import { Logger } from "./logging";
import {
CODEQL_OVERLAY_MINIMUM_VERSION,
OverlayDatabaseMode,
} from "./overlay-database-utils";
import { ToolsSource } from "./setup-codeql";
import { ZstdAvailability } from "./tar";
import { ToolsDownloadStatusReport } from "./tools-download";
import { ToolsFeature } from "./tools-features";
import { TracerConfig, getCombinedTracerConfig } from "./tracer-config";
import * as util from "./util";
export async function initCodeQL(
toolsInput: string | undefined,
apiDetails: GitHubApiDetails,
tempDir: string,
variant: util.GitHubVariant,
defaultCliVersion: CodeQLDefaultVersionInfo,
features: FeatureEnablement,
logger: Logger,
): Promise<{
codeql: CodeQL;
toolsDownloadStatusReport?: ToolsDownloadStatusReport;
toolsSource: ToolsSource;
toolsVersion: string;
zstdAvailability: ZstdAvailability;
}> {
logger.startGroup("Setup CodeQL tools");
const {
codeql,
toolsDownloadStatusReport,
toolsSource,
toolsVersion,
zstdAvailability,
} = await setupCodeQL(
toolsInput,
apiDetails,
tempDir,
variant,
defaultCliVersion,
logger,
features,
true,
);
await codeql.printVersion();
logger.endGroup();
return {
codeql,
toolsDownloadStatusReport,
toolsSource,
toolsVersion,
zstdAvailability,
};
}
export async function initConfig(
inputs: configUtils.InitConfigInputs,
codeql: CodeQL,
): Promise<configUtils.Config> {
const logger = inputs.logger;
logger.startGroup("Load language configuration");
const config = await configUtils.initConfig(inputs);
if (
!(await codeql.supportsFeature(
ToolsFeature.InformsAboutUnsupportedPathFilters,
))
) {
printPathFiltersWarning(config, logger);
}
logger.endGroup();
return config;
}
export async function getOverlayDatabaseMode(
codeqlVersion: string,
config: configUtils.Config,
sourceRoot: string,
logger: Logger,
): Promise<OverlayDatabaseMode> {
const overlayDatabaseMode = process.env.CODEQL_OVERLAY_DATABASE_MODE;
if (
overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
overlayDatabaseMode === OverlayDatabaseMode.OverlayBase
) {
if (config.buildMode !== util.BuildMode.None) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`build-mode is set to "${config.buildMode}" instead of "none". ` +
"Falling back to creating a normal full database instead.",
);
return OverlayDatabaseMode.None;
}
if (semver.lt(codeqlVersion, CODEQL_OVERLAY_MINIMUM_VERSION)) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`the CodeQL CLI is older than ${CODEQL_OVERLAY_MINIMUM_VERSION}. ` +
"Falling back to creating a normal full database instead.",
);
return OverlayDatabaseMode.None;
}
if ((await getGitRoot(sourceRoot)) === undefined) {
logger.warning(
`Cannot build an ${overlayDatabaseMode} database because ` +
`the source root "${sourceRoot}" is not inside a git repository. ` +
"Falling back to creating a normal full database instead.",
);
return OverlayDatabaseMode.None;
}
return overlayDatabaseMode as OverlayDatabaseMode;
}
return OverlayDatabaseMode.None;
}
export async function runInit(
codeql: CodeQL,
config: configUtils.Config,
sourceRoot: string,
processName: string | undefined,
registriesInput: string | undefined,
apiDetails: GitHubApiCombinedDetails,
overlayDatabaseMode: OverlayDatabaseMode,
logger: Logger,
): Promise<TracerConfig | undefined> {
fs.mkdirSync(config.dbLocation, { recursive: true });
const { registriesAuthTokens, qlconfigFile } =
await configUtils.generateRegistries(
registriesInput,
config.tempDir,
logger,
);
await configUtils.wrapEnvironment(
{
GITHUB_TOKEN: apiDetails.auth,
CODEQL_REGISTRIES_AUTH: registriesAuthTokens,
},
// Init a database cluster
async () =>
await codeql.databaseInitCluster(
config,
sourceRoot,
processName,
qlconfigFile,
overlayDatabaseMode,
logger,
),
);
return await getCombinedTracerConfig(codeql, config);
}
export function printPathFiltersWarning(
config: configUtils.Config,
logger: Logger,
) {
// Index include/exclude/filters only work in javascript/python/ruby.
// If any other languages are detected/configured then show a warning.
if (
(config.originalUserInput.paths?.length ||
config.originalUserInput["paths-ignore"]?.length) &&
!config.languages.every(isScannedLanguage)
) {
logger.warning(
'The "paths"/"paths-ignore" fields of the config only have effect for JavaScript, Python, and Ruby',
);
}
}
/**
* If we are running python 3.12+ on windows, we need to switch to python 3.11.
* This check happens in a powershell script.
*/
export async function checkInstallPython311(
languages: Language[],
codeql: CodeQL,
) {
if (
languages.includes(Language.python) &&
process.platform === "win32" &&
!(await codeql.getVersion()).features?.supportsPython312
) {
const script = path.resolve(
__dirname,
"../python-setup",
"check_python12.ps1",
);
await new toolrunner.ToolRunner(await io.which("powershell", true), [
script,
]).exec();
}
}
export function cleanupDatabaseClusterDirectory(
config: configUtils.Config,
logger: Logger,
// We can't stub the fs module in tests, so we allow the caller to override the rmSync function
// for testing.
rmSync = fs.rmSync,
): void {
if (
fs.existsSync(config.dbLocation) &&
(fs.statSync(config.dbLocation).isFile() ||
fs.readdirSync(config.dbLocation).length)
) {
logger.warning(
`The database cluster directory ${config.dbLocation} must be empty. Attempting to clean it up.`,
);
try {
rmSync(config.dbLocation, {
force: true,
maxRetries: 3,
recursive: true,
});
logger.info(
`Cleaned up database cluster directory ${config.dbLocation}.`,
);
} catch (e) {
const blurb = `The CodeQL Action requires an empty database cluster directory. ${
getOptionalInput("db-location")
? `This is currently configured to be ${config.dbLocation}. `
: `By default, this is located at ${config.dbLocation}. ` +
"You can customize it using the 'db-location' input to the init Action. "
}An attempt was made to clean up the directory, but this failed.`;
// Hosted runners are automatically cleaned up, so this error should not occur for hosted runners.
if (isSelfHostedRunner()) {
throw new util.ConfigurationError(
`${blurb} This can happen if another process is using the directory or the directory is owned by a different user. ` +
`Please clean up the directory manually and rerun the job. Details: ${util.getErrorMessage(
e,
)}`,
);
} else {
throw new Error(
`${blurb} This shouldn't typically happen on hosted runners. ` +
"If you are using an advanced setup, please check your workflow, otherwise we " +
`recommend rerunning the job. Details: ${util.getErrorMessage(e)}`,
);
}
}
}
}