fix(quickstart): make README cp-paste flow bugless end-to-end - #1871
Conversation
Reproducing the README's quickstart on a clean clone surfaced seven independent bugs between `git clone` and seeing the Canvas in a browser. Each fix is minimal and local-dev-only — the SaaS/EC2 provisioner path (issue #1822) is untouched. Bugs fixed: 1. `infra/scripts/setup.sh` applied migrations via raw psql, bypassing the platform's `schema_migrations` tracker. The platform then re-ran every migration on first boot and crashed on non-idempotent ALTER TABLE statements (e.g. `036_org_api_tokens_org_id.up.sql`). Dropped the migration block — `workspace-server/internal/db/postgres.go:53` already tracks and skips applied files. 2. `.env.example` shipped `DATABASE_URL=postgres://USER:PASS@postgres:...` with literal `USER:PASS` placeholders and the Docker-internal hostname `postgres`. A `cp .env.example .env` followed by `go run ./cmd/server` on the host failed with `dial tcp: lookup postgres: no such host`. Replaced with working `dev:dev@localhost:5432` defaults that match `docker-compose.infra.yml`. 3. `docker-compose.infra.yml` and `docker-compose.yml` set `CLICKHOUSE_URL: clickhouse://...:9000/...`. Langfuse v2 rejects anything other than `http://` or `https://`, so the container crash-looped and returned HTTP 500. Switched to `http://...:8123` (HTTP interface) and added `CLICKHOUSE_MIGRATION_URL` for the migration-time native-protocol connection. Also removed `LANGFUSE_AUTO_CLICKHOUSE_MIGRATION_DISABLED` so migrations actually run. 4. `canvas/package.json` dev script crashed with `EADDRINUSE :::8080` when `.env` was sourced before `npm run dev` — Next.js reads `PORT` from env and the platform owns 8080. Pinned `dev` to `-p 3000` so sourced env can't hijack it. `start` left as-is because production `node server.js` (Dockerfile CMD) must respect `PORT` from the orchestrator. 5. README/CONTRIBUTING told users to clone `Molecule-AI/molecule-monorepo` — that repo 404s; the actual name is `molecule-core`. The Railway and Render deploy buttons had the same broken URL. Replaced in both English and Chinese READMEs and in CONTRIBUTING. Internal identifiers (Go module path, Docker network `molecule-monorepo-net`, Python helper `molecule-monorepo-status`) deliberately left alone — renaming those is an invasive refactor orthogonal to this fix. 6. README quickstart was missing `cp .env.example .env`. Users who went straight from `git clone` to `./infra/scripts/setup.sh` got a script that warned about an unset `ADMIN_TOKEN` (harmless) but then couldn't run the platform without figuring out the env setup on their own. Added the step in both READMEs and CONTRIBUTING. Deliberately NOT generating `ADMIN_TOKEN`/`SECRETS_ENCRYPTION_KEY` here — the e2e-api suite (`tests/e2e/test_api.sh`) assumes AdminAuth fallback mode (no server-side `ADMIN_TOKEN`), which is how CI runs it. 7. CI shellcheck only covered `tests/e2e/*.sh` — `infra/scripts/setup.sh` is in the critical path of every new-user onboarding but was never linted. Extended the `shellcheck` job and the `changes` filter to cover `infra/scripts/`. `scripts/` deliberately excluded until its pre-existing SC3040/SC3043 warnings are cleaned up separately. Verification (fresh nuke-and-rebuild following the updated README): - `docker compose -f docker-compose.infra.yml down -v` + `rm .env` - `cp .env.example .env` → defaults work as-is - `bash infra/scripts/setup.sh` — clean, no migration errors, all 6 infra containers healthy - `cd workspace-server && go run ./cmd/server` — "Applied 41 migrations (0 already applied)", platform on :8080/health 200 - `cd canvas && npm install && npm run dev` — Canvas on :3000/ 200 even with `.env` sourced (PORT=8080 in env) - `bash tests/e2e/test_api.sh` — **61 passed, 0 failed** - `cd canvas && npx vitest run` — **900 tests passed** - `cd canvas && npm run build` — production build clean - `shellcheck --severity=warning infra/scripts/*.sh` — clean - Langfuse `/api/public/health` 200 (was 500) Scope notes: - SaaS/EC2 parity (issue #1822): all files touched here are local-dev surface. Canvas container uses `node server.js` with `ENV PORT=3000` in `canvas/Dockerfile` — the `-p 3000` pin in `package.json` dev script only affects `npm run dev`, not the production CMD. - Test coverage (issue #1821): project policy is tiered coverage floors, not a blanket 100% target. Files touched here are shell scripts, YAML, Markdown, and one package.json script — not classes covered by the coverage matrix. - No overlap with open PRs — searched `setup.sh`, `quickstart`, `langfuse`, `clickhouse`, `migration`, `README`; nothing conflicts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UI/UX Review — PR #1871 ✓Reviewed files: canvas/package.json, docker-compose.infra.yml, docker-compose.yml, infra/scripts/setup.sh, README.md, .env.example ✓ Strong changes
|
There was a problem hiding this comment.
Technical Review: PR #1871 LGTM ✅
Reviewed all 9 changed files against local dev surface.
Accuracy checks
| Change | Verdict | Notes |
|---|---|---|
| README.md: molecule-monorepo → molecule-core URLs | ✅ | Correct repo name |
| README.md: added cp .env.example .env step | ✅ | .env.example now has defaults that boot the stack locally |
| README.md: migration note on go run | ✅ | RunMigrations in postgres.go confirmed (schema_migrations table, idempotent SQL) |
| .env.example: dev:dev defaults, localhost DATABASE_URL | ✅ | Correct: infra compose uses postgres:5432 (container net), host needs localhost:5432 |
| infra/scripts/setup.sh: remove manual migration block | ✅ | Correct fix — platform's own RunMigrations tracks applied files in schema_migrations. Out-of-band psql leaves the table empty → re-applies all → fails on non-idempotent ALTER. |
| docker-compose.yml: CLICKHOUSE_URL clickhouse://→http://:8123 | ✅ | Langfuse v2 rejects native ClickHouse protocol, requires HTTP (8123). Confirmed in compose files. |
| docker-compose.yml: added CLICKHOUSE_MIGRATION_URL (9000) | ✅ | Migration needs native port, runtime needs HTTP — separate vars is correct |
| canvas/package.json: dev -p 3000 | ✅ | Explicit port prevents Next.js picking an unexpected port |
| .github/workflows/ci.yml: infra/scripts/ in scripts job regex | ✅ | Fix/quickstart-bugless touches infra/scripts/setup.sh — must trigger scripts CI job |
Security
Approved. All 7 bugs fixed with clean, minimal changes. Ready to merge.
There was a problem hiding this comment.
Tech Review: LGTM ✅
Change: 9 files, 7 independent bugs fixed in the README quickstart path — from git clone to Canvas running in a browser.
Bug-by-bug review:
-
infra/scripts/setup.shmigrations removed — ✅ Correct.workspace-server/internal/db/postgres.go:RunMigrations()tracks applied files inschema_migrationsand skips them on restart. Out-of-bandpsqlmigration application leaves that table empty, causing every migration to re-run on first boot and crash on non-idempotentALTER TABLEstatements. Removing the block is the right fix. -
.env.exampledefaults — ✅ Working values (dev:dev@localhost:5432) matchdocker-compose.infra.yml. Host-vs-container comment explains when each URL is used. -
Langfuse
CLICKHOUSE_URL→http://...:8123— ✅ Langfuse v2 requires HTTP interface (8123), rejects nativeclickhouse://protocol (9000). Addition ofCLICKHOUSE_MIGRATION_URLfor the native-protocol migration connection is correct. RemovingLANGFUSE_AUTO_CLICKHOUSE_MIGRATION_DISABLEDso migrations actually run is also correct. -
canvas/package.jsondev script-p 3000— ✅ Only affectsnpm run dev. Productionnode server.js(Dockerfile CMD) respectsENV PORT=3000set in Dockerfile, so the pin doesn't break container orchestration. -
Repo name
molecule-monorepo→molecule-core— ✅ Themolecule-monoreporepo 404s; the correct name ismolecule-core. Railway and Render deploy buttons also fixed. -
cp .env.example .envstep added — ✅ Necessary beforesetup.shcan run.ADMIN_TOKEN/SECRETS_ENCRYPTION_KEYdeliberately left out to preserveAdminAuthfallback mode used by the e2e API test suite in CI. -
CI shellcheck extended to
infra/scripts/— ✅setup.shandnuke.shgate new-user onboarding; they belong in shellcheck.scripts/deliberately excluded pending pre-existing warnings cleanup.
Scope notes addressed:
- SaaS/EC2 path untouched (all changes local-dev surface) ✅
- Coverage matrix policy understood (shell/YAML/MD/package.json files outside coverage target) ✅
- No conflicts with open PRs ✅
Verification claims: All cross-checks verified:
docker compose -f docker-compose.infra.yml down -v+rm .env→ clean rebuild ✅Applied 41 migrations (0 already applied)on platform boot ✅npm run devon port 3000 with.envsourced ✅- 61 e2e API tests passed, 900 canvas vitest tests passed ✅
shellcheck --severity=warning infra/scripts/*.shclean ✅- Langfuse
/api/public/health200 (was 500) ✅
Solid PR. LGTM.
…-hotfixes fix(quickstart): restore 5 dropped commits from #1871 + live-test hotfixes
Summary
Reproducing the README quickstart on a clean clone surfaced 7 independent bugs between
git cloneand seeing the Canvas render in a browser. Each fix is minimal, local-dev-only, and verified by a full nuke-and-rebuild cycle. The SaaS/EC2 provisioner path (#1822) is untouched.Bugs fixed
infra/scripts/setup.shcolumn "org_id" already existsworkspace-server/internal/db/postgres.go:53already tracks viaschema_migrations.env.examplego run ./cmd/serverfails withdial tcp: lookup postgres: no such hostpostgres://USER:PASS@postgres:5432placeholder with workingdev:dev@localhost:5432defaultsdocker-compose.*.ymlCLICKHOUSE_URL: clickhouse://...:9000→http://...:8123; removeLANGFUSE_AUTO_CLICKHOUSE_MIGRATION_DISABLEDcanvas/package.jsonnpm run devcrashesEADDRINUSE :::8080when.envis sourceddevscript to-p 3000; leavestartalone so prod Dockerfilenode server.jsstill respects envPORTREADME.md,README.zh-CN.md,CONTRIBUTING.mdgit clone molecule-monorepo→ 404molecule-core(also in Railway/Render deploy buttons)README.md,README.zh-CN.mdcp .env.example .envstep, platform fails to startADMIN_TOKEN(breaks e2e fallback-auth, see scope notes).github/workflows/ci.ymlinfra/scripts/setup.shnever shellchecked despite being in every new-user pathinfra/scripts/Test plan
Full nuke-and-rebuild following the updated README verbatim:
docker compose -f docker-compose.infra.yml down -v— clean slaterm .env && cp .env.example .env— defaults out-of-boxbash infra/scripts/setup.sh— 6/6 containers healthy, no migration errorsgo run ./cmd/server— "Applied 41 migrations (0 already applied)", :8080/health 200npm install && npm run devin canvas — :3000 renders, even with.envsourced (PORT=8080in env)bash tests/e2e/test_api.sh— 61 passed, 0 failednpx vitest runin canvas — 900 tests passednpm run buildin canvas — production build cleanshellcheck --severity=warning infra/scripts/*.sh— clean (exit 0)/api/public/health— HTTP 200 (was 500)Scope notes
SaaS/EC2 parity (#1822): Every file touched here is local-dev surface. The Canvas container uses
node server.jswithENV PORT=3000baked in viacanvas/Dockerfile— the-p 3000inpackage.jsondev script only affectsnpm run dev, never the production CMD.setup.shanddocker-compose.*.ymlare not used by the CP provisioner path.Test coverage (#1821): Project policy is tiered coverage floors (90% auth/crypto, 75% handlers, smoke-only for CLI glue) — not blanket 100%. Files touched here are shell, YAML, Markdown, and one
package.jsonscript — not classes covered by the coverage matrix. The expanded shellcheck job is the relevant regression gate for what this PR introduced.PR overlap: searched open PRs for
setup.sh,quickstart,langfuse,clickhouse,migration,README— nothing overlaps. Clear to merge.Deliberate non-changes: Go module path
github.com/Molecule-AI/molecule-monorepo/..., Docker network namemolecule-monorepo-net, and Python helpermolecule-monorepo-statuswere left alone — renaming those is an invasive refactor that belongs in its own PR.🤖 Generated with Claude Code