diff --git a/.changeset/local-auth-compose-entrypoint.md b/.changeset/local-auth-compose-entrypoint.md new file mode 100644 index 0000000..0579111 --- /dev/null +++ b/.changeset/local-auth-compose-entrypoint.md @@ -0,0 +1,5 @@ +--- +"seamless-cli": patch +--- + +`seamless init --auth=local` now produces an auth service that starts. The generated compose bind-mounts `./auth` over `/app`, which hid the image's `chmod +x ./validateEnvs.sh` (the script is mode 644 in the clone) and left the entrypoint looking for a `dist/server.js` that `Dockerfile.dev` never builds. The auth service now runs the same command as the auth server's own `docker-compose.dev.yml`: sync dependencies, run migrations (creating the database on first boot), then watch the TypeScript sources. diff --git a/src/generators/docker/docker.test.ts b/src/generators/docker/docker.test.ts index d5ef1db..e02521c 100644 --- a/src/generators/docker/docker.test.ts +++ b/src/generators/docker/docker.test.ts @@ -458,6 +458,21 @@ describe("generateDockerCompose output shape", () => { expect(compose).toMatch(/\nvolumes:\n pgdata:\n auth-keys:\n$/); }); + // A clone leaves validateEnvs.sh at mode 644 and has no dist/, and the bind + // mount hides whatever the image did about either, so the image entrypoint + // fails with "permission denied" and then MODULE_NOT_FOUND. + it("runs the source-built auth server without the image entrypoint", async () => { + const compose = await render("local", "api", false); + const auth = compose.slice(compose.indexOf("\n auth:"), compose.indexOf("\n api:")); + + expect(auth).toContain('entrypoint: ["/bin/sh", "-c"]'); + expect(auth).toContain("sh ./syncDevDeps.sh &&"); + expect(auth).toContain("npm run migrate:up || (npm run db:create && npm run migrate:up)"); + expect(auth).toContain("npm run dev:container"); + expect(auth).not.toContain("validateEnvs.sh &&"); + expect(auth).not.toContain("dist/server.js"); + }); + // The local auth server bind-mounts ./auth over /app, so its keys already // land on the host and a named volume would only shadow them. it("declares no key volume for the source-built auth server", async () => { diff --git a/src/generators/docker/docker.ts b/src/generators/docker/docker.ts index 9970169..de20c51 100644 --- a/src/generators/docker/docker.ts +++ b/src/generators/docker/docker.ts @@ -145,6 +145,16 @@ async function authService( dockerfile: Dockerfile.dev ports: - "127.0.0.1:5312:5312" + # The bind mount hides the image's chmod of validateEnvs.sh, and Dockerfile.dev + # builds no dist/, so its entrypoint cannot run here. This mirrors the auth + # server's own docker-compose.dev.yml: sync dependencies, migrate (creating the + # database on first boot), then watch the TypeScript sources. + entrypoint: ["/bin/sh", "-c"] + command: + - > + sh ./syncDevDeps.sh && + (npm run migrate:up || (npm run db:create && npm run migrate:up)) && + npm run dev:container env_file: - ./auth/.env environment: