create-svc 0.1.65 → 0.1.67
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
package/src/scaffold.test.ts
CHANGED
|
@@ -194,6 +194,8 @@ test("scaffolds all runtime/framework variants with shared cloudrun config", asy
|
|
|
194
194
|
expect(goMod).toContain("connectrpc.com/connect");
|
|
195
195
|
expect(mainGo).toContain("NewWaitlistService");
|
|
196
196
|
expect(mainGo).toContain("WaitlistServiceName");
|
|
197
|
+
const bufConfig = await Bun.file(join(generatedRoot, "buf.yaml")).text();
|
|
198
|
+
expect(bufConfig).toContain("name: buf.build/anmho/dns-api");
|
|
197
199
|
} else {
|
|
198
200
|
expect(goMod).not.toContain("connectrpc.com/connect");
|
|
199
201
|
expect(mainGo).toContain("NewWaitlistService");
|
|
@@ -325,6 +327,9 @@ test("scaffolds a backend package cleanly into a nested monorepo-style directory
|
|
|
325
327
|
expect(readme).toContain("GCP_DEPLOYER_SERVICE_ACCOUNT");
|
|
326
328
|
expect(readme).toContain("NEON_API_KEY");
|
|
327
329
|
expect(readme).toContain("CLOUDFLARE_API_TOKEN");
|
|
330
|
+
expect(readme).toContain("ConnectRPC service builds import the generated bindings checked into this repo");
|
|
331
|
+
expect(readme).toContain("does not rewrite this");
|
|
332
|
+
expect(readme).toContain("service's Go imports away from local generated packages");
|
|
328
333
|
|
|
329
334
|
const packageJson = await Bun.file(join(generatedRoot, "package.json")).text();
|
|
330
335
|
expect(packageJson).toContain('"hono"');
|
|
@@ -350,7 +350,8 @@ async function runSdk(args: string[]) {
|
|
|
350
350
|
if (subcommand === "publish") {
|
|
351
351
|
requireCommand("buf");
|
|
352
352
|
run("buf", ["push"]);
|
|
353
|
-
|
|
353
|
+
await writeSdkMode("remote");
|
|
354
|
+
return "Schema pushed to Buf Schema Registry and recorded for consumers";
|
|
354
355
|
}
|
|
355
356
|
|
|
356
357
|
if (subcommand === "build") {
|
|
@@ -360,18 +361,18 @@ async function runSdk(args: string[]) {
|
|
|
360
361
|
run("make", ["gen"]);
|
|
361
362
|
}
|
|
362
363
|
await writeSdkMode("local");
|
|
363
|
-
return "Local SDK artifacts generated and
|
|
364
|
+
return "Local SDK artifacts generated and recorded";
|
|
364
365
|
}
|
|
365
366
|
|
|
366
367
|
if (subcommand === "use-local") {
|
|
367
368
|
await assertLocalSdkArtifacts();
|
|
368
369
|
await writeSdkMode("local");
|
|
369
|
-
return "Local SDK artifacts
|
|
370
|
+
return "Local SDK artifacts recorded";
|
|
370
371
|
}
|
|
371
372
|
|
|
372
373
|
if (subcommand === "use-remote") {
|
|
373
374
|
await writeSdkMode("remote");
|
|
374
|
-
return `Remote Buf SDK
|
|
375
|
+
return `Remote Buf SDK recorded for consumers: ${bufModule()}`;
|
|
375
376
|
}
|
|
376
377
|
|
|
377
378
|
throw new Error("Usage: service sdk <build|publish|use-local|use-remote>");
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { chmod, mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { scaffoldProject, type ScaffoldConfig } from "../../scaffold";
|
|
6
|
+
|
|
7
|
+
function baseConfig(directory: string): ScaffoldConfig {
|
|
8
|
+
return {
|
|
9
|
+
directory,
|
|
10
|
+
serviceName: "sdk-proof",
|
|
11
|
+
modulePath: "github.com/anmho/sdk-proof",
|
|
12
|
+
target: "cloudrun",
|
|
13
|
+
runtime: "go",
|
|
14
|
+
framework: "connectrpc",
|
|
15
|
+
region: "us-west1",
|
|
16
|
+
gcpProjectMode: "use_existing",
|
|
17
|
+
gcpProject: "anmho-services",
|
|
18
|
+
gcpProjectName: "services",
|
|
19
|
+
billingAccount: "",
|
|
20
|
+
quotaProjectId: "anmho-infra-prod",
|
|
21
|
+
profile: "microservice",
|
|
22
|
+
git: {
|
|
23
|
+
enabled: false,
|
|
24
|
+
owner: "anmho",
|
|
25
|
+
repository: "sdk-proof",
|
|
26
|
+
},
|
|
27
|
+
neonDatabaseName: "sdk_proof",
|
|
28
|
+
apiHostname: "api.sdk-proof.anmho.com",
|
|
29
|
+
generatorRoot: join(import.meta.dir, "..", "..", ".."),
|
|
30
|
+
autoDeploy: false,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
test("service sdk publish pushes the named Buf module and selects remote SDK mode", async () => {
|
|
35
|
+
const root = await mkdtemp(join(tmpdir(), "create-svc-sdk-"));
|
|
36
|
+
const generatedRoot = join(root, "sdk-proof");
|
|
37
|
+
const fakeBin = join(root, "bin");
|
|
38
|
+
const bufLog = join(root, "buf.log");
|
|
39
|
+
|
|
40
|
+
await scaffoldProject(baseConfig(generatedRoot));
|
|
41
|
+
await mkdir(join(generatedRoot, "node_modules"));
|
|
42
|
+
await mkdir(fakeBin);
|
|
43
|
+
await writeFile(
|
|
44
|
+
join(fakeBin, "buf"),
|
|
45
|
+
["#!/bin/sh", `echo "$@" > "${bufLog}"`, "exit 0", ""].join("\n")
|
|
46
|
+
);
|
|
47
|
+
await chmod(join(fakeBin, "buf"), 0o755);
|
|
48
|
+
|
|
49
|
+
const result = Bun.spawnSync(["bun", join(import.meta.dir, "..", "..", "..", "index.ts"), "sdk", "publish"], {
|
|
50
|
+
cwd: generatedRoot,
|
|
51
|
+
env: { ...process.env, PATH: `${fakeBin}:${process.env.PATH ?? ""}` },
|
|
52
|
+
stdout: "pipe",
|
|
53
|
+
stderr: "pipe",
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(result.success, [result.stdout.toString(), result.stderr.toString()].join("\n")).toBeTrue();
|
|
57
|
+
expect(result.stdout.toString()).toContain("recorded for consumers");
|
|
58
|
+
expect((await readFile(bufLog, "utf8")).trim()).toBe("push");
|
|
59
|
+
const sdkState = JSON.parse(await Bun.file(join(generatedRoot, ".service", "sdk.json")).text());
|
|
60
|
+
expect(sdkState).toMatchObject({
|
|
61
|
+
mode: "remote",
|
|
62
|
+
module: "buf.build/anmho/sdk-proof",
|
|
63
|
+
localPath: "./gen/waitlist/v1",
|
|
64
|
+
});
|
|
65
|
+
const bufConfig = await Bun.file(join(generatedRoot, "buf.yaml")).text();
|
|
66
|
+
expect(bufConfig).toContain("name: buf.build/anmho/sdk-proof");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("service sdk publish leaves local SDK mode when Buf push fails", async () => {
|
|
70
|
+
const root = await mkdtemp(join(tmpdir(), "create-svc-sdk-"));
|
|
71
|
+
const generatedRoot = join(root, "sdk-proof");
|
|
72
|
+
const fakeBin = join(root, "bin");
|
|
73
|
+
|
|
74
|
+
await scaffoldProject(baseConfig(generatedRoot));
|
|
75
|
+
await mkdir(join(generatedRoot, "node_modules"));
|
|
76
|
+
await mkdir(fakeBin);
|
|
77
|
+
await mkdir(join(generatedRoot, ".service"));
|
|
78
|
+
await Bun.write(
|
|
79
|
+
join(generatedRoot, ".service", "sdk.json"),
|
|
80
|
+
`${JSON.stringify(
|
|
81
|
+
{
|
|
82
|
+
mode: "local",
|
|
83
|
+
module: "buf.build/anmho/sdk-proof",
|
|
84
|
+
localPath: "./gen/waitlist/v1",
|
|
85
|
+
updatedAt: "2026-05-25T00:00:00.000Z",
|
|
86
|
+
},
|
|
87
|
+
null,
|
|
88
|
+
2
|
|
89
|
+
)}\n`
|
|
90
|
+
);
|
|
91
|
+
await writeFile(join(fakeBin, "buf"), ["#!/bin/sh", "echo denied >&2", "exit 1", ""].join("\n"));
|
|
92
|
+
await chmod(join(fakeBin, "buf"), 0o755);
|
|
93
|
+
|
|
94
|
+
const before = JSON.parse(await Bun.file(join(generatedRoot, ".service", "sdk.json")).text());
|
|
95
|
+
expect(before.mode).toBe("local");
|
|
96
|
+
|
|
97
|
+
const result = Bun.spawnSync(["bun", join(import.meta.dir, "..", "..", "..", "index.ts"), "sdk", "publish"], {
|
|
98
|
+
cwd: generatedRoot,
|
|
99
|
+
env: { ...process.env, PATH: `${fakeBin}:${process.env.PATH ?? ""}` },
|
|
100
|
+
stdout: "pipe",
|
|
101
|
+
stderr: "pipe",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(result.success).toBeFalse();
|
|
105
|
+
const after = JSON.parse(await Bun.file(join(generatedRoot, ".service", "sdk.json")).text());
|
|
106
|
+
expect(after.mode).toBe("local");
|
|
107
|
+
});
|
|
@@ -258,6 +258,18 @@ secrets only when you add a provider adapter. A generic adapter can honor:
|
|
|
258
258
|
|
|
259
259
|
- `WEBHOOK_<PROVIDER>_SECRET`
|
|
260
260
|
|
|
261
|
+
## ConnectRPC SDK publishing
|
|
262
|
+
|
|
263
|
+
ConnectRPC service builds import the generated bindings checked into this repo
|
|
264
|
+
under `gen/`. That keeps the API and worker images self-contained and does not
|
|
265
|
+
change when SDK metadata changes.
|
|
266
|
+
|
|
267
|
+
Use `service sdk build` after editing protobufs to regenerate local
|
|
268
|
+
bindings for this service. Use `service sdk publish` to push the
|
|
269
|
+
schema to the Buf Schema Registry for external consumers. A successful publish
|
|
270
|
+
records the remote module in `.service/sdk.json`; it does not rewrite this
|
|
271
|
+
service's Go imports away from local generated packages.
|
|
272
|
+
|
|
261
273
|
## GitHub Actions deployment
|
|
262
274
|
|
|
263
275
|
The scaffold emits a minimal deployment workflow slice for Cloud Run:
|