diff --git a/.github/scripts/validate-pr.js b/.github/scripts/validate-pr.js index 45545fc..1cc5257 100644 --- a/.github/scripts/validate-pr.js +++ b/.github/scripts/validate-pr.js @@ -1,4 +1,8 @@ import { Octokit } from "@octokit/rest"; +import { + isCowJsonFile, + isValidatorMaintenancePullRequest +} from "./validation-helpers.js"; // Environment variables const token = process.env.GITHUB_TOKEN; @@ -45,7 +49,12 @@ async function run() { pull_number: pr_number }); - const jsonFiles = files.filter(f => f.filename.endsWith(".json")); + if (isValidatorMaintenancePullRequest(files)) { + console.log("✅ Validator maintenance PR detected; cow submission checks skipped."); + process.exit(0); + } + + const jsonFiles = files.filter(f => isCowJsonFile(f.filename)); const imageFiles = files.filter(f => f.filename.startsWith("images/")); const requiredKeys = ["name", "breed", "image"]; diff --git a/.github/scripts/validation-helpers.js b/.github/scripts/validation-helpers.js new file mode 100644 index 0000000..9ca60ae --- /dev/null +++ b/.github/scripts/validation-helpers.js @@ -0,0 +1,15 @@ +export function isCowJsonFile(filename) { + return filename.startsWith("cows/") && filename.endsWith(".json"); +} + +export function isValidatorMaintenancePullRequest(files) { + const allowedFiles = new Set([ + ".github/workflows/validate-pr.yml", + "package-lock.json", + "package.json" + ]); + + return files.length > 0 && files.every(({ filename }) => + filename.startsWith(".github/scripts/") || allowedFiles.has(filename) + ); +} diff --git a/.github/scripts/validation-helpers.test.js b/.github/scripts/validation-helpers.test.js new file mode 100644 index 0000000..3376faf --- /dev/null +++ b/.github/scripts/validation-helpers.test.js @@ -0,0 +1,43 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + isCowJsonFile, + isValidatorMaintenancePullRequest +} from "./validation-helpers.js"; + +test("accepts JSON files in the cows directory", () => { + assert.equal(isCowJsonFile("cows/moonlight.json"), true); +}); + +test("rejects JSON files outside the cows directory", () => { + assert.equal(isCowJsonFile("moonlight.json"), false); + assert.equal(isCowJsonFile("examples/moonlight.json"), false); +}); + +test("rejects non-JSON files", () => { + assert.equal(isCowJsonFile("cows/moonlight.png"), false); +}); + +test("identifies validator maintenance pull requests", () => { + const files = [ + { filename: ".github/scripts/validate-pr.js" }, + { filename: ".github/scripts/validation-helpers.test.js" }, + { filename: ".github/workflows/validate-pr.yml" }, + { filename: "package.json" } + ]; + + assert.equal(isValidatorMaintenancePullRequest(files), true); +}); + +test("does not skip cow submissions or unrelated changes", () => { + assert.equal(isValidatorMaintenancePullRequest([]), false); + assert.equal( + isValidatorMaintenancePullRequest([{ filename: "cows/moonlight.json" }]), + false + ); + assert.equal( + isValidatorMaintenancePullRequest([{ filename: "README.md" }]), + false + ); +}); diff --git a/.github/workflows/validate-pr.yml b/.github/workflows/validate-pr.yml index 77677bd..932f772 100644 --- a/.github/workflows/validate-pr.yml +++ b/.github/workflows/validate-pr.yml @@ -28,6 +28,9 @@ jobs: - name: Install dependencies run: npm ci + - name: Run validator tests + run: npm test + - name: Validate pull request run: node .github/scripts/validate-pr.js env: diff --git a/package.json b/package.json index 51b9359..a910655 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,10 @@ "name": "fantasy-cow", "version": "1.0.0", "description": "A small project that teaches how to create a first Pull Request.", + "type": "module", + "scripts": { + "test": "node --test .github/scripts/*.test.js" + }, "dependencies": { "@octokit/rest": "^22.0.0" }