Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion lib/analyze-action-post.js

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

4 changes: 2 additions & 2 deletions lib/analyze-action.js

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

2 changes: 1 addition & 1 deletion lib/autobuild-action.js

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

4 changes: 2 additions & 2 deletions lib/init-action-post.js

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

2 changes: 1 addition & 1 deletion lib/init-action.js

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

2 changes: 1 addition & 1 deletion lib/resolve-environment-action.js

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

2 changes: 1 addition & 1 deletion lib/setup-codeql-action.js

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

4 changes: 2 additions & 2 deletions lib/upload-lib.js

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

4 changes: 2 additions & 2 deletions lib/upload-sarif-action.js

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

166 changes: 165 additions & 1 deletion src/git-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as sinon from "sinon";

import * as actionsUtil from "./actions-util";
import * as gitUtils from "./git-utils";
import { setupActionsVars, setupTests } from "./testing-utils";
import { setupActionsVars, setupTests, SHA256_GITHUB_SHA } from "./testing-utils";
import { withTmpDir } from "./util";

setupTests(test);
Expand Down Expand Up @@ -193,6 +193,94 @@ test.serial(
},
);

test.serial(
"getRef() returns merge PR ref if GITHUB_SHA still checked out (SHA-256)",
async (t) => {
await withTmpDir(async (tmpDir: string) => {
setupActionsVars(tmpDir, tmpDir);
const expectedRef = "refs/pull/1/merge";
const currentSha = "a".repeat(64);
process.env["GITHUB_REF"] = expectedRef;
process.env["GITHUB_SHA"] = currentSha;

const callback = sinon.stub(gitUtils, "getCommitOid");
callback.withArgs("HEAD").resolves(currentSha);

const actualRef = await gitUtils.getRef();
t.deepEqual(actualRef, expectedRef);
callback.restore();
});
},
);

test.serial(
"getRef() returns merge PR ref if GITHUB_REF still checked out but sha has changed (actions checkout@v1) (SHA-256)",
async (t) => {
await withTmpDir(async (tmpDir: string) => {
setupActionsVars(tmpDir, tmpDir);
const expectedRef = "refs/pull/1/merge";
process.env["GITHUB_REF"] = expectedRef;
process.env["GITHUB_SHA"] = "b".repeat(64);
const sha = "a".repeat(64);

const callback = sinon.stub(gitUtils, "getCommitOid");
callback.withArgs("refs/remotes/pull/1/merge").resolves(sha);
callback.withArgs("HEAD").resolves(sha);

const actualRef = await gitUtils.getRef();
t.deepEqual(actualRef, expectedRef);
callback.restore();
});
},
);

test.serial(
"getRef() returns head PR ref if GITHUB_REF no longer checked out (SHA-256)",
async (t) => {
await withTmpDir(async (tmpDir: string) => {
setupActionsVars(tmpDir, tmpDir);
process.env["GITHUB_REF"] = "refs/pull/1/merge";
process.env["GITHUB_SHA"] = "a".repeat(64);

const callback = sinon.stub(gitUtils, "getCommitOid");
callback.withArgs(tmpDir, "refs/pull/1/merge").resolves("a".repeat(64));
callback.withArgs(tmpDir, "HEAD").resolves("b".repeat(64));

const actualRef = await gitUtils.getRef();
t.deepEqual(actualRef, "refs/pull/1/head");
callback.restore();
});
},
);

test.serial(
"getRef() returns ref provided as an input and ignores current HEAD (SHA-256)",
async (t) => {
await withTmpDir(async (tmpDir: string) => {
setupActionsVars(tmpDir, tmpDir);
const getAdditionalInputStub = sinon.stub(
actionsUtil,
"getOptionalInput",
);
getAdditionalInputStub.withArgs("ref").resolves("refs/pull/2/merge");
getAdditionalInputStub.withArgs("sha").resolves("b".repeat(64));

// These values are be ignored
process.env["GITHUB_REF"] = "refs/pull/1/merge";
process.env["GITHUB_SHA"] = "a".repeat(64);

const callback = sinon.stub(gitUtils, "getCommitOid");
callback.withArgs("refs/pull/1/merge").resolves("b".repeat(64));
callback.withArgs("HEAD").resolves("b".repeat(64));

const actualRef = await gitUtils.getRef();
t.deepEqual(actualRef, "refs/pull/2/merge");
callback.restore();
getAdditionalInputStub.restore();
});
},
);

test.serial("isAnalyzingDefaultBranch()", async (t) => {
process.env["GITHUB_EVENT_NAME"] = "push";
process.env["CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH"] = "true";
Expand Down Expand Up @@ -305,6 +393,27 @@ test.serial("determineBaseBranchHeadCommitOid other error", async (t) => {
infoStub.restore();
});

test.serial(
"determineBaseBranchHeadCommitOid returns baseOid for SHA-256 merge commit",
async (t) => {
const mergeSha = "a".repeat(64);
const baseOid = "b".repeat(64);
const headOid = "c".repeat(64);

process.env["GITHUB_EVENT_NAME"] = "pull_request";
process.env["GITHUB_SHA"] = mergeSha;

sinon
.stub(gitUtils as any, "runGitCommand")
.resolves(
`commit ${mergeSha}\nparent ${baseOid}\nparent ${headOid}\n`,
);

const result = await gitUtils.determineBaseBranchHeadCommitOid(__dirname);
t.deepEqual(result, baseOid);
},
);

test.serial("decodeGitFilePath unquoted strings", async (t) => {
t.deepEqual(gitUtils.decodeGitFilePath("foo"), "foo");
t.deepEqual(gitUtils.decodeGitFilePath("foo bar"), "foo bar");
Expand Down Expand Up @@ -482,6 +591,61 @@ test.serial(
},
);

test.serial(
"getFileOidsUnderPath handles SHA-256 OIDs (64-char)",
async (t) => {
await withTmpDir(async (tmpDir) => {
sinon
.stub(gitUtils as any, "runGitCommand")
.callsFake(async (_cwd: any, args: any) => {
if (args[0] === "rev-parse") {
return `${tmpDir}\n`;
}
return (
"100644 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2c0d4b7e8f9a1234567890ab 0\tlib/git-utils.js\n" +
"100644 aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 0\tsrc/git-utils.ts"
);
});

const result = await gitUtils.getFileOidsUnderPath("/fake/path");

t.deepEqual(result, {
"lib/git-utils.js":
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2c0d4b7e8f9a1234567890ab",
"src/git-utils.ts":
"aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899",
});
});
},
);

test.serial(
"getFileOidsUnderPath handles mixed SHA-1 and SHA-256 OIDs",
async (t) => {
await withTmpDir(async (tmpDir) => {
sinon
.stub(gitUtils as any, "runGitCommand")
.callsFake(async (_cwd: any, args: any) => {
if (args[0] === "rev-parse") {
return `${tmpDir}\n`;
}
return (
"100644 30d998ded095371488be3a729eb61d86ed721a18 0\tlib/sha1-file.js\n" +
"100644 aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 0\tsrc/sha256-file.ts"
);
});

const result = await gitUtils.getFileOidsUnderPath("/fake/path");

t.deepEqual(result, {
"lib/sha1-file.js": "30d998ded095371488be3a729eb61d86ed721a18",
"src/sha256-file.ts":
"aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899",
});
});
},
);

test.serial(
"getGitVersionOrThrow returns version for valid git output",
async (t) => {
Expand Down
6 changes: 3 additions & 3 deletions src/git-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ export const determineBaseBranchHeadCommitOid = async function (
// Let's confirm our assumptions: We had a merge commit and the parsed parent data looks correct
if (
commitOid === mergeSha &&
headOid.length === 40 &&
baseOid.length === 40
(headOid.length === 40 || headOid.length === 64) &&
(baseOid.length === 40 || baseOid.length === 64)
) {
return baseOid;
}
Expand Down Expand Up @@ -296,7 +296,7 @@ export const getFileOidsUnderPath = async function (
// 100644 4c51bc1d9e86cd86e01b0f340cb8ce095c33b283 0\tsrc/git-utils.test.ts
// 100644 6b792ea543ce75d7a8a03df591e3c85311ecb64f 0\tsrc/git-utils.ts
// The fields are: <mode> <oid> <stage>\t<path>
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40,64}) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
Expand Down
3 changes: 3 additions & 0 deletions src/testing-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ export const DEFAULT_ACTIONS_VARS = {
RUNNER_OS: "Linux",
} as const satisfies Record<string, string>;

/** A 64-character SHA-256 Git OID for use in SHA-256 repository test scenarios. */
export const SHA256_GITHUB_SHA = "0".repeat(64);

// Sets environment variables that make using some libraries designed for
// use only on actions safe to use outside of actions.
export function setupActionsVars(
Expand Down
31 changes: 30 additions & 1 deletion src/upload-lib.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as api from "./api-client";
import * as diffUtils from "./diff-informed-analysis-utils";
import { getRunnerLogger, Logger } from "./logging";
import * as sarif from "./sarif";
import { setupTests } from "./testing-utils";
import { setupTests, SHA256_GITHUB_SHA } from "./testing-utils";
import * as uploadLib from "./upload-lib";
import { UploadPayload } from "./upload-lib/types";
import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util";
Expand Down Expand Up @@ -110,6 +110,35 @@ test.serial(
},
);

test.serial(
"validate correct payload used for PR merge commit with SHA-256 OIDs",
async (t) => {
process.env["GITHUB_EVENT_NAME"] = "pull_request";
process.env["GITHUB_SHA"] = SHA256_GITHUB_SHA;
process.env["GITHUB_BASE_REF"] = "master";
process.env["GITHUB_EVENT_PATH"] =
`${__dirname}/../src/testdata/pull_request.json`;

const sha256MergeBase = "b".repeat(64);
const prMergePayload: any = uploadLib.buildPayload(
SHA256_GITHUB_SHA,
"refs/pull/123/merge",
"key",
undefined,
"",
1234,
1,
"/opt/src",
undefined,
["CodeQL", "eslint"],
sha256MergeBase,
);
// Uploads for a merge commit use the merge base (SHA-256)
t.deepEqual(prMergePayload.base_ref, "refs/heads/master");
t.deepEqual(prMergePayload.base_sha, sha256MergeBase);
},
);

test.serial("finding SARIF files", async (t) => {
await withTmpDir(async (tmpDir) => {
// include a couple of sarif files
Expand Down
Loading