mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 09:14:58 +00:00
Address review comments
This commit is contained in:
40
.github/workflows/pr-checks.yml
vendored
40
.github/workflows/pr-checks.yml
vendored
@@ -73,8 +73,8 @@ jobs:
|
|||||||
|
|
||||||
# These checks do not need to be run as part of the same matrix that we use for the `unit-tests`
|
# These checks do not need to be run as part of the same matrix that we use for the `unit-tests`
|
||||||
# job.
|
# job.
|
||||||
pr-checks:
|
other-checks:
|
||||||
name: PR Checks
|
name: Other checks
|
||||||
if: github.triggering_actor != 'dependabot[bot]'
|
if: github.triggering_actor != 'dependabot[bot]'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -96,12 +96,15 @@ jobs:
|
|||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
id: install-deps
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: Verify PR checks up to date
|
- name: Verify PR checks up to date
|
||||||
|
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
|
||||||
run: .github/workflows/script/verify-pr-checks.sh
|
run: .github/workflows/script/verify-pr-checks.sh
|
||||||
|
|
||||||
- name: Run pr-checks tests
|
- name: Run pr-checks tests
|
||||||
|
if: ${{ !cancelled() && steps.install-deps.outcome == 'success' }}
|
||||||
working-directory: pr-checks
|
working-directory: pr-checks
|
||||||
run: npx tsx --test
|
run: npx tsx --test
|
||||||
|
|
||||||
@@ -117,6 +120,7 @@ jobs:
|
|||||||
echo "node_version=${NODE_VERSION}" >> $GITHUB_OUTPUT
|
echo "node_version=${NODE_VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Fetch base commit
|
- name: Fetch base commit
|
||||||
|
id: fetch-base
|
||||||
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
|
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
|
||||||
# check in those cases.
|
# check in those cases.
|
||||||
if: >-
|
if: >-
|
||||||
@@ -125,29 +129,28 @@ jobs:
|
|||||||
github.event.pull_request.user.login != 'dependabot[bot]'
|
github.event.pull_request.user.login != 'dependabot[bot]'
|
||||||
env:
|
env:
|
||||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||||
run: git fetch --no-tags --depth=1 origin "$BASE_SHA"
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
# Compare against the merge base so the size delta reflects only the commits actually
|
||||||
|
# added by this PR, ignoring any changes that have landed on the base branch since the
|
||||||
|
# PR branched off.
|
||||||
|
merge_base=$(gh api "repos/$GITHUB_REPOSITORY/compare/$BASE_SHA...$HEAD_SHA" --jq '.merge_base_commit.sha')
|
||||||
|
echo "merge_base=$merge_base" >> "$GITHUB_OUTPUT"
|
||||||
|
git fetch --no-tags --depth=1 origin "$merge_base" "$HEAD_SHA"
|
||||||
|
|
||||||
- name: Check repo size
|
- name: Check repo size
|
||||||
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
|
if: steps.fetch-base.outcome == 'success'
|
||||||
# check in those cases.
|
|
||||||
if: >-
|
|
||||||
github.event_name == 'pull_request' &&
|
|
||||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
||||||
github.event.pull_request.user.login != 'dependabot[bot]'
|
|
||||||
working-directory: pr-checks
|
working-directory: pr-checks
|
||||||
env:
|
env:
|
||||||
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
||||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
BASE_SHA: ${{ steps.fetch-base.outputs.merge_base }}
|
||||||
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
run: npx tsx check-repo-size.ts --output-dir "$RUNNER_TEMP/repo-size"
|
run: npx tsx check-repo-size.ts --output-dir "$RUNNER_TEMP/repo-size"
|
||||||
|
|
||||||
- name: Upload repo size comment
|
- name: Upload repo size comment
|
||||||
# Forks and Dependabot PRs don't have permission to write comments, so skip the repo size
|
if: steps.fetch-base.outcome == 'success'
|
||||||
# check in those cases.
|
|
||||||
if: >-
|
|
||||||
github.event_name == 'pull_request' &&
|
|
||||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
||||||
github.event.pull_request.user.login != 'dependabot[bot]'
|
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: repo-size-comment
|
name: repo-size-comment
|
||||||
@@ -176,14 +179,14 @@ jobs:
|
|||||||
|
|
||||||
post-repo-size-comment:
|
post-repo-size-comment:
|
||||||
name: Post repo size comment
|
name: Post repo size comment
|
||||||
needs: pr-checks
|
needs: other-checks
|
||||||
# Keep write permissions isolated from the job that checks out and tests PR code. This job only
|
# Keep write permissions isolated from the job that checks out and tests PR code. This job only
|
||||||
# posts the candidate comment body produced by the read-only `pr-checks` job.
|
# posts the candidate comment body produced by the read-only `pr-checks` job.
|
||||||
if: >-
|
if: >-
|
||||||
github.event_name == 'pull_request' &&
|
github.event_name == 'pull_request' &&
|
||||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
github.event.pull_request.head.repo.full_name == github.repository &&
|
||||||
github.event.pull_request.user.login != 'dependabot[bot]' &&
|
github.event.pull_request.user.login != 'dependabot[bot]' &&
|
||||||
needs.pr-checks.result == 'success'
|
needs.other-checks.result == 'success'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
@@ -205,7 +208,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
COMMENT_MARKER: "<!-- repo-size-diff-bot -->"
|
COMMENT_MARKER: "<!-- repo-size-diff-bot -->"
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
run: |
|
run: |
|
||||||
significant=$(jq -r '.significant' repo-size-comment/metadata.json)
|
significant=$(jq -r '.significant' repo-size-comment/metadata.json)
|
||||||
|
|||||||
@@ -25,24 +25,18 @@ import {
|
|||||||
|
|
||||||
describe("formatBytes", async () => {
|
describe("formatBytes", async () => {
|
||||||
const cases: Array<[number, boolean, string]> = [
|
const cases: Array<[number, boolean, string]> = [
|
||||||
// Unsigned: bytes / KiB / MiB boundaries.
|
// Unsigned values, including sub-KiB amounts which round to 0.00.
|
||||||
[0, false, "0 B"],
|
[0, false, "0.00 KiB"],
|
||||||
[1, false, "1 B"],
|
[512, false, "0.50 KiB"],
|
||||||
[1023, false, "1023 B"],
|
|
||||||
[1024, false, "1.00 KiB"],
|
[1024, false, "1.00 KiB"],
|
||||||
[2048, false, "2.00 KiB"],
|
[1024 * 1024, false, "1024.00 KiB"],
|
||||||
[1024 * 1024 - 1, false, "1024.00 KiB"],
|
[2 * 1024 * 1024, false, "2048.00 KiB"],
|
||||||
[1024 * 1024, false, "1.00 MiB"],
|
|
||||||
[2.5 * 1024 * 1024, false, "2.50 MiB"],
|
|
||||||
// Negative values always use a leading minus.
|
// Negative values always use a leading minus.
|
||||||
[-512, false, "-512 B"],
|
[-2 * 1024 * 1024, false, "-2048.00 KiB"],
|
||||||
[-2048, false, "-2.00 KiB"],
|
|
||||||
[-2 * 1024 * 1024, false, "-2.00 MiB"],
|
|
||||||
// signed=true prepends a + to non-negative values.
|
// signed=true prepends a + to non-negative values.
|
||||||
[0, true, "+0 B"],
|
[0, true, "+0.00 KiB"],
|
||||||
[512, true, "+512 B"],
|
[2 * 1024 * 1024, true, "+2048.00 KiB"],
|
||||||
[2048, true, "+2.00 KiB"],
|
[-2 * 1024 * 1024, true, "-2048.00 KiB"],
|
||||||
[-512, true, "-512 B"],
|
|
||||||
];
|
];
|
||||||
for (const [bytes, signed, expected] of cases) {
|
for (const [bytes, signed, expected] of cases) {
|
||||||
await it(`formats ${bytes} (signed=${signed}) as ${expected}`, () => {
|
await it(`formats ${bytes} (signed=${signed}) as ${expected}`, () => {
|
||||||
@@ -94,8 +88,8 @@ describe("buildCommentBody", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert.match(body, new RegExp(`^${escapeRegExp(COMMENT_MARKER)}`));
|
assert.match(body, new RegExp(`^${escapeRegExp(COMMENT_MARKER)}`));
|
||||||
assert.match(body, /Base \(`main`\) \| 1\.91 MiB \(2000000 bytes\)/);
|
assert.match(body, /Base \(`main`\) \| 1953\.13 KiB \(2000000 bytes\)/);
|
||||||
assert.match(body, /This PR \| 2\.19 MiB \(2300000 bytes\)/);
|
assert.match(body, /This PR \| 2246\.09 KiB \(2300000 bytes\)/);
|
||||||
assert.match(
|
assert.match(
|
||||||
body,
|
body,
|
||||||
/\*\*Delta\*\* \| \*\*\+292\.97 KiB \(\+300000 bytes, \+15\.00%\)\*\*/,
|
/\*\*Delta\*\* \| \*\*\+292\.97 KiB \(\+300000 bytes, \+15\.00%\)\*\*/,
|
||||||
@@ -118,7 +112,7 @@ describe("buildCommentBody", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("readArgs", async () => {
|
describe("readArgs", async () => {
|
||||||
await it("defaults the base ref for local runs", () => {
|
await it("defaults the base ref and head commit for local runs", () => {
|
||||||
const originalEnv = process.env;
|
const originalEnv = process.env;
|
||||||
const originalArgv = process.argv;
|
const originalArgv = process.argv;
|
||||||
|
|
||||||
@@ -130,6 +124,7 @@ describe("readArgs", async () => {
|
|||||||
|
|
||||||
assert.equal(args.baseRef, DEFAULT_BASE_REF);
|
assert.equal(args.baseRef, DEFAULT_BASE_REF);
|
||||||
assert.equal(args.baseCommitish, `origin/${DEFAULT_BASE_REF}`);
|
assert.equal(args.baseCommitish, `origin/${DEFAULT_BASE_REF}`);
|
||||||
|
assert.equal(args.headCommitish, "HEAD");
|
||||||
assert.equal(args.outputDir, "/tmp/out");
|
assert.equal(args.outputDir, "/tmp/out");
|
||||||
assert.equal(args.runUrl, undefined);
|
assert.equal(args.runUrl, undefined);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -138,7 +133,7 @@ describe("readArgs", async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await it("uses the base SHA when provided by the workflow", () => {
|
await it("uses the base and head SHAs when provided by the workflow", () => {
|
||||||
const originalEnv = process.env;
|
const originalEnv = process.env;
|
||||||
const originalArgv = process.argv;
|
const originalArgv = process.argv;
|
||||||
|
|
||||||
@@ -146,6 +141,7 @@ describe("readArgs", async () => {
|
|||||||
process.env = {
|
process.env = {
|
||||||
BASE_REF: "main",
|
BASE_REF: "main",
|
||||||
BASE_SHA: "abc123",
|
BASE_SHA: "abc123",
|
||||||
|
HEAD_SHA: "def456",
|
||||||
RUN_URL: "https://example.test/run",
|
RUN_URL: "https://example.test/run",
|
||||||
};
|
};
|
||||||
process.argv = ["node", "check-repo-size.ts", "--output-dir", "/tmp/out"];
|
process.argv = ["node", "check-repo-size.ts", "--output-dir", "/tmp/out"];
|
||||||
@@ -154,6 +150,7 @@ describe("readArgs", async () => {
|
|||||||
|
|
||||||
assert.equal(args.baseRef, "main");
|
assert.equal(args.baseRef, "main");
|
||||||
assert.equal(args.baseCommitish, "abc123");
|
assert.equal(args.baseCommitish, "abc123");
|
||||||
|
assert.equal(args.headCommitish, "def456");
|
||||||
assert.equal(args.outputDir, "/tmp/out");
|
assert.equal(args.outputDir, "/tmp/out");
|
||||||
assert.equal(args.runUrl, "https://example.test/run");
|
assert.equal(args.runUrl, "https://example.test/run");
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ import * as fs from "node:fs";
|
|||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import { parseArgs } from "node:util";
|
import { parseArgs } from "node:util";
|
||||||
|
|
||||||
|
import { getErrorMessage } from "../src/util";
|
||||||
|
|
||||||
|
import { REPO_ROOT } from "./config";
|
||||||
|
|
||||||
/** Hidden marker used to find the existing sticky comment on a PR. */
|
/** Hidden marker used to find the existing sticky comment on a PR. */
|
||||||
export const COMMENT_MARKER = "<!-- repo-size-diff-bot -->";
|
export const COMMENT_MARKER = "<!-- repo-size-diff-bot -->";
|
||||||
|
|
||||||
@@ -62,15 +66,13 @@ export async function measureArchiveSize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a byte count into a human-readable string with binary units. If `signed` is true, a
|
* Format a byte count as KiB. If `signed` is true, a leading `+` is prepended for non-negative
|
||||||
* leading `+` is prepended for non-negative values so gains and losses are visually distinct.
|
* values so gains and losses are visually distinct.
|
||||||
*/
|
*/
|
||||||
export function formatBytes(bytes: number, signed = false): string {
|
export function formatBytes(bytes: number, signed = false): string {
|
||||||
const sign = bytes < 0 ? "-" : signed ? "+" : "";
|
const sign = bytes < 0 ? "-" : signed ? "+" : "";
|
||||||
const abs = Math.abs(bytes);
|
const kib = Math.abs(bytes) / 1024;
|
||||||
if (abs < 1024) return `${sign}${abs} B`;
|
return `${sign}${kib.toFixed(2)} KiB`;
|
||||||
if (abs < 1024 * 1024) return `${sign}${(abs / 1024).toFixed(2)} KiB`;
|
|
||||||
return `${sign}${(abs / 1024 / 1024).toFixed(2)} MiB`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Format a fraction as a signed percentage with 2 decimal places. */
|
/** Format a fraction as a signed percentage with 2 decimal places. */
|
||||||
@@ -131,6 +133,8 @@ interface MainArgs {
|
|||||||
baseRef: string;
|
baseRef: string;
|
||||||
/** Base commit-ish to archive. Defaults to `origin/<baseRef>` for local runs. */
|
/** Base commit-ish to archive. Defaults to `origin/<baseRef>` for local runs. */
|
||||||
baseCommitish: string;
|
baseCommitish: string;
|
||||||
|
/** Head commit-ish to archive. Defaults to `HEAD` for local runs. */
|
||||||
|
headCommitish: string;
|
||||||
/** Optional URL of the workflow run, surfaced in the comment footer. */
|
/** Optional URL of the workflow run, surfaced in the comment footer. */
|
||||||
runUrl?: string;
|
runUrl?: string;
|
||||||
/** Directory where `body.md` and `metadata.json` are written. */
|
/** Directory where `body.md` and `metadata.json` are written. */
|
||||||
@@ -152,10 +156,12 @@ export function readArgs(): MainArgs {
|
|||||||
|
|
||||||
const baseRef = process.env.BASE_REF ?? DEFAULT_BASE_REF;
|
const baseRef = process.env.BASE_REF ?? DEFAULT_BASE_REF;
|
||||||
const baseCommitish = process.env.BASE_SHA ?? `origin/${baseRef}`;
|
const baseCommitish = process.env.BASE_SHA ?? `origin/${baseRef}`;
|
||||||
|
const headCommitish = process.env.HEAD_SHA ?? "HEAD";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
baseRef,
|
baseRef,
|
||||||
baseCommitish,
|
baseCommitish,
|
||||||
|
headCommitish,
|
||||||
runUrl: process.env.RUN_URL,
|
runUrl: process.env.RUN_URL,
|
||||||
outputDir,
|
outputDir,
|
||||||
};
|
};
|
||||||
@@ -164,16 +170,12 @@ export function readArgs(): MainArgs {
|
|||||||
async function main(): Promise<number> {
|
async function main(): Promise<number> {
|
||||||
const args = readArgs();
|
const args = readArgs();
|
||||||
|
|
||||||
// The script lives at `<repoRoot>/pr-checks/check-repo-size.ts`, so the repo root is the parent
|
|
||||||
// directory.
|
|
||||||
const repoRoot = path.resolve(__dirname, "..");
|
|
||||||
|
|
||||||
console.log(`Measuring base archive size for ${args.baseCommitish}...`);
|
console.log(`Measuring base archive size for ${args.baseCommitish}...`);
|
||||||
const baseSize = await measureArchiveSize(args.baseCommitish, repoRoot);
|
const baseSize = await measureArchiveSize(args.baseCommitish, REPO_ROOT);
|
||||||
console.log(` ${baseSize} bytes`);
|
console.log(` ${baseSize} bytes`);
|
||||||
|
|
||||||
console.log("Measuring PR archive size for HEAD...");
|
console.log(`Measuring PR archive size for ${args.headCommitish}...`);
|
||||||
const prSize = await measureArchiveSize("HEAD", repoRoot);
|
const prSize = await measureArchiveSize(args.headCommitish, REPO_ROOT);
|
||||||
console.log(` ${prSize} bytes`);
|
console.log(` ${prSize} bytes`);
|
||||||
|
|
||||||
const delta = prSize - baseSize;
|
const delta = prSize - baseSize;
|
||||||
@@ -209,13 +211,15 @@ async function main(): Promise<number> {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require.main === module) {
|
async function run(): Promise<void> {
|
||||||
void (async () => {
|
try {
|
||||||
try {
|
process.exit(await main());
|
||||||
process.exit(await main());
|
} catch (err) {
|
||||||
} catch (err) {
|
console.error(getErrorMessage(err));
|
||||||
console.error(err instanceof Error ? err.message : String(err));
|
process.exit(1);
|
||||||
process.exit(1);
|
}
|
||||||
}
|
}
|
||||||
})();
|
|
||||||
|
if (require.main === module) {
|
||||||
|
void run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,17 @@ export const OLDEST_SUPPORTED_MAJOR_VERSION = 3;
|
|||||||
/** The `pr-checks` directory. */
|
/** The `pr-checks` directory. */
|
||||||
export const PR_CHECKS_DIR = __dirname;
|
export const PR_CHECKS_DIR = __dirname;
|
||||||
|
|
||||||
|
/** The repository root. */
|
||||||
|
export const REPO_ROOT = path.join(PR_CHECKS_DIR, "..");
|
||||||
|
|
||||||
/** The path of the file configuring which checks shouldn't be required. */
|
/** The path of the file configuring which checks shouldn't be required. */
|
||||||
export const PR_CHECK_EXCLUDED_FILE = path.join(PR_CHECKS_DIR, "excluded.yml");
|
export const PR_CHECK_EXCLUDED_FILE = path.join(PR_CHECKS_DIR, "excluded.yml");
|
||||||
|
|
||||||
/** The path to the esbuild metadata file. */
|
/** The path to the esbuild metadata file. */
|
||||||
export const BUNDLE_METADATA_FILE = path.join(PR_CHECKS_DIR, "..", "meta.json");
|
export const BUNDLE_METADATA_FILE = path.join(REPO_ROOT, "meta.json");
|
||||||
|
|
||||||
/** The `src` directory. */
|
/** The `src` directory. */
|
||||||
const SOURCE_ROOT = path.join(PR_CHECKS_DIR, "..", "src");
|
const SOURCE_ROOT = path.join(REPO_ROOT, "src");
|
||||||
|
|
||||||
/** The path to the built-in languages file. */
|
/** The path to the built-in languages file. */
|
||||||
export const BUILTIN_LANGUAGES_FILE = path.join(
|
export const BUILTIN_LANGUAGES_FILE = path.join(
|
||||||
|
|||||||
Reference in New Issue
Block a user