Repository: JoshuaKGoldberg/create-typescript-app (ts)

Issue:
🚀 Feature: Allow adding more build steps to `release.yml`
### Feature Request Checklist

- [x] I have pulled the latest `main` branch of the repository.
- [x] I have [searched for related issues](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aissue) and found none that matched my issue.

### Overview

`blockReleaseIt` hardcodes that `release.yml` runs `pnpm build`:

https://github.com/JoshuaKGoldberg/create-typescript-app/blob/3260079633ec4215b790b3cf446125aed65c1de6/src/blocks/blockReleaseIt.ts#L138-L140

...but some repos may need different/more steps. For example, emojipedia runs two builders in https://github.com/JoshuaKGoldberg/emojipedia/blob/4b96f1ede3e0e939fe26e1c75b2cb7a644e817ef/.github/workflows/release.yml#L13-L14:

```yml
      - run: pnpm build
      - run: pnpm build:data
```

### Additional Info

🎁 

Pull request:
feat: allow customizing release.yml build steps
## PR Checklist

- [x] Addresses an existing open issue: fixes #2052
- [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22)
- [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/main/.github/CONTRIBUTING.md) were taken

## Overview

🎁 

Patch:
diff --git a/src/blocks/blockReleaseIt.ts b/src/blocks/blockReleaseIt.ts
index ad40073..9be1090 100644
--- a/src/blocks/blockReleaseIt.ts
+++ b/src/blocks/blockReleaseIt.ts
@@ -1,3 +1,5 @@
+import { z } from "zod";
+
 import { base } from "../base.js";
 import { getPackageDependencies } from "../data/packageData.js";
 import { resolveUses } from "./actions/resolveUses.js";
@@ -12,7 +14,19 @@ export const blockReleaseIt = base.createBlock({
 	about: {
 		name: "release-it",
 	},
-	produce({ options }) {
+	addons: {
+		builders: z
+			.array(
+				z.object({
+					order: z.number(),
+					run: z.string(),
+				}),
+			)
+			.default([]),
+	},
+	produce({ addons, options }) {
+		const { builders } = addons;
+
 		return {
 			addons: [
 				blockCSpell({
@@ -135,9 +149,9 @@ export const blockReleaseIt = base.createBlock({
 								{
 									uses: "./.github/actions/prepare",
 								},
-								{
-									run: "pnpm build",
-								},
+								...builders
+									.sort((a, b) => a.order - b.order)
+									.map(({ run }) => ({ run })),
 								{
 									env: {
 										GITHUB_TOKEN: "${{ secrets.ACCESS_TOKEN }}",
diff --git a/src/blocks/blockTSup.ts b/src/blocks/blockTSup.ts
index 7d605fd..793ee9f 100644
--- a/src/blocks/blockTSup.ts
+++ b/src/blocks/blockTSup.ts
@@ -6,6 +6,7 @@ import { blockDevelopmentDocs } from "./blockDevelopmentDocs.js";
 import { blockESLint } from "./blockESLint.js";
 import { blockGitHubActionsCI } from "./blockGitHubActionsCI.js";
 import { blockPackageJson } from "./blockPackageJson.js";
+import { blockReleaseIt } from "./blockReleaseIt.js";
 import { blockRemoveDependencies } from "./blockRemoveDependencies.js";
 import { blockRemoveFiles } from "./blockRemoveFiles.js";
 import { blockRemoveWorkflows } from "./blockRemoveWorkflows.js";
@@ -65,6 +66,14 @@ pnpm build --watch
 						},
 					},
 				}),
+				blockReleaseIt({
+					builders: [
+						{
+							order: 0,
+							run: "pnpm build",
+						},
+					],
+				}),
 			],
 			files: {
 				"tsup.config.ts": `import { defineConfig } from "tsup";


Test patch:
diff --git a/src/blocks/blockReleaseIt.test.ts b/src/blocks/blockReleaseIt.test.ts
new file mode 100644
index 0000000..87fef4d
--- /dev/null
+++ b/src/blocks/blockReleaseIt.test.ts
@@ -0,0 +1,306 @@
+import { testBlock } from "bingo-stratum-testers";
+import { describe, expect, test } from "vitest";
+
+import { blockReleaseIt } from "./blockReleaseIt.js";
+import { optionsBase } from "./options.fakes.js";
+
+describe("blockReleaseIt", () => {
+	test("without addons", () => {
+		const creation = testBlock(blockReleaseIt, { options: optionsBase });
+
+		expect(creation).toMatchInlineSnapshot(`
+			{
+			  "addons": [
+			    {
+			      "addons": {
+			        "words": [
+			          "apexskier",
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "properties": {
+			          "devDependencies": {
+			            "@release-it/conventional-changelog": "10.0.0",
+			            "release-it": "18.1.2",
+			          },
+			          "publishConfig": {
+			            "provenance": true,
+			          },
+			          "scripts": {
+			            "should-semantic-release": undefined,
+			          },
+			        },
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "badges": [
+			          {
+			            "alt": "📦 npm version",
+			            "href": "http://npmjs.com/package/test-repository",
+			            "src": "https://img.shields.io/npm/v/test-repository?color=21bb42&label=%F0%9F%93%A6%20npm",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "dependencies": [
+			          "should-semantic-release",
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "secrets": [
+			          {
+			            "description": "a GitHub PAT with repo and workflow permissions",
+			            "name": "ACCESS_TOKEN",
+			          },
+			          {
+			            "description": "an npm access token with automation permissions",
+			            "name": "NPM_TOKEN",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			  ],
+			  "files": {
+			    ".github": {
+			      "workflows": {
+			        "post-release.yml": "jobs:
+			  post_release:
+			    runs-on: ubuntu-latest
+			    steps:
+			      - uses: actions/checkout@v4
+			        with:
+			          fetch-depth: 0
+			      - run: echo "npm_version=$(npm pkg get version | tr -d '"')" >> "$GITHUB_ENV"
+			      - uses: apexskier/github-release-commenter@v1
+			        with:
+			          GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
+			          comment-template: |
+			              :tada: This is included in version {release_link} :tada:
+
+			              The release is available on:
+
+			              * [GitHub releases](https://github.com/test-owner/test-repository/releases/tag/{release_tag})
+			              * [npm package (@latest dist-tag)](https://www.npmjs.com/package/test-repository/v/\${{ env.npm_version }})
+
+			              Cheers! 📦🚀
+
+			name: Post Release
+
+			on:
+			  release:
+			    types:
+			      - published
+
+			permissions:
+			  issues: write
+			  pull-requests: write
+			",
+			        "release.yml": "concurrency:
+			  group: \${{ github.workflow }}
+
+			jobs:
+			  release:
+			    runs-on: ubuntu-latest
+			    steps:
+			      - uses: actions/checkout@v4
+			        with:
+			          fetch-depth: 0
+			          ref: main
+			          token: \${{ secrets.ACCESS_TOKEN }}
+			      - uses: ./.github/actions/prepare
+			      - env:
+			          GITHUB_TOKEN: \${{ secrets.ACCESS_TOKEN }}
+			          NPM_TOKEN: \${{ secrets.NPM_TOKEN }}
+			        uses: JoshuaKGoldberg/release-it-action@v0.2.2
+
+			name: Release
+
+			on:
+			  push:
+			    branches:
+			      - main
+
+			permissions:
+			  contents: write
+			  id-token: write
+			",
+			      },
+			    },
+			    ".release-it.json": "{"git":{"commitMessage":"chore: release v\${version}","requireCommits":true},"github":{"release":true,"releaseName":"v\${version}"},"npm":{"publishArgs":["--access public","--provenance"]},"plugins":{"@release-it/conventional-changelog":{"infile":"CHANGELOG.md","preset":"angular","types":[{"section":"Features","type":"feat"},{"section":"Bug Fixes","type":"fix"},{"section":"Performance Improvements","type":"perf"},{"hidden":true,"type":"build"},{"hidden":true,"type":"chore"},{"hidden":true,"type":"ci"},{"hidden":true,"type":"docs"},{"hidden":true,"type":"refactor"},{"hidden":true,"type":"style"},{"hidden":true,"type":"test"}]}}}",
+			  },
+			}
+		`);
+	});
+
+	test("with addons", () => {
+		const creation = testBlock(blockReleaseIt, {
+			addons: {
+				builders: [
+					{
+						order: 1,
+						run: "one",
+					},
+					{
+						order: 0,
+						run: "zero",
+					},
+					{
+						order: 2,
+						run: "two",
+					},
+				],
+			},
+			options: optionsBase,
+		});
+
+		expect(creation).toMatchInlineSnapshot(`
+			{
+			  "addons": [
+			    {
+			      "addons": {
+			        "words": [
+			          "apexskier",
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "properties": {
+			          "devDependencies": {
+			            "@release-it/conventional-changelog": "10.0.0",
+			            "release-it": "18.1.2",
+			          },
+			          "publishConfig": {
+			            "provenance": true,
+			          },
+			          "scripts": {
+			            "should-semantic-release": undefined,
+			          },
+			        },
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "badges": [
+			          {
+			            "alt": "📦 npm version",
+			            "href": "http://npmjs.com/package/test-repository",
+			            "src": "https://img.shields.io/npm/v/test-repository?color=21bb42&label=%F0%9F%93%A6%20npm",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "dependencies": [
+			          "should-semantic-release",
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			    {
+			      "addons": {
+			        "secrets": [
+			          {
+			            "description": "a GitHub PAT with repo and workflow permissions",
+			            "name": "ACCESS_TOKEN",
+			          },
+			          {
+			            "description": "an npm access token with automation permissions",
+			            "name": "NPM_TOKEN",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
+			  ],
+			  "files": {
+			    ".github": {
+			      "workflows": {
+			        "post-release.yml": "jobs:
+			  post_release:
+			    runs-on: ubuntu-latest
+			    steps:
+			      - uses: actions/checkout@v4
+			        with:
+			          fetch-depth: 0
+			      - run: echo "npm_version=$(npm pkg get version | tr -d '"')" >> "$GITHUB_ENV"
+			      - uses: apexskier/github-release-commenter@v1
+			        with:
+			          GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
+			          comment-template: |
+			              :tada: This is included in version {release_link} :tada:
+
+			              The release is available on:
+
+			              * [GitHub releases](https://github.com/test-owner/test-repository/releases/tag/{release_tag})
+			              * [npm package (@latest dist-tag)](https://www.npmjs.com/package/test-repository/v/\${{ env.npm_version }})
+
+			              Cheers! 📦🚀
+
+			name: Post Release
+
+			on:
+			  release:
+			    types:
+			      - published
+
+			permissions:
+			  issues: write
+			  pull-requests: write
+			",
+			        "release.yml": "concurrency:
+			  group: \${{ github.workflow }}
+
+			jobs:
+			  release:
+			    runs-on: ubuntu-latest
+			    steps:
+			      - uses: actions/checkout@v4
+			        with:
+			          fetch-depth: 0
+			          ref: main
+			          token: \${{ secrets.ACCESS_TOKEN }}
+			      - uses: ./.github/actions/prepare
+			      - run: zero
+			      - run: one
+			      - run: two
+			      - env:
+			          GITHUB_TOKEN: \${{ secrets.ACCESS_TOKEN }}
+			          NPM_TOKEN: \${{ secrets.NPM_TOKEN }}
+			        uses: JoshuaKGoldberg/release-it-action@v0.2.2
+
+			name: Release
+
+			on:
+			  push:
+			    branches:
+			      - main
+
+			permissions:
+			  contents: write
+			  id-token: write
+			",
+			      },
+			    },
+			    ".release-it.json": "{"git":{"commitMessage":"chore: release v\${version}","requireCommits":true},"github":{"release":true,"releaseName":"v\${version}"},"npm":{"publishArgs":["--access public","--provenance"]},"plugins":{"@release-it/conventional-changelog":{"infile":"CHANGELOG.md","preset":"angular","types":[{"section":"Features","type":"feat"},{"section":"Bug Fixes","type":"fix"},{"section":"Performance Improvements","type":"perf"},{"hidden":true,"type":"build"},{"hidden":true,"type":"chore"},{"hidden":true,"type":"ci"},{"hidden":true,"type":"docs"},{"hidden":true,"type":"refactor"},{"hidden":true,"type":"style"},{"hidden":true,"type":"test"}]}}}",
+			  },
+			}
+		`);
+	});
+});
diff --git a/src/blocks/blockTSup.test.ts b/src/blocks/blockTSup.test.ts
index fa24c7a..cdb4482 100644
--- a/src/blocks/blockTSup.test.ts
+++ b/src/blocks/blockTSup.test.ts
@@ -73,6 +73,17 @@ describe("blockTSup", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "builders": [
+			          {
+			            "order": 0,
+			            "run": "pnpm build",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			  ],
 			  "files": {
 			    "tsup.config.ts": "import { defineConfig } from "tsup";
@@ -157,6 +168,17 @@ describe("blockTSup", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "builders": [
+			          {
+			            "order": 0,
+			            "run": "pnpm build",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "dependencies": [
@@ -273,6 +295,17 @@ describe("blockTSup", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "builders": [
+			          {
+			            "order": 0,
+			            "run": "pnpm build",
+			          },
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			  ],
 			  "files": {
 			    "tsup.config.ts": "import { defineConfig } from "tsup";