diff --git a/__tests__/ci.test.js b/__tests__/ci.test.js index fcde6b5..208402a 100644 --- a/__tests__/ci.test.js +++ b/__tests__/ci.test.js @@ -15,10 +15,13 @@ const dockerfile = fs.readFileSync(path.join(ROOT, "Dockerfile"), "utf-8"); // Comment lines stripped, so an explanation that quotes a key cannot satisfy // (or break) a pin. -const ciCode = ci - .split("\n") - .filter((line) => !/^\s*#/.test(line)) - .join("\n"); +function stripCommentLines(text) { + return text + .split("\n") + .filter((line) => !/^\s*#/.test(line)) + .join("\n"); +} +const ciCode = stripCommentLines(ci); // Lines of a top-level-indented block (` pull_request:`), up to the next key at // the same or a lower indentation. @@ -77,10 +80,32 @@ describe("CI workflow", () => { if (/^\s*uses:|\n\s*uses:/.test(step)) expect(step).not.toMatch(/working-directory:/); } }); + + // `continue-on-error: true` turns a red step green without a trace in the + // commit status. Any spelling of the key counts: a block key or a list item, + // but also a flow mapping and a quoted key, which a pin anchored at the start + // of the line let through (#35). Unanchored on purpose: the key quoted in a + // `run:` script, a step name or a trailing comment fails the pin too, loudly. + // Only full comment lines are exempt, being stripped from `ciCode`. + const CONTINUE_ON_ERROR = /continue-on-error["']?\s*:/; + test("never lets a failing step pass", () => { - // `continue-on-error: true` turns a red step green without a trace in the - // commit status. Anchored on the key position, so only a real key counts. - expect(ciCode).not.toMatch(/^\s*(- )?continue-on-error\s*:/m); + expect(ciCode).not.toMatch(CONTINUE_ON_ERROR); + }); + + // The detector itself, through the same comment stripping as `ciCode`. Anchor + // it at the start of the line again and the last two spellings turn red. + test.each([ + ["a block key", " - name: x\n run: npm test\n continue-on-error: true"], + ["a list item", " - continue-on-error: true\n run: npm test"], + ["a flow mapping", " - { name: x, run: false, continue-on-error: true }"], + ["a quoted key", ' - name: x\n "continue-on-error": true'], + ])("the continue-on-error pin catches %s", (_, step) => { + expect(stripCommentLines(step)).toMatch(CONTINUE_ON_ERROR); + }); + + test("the continue-on-error pin ignores a full comment line quoting the key", () => { + expect(stripCommentLines(" # never add continue-on-error: true here")).not.toMatch(CONTINUE_ON_ERROR); }); });