From 5f789b6051284537beebb72ace111d9ccd6a5a50 Mon Sep 17 00:00:00 2001 From: stephansama Date: Mon, 23 Jun 2025 19:02:24 -0400 Subject: [PATCH 1/2] chore: initial commit --- .../fixtures/multiple-gitmodules.ini | 7 +++--- src/__tests__/main.test.ts | 22 +++++++++---------- src/__tests__/markdown.test.ts | 6 ++--- src/__tests__/utils.ts | 4 ++-- src/main.ts | 17 +++++++++++++- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/__tests__/fixtures/multiple-gitmodules.ini b/src/__tests__/fixtures/multiple-gitmodules.ini index 76ee604..81a0a18 100644 --- a/src/__tests__/fixtures/multiple-gitmodules.ini +++ b/src/__tests__/fixtures/multiple-gitmodules.ini @@ -1,11 +1,9 @@ -[submodule "ports/nvim"] - path = ports/nvim +[submodule ".config/nvim"] + path = .config/nvim url = https://github.com/catppuccin/nvim.git - - [submodule "ports/mdBook"] url = "https://github.com/catppuccin/mdBook.git" path = ports/mdBook @@ -13,3 +11,4 @@ path = ports/vscode-icons url = https://github.com/catppuccin/vscode-icons.git + diff --git a/src/__tests__/main.test.ts b/src/__tests__/main.test.ts index bcaa02e..ed528db 100644 --- a/src/__tests__/main.test.ts +++ b/src/__tests__/main.test.ts @@ -193,21 +193,14 @@ test("extract multiple git submodules from .gitmodules", async () => { const input = await readFile( "src/__tests__/fixtures/multiple-gitmodules.ini" ); - const [nvim, mdBook, vscodeIcons] = [ - nvimSubmodule(), + const [mdBook, vscodeIcons, nvim] = [ mdBookSubmodule(), vscodeIconsSubmodule(), + nvimSubmodule(), ]; - const expected: Submodule[] = [nvim, mdBook, vscodeIcons]; + const expected: Submodule[] = [mdBook, vscodeIcons, nvim]; vi.mocked(getExecOutput) - .mockReturnValueOnce( - Promise.resolve({ - exitCode: 0, - stdout: `\n${nvim.previousCommitSha}`, - stderr: "", - }) - ) .mockReturnValueOnce( Promise.resolve({ exitCode: 0, @@ -225,7 +218,7 @@ test("extract multiple git submodules from .gitmodules", async () => { .mockReturnValueOnce( Promise.resolve({ exitCode: 0, - stdout: `\n${nvim.previousTag}`, + stdout: `\n${nvim.previousCommitSha}`, stderr: "", }) ) @@ -263,6 +256,13 @@ test("extract multiple git submodules from .gitmodules", async () => { stdout: `\n${vscodeIcons.previousTag}`, stderr: "", }) + ) + .mockReturnValueOnce( + Promise.resolve({ + exitCode: 0, + stdout: `\n${nvim.previousTag}`, + stderr: "", + }), ); const actual = await parseGitmodules(input); diff --git a/src/__tests__/markdown.test.ts b/src/__tests__/markdown.test.ts index 0a218f3..a6651cc 100644 --- a/src/__tests__/markdown.test.ts +++ b/src/__tests__/markdown.test.ts @@ -18,7 +18,7 @@ test("markdown pr body for multiple submodules", async () => { const expected = ` | --- | --- | --- | | [catppuccin/mdBook](https://github.com/catppuccin/mdBook.git) | ports/mdBook | [a19a19b...c9868d3](https://github.com/catppuccin/mdBook/compare/a19a19bd14f26c3bba311bbffc5a74710add5ac2...c9868d34c04df61207141ba4b7dc51d270fda7ec) | -| [catppuccin/nvim](https://github.com/catppuccin/nvim.git) | ports/nvim | [774a4ed...4fd72a9](https://github.com/catppuccin/nvim/compare/774a4ed9a69d0a2633da60f73aa63a8e23aacced...4fd72a9ab64b393c2c22b168508fd244877fec96) | +| [catppuccin/nvim](https://github.com/catppuccin/nvim.git) | .config/nvim | [774a4ed...4fd72a9](https://github.com/catppuccin/nvim/compare/774a4ed9a69d0a2633da60f73aa63a8e23aacced...4fd72a9ab64b393c2c22b168508fd244877fec96) | | [catppuccin/vscode-icons](https://github.com/catppuccin/vscode-icons.git) | ports/vscode-icons | [71d98b8...da859f0](https://github.com/catppuccin/vscode-icons/compare/71d98b81bfdb6b8d3527037c3017eb07e6ec0621...da859f02ffb1ec834ce2efabb7f5bab8667e294c) | `; @@ -54,7 +54,7 @@ test("markdown pr body for multiple submodules using tag strategy", async () => const expected = ` | --- | --- | --- | | [catppuccin/mdBook](https://github.com/catppuccin/mdBook.git) | ports/mdBook | [v0.1.2...v2.2.0](https://github.com/catppuccin/mdBook/compare/v0.1.2...v2.2.0) | -| [catppuccin/nvim](https://github.com/catppuccin/nvim.git) | ports/nvim | [v1.8.0...v1.9.0](https://github.com/catppuccin/nvim/compare/v1.8.0...v1.9.0) | +| [catppuccin/nvim](https://github.com/catppuccin/nvim.git) | .config/nvim | [v1.8.0...v1.9.0](https://github.com/catppuccin/nvim/compare/v1.8.0...v1.9.0) | | [catppuccin/vscode-icons](https://github.com/catppuccin/vscode-icons.git) | ports/vscode-icons | [v1.14.0...v1.15.0](https://github.com/catppuccin/vscode-icons/compare/v1.14.0...v1.15.0) | `; @@ -91,7 +91,7 @@ test("markdown pr body for multiple submodules using tag strategy and previous c const expected = ` | --- | --- | --- | | [catppuccin/mdBook](https://github.com/catppuccin/mdBook.git) | ports/mdBook | [a19a19b...v2.2.0](https://github.com/catppuccin/mdBook/compare/a19a19bd14f26c3bba311bbffc5a74710add5ac2...v2.2.0) | -| [catppuccin/nvim](https://github.com/catppuccin/nvim.git) | ports/nvim | [774a4ed...v1.9.0](https://github.com/catppuccin/nvim/compare/774a4ed9a69d0a2633da60f73aa63a8e23aacced...v1.9.0) | +| [catppuccin/nvim](https://github.com/catppuccin/nvim.git) | .config/nvim | [774a4ed...v1.9.0](https://github.com/catppuccin/nvim/compare/774a4ed9a69d0a2633da60f73aa63a8e23aacced...v1.9.0) | | [catppuccin/vscode-icons](https://github.com/catppuccin/vscode-icons.git) | ports/vscode-icons | [v1.14.0...v1.15.0](https://github.com/catppuccin/vscode-icons/compare/v1.14.0...v1.15.0) | `; diff --git a/src/__tests__/utils.ts b/src/__tests__/utils.ts index 27bfc04..5c089d9 100644 --- a/src/__tests__/utils.ts +++ b/src/__tests__/utils.ts @@ -80,8 +80,8 @@ export const vscodeIconsSubmodule = ( }; export const nvimSubmodule = ( - name: string = "ports/nvim", - path: string = "ports/nvim", + name: string = ".config/nvim", + path: string = ".config/nvim", url: string = "https://github.com/catppuccin/nvim.git", remoteName: string = "catppuccin/nvim", previousShortCommitSha: string = "774a4ed", diff --git a/src/main.ts b/src/main.ts index c8d46a5..e299119 100644 --- a/src/main.ts +++ b/src/main.ts @@ -112,11 +112,26 @@ export const getRemoteName = (url: string) => { return url.substring(startIndex).replace(/^\/+/, ""); } +type IniSubmodule = Record<"path" | "url", string>; + +function cleanUpParsed( + parsed: Record>, +) { + return Object.entries(parsed) + .map(([key, value]) => { + if (value.path && value.url) return { [key]: value }; + const [[nestedKey, nestedValue]] = Object.entries(value); + return { [`${key} .${nestedKey}`]: nestedValue }; + }) + .reduce((prev, curr) => ({ ...prev, ...curr }), {}); +} + + export const parseGitmodules = async ( content: string ): Promise => { const parsed = parse(content); - const gitmodules = await gitmodulesSchema.parseAsync(parsed); + const gitmodules = await gitmodulesSchema.parseAsync(cleanUpParsed(parsed)); return await Promise.all( Object.entries(gitmodules).map(async ([key, values]) => { const name = key.split('"')[1].trim(); From 8007d3bb0d488f06b0bc418796ba164ad7a0a89d Mon Sep 17 00:00:00 2001 From: Logan McAnsh Date: Mon, 6 Oct 2025 15:52:11 +0000 Subject: [PATCH 2/2] feat: add validation for gitmodules schema and clean up parsing logic Signed-off-by: GitHub --- pnpm-workspace.yaml | 2 ++ src/main.ts | 40 +++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 21 deletions(-) create mode 100644 pnpm-workspace.yaml diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..efc037a --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +onlyBuiltDependencies: + - esbuild diff --git a/src/main.ts b/src/main.ts index e299119..7bc477c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,13 +10,26 @@ import { parse } from "ini"; const updateStrategy = z.enum(["commit", "tag"]); type UpdateStrategy = z.infer; +const submodule = z.object({ + path: z.string(), + url: z.string().regex(/[A-Za-z][A-Za-z0-9+.-]*/), +}); + const gitmodulesSchema = z.record( z.string(), - z.object({ - path: z.string(), - url: z.string().regex(/[A-Za-z][A-Za-z0-9+.-]*/), - }), -); + z.union([ + submodule, + z.record(z.string(), submodule) + ]) +).transform(submodules => { + return Object.entries(submodules) + .map(([key, value]) => { + if (value.path && value.url) return { [key]: value }; + const [[nestedKey, nestedValue]] = Object.entries(value); + return { [`${key} .${nestedKey}`]: nestedValue }; + }) + .reduce((prev, curr) => ({ ...prev, ...curr }), {}); +}); export type Inputs = { gitmodulesPath: string; @@ -112,26 +125,11 @@ export const getRemoteName = (url: string) => { return url.substring(startIndex).replace(/^\/+/, ""); } -type IniSubmodule = Record<"path" | "url", string>; - -function cleanUpParsed( - parsed: Record>, -) { - return Object.entries(parsed) - .map(([key, value]) => { - if (value.path && value.url) return { [key]: value }; - const [[nestedKey, nestedValue]] = Object.entries(value); - return { [`${key} .${nestedKey}`]: nestedValue }; - }) - .reduce((prev, curr) => ({ ...prev, ...curr }), {}); -} - - export const parseGitmodules = async ( content: string ): Promise => { const parsed = parse(content); - const gitmodules = await gitmodulesSchema.parseAsync(cleanUpParsed(parsed)); + const gitmodules = await gitmodulesSchema.parseAsync(parsed); return await Promise.all( Object.entries(gitmodules).map(async ([key, values]) => { const name = key.split('"')[1].trim();