create-svc 0.1.81 → 0.1.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-svc",
3
- "version": "0.1.81",
3
+ "version": "0.1.82",
4
4
  "description": "Local microservice bootstrap CLI for Cloud Run and Workers services with Neon-backed data.",
5
5
  "module": "index.ts",
6
6
  "type": "module",
@@ -110,3 +110,7 @@ export function migrationCommandForRuntime(runtime: string): RuntimeMigrationCom
110
110
 
111
111
  throw new Error(`migrate is not available for ${runtime}`);
112
112
  }
113
+
114
+ export function cloudRunServiceNamesForDestroy(serviceName: string) {
115
+ return [serviceName, `${serviceName}-worker`];
116
+ }
@@ -24,7 +24,7 @@ import {
24
24
  writeRenderedManifest,
25
25
  writeRenderedWorkerManifest,
26
26
  } from "./lib";
27
- import { migrationCommandForRuntime } from "./deploy-args";
27
+ import { cloudRunServiceNamesForDestroy, migrationCommandForRuntime } from "./deploy-args";
28
28
 
29
29
  type DeployOptions = {
30
30
  bootstrapResult?: BootstrapResult;
@@ -49,7 +49,9 @@ export async function deploy(args = Bun.argv.slice(2), deployOptions: DeployOpti
49
49
  throw new Error("Refusing to destroy the main environment");
50
50
  }
51
51
 
52
- await runStep(`Deleting Cloud Run service ${target.serviceName}`, () => deleteService(target.serviceName));
52
+ for (const serviceName of cloudRunServiceNamesForDestroy(target.serviceName)) {
53
+ await runStep(`Deleting Cloud Run service ${serviceName}`, () => deleteService(serviceName));
54
+ }
53
55
  await runStep(`Deleting Neon branch ${target.branchName}`, async () => {
54
56
  const branches = await listBranches(neon.projectId);
55
57
  const branch = branches.find((candidate: { name: string }) => candidate.name === target.branchName);
@@ -1,5 +1,5 @@
1
1
  import { afterEach, expect, test } from "bun:test";
2
- import { localDockerBuildArgs, migrationCommandForRuntime, parseDeployArgs } from "./deploy-args";
2
+ import { cloudRunServiceNamesForDestroy, localDockerBuildArgs, migrationCommandForRuntime, parseDeployArgs } from "./deploy-args";
3
3
 
4
4
  const originalBuild = process.env.SERVICE_BUILD;
5
5
  const originalBuildStrategy = process.env.SERVICE_BUILD_STRATEGY;
@@ -49,3 +49,7 @@ test("migrationCommandForRuntime uses generated migration tooling", () => {
49
49
  args: ["migrate", "apply", "--env", "local"],
50
50
  });
51
51
  });
52
+
53
+ test("cloudRunServiceNamesForDestroy includes api and worker services", () => {
54
+ expect(cloudRunServiceNamesForDestroy("omnichannel-pr-6")).toEqual(["omnichannel-pr-6", "omnichannel-pr-6-worker"]);
55
+ });
@@ -56,6 +56,7 @@ describe("local dev cleanup", () => {
56
56
 
57
57
  try {
58
58
  await waitForServer(port);
59
+ await waitForServiceOwnedListener(root, port, child.pid);
59
60
 
60
61
  const result = await stopLocalDev({ root, dockerCompose: false, ports: [port] });
61
62
 
@@ -115,6 +116,18 @@ async function waitForListenerStop(port: number, pid: number) {
115
116
  throw new Error(`process ${pid} on port ${port} did not stop listening`);
116
117
  }
117
118
 
119
+ async function waitForServiceOwnedListener(root: string, port: number, pid: number) {
120
+ const deadline = Date.now() + 5_000;
121
+ while (Date.now() < deadline) {
122
+ const plan = await buildLocalDevCleanupPlan({ root, dockerCompose: false, ports: [port] });
123
+ if (plan.portProcesses.some((process) => process.pid === pid && process.port === port)) {
124
+ return;
125
+ }
126
+ await Bun.sleep(50);
127
+ }
128
+ throw new Error(`process ${pid} on port ${port} was not detected as service-owned`);
129
+ }
130
+
118
131
  async function isReachable(port: number) {
119
132
  try {
120
133
  const response = await fetch(`http://127.0.0.1:${port}`, { signal: AbortSignal.timeout(250) });