diff --git a/.changeset/fix-ci-command-hanging.md b/.changeset/fix-ci-command-hanging.md new file mode 100644 index 000000000..6d5291854 --- /dev/null +++ b/.changeset/fix-ci-command-hanging.md @@ -0,0 +1,10 @@ +--- +"lingo.dev": patch +--- + +Fix CI command hanging due to process.exit calls + +- Remove PostHog shutdown() call that was causing process to hang +- Replace process.exit() with proper exception throwing in i18n and run commands +- Upgrade posthog-node from 5.5.1 to 5.8.1 for better stability +- This fixes the CI command integration where process.exit() was terminating the parent process instead of returning control \ No newline at end of file diff --git a/packages/cli/README.md b/packages/cli/README.md index 7d033ab0b..92eca4c42 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -35,7 +35,6 @@

- --- ## Meet the Compiler 🆕 diff --git a/packages/cli/package.json b/packages/cli/package.json index 919c1ba6a..3332a849d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -182,7 +182,7 @@ "p-limit": "^6.2.0", "php-array-reader": "^2.1.2", "plist": "^3.1.0", - "posthog-node": "^5.5.1", + "posthog-node": "^5.8.1", "prettier": "^3.4.2", "react": "^18.3.1", "rehype-stringify": "^10.0.1", diff --git a/packages/cli/src/cli/cmd/i18n.ts b/packages/cli/src/cli/cmd/i18n.ts index f4628b9e3..e9a31776c 100644 --- a/packages/cli/src/cli/cmd/i18n.ts +++ b/packages/cli/src/cli/cmd/i18n.ts @@ -24,7 +24,6 @@ import createProcessor from "../processor"; import { withExponentialBackoff } from "../utils/exp-backoff"; import trackEvent from "../utils/observability"; import { createDeltaProcessor } from "../utils/delta"; -import { exitGracefully } from "../utils/exit-gracefully"; export default new Command() .command("i18n") @@ -117,7 +116,7 @@ export default new Command() ora.succeed(`Authenticated as ${auth.email}`); } - trackEvent(authId, "cmd.i18n.start", { + await trackEvent(authId, "cmd.i18n.start", { i18nConfig, flags, }); @@ -143,7 +142,9 @@ export default new Command() ora.fail( "No buckets found. All buckets were filtered out by --file option.", ); - process.exit(1); + throw new Error( + "No buckets found. All buckets were filtered out by --file option.", + ); } else { ora.info(`\x1b[36mProcessing only filtered buckets:\x1b[0m`); buckets.map((bucket: any) => { @@ -296,7 +297,9 @@ export default new Command() `Localization data has changed; please update i18n.lock or run without --frozen.`, ); ora.fail(` Details: ${message}`); - process.exit(1); + throw new Error( + `Localization data has changed; please update i18n.lock or run without --frozen. Details: ${message}`, + ); } else { ora.succeed("No lockfile updates required."); } @@ -499,25 +502,23 @@ export default new Command() console.log(); if (!hasErrors) { ora.succeed("Localization completed."); - trackEvent(authId, "cmd.i18n.success", { + await trackEvent(authId, "cmd.i18n.success", { i18nConfig, flags, }); } else { ora.warn("Localization completed with errors."); - trackEvent(authId || "unknown", "cmd.i18n.error", { + await trackEvent(authId || "unknown", "cmd.i18n.error", { flags, }); } - exitGracefully(); } catch (error: any) { ora.fail(error.message); - trackEvent(authId || "unknown", "cmd.i18n.error", { + await trackEvent(authId || "unknown", "cmd.i18n.error", { flags, error, }); - process.exit(1); } }); diff --git a/packages/cli/src/cli/cmd/run/index.ts b/packages/cli/src/cli/cmd/run/index.ts index f2671cdd1..3a05ecff2 100644 --- a/packages/cli/src/cli/cmd/run/index.ts +++ b/packages/cli/src/cli/cmd/run/index.ts @@ -14,7 +14,6 @@ import { } from "../../utils/ui"; import trackEvent from "../../utils/observability"; import { determineAuthId } from "./_utils"; -import { exitGracefully } from "../../utils/exit-gracefully"; export default new Command() .command("run") @@ -92,7 +91,7 @@ export default new Command() authId = await determineAuthId(ctx); - trackEvent(authId, "cmd.run.start", { + await trackEvent(authId, "cmd.run.start", { config: ctx.config, flags: ctx.flags, }); @@ -113,13 +112,12 @@ export default new Command() await watch(ctx); } - trackEvent(authId, "cmd.run.success", { + await trackEvent(authId, "cmd.run.success", { config: ctx.config, flags: ctx.flags, }); - exitGracefully(); } catch (error: any) { - trackEvent(authId || "unknown", "cmd.run.error", {}); - process.exit(1); + await trackEvent(authId || "unknown", "cmd.run.error", {}); + throw error; } }); diff --git a/packages/cli/src/cli/utils/observability.ts b/packages/cli/src/cli/utils/observability.ts index 20ea948f9..45c9853fb 100644 --- a/packages/cli/src/cli/utils/observability.ts +++ b/packages/cli/src/cli/utils/observability.ts @@ -1,6 +1,20 @@ import pkg from "node-machine-id"; const { machineIdSync } = pkg; +export async function createPosthogClient() { + const { PostHog } = await import("posthog-node"); + const posthog = new PostHog( + "phc_eR0iSoQufBxNY36k0f0T15UvHJdTfHlh8rJcxsfhfXk", + { + host: "https://eu.i.posthog.com", + flushAt: 1, + flushInterval: 0, + }, + ); + + return posthog; +} + export default async function trackEvent( distinctId: string | null | undefined, event: string, @@ -13,15 +27,7 @@ export default async function trackEvent( try { const actualId = distinctId || `device-${machineIdSync()}`; - const { PostHog } = await import("posthog-node"); - const posthog = new PostHog( - "phc_eR0iSoQufBxNY36k0f0T15UvHJdTfHlh8rJcxsfhfXk", - { - host: "https://eu.i.posthog.com", - flushAt: 1, - flushInterval: 0, - }, - ); + const posthog = await createPosthogClient(); await posthog.capture({ distinctId: actualId, @@ -34,8 +40,6 @@ export default async function trackEvent( }, }, }); - - await posthog.shutdown(); } catch (error) { if (process.env.DEBUG) { console.error(error); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 916f326d8..a3a0f503d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -440,8 +440,8 @@ importers: specifier: ^3.1.0 version: 3.1.0 posthog-node: - specifier: ^5.5.1 - version: 5.5.1 + specifier: ^5.8.1 + version: 5.8.1 prettier: specifier: ^3.4.2 version: 3.4.2 @@ -2826,6 +2826,9 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@posthog/core@1.0.2': + resolution: {integrity: sha512-hWk3rUtJl2crQK0WNmwg13n82hnTwB99BT99/XI5gZSvIlYZ1TPmMZE8H2dhJJ98J/rm9vYJ/UXNzw3RV5HTpQ==} + '@prettier/sync@0.6.1': resolution: {integrity: sha512-yF9G8vK/LYUTF3Cijd7VC9La3b20F20/J/fgoR4H0B8JGOWnZVZX6+I6+vODPosjmMcpdlUV+gUqJQZp3kLOcw==} peerDependencies: @@ -7615,6 +7618,10 @@ packages: resolution: {integrity: sha512-y2TBl6H27vEbXk7sqG8QISmYaUN/UcPOYYDAK0wtnXRG3ySb93mG//vri1zS2hZvYHbBv0Tz8sLpZRCq4/v99A==} engines: {node: '>=20'} + posthog-node@5.8.1: + resolution: {integrity: sha512-YJYlYnlpItVjHqM9IhvZx8TzK8gnx2nU+0uhiog4RN47NnV0Z0K1AdC4ul+O8VuvS/jHqKCQvL8iAONRA37+0A==} + engines: {node: '>=20'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -11339,6 +11346,8 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@posthog/core@1.0.2': {} + '@prettier/sync@0.6.1(prettier@3.4.2)': dependencies: make-synchronized: 0.8.0 @@ -16853,6 +16862,10 @@ snapshots: posthog-node@5.5.1: {} + posthog-node@5.8.1: + dependencies: + '@posthog/core': 1.0.2 + prelude-ls@1.2.1: {} prettier@2.8.8: {}