mirror of
https://github.com/github/codeql-action.git
synced 2026-04-01 01:02:17 +00:00
250 lines
6.7 KiB
TypeScript
Executable File
250 lines
6.7 KiB
TypeScript
Executable File
#!/usr/bin/env npx tsx
|
|
|
|
/*
|
|
Tests for the sync-back.ts script
|
|
*/
|
|
|
|
import * as assert from "node:assert/strict";
|
|
import * as fs from "node:fs";
|
|
import * as os from "node:os";
|
|
import * as path from "node:path";
|
|
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
|
|
import {
|
|
scanGeneratedWorkflows,
|
|
updateSyncTs,
|
|
updateTemplateFiles,
|
|
} from "./sync-back";
|
|
|
|
let testDir: string;
|
|
let workflowDir: string;
|
|
let checksDir: string;
|
|
let syncTsPath: string;
|
|
|
|
beforeEach(() => {
|
|
/** Set up temporary directories and files for testing */
|
|
testDir = fs.mkdtempSync(path.join(os.tmpdir(), "sync-back-test-"));
|
|
workflowDir = path.join(testDir, ".github", "workflows");
|
|
checksDir = path.join(testDir, "pr-checks", "checks");
|
|
fs.mkdirSync(workflowDir, { recursive: true });
|
|
fs.mkdirSync(checksDir, { recursive: true });
|
|
|
|
// Create sync.ts file path
|
|
syncTsPath = path.join(testDir, "pr-checks", "sync.ts");
|
|
});
|
|
|
|
afterEach(() => {
|
|
/** Clean up temporary directories */
|
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("scanGeneratedWorkflows", async () => {
|
|
await it("basic workflow scanning", () => {
|
|
/** Test basic workflow scanning functionality */
|
|
const workflowContent = `
|
|
name: Test Workflow
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v5
|
|
- uses: actions/setup-go@v6
|
|
`;
|
|
|
|
fs.writeFileSync(path.join(workflowDir, "__test.yml"), workflowContent);
|
|
|
|
const result = scanGeneratedWorkflows(workflowDir);
|
|
|
|
assert.equal(result["actions/checkout"], "v4");
|
|
assert.equal(result["actions/setup-node"], "v5");
|
|
assert.equal(result["actions/setup-go"], "v6");
|
|
});
|
|
|
|
await it("scanning workflows with version comments", () => {
|
|
/** Test scanning workflows with version comments */
|
|
const workflowContent = `
|
|
name: Test Workflow
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
|
|
- uses: actions/setup-python@v6 # Latest Python
|
|
`;
|
|
|
|
fs.writeFileSync(path.join(workflowDir, "__test.yml"), workflowContent);
|
|
|
|
const result = scanGeneratedWorkflows(workflowDir);
|
|
|
|
assert.equal(result["actions/checkout"], "v4");
|
|
assert.equal(
|
|
result["ruby/setup-ruby"],
|
|
"44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0",
|
|
);
|
|
assert.equal(result["actions/setup-python"], "v6 # Latest Python");
|
|
});
|
|
|
|
await it("ignores local actions", () => {
|
|
/** Test that local actions (starting with ./) are ignored */
|
|
const workflowContent = `
|
|
name: Test Workflow
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: ./.github/actions/local-action
|
|
- uses: ./another-local-action@v1
|
|
`;
|
|
|
|
fs.writeFileSync(path.join(workflowDir, "__test.yml"), workflowContent);
|
|
|
|
const result = scanGeneratedWorkflows(workflowDir);
|
|
|
|
assert.equal(result["actions/checkout"], "v4");
|
|
assert.equal("./.github/actions/local-action" in result, false);
|
|
assert.equal("./another-local-action" in result, false);
|
|
});
|
|
});
|
|
|
|
describe("updateSyncTs", async () => {
|
|
await it("updates sync.ts file", () => {
|
|
/** Test updating sync.ts file */
|
|
const syncTsContent = `
|
|
const steps = [
|
|
{
|
|
uses: "actions/setup-node@v4",
|
|
with: { "node-version": "16" },
|
|
},
|
|
{
|
|
uses: "actions/setup-go@v5",
|
|
with: { "go-version": "1.19" },
|
|
},
|
|
];
|
|
`;
|
|
|
|
fs.writeFileSync(syncTsPath, syncTsContent);
|
|
|
|
const actionVersions = {
|
|
"actions/setup-node": "v5",
|
|
"actions/setup-go": "v6",
|
|
};
|
|
|
|
const result = updateSyncTs(syncTsPath, actionVersions);
|
|
assert.equal(result, true);
|
|
|
|
const updatedContent = fs.readFileSync(syncTsPath, "utf8");
|
|
|
|
assert.ok(updatedContent.includes('uses: "actions/setup-node@v5"'));
|
|
assert.ok(updatedContent.includes('uses: "actions/setup-go@v6"'));
|
|
});
|
|
|
|
await it("strips comments from versions", () => {
|
|
/** Test updating sync.ts file when versions have comments */
|
|
const syncTsContent = `
|
|
const steps = [
|
|
{
|
|
uses: "actions/setup-node@v4",
|
|
with: { "node-version": "16" },
|
|
},
|
|
];
|
|
`;
|
|
|
|
fs.writeFileSync(syncTsPath, syncTsContent);
|
|
|
|
const actionVersions = {
|
|
"actions/setup-node": "v5 # Latest version",
|
|
};
|
|
|
|
const result = updateSyncTs(syncTsPath, actionVersions);
|
|
assert.equal(result, true);
|
|
|
|
const updatedContent = fs.readFileSync(syncTsPath, "utf8");
|
|
|
|
// sync.ts should get the version without comment
|
|
assert.ok(updatedContent.includes('uses: "actions/setup-node@v5"'));
|
|
assert.ok(!updatedContent.includes("# Latest version"));
|
|
});
|
|
|
|
await it("returns false when no changes are needed", () => {
|
|
/** Test that updateSyncTs returns false when no changes are needed */
|
|
const syncTsContent = `
|
|
const steps = [
|
|
{
|
|
uses: "actions/setup-node@v5",
|
|
with: { "node-version": "16" },
|
|
},
|
|
];
|
|
`;
|
|
|
|
fs.writeFileSync(syncTsPath, syncTsContent);
|
|
|
|
const actionVersions = {
|
|
"actions/setup-node": "v5",
|
|
};
|
|
|
|
const result = updateSyncTs(syncTsPath, actionVersions);
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("updateTemplateFiles", async () => {
|
|
await it("updates template files", () => {
|
|
/** Test updating template files */
|
|
const templateContent = `
|
|
name: Test Template
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 16
|
|
`;
|
|
|
|
const templatePath = path.join(checksDir, "test.yml");
|
|
fs.writeFileSync(templatePath, templateContent);
|
|
|
|
const actionVersions = {
|
|
"actions/checkout": "v4",
|
|
"actions/setup-node": "v5 # Latest",
|
|
};
|
|
|
|
const result = updateTemplateFiles(checksDir, actionVersions);
|
|
assert.equal(result.length, 1);
|
|
assert.ok(result.includes(templatePath));
|
|
|
|
const updatedContent = fs.readFileSync(templatePath, "utf8");
|
|
|
|
assert.ok(updatedContent.includes("uses: actions/checkout@v4"));
|
|
assert.ok(updatedContent.includes("uses: actions/setup-node@v5 # Latest"));
|
|
});
|
|
|
|
await it("preserves version comments", () => {
|
|
/** Test that updating template files preserves version comments */
|
|
const templateContent = `
|
|
name: Test Template
|
|
steps:
|
|
- uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.256.0
|
|
`;
|
|
|
|
const templatePath = path.join(checksDir, "test.yml");
|
|
fs.writeFileSync(templatePath, templateContent);
|
|
|
|
const actionVersions = {
|
|
"ruby/setup-ruby": "55511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0",
|
|
};
|
|
|
|
const result = updateTemplateFiles(checksDir, actionVersions);
|
|
assert.equal(result.length, 1);
|
|
|
|
const updatedContent = fs.readFileSync(templatePath, "utf8");
|
|
|
|
assert.ok(
|
|
updatedContent.includes(
|
|
"uses: ruby/setup-ruby@55511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0",
|
|
),
|
|
);
|
|
});
|
|
});
|