Skip to content

Commit f6d1bad

Browse files
Merge pull request #573 from github/upload-database
Upload CodeQL databases
2 parents 6a7c236 + f3cd5fa commit f6d1bad

10 files changed

Lines changed: 213 additions & 4 deletions

analyze/action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ inputs:
3434
category:
3535
description: String used by Code Scanning for matching the analyses
3636
required: false
37+
upload-database:
38+
description: Whether to upload the resulting CodeQL database
39+
required: false
40+
default: "true"
3741
token:
3842
default: ${{ github.token }}
3943
matrix:

lib/actions-util.js

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/actions-util.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/analyze-action.js

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/analyze-action.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/codeql.js

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/codeql.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/actions-util.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,3 +691,30 @@ export function getRelativeScriptPath(): string {
691691
const actionsDirectory = path.join(path.dirname(runnerTemp), "_actions");
692692
return path.relative(actionsDirectory, __filename);
693693
}
694+
695+
// Reads the contents of GITHUB_EVENT_PATH as a JSON object
696+
function getWorkflowEvent(): any {
697+
const eventJsonFile = getRequiredEnvParam("GITHUB_EVENT_PATH");
698+
try {
699+
return JSON.parse(fs.readFileSync(eventJsonFile, "utf-8"));
700+
} catch (e) {
701+
throw new Error(
702+
`Unable to read workflow event JSON from ${eventJsonFile}: ${e}`
703+
);
704+
}
705+
}
706+
707+
// Is the version of the repository we are currently analyzing from the default branch,
708+
// or alternatively from another branch or a pull request.
709+
export async function isAnalyzingDefaultBranch(): Promise<boolean> {
710+
// Get the current ref and trim and refs/heads/ prefix
711+
let currentRef = await getRef();
712+
currentRef = currentRef.startsWith("refs/heads/")
713+
? currentRef.substr("refs/heads/".length)
714+
: currentRef;
715+
716+
const event = getWorkflowEvent();
717+
const defaultBranch = event?.repository?.default_branch;
718+
719+
return currentRef === defaultBranch;
720+
}

src/analyze-action.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ import {
1010
QueriesStatusReport,
1111
runCleanup,
1212
} from "./analyze";
13+
import { getApiClient, GitHubApiDetails } from "./api-client";
14+
import { getCodeQL } from "./codeql";
1315
import { Config, getConfig } from "./config-utils";
14-
import { getActionsLogger } from "./logging";
16+
import { getActionsLogger, Logger } from "./logging";
17+
import { parseRepositoryNwo, RepositoryNwo } from "./repository";
1518
import * as upload_lib from "./upload-lib";
1619
import * as util from "./util";
1720

@@ -49,6 +52,73 @@ async function sendStatusReport(
4952
await actionsUtil.sendStatusReport(statusReport);
5053
}
5154

55+
async function uploadDatabases(
56+
repositoryNwo: RepositoryNwo,
57+
config: Config,
58+
apiDetails: GitHubApiDetails,
59+
logger: Logger
60+
): Promise<void> {
61+
if (actionsUtil.getRequiredInput("upload-database") !== "true") {
62+
logger.debug("Database upload disabled in workflow. Skipping upload.");
63+
return;
64+
}
65+
66+
// Do nothing when not running against github.com
67+
if (config.gitHubVersion.type !== util.GitHubVariant.DOTCOM) {
68+
logger.debug("Not running against github.com. Skipping upload.");
69+
return;
70+
}
71+
72+
if (!(await actionsUtil.isAnalyzingDefaultBranch())) {
73+
// We only want to upload a database if we are analyzing the default branch.
74+
logger.debug("Not analyzing default branch. Skipping upload.");
75+
return;
76+
}
77+
78+
const client = getApiClient(apiDetails);
79+
const optInResponse = await client.request(
80+
"GET /repos/:owner/:repo/code-scanning/databases",
81+
{
82+
owner: repositoryNwo.owner,
83+
repo: repositoryNwo.repo,
84+
}
85+
);
86+
if (optInResponse.status !== 204) {
87+
// Repository is not opted in to database uploads.
88+
logger.debug(
89+
"Repository is not opted in to database uploads. Skipping upload."
90+
);
91+
return;
92+
}
93+
94+
const codeql = getCodeQL(config.codeQLCmd);
95+
for (const language of config.languages) {
96+
// Bundle the database up into a single zip file
97+
const databasePath = util.getCodeQLDatabasePath(config, language);
98+
const databaseBundlePath = `${databasePath}.zip`;
99+
await codeql.databaseBundle(databasePath, databaseBundlePath);
100+
101+
// Upload the database bundle
102+
const payload = fs.readFileSync(databaseBundlePath);
103+
const uploadResponse = await client.request(
104+
`PUT /repos/:owner/:repo/code-scanning/databases/${language}`,
105+
{
106+
owner: repositoryNwo.owner,
107+
repo: repositoryNwo.repo,
108+
data: payload,
109+
}
110+
);
111+
if (uploadResponse.status === 201) {
112+
logger.debug(`Successfully uploaded database for ${language}`);
113+
} else {
114+
// Log a warning but don't fail the workflow
115+
logger.warning(
116+
`Failed to upload database for ${language}. ${uploadResponse.data}`
117+
);
118+
}
119+
}
120+
}
121+
52122
async function run() {
53123
const startedAt = new Date();
54124
let stats: AnalysisStatusReport | undefined = undefined;
@@ -116,6 +186,11 @@ async function run() {
116186
logger.info("Not uploading results");
117187
stats = { ...queriesStats };
118188
}
189+
190+
const repositoryNwo = parseRepositoryNwo(
191+
util.getRequiredEnvParam("GITHUB_REPOSITORY")
192+
);
193+
await uploadDatabases(repositoryNwo, config, apiDetails, logger);
119194
} catch (error) {
120195
core.setFailed(error.message);
121196
console.log(error);

0 commit comments

Comments
 (0)