diff --git a/.github/actions/prepare/action.yml b/.github/actions/prepare/action.yml index 031449138..33e3f1ec3 100644 --- a/.github/actions/prepare/action.yml +++ b/.github/actions/prepare/action.yml @@ -8,7 +8,7 @@ runs: - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4 with: cache: pnpm - node-version: "20" + node-version: 22.14.0 - run: pnpm install --frozen-lockfile shell: bash using: composite diff --git a/src/base.ts b/src/base.ts index 9a7996afd..df4872534 100644 --- a/src/base.ts +++ b/src/base.ts @@ -130,7 +130,6 @@ export const base = createBase({ minimum: z.string(), pinned: z.string().optional(), }) - .optional() .describe("Node.js engine version(s) to pin and require a minimum of"), owner: z.string().describe("organization or user owning the repository"), packageData: z diff --git a/src/blocks/blockCSpell.test.ts b/src/blocks/blockCSpell.test.ts index 0a1be9544..fb8ae68b6 100644 --- a/src/blocks/blockCSpell.test.ts +++ b/src/blocks/blockCSpell.test.ts @@ -280,7 +280,7 @@ describe("blockCSpell", () => { "scripts": [ { "commands": [ - "node path/to/cspell-populate-words/bin/index.mjs --words "access" --words "public" --words "description" --words "Test description" --words "directory" --words "." --words "documentation" --words "readme" --words "usage" --words "Test usage." --words "email" --words "github" --words "github@email.com" --words "npm" --words "npm@email.com" --words "emoji" --words "💖" --words "owner" --words "test-owner" --words "preset" --words "minimal" --words "repository" --words "test-repository" --words "title" --words "Test Title"", + "node path/to/cspell-populate-words/bin/index.mjs --words "access" --words "public" --words "description" --words "Test description" --words "directory" --words "." --words "documentation" --words "readme" --words "usage" --words "Test usage." --words "email" --words "github" --words "github@email.com" --words "npm" --words "npm@email.com" --words "emoji" --words "💖" --words "node" --words "minimum" --words "20.12.0" --words "owner" --words "test-owner" --words "preset" --words "minimal" --words "repository" --words "test-repository" --words "title" --words "Test Title"", ], "phase": 3, }, diff --git a/src/blocks/blockGitHubActionsCI.test.ts b/src/blocks/blockGitHubActionsCI.test.ts index 0f167df68..b8b5dee2c 100644 --- a/src/blocks/blockGitHubActionsCI.test.ts +++ b/src/blocks/blockGitHubActionsCI.test.ts @@ -5,6 +5,217 @@ import { blockGitHubActionsCI } from "./blockGitHubActionsCI.js"; import { optionsBase } from "./options.fakes.js"; describe("blockGitHubActionsCI", () => { + test("without options.node.pinned", () => { + const creation = testBlock(blockGitHubActionsCI, { + options: { + ...optionsBase, + node: { + minimum: "20.12.0", + }, + }, + }); + + expect(creation).toMatchInlineSnapshot(` + { + "addons": [ + { + "addons": { + "requiredStatusChecks": undefined, + }, + "block": [Function], + }, + ], + "files": { + ".github": { + "actions": { + "prepare": { + "action.yml": "description: Prepares the repo for a typical CI job + + name: Prepare + + runs: + steps: + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + cache: pnpm + node-version: 20.12.0 + - run: pnpm install --frozen-lockfile + shell: bash + using: composite + ", + }, + }, + "workflows": { + "accessibility-alt-text-bot.yml": "jobs: + accessibility_alt_text_bot: + if: \${{ !endsWith(github.actor, '[bot]') }} + runs-on: ubuntu-latest + steps: + - uses: github/accessibility-alt-text-bot@v1.4.0 + + + name: Accessibility Alt Text Bot + + + on: + issue_comment: + types: + - created + - edited + issues: + types: + - edited + - opened + pull_request: + types: + - edited + - opened + + + permissions: + issues: write + pull-requests: write + ", + "ci.yml": undefined, + "pr-review-requested.yml": "jobs: + pr_review_requested: + runs-on: ubuntu-latest + steps: + - uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: 'status: waiting for author' + - if: failure() + run: | + echo "Don't worry if the previous step failed." + echo "See https://github.com/actions-ecosystem/action-remove-labels/issues/221." + + + name: PR Review Requested + + + on: + pull_request_target: + types: + - review_requested + + + permissions: + pull-requests: write + ", + }, + }, + }, + } + `); + }); + + test("with options.node.pinned", () => { + const creation = testBlock(blockGitHubActionsCI, { + options: { + ...optionsBase, + node: { + minimum: "20.12.0", + pinned: "22.12.0", + }, + }, + }); + + expect(creation).toMatchInlineSnapshot(` + { + "addons": [ + { + "addons": { + "requiredStatusChecks": undefined, + }, + "block": [Function], + }, + ], + "files": { + ".github": { + "actions": { + "prepare": { + "action.yml": "description: Prepares the repo for a typical CI job + + name: Prepare + + runs: + steps: + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + cache: pnpm + node-version: 22.12.0 + - run: pnpm install --frozen-lockfile + shell: bash + using: composite + ", + }, + }, + "workflows": { + "accessibility-alt-text-bot.yml": "jobs: + accessibility_alt_text_bot: + if: \${{ !endsWith(github.actor, '[bot]') }} + runs-on: ubuntu-latest + steps: + - uses: github/accessibility-alt-text-bot@v1.4.0 + + + name: Accessibility Alt Text Bot + + + on: + issue_comment: + types: + - created + - edited + issues: + types: + - edited + - opened + pull_request: + types: + - edited + - opened + + + permissions: + issues: write + pull-requests: write + ", + "ci.yml": undefined, + "pr-review-requested.yml": "jobs: + pr_review_requested: + runs-on: ubuntu-latest + steps: + - uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: 'status: waiting for author' + - if: failure() + run: | + echo "Don't worry if the previous step failed." + echo "See https://github.com/actions-ecosystem/action-remove-labels/issues/221." + + + name: PR Review Requested + + + on: + pull_request_target: + types: + - review_requested + + + permissions: + pull-requests: write + ", + }, + }, + }, + } + `); + }); + test("without addons or mode", () => { const creation = testBlock(blockGitHubActionsCI, { options: optionsBase, @@ -34,7 +245,7 @@ describe("blockGitHubActionsCI", () => { - uses: actions/setup-node@v4 with: cache: pnpm - node-version: '20' + node-version: 20.12.0 - run: pnpm install --frozen-lockfile shell: bash using: composite @@ -144,7 +355,7 @@ describe("blockGitHubActionsCI", () => { - uses: actions/setup-node@v4 with: cache: pnpm - node-version: '20' + node-version: 20.12.0 - run: pnpm install --frozen-lockfile shell: bash using: composite @@ -261,7 +472,7 @@ describe("blockGitHubActionsCI", () => { - uses: actions/setup-node@v4 with: cache: pnpm - node-version: '20' + node-version: 20.12.0 - run: pnpm install --frozen-lockfile shell: bash using: composite diff --git a/src/blocks/blockGitHubActionsCI.ts b/src/blocks/blockGitHubActionsCI.ts index 7404f93b0..51baa03de 100644 --- a/src/blocks/blockGitHubActionsCI.ts +++ b/src/blocks/blockGitHubActionsCI.ts @@ -64,7 +64,11 @@ export const blockGitHubActionsCI = base.createBlock({ "v4", options.workflowsVersions, ), - with: { cache: "pnpm", "node-version": "20" }, + with: { + cache: "pnpm", + "node-version": + options.node.pinned ?? options.node.minimum, + }, }, { run: "pnpm install --frozen-lockfile", diff --git a/src/blocks/blockNvmrc.test.ts b/src/blocks/blockNvmrc.test.ts index 341801bda..135135aa2 100644 --- a/src/blocks/blockNvmrc.test.ts +++ b/src/blocks/blockNvmrc.test.ts @@ -18,7 +18,7 @@ describe("blockNvmrc", () => { }); }); - it("also includes files when options.node exists", () => { + it("also includes files when options.node.pinned exists", () => { const creation = testBlock(blockNvmrc, { options: { ...optionsBase, diff --git a/src/blocks/blockNvmrc.ts b/src/blocks/blockNvmrc.ts index 413d7f67a..467c12149 100644 --- a/src/blocks/blockNvmrc.ts +++ b/src/blocks/blockNvmrc.ts @@ -12,7 +12,7 @@ export const blockNvmrc = base.createBlock({ overrides: [{ files: ".nvmrc", options: { parser: "yaml" } }], }), ], - ...(options.node?.pinned && { + ...(options.node.pinned && { files: { ".nvmrc": `${options.node.pinned}\n`, }, diff --git a/src/blocks/blockPackageJson.test.ts b/src/blocks/blockPackageJson.test.ts index ae4884a45..1c43051e2 100644 --- a/src/blocks/blockPackageJson.test.ts +++ b/src/blocks/blockPackageJson.test.ts @@ -17,7 +17,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"]}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}", }, "scripts": [ { @@ -50,7 +50,7 @@ describe("blockPackageJson", () => { }, ], "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"]}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}", }, "scripts": [ { @@ -81,7 +81,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"other":true}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"engines":{"node":">=20.12.0"},"other":true}", }, "scripts": [ { @@ -116,7 +116,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"devDependencies":{"is-even":"4.5.6"},"other":true}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"devDependencies":{"is-even":"4.5.6"},"engines":{"node":">=20.12.0"},"other":true}", }, "scripts": [ { @@ -142,7 +142,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","keywords":["abc","def","ghi"],"repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"]}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","keywords":["abc","def","ghi"],"repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}", }, "scripts": [ { @@ -195,7 +195,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","bin":"bin/index.js","files":["README.md","bin/index.js","package.json"]}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","bin":"bin/index.js","files":["README.md","bin/index.js","package.json"],"engines":{"node":">=20.12.0"}}", }, "scripts": [ { @@ -223,7 +223,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","bin":{"absolute":"bin/absolute.js","relative":"./bin/relative.js"},"files":["README.md","bin/absolute.js","bin/relative.js","package.json"]}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","bin":{"absolute":"bin/absolute.js","relative":"./bin/relative.js"},"files":["README.md","bin/absolute.js","bin/relative.js","package.json"],"engines":{"node":">=20.12.0"}}", }, "scripts": [ { @@ -258,7 +258,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"peerDependencies":{"@types/estree":">=1","eslint":">=8"},"peerDependenciesMeta":{"@types/estree":{"optional":true}}}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"peerDependencies":{"@types/estree":">=1","eslint":">=8"},"peerDependenciesMeta":{"@types/estree":{"optional":true}},"engines":{"node":">=20.12.0"}}", }, "scripts": [ { @@ -281,7 +281,7 @@ describe("blockPackageJson", () => { expect(creation).toMatchInlineSnapshot(` { "files": { - "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"]}", + "package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"npm@email.com"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}", }, "scripts": [ { diff --git a/src/blocks/blockPackageJson.ts b/src/blocks/blockPackageJson.ts index 6d30b1700..2f9c55cd1 100644 --- a/src/blocks/blockPackageJson.ts +++ b/src/blocks/blockPackageJson.ts @@ -53,11 +53,9 @@ export const blockPackageJson = base.createBlock({ devDependencies: Object.keys(devDependencies).length ? devDependencies : undefined, - ...(options.node && { - engines: { - node: `>=${options.node.minimum}`, - }, - }), + engines: { + node: `>=${options.node.minimum}`, + }, ...(options.pnpm && { packageManager: `pnpm@${options.pnpm}`, }), diff --git a/src/blocks/options.fakes.ts b/src/blocks/options.fakes.ts index 6acd668c8..f7a5f2eea 100644 --- a/src/blocks/options.fakes.ts +++ b/src/blocks/options.fakes.ts @@ -14,6 +14,9 @@ export const optionsBase = { npm: "npm@email.com", }, emoji: "💖", + node: { + minimum: "20.12.0", + }, owner: "test-owner", preset: "minimal", repository: "test-repository",