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

Issue:
📝 Documentation: Streamline VS Code debugging mentions in .github/DEVELOPMENT.md
### Bug Report 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

Following #1290 and split out of #1670: there are a few places that debugging with VS Code is mentioned now:

* _Testing_ > _Debugging Tests_
* _Debugging_:
  * _Unit Tests_
  * _`bin` Apps_

I'm now realizing there's a bit of duplication there for testing. I'll go ahead and dedup so that debugging is mentioned in the individual sections, rather than its own.

### Additional Info

Filing this as a docs issue because it's not really a "bug", more of a cleanup. Even though it's going to produce a different output and should arguably be sent in as a `feat: ...` or `fix: ...`.

Pull request:
docs: streamlined and organized DEVELOPMENT.md
## PR Checklist

- [x] Addresses an existing open issue: fixes #1710
- [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

Mostly re-applies changes from #1670.

💖 

Patch:
diff --git a/.github/DEVELOPMENT.md b/.github/DEVELOPMENT.md
index 30091f4..39161bc 100644
--- a/.github/DEVELOPMENT.md
+++ b/.github/DEVELOPMENT.md
@@ -28,6 +28,12 @@ Add `--watch` to run the builder in a watch mode that continuously cleans and re
 pnpm build --watch
 ```
 
+### Built App Debugging
+
+This repository includes a [VS Code launch configuration](https://code.visualstudio.com/docs/editor/debugging) for debugging.
+To debug a `bin` app, add a breakpoint to your code, then run _Debug Program_ from the VS Code Debug panel (or press F5).
+VS Code will automatically run the `build` task in the background before running `./bin/index.js`.
+
 ## Formatting
 
 [Prettier](https://prettier.io) is used to format code.
@@ -58,7 +64,7 @@ For example, ESLint can be run with `--fix` to auto-fix some lint rule complaint
 pnpm run lint --fix
 ```
 
-Note that you'll likely need to run `pnpm build` before `pnpm lint` so that lint rules which check the file system can pick up on any built files.
+Note that you'll need to run `pnpm build` before `pnpm lint` so that lint rules which check the file system can pick up on any built files.
 
 ## Testing
 
@@ -99,19 +105,6 @@ Add `--watch` to keep the type checker running in a watch mode that updates the
 pnpm tsc --watch
 ```
 
-## Debugging
-
-This repository includes a [VS Code launch configuration](https://code.visualstudio.com/docs/editor/debugging) for debugging.
-Depending upon the type of usage, it can include debugging for unit tests _and_ for executable (or "bin") apps.
-
-### Unit Tests
-
-To debug a unit test, open a test file, then run _Debug Current Test File_ from the VS Code Debug panel (or press F5).
-
-### `bin` Apps
-
-To debug a `bin` app, add a breakpoint to your code, then run _Debug Program_ from the VS Code Debug panel (or press F5).
-
 ## Setup Scripts
 
 As described in the `README.md` file and `docs/`, this template repository comes with three scripts that can set up an existing or new repository.
@@ -152,7 +145,7 @@ That end-to-end test executes `script/create-test-e2e.ts`, which:
 2. Asserts that commands such as `build` and `lint` each pass
 
 The `pnpm run test:create` script is run in CI to ensure that templating changes are in sync with the template's actual files.
-See `.github/workflows/test-create.yml`.
+See `.github/workflows/ci.yml`'s `test_creation_script` job.
 
 ### The Initialization Script
 
@@ -184,7 +177,7 @@ That end-to-end test executes `script/initialize-test-e2e.ts`, which:
 5. Runs initialization a second time, capturing test coverage
 
 The `pnpm run test:initialize` script is run in CI to ensure that templating changes are in sync with the template's actual files.
-See `.github/workflows/test-initialize.yml`.
+See `.github/workflows/ci.yml`'s `test_initialization_script` job.
 
 ### The Migration Script
 
@@ -228,7 +221,7 @@ That end-to-end test executes `script/migrate-test-e2e.ts`, which:
 3. Checks that the local repository's files were changed correctly (e.g. removed initialization-only files)
 
 The `pnpm run test:migrate` script is run in CI to ensure that templating changes are in sync with the template's actual files.
-See `.github/workflows/test-migrate.yml`.
+See `.github/workflows/ci.yml`'s `test_migration_script` job.
 
 > Tip: if the migration test is failing in CI and you don't see any errors, try [downloading the full logs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs#downloading-logs).
 
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d831a4c..5256324 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -65,9 +65,49 @@ jobs:
       - uses: actions/checkout@v4
       - uses: ./.github/actions/prepare
       - run: pnpm run test --coverage
-      - uses: codecov/codecov-action@v3
+      - if: always()
+        uses: codecov/codecov-action@v3
         with:
           flags: unit
+  test_creation_script:
+    name: Test Creation Script
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+      - uses: ./.github/actions/prepare
+      - run: pnpm run build
+      - run: pnpm run test:create
+      - if: always()
+        uses: codecov/codecov-action@v3
+        with:
+          files: coverage-create/lcov.info
+          flags: create
+  test_initialization_script:
+    name: Test Initialization Script
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+      - uses: ./.github/actions/prepare
+      - run: pnpm run build
+      - run: pnpm run test:initialize
+      - if: always()
+        uses: codecov/codecov-action@v3
+        with:
+          files: coverage-initialize/lcov.info
+          flags: initialize
+  test_migration_script:
+    name: Test Migration Script
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+      - uses: ./.github/actions/prepare
+      - run: pnpm run build
+      - run: pnpm run test:migrate
+      - if: always()
+        uses: codecov/codecov-action@v3
+        with:
+          files: coverage-migrate/lcov.info
+          flags: migrate
   type_check:
     name: Type Check
     runs-on: ubuntu-latest
diff --git a/src/steps/writing/creation/dotGitHub/createDevelopment/index.ts b/src/steps/writing/creation/dotGitHub/createDevelopment/index.ts
index ff86c0a..5ce29ce 100644
--- a/src/steps/writing/creation/dotGitHub/createDevelopment/index.ts
+++ b/src/steps/writing/creation/dotGitHub/createDevelopment/index.ts
@@ -26,6 +26,11 @@ Add \`--watch\` to run the builder in a watch mode that continuously cleans and
 \`\`\`shell
 pnpm build --watch
 \`\`\``,
+		...(options.bin && {
+			"### Built App Debugging": `This repository includes a [VS Code launch configuration](https://code.visualstudio.com/docs/editor/debugging) for debugging.
+To debug a \`bin\` app, add a breakpoint to your code, then run _Debug Program_ from the VS Code Debug panel (or press F5).
+VS Code will automatically run the \`build\` task in the background before running \`${options.bin}\`.`,
+		}),
 		"## Formatting": `[Prettier](https://prettier.io) is used to format code.
 It should be applied automatically when you save files in VS Code or make a Git commit.
 
@@ -40,8 +45,7 @@ pnpm format --write
 pnpm run lint --fix
 \`\`\`
 
-Note that you'll likely need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.`,
-
+Note that you'll need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.`,
 		...(!options.excludeTests && {
 			"## Testing": `[Vitest](https://vitest.dev) is used for tests.
 You can run it locally on the command-line:
@@ -83,14 +87,35 @@ pnpm tsc --watch
 		Object.keys(newSections).map((key) => key.replace(/^#* /, "")),
 	]);
 
-	const preservedSections = Object.fromEntries(
-		splitIntoSections(existingContents).filter(([key]) => {
-			const keyText = key.replace(/^#* /, "");
-			return !newSectionHeadings.has(
-				headingAliases.get(keyText.toLowerCase()) ?? keyText,
-			);
-		}),
-	);
+	const existingSectionsSplit = splitIntoSections(existingContents);
+	const preservedSectionsSplit = existingSectionsSplit.filter(([key]) => {
+		const keyText = key.replace(/^#* /, "");
+		return !newSectionHeadings.has(
+			headingAliases.get(keyText.toLowerCase()) ?? keyText,
+		);
+	});
+	const preservedSections = Object.fromEntries(preservedSectionsSplit);
+
+	const sectionLines: string[] = [];
+	const seen = new Set<string>();
+
+	for (const sections of [newSections, preservedSections]) {
+		for (const heading in sections) {
+			if (seen.has(heading)) {
+				continue;
+			}
+
+			seen.add(heading);
+
+			// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+			const contents = sections[heading as keyof typeof sections]!;
+
+			sectionLines.push("");
+			sectionLines.push(heading);
+			sectionLines.push("");
+			sectionLines.push(contents);
+		}
+	}
 
 	const result = `# Development
 ${
@@ -111,14 +136,7 @@ pnpm install
 
 > This repository includes a list of suggested VS Code extensions.
 > It's a good idea to use [VS Code](https://code.visualstudio.com) and accept its suggestion to install them, as they'll help with development.
-
-${Object.entries({ ...newSections, ...preservedSections })
-	.map(
-		([heading, content]) => `${heading}
-
-${content}`,
-	)
-	.join("\n\n")}
+${sectionLines.join("\n")}
 `;
 
 	return result;
@@ -129,7 +147,7 @@ function createLintingSection(options: Options) {
 		!options.excludeLintKnip &&
 			`- \`pnpm lint:knip\` ([knip](https://github.com/webpro/knip)): Detects unused files, dependencies, and code exports`,
 		!options.excludeLintMd &&
-			`- \`pnpm lint:md\` ([Markdownlint](https://github.com/DavidAnson/markdownlint): Checks Markdown source files`,
+			`- \`pnpm lint:md\` ([Markdownlint](https://github.com/DavidAnson/markdownlint)): Checks Markdown source files`,
 		!options.excludeLintPackages &&
 			`- \`pnpm lint:packages\` ([pnpm dedupe --check](https://pnpm.io/cli/dedupe)): Checks for unnecessarily duplicated packages in the \`pnpm-lock.yml\` file`,
 		!options.excludeLintSpelling &&
diff --git a/src/steps/writing/creation/dotGitHub/createMultiWorkflowFile.ts b/src/steps/writing/creation/dotGitHub/createMultiWorkflowFile.ts
index 1673210..0d38bef 100644
--- a/src/steps/writing/creation/dotGitHub/createMultiWorkflowFile.ts
+++ b/src/steps/writing/creation/dotGitHub/createMultiWorkflowFile.ts
@@ -10,7 +10,10 @@ export interface MultiWorkflowJobOptions {
 	steps: MultiWorkflowJobStep[];
 }
 
-export type MultiWorkflowJobStep = { run: string } | { uses: string };
+export type MultiWorkflowJobStep = { if?: string } & (
+	| { run: string }
+	| { uses: string }
+);
 
 export function createMultiWorkflowFile({
 	jobs,
diff --git a/src/steps/writing/creation/dotGitHub/createWorkflows.ts b/src/steps/writing/creation/dotGitHub/createWorkflows.ts
index 064a6a1..72ecc78 100644
--- a/src/steps/writing/creation/dotGitHub/createWorkflows.ts
+++ b/src/steps/writing/creation/dotGitHub/createWorkflows.ts
@@ -88,7 +88,7 @@ export function createWorkflows(options: Options) {
 								name: "Test",
 								steps: [
 									{ run: "pnpm run test --coverage" },
-									{ uses: "codecov/codecov-action@v3" },
+									{ if: "always()", uses: "codecov/codecov-action@v3" },
 								],
 							},
 						]),


Test patch:
diff --git a/script/__snapshots__/migrate-test-e2e.ts.snap b/script/__snapshots__/migrate-test-e2e.ts.snap
index 8fe95da..3428595 100644
--- a/script/__snapshots__/migrate-test-e2e.ts.snap
+++ b/script/__snapshots__/migrate-test-e2e.ts.snap
@@ -17,11 +17,50 @@ exports[`expected file changes > .github/workflows/ci.yml 1`] = `
      name: Build
      runs-on: ubuntu-latest
 @@ ... @@ jobs:
-       - uses: ./.github/actions/prepare
        - run: pnpm run test --coverage
-       - uses: codecov/codecov-action@v3
+       - if: always()
+         uses: codecov/codecov-action@v3
 -        with:
 -          flags: unit
+-  test_creation_script:
+-    name: Test Creation Script
+-    runs-on: ubuntu-latest
+-    steps:
+-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+-      - uses: ./.github/actions/prepare
+-      - run: pnpm run build
+-      - run: pnpm run test:create
+-      - if: always()
+-        uses: codecov/codecov-action@v3
+-        with:
+-          files: coverage-create/lcov.info
+-          flags: create
+-  test_initialization_script:
+-    name: Test Initialization Script
+-    runs-on: ubuntu-latest
+-    steps:
+-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+-      - uses: ./.github/actions/prepare
+-      - run: pnpm run build
+-      - run: pnpm run test:initialize
+-      - if: always()
+-        uses: codecov/codecov-action@v3
+-        with:
+-          files: coverage-initialize/lcov.info
+-          flags: initialize
+-  test_migration_script:
+-    name: Test Migration Script
+-    runs-on: ubuntu-latest
+-    steps:
+-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+-      - uses: ./.github/actions/prepare
+-      - run: pnpm run build
+-      - run: pnpm run test:migrate
+-      - if: always()
+-        uses: codecov/codecov-action@v3
+-        with:
+-          files: coverage-migrate/lcov.info
+-          flags: migrate
    type_check:
      name: Type Check
      runs-on: ubuntu-latest"
@@ -93,9 +132,7 @@ exports[`expected file changes > cspell.json 1`] = `
  		"markdownlintignore",
  		"mtfoley",
  		"npmignore",
--		"npmpackagejsonlintrc",
- 		"outro",
--		"packagejson",
+@@ ... @@
  		"tada",
  		"tseslint",
  		"tsup",
diff --git a/src/steps/writing/creation/dotGitHub/createDevelopment/index.test.ts b/src/steps/writing/creation/dotGitHub/createDevelopment/index.test.ts
index cddd40e..0dd4598 100644
--- a/src/steps/writing/creation/dotGitHub/createDevelopment/index.test.ts
+++ b/src/steps/writing/creation/dotGitHub/createDevelopment/index.test.ts
@@ -87,7 +87,7 @@ describe("createDevelopment", () => {
 
 			- \`pnpm lint\` ([ESLint](https://eslint.org) with [typescript-eslint](https://typescript-eslint.io)): Lints JavaScript and TypeScript source files
 			- \`pnpm lint:knip\` ([knip](https://github.com/webpro/knip)): Detects unused files, dependencies, and code exports
-			- \`pnpm lint:md\` ([Markdownlint](https://github.com/DavidAnson/markdownlint): Checks Markdown source files
+			- \`pnpm lint:md\` ([Markdownlint](https://github.com/DavidAnson/markdownlint)): Checks Markdown source files
 			- \`pnpm lint:packages\` ([pnpm dedupe --check](https://pnpm.io/cli/dedupe)): Checks for unnecessarily duplicated packages in the \`pnpm-lock.yml\` file
 			- \`pnpm lint:spelling\` ([cspell](https://cspell.org)): Spell checks across all source files
 
@@ -99,7 +99,7 @@ describe("createDevelopment", () => {
 			pnpm run lint --fix
 			\`\`\`
 
-			Note that you'll likely need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.
+			Note that you'll need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.
 
 			## Testing
 
@@ -216,7 +216,7 @@ describe("createDevelopment", () => {
 			pnpm run lint --fix
 			\`\`\`
 
-			Note that you'll likely need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.
+			Note that you'll need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.
 
 			## Testing
 
@@ -303,7 +303,17 @@ Def 456.
 
 			## Building
 
-			Will be removed.
+			Run [**tsup**](https://tsup.egoist.dev) locally to build source files from \`src/\` into output files in \`lib/\`:
+
+			\`\`\`shell
+			pnpm build
+			\`\`\`
+
+			Add \`--watch\` to run the builder in a watch mode that continuously cleans and recreates \`lib/\` as you save files:
+
+			\`\`\`shell
+			pnpm build --watch
+			\`\`\`
 
 			## Formatting
 
@@ -323,7 +333,7 @@ Def 456.
 
 			- \`pnpm lint\` ([ESLint](https://eslint.org) with [typescript-eslint](https://typescript-eslint.io)): Lints JavaScript and TypeScript source files
 			- \`pnpm lint:knip\` ([knip](https://github.com/webpro/knip)): Detects unused files, dependencies, and code exports
-			- \`pnpm lint:md\` ([Markdownlint](https://github.com/DavidAnson/markdownlint): Checks Markdown source files
+			- \`pnpm lint:md\` ([Markdownlint](https://github.com/DavidAnson/markdownlint)): Checks Markdown source files
 			- \`pnpm lint:packages\` ([pnpm dedupe --check](https://pnpm.io/cli/dedupe)): Checks for unnecessarily duplicated packages in the \`pnpm-lock.yml\` file
 			- \`pnpm lint:spelling\` ([cspell](https://cspell.org)): Spell checks across all source files
 
@@ -335,7 +345,7 @@ Def 456.
 			pnpm run lint --fix
 			\`\`\`
 
-			Note that you'll likely need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.
+			Note that you'll need to run \`pnpm build\` before \`pnpm lint\` so that lint rules which check the file system can pick up on any built files.
 
 			## Testing
 
diff --git a/src/steps/writing/creation/dotGitHub/createWorkflows.test.ts b/src/steps/writing/creation/dotGitHub/createWorkflows.test.ts
index d348abd..2f5356d 100644
--- a/src/steps/writing/creation/dotGitHub/createWorkflows.test.ts
+++ b/src/steps/writing/creation/dotGitHub/createWorkflows.test.ts
@@ -126,7 +126,8 @@ describe("createWorkflows", () => {
 			      - uses: actions/checkout@v4
 			      - uses: ./.github/actions/prepare
 			      - run: pnpm run test --coverage
-			      - uses: codecov/codecov-action@v3
+			      - if: always()
+			        uses: codecov/codecov-action@v3
 			  type_check:
 			    name: Type Check
 			    runs-on: ubuntu-latest