diff --git a/biome.json b/biome.json index 10ed704..74a58e7 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.9/schema.json", "vcs": { "enabled": false, "clientKind": "git", diff --git a/package.json b/package.json index deb1790..1dddf9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@octomind/octomind", - "version": "3.4.0", + "version": "3.4.1", "description": "a command line client for octomind apis", "main": "./dist/index.js", "packageManager": "pnpm@10.26.0+sha512.3b3f6c725ebe712506c0ab1ad4133cf86b1f4b687effce62a9b38b4d72e3954242e643190fc51fa1642949c735f403debd44f5cb0edd657abe63a8b6a7e1e402", @@ -26,7 +26,7 @@ "lint": "pnpm apigen && npx genversion -des src/version.ts && biome check", "tsc": "tsc --project tsconfig.build.json", "dev:staging": "pnpm apigen && OCTOMIND_CONFIG_FILE=octomind.dev.staging.json OCTOMIND_API_URL=https://preview.octomind.dev/api tsx src/index.ts", - "dev:prod": "pnpm apigen && OCTOMIND_CONFIG_FILE=octomind.dev.staging.json OCTOMIND_API_URL=https://app.octomind.dev/api tsx src/index.ts", + "dev:prod": "pnpm apigen && OCTOMIND_CONFIG_FILE=octomind.dev.prod.json OCTOMIND_API_URL=https://app.octomind.dev/api tsx src/index.ts", "apigen": "openapi-typescript https://preview.octomind.dev/openapi.yaml --output src/api.ts && orval", "build": "pnpm apigen && npx genversion -des src/version.ts && pnpm gendoc && tsc --project tsconfig.build.json", "octomind": "pnpm apigen && tsx src/index.ts", diff --git a/src/tools/sync/git.ts b/src/tools/sync/git.ts index bffbb1f..3e07f65 100644 --- a/src/tools/sync/git.ts +++ b/src/tools/sync/git.ts @@ -4,6 +4,8 @@ import { simpleGit } from "simple-git"; import { ExecutionContext } from "./types"; +const FALLBACK_DEFAULT_BRANCH = "refs/heads/main"; + export const parseGitRemote = async (): Promise<{ owner?: string; repo?: string; @@ -41,11 +43,34 @@ export type GitContext = ExecutionContext & { defaultBranch?: string; }; -export const getDefaultBranch = async (): Promise => { - const symbolicRef = ( - await simpleGit().raw("symbolic-ref", "refs/remotes/origin/HEAD") - ).trim(); - return symbolicRef.replace("refs/remotes/origin/", "refs/heads/"); +export const getDefaultBranch = async ( + allowedMethod: "symbolicRef+origin" | "origin" = "symbolicRef+origin", +): Promise => { + if (allowedMethod === "symbolicRef+origin") { + const symbolicRef = ( + await simpleGit().raw("symbolic-ref", "refs/remotes/origin/HEAD") + ).trim(); + const symbolicRefBranch = symbolicRef.replace( + "refs/remotes/origin/", + "refs/heads/", + ); + + if (symbolicRefBranch) { + return symbolicRefBranch; + } + } + + const origin = await simpleGit().remote(["show", "origin"]); + if (!origin) { + console.warn("could not identify default branch, falling back to 'main'"); + return FALLBACK_DEFAULT_BRANCH; + } + + const originDefaultBranch = /HEAD branch:((.*))/.exec(origin); + + return originDefaultBranch?.groups?.["branchName"] + ? `refs/heads/${originDefaultBranch?.groups?.["branchName"]}` + : FALLBACK_DEFAULT_BRANCH; }; export const getGitContext = async (): Promise => { diff --git a/tests/tools/sync/git.integration.spec.ts b/tests/tools/sync/git.integration.spec.ts index 7ccf156..84e5738 100644 --- a/tests/tools/sync/git.integration.spec.ts +++ b/tests/tools/sync/git.integration.spec.ts @@ -1,4 +1,4 @@ -import {parseGitRemote} from "../../../src/tools/sync/git"; +import {getDefaultBranch, parseGitRemote} from "../../../src/tools/sync/git"; describe('git', () => { it("should return the actual owner and repo", async () => { @@ -7,4 +7,12 @@ describe('git', () => { expect(remote.owner).toEqual("OctoMind-dev"); expect(remote.repo).toEqual("cli"); }) + + it.each(["origin"] as const)("should return the actual default branch for method '%s'", async (allowedMethod) => { + const defaultBranch = await getDefaultBranch(allowedMethod); + + expect(defaultBranch).toEqual("refs/heads/main"); + }); + + }) \ No newline at end of file diff --git a/tests/tools/sync/git.spec.ts b/tests/tools/sync/git.spec.ts index 4ba0010..0b07136 100644 --- a/tests/tools/sync/git.spec.ts +++ b/tests/tools/sync/git.spec.ts @@ -1,5 +1,5 @@ import {simpleGit} from "simple-git"; -import {parseGitRemote, getGitContext} from "../../../src/tools/sync/git"; +import {parseGitRemote, getGitContext, getDefaultBranch} from "../../../src/tools/sync/git"; import {mock} from "jest-mock-extended"; jest.mock("simple-git"); @@ -14,6 +14,19 @@ describe("git", () => { console.error = jest.fn(); }) + describe("getDefaultBranch", () => { + it("should fallback if both origin and symbolic ref fail", async () => { + console.warn = jest.fn(); + mockGit.raw.mockResolvedValue("") + mockGit.remote.mockResolvedValue("") + + const defaultBranch = await getDefaultBranch(); + + expect(defaultBranch).toEqual("refs/heads/main") + expect(console.warn).toHaveBeenCalled() + }) + }) + describe("parseGitRemote", () => { it("parses SSH git remote format (git@github.com:owner/repo.git)", async () => { mockGit.remote.mockResolvedValue("git@github.com:my-org/my-repo.git");