Repository navigation
Conversation
This was referenced Oct 16, 2026
ditadi
force-pushed
the
stack/database-dev-flow/05-db-init
branch
from
October 19, 2026 20:35
960b211 to
c56de21
Compare
`appkit db init` gives a checkout its own Lakebase branch, forked from the project's default branch: your dev branch, or with --session a branch for this checkout that expires after 7 days (or --ttl). It asks nothing. It refuses the default branch, protected branches and branches databricks.yml deploys to before any change, and when the project is at its branch limit it lists your branches to delete. It makes sure the branch has a read-write endpoint that suspends after 5 idle minutes and a Postgres role for you, points .env at it with an atomic 0600 write, hands you the app schema when the fork copied it owned by another Lakebase role, installs drizzle-kit when the app lacks it, then starts the schema by migrating, introspecting or cleaning. `appkit db clean` drops the app schema (only your objects in public) and lists what outside it went along; --delete-branch deletes this checkout's session branch instead. `appkit db seed` runs config/database/seed.sql in one transaction with the app schema on the search_path. Both run only on a branch created for you or this checkout. Signed-off-by: ditadi <victordperd@gmail.com>
ditadi
force-pushed
the
stack/database-dev-flow/05-db-init
branch
from
October 20, 2026 12:22
c56de21 to
98ef27b
Compare
Contributor
🤖 AppKit PR bot🔬 Run evalsStart an eval for this PR from the evals-monitor app: Go to Evals Monitor → 📦 Try this PR's app templateScaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh run download 41109404809 -R databricks/appkit -n appkit-template-0.89.0-pr.aa5285d-stack-database-dev-flow-05-db-init-672 -D appkit-pr-672 \
&& unzip -o "appkit-pr-672/appkit-template-0.89.0-pr.aa5285d-stack-database-dev-flow-05-db-init-672.zip" -d "appkit-pr-672" \
&& databricks apps init --template "appkit-pr-672"The template pins |
This was referenced Oct 20, 2026
Contributor
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 1.4 MB (+78 B) | 515 KB (+4 B) |
| Type declarations | 478 KB | 175 KB (+2 B) |
| Source maps | 2.8 MB (+317 B) | 958 KB (+88 B) |
| Other | 11 KB | 3.7 KB |
| Total | 4.7 MB (+395 B) | 1.6 MB (+94 B) |
Per-entry composition (own code — deps external (as shipped))
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
. |
106 KB | 2.5 KB | 108 KB | external | 343 KB |
./beta |
108 KB | 485 B | 108 KB | external | 323 KB |
./beta/database-tooling |
45 KB (+16 B) | 0 B | 45 KB (+16 B) | external | 134 KB (+50 B) |
./testing |
45 KB | 32 KB | 77 KB | external | 223 KB |
./tsdown |
520 B | 0 B | 520 B | external | 813 B |
./type-generator |
26 KB | 0 B | 26 KB | external | 74 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
. |
index.js |
initial | 101 KB |
. |
utils.js |
initial | 4.6 KB |
. |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./beta |
beta.js |
initial | 88 KB |
./beta |
modular.js |
initial | 6.0 KB |
./beta |
stream-manager.js |
initial | 5.9 KB |
./beta |
service-context.js |
initial | 4.2 KB |
./beta |
databricks.js |
initial | 3.3 KB |
./beta |
client.js |
initial | 647 B |
./beta |
index.js |
initial | 20 B |
./beta |
supervisor-api.js |
lazy | 192 B |
./beta |
databricks.js |
lazy | 178 B |
./beta |
index.js |
lazy | 115 B |
./beta/database-tooling |
index.js |
initial | 45 KB |
./testing |
manifest.js |
initial | 32 KB |
./testing |
index.js |
initial | 10 KB |
./testing |
wide-event-emitter.js |
initial | 2.9 KB |
./testing |
index.js |
lazy | 28 KB |
./testing |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./testing |
utils.js |
lazy | 1.8 KB |
./tsdown |
index.js |
initial | 520 B |
./type-generator |
index.js |
initial | 26 KB |
@databricks/appkit-ui
npm tarball (packed): 397 KB (+4 B) — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 429 KB | 147 KB |
| Type declarations | 267 KB | 98 KB (+1 B) |
| Source maps | 853 KB | 286 KB |
| CSS | 16 KB | 3.2 KB |
| Total | 1.5 MB | 534 KB (+1 B) |
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
./js |
5.3 KB | 49 KB | 55 KB | 208 KB | 14 KB |
./js/beta |
2.1 KB | 0 B | 2.1 KB | 0 B | 5.0 KB |
./react |
433 KB | 49 KB | 481 KB | 1.3 MB | 177 KB |
./react/beta |
4.9 KB | 0 B | 4.9 KB | 0 B | 12 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
./js |
index.js |
initial | 5.2 KB |
./js |
chunk |
initial | 120 B |
./js |
apache-arrow |
lazy | 49 KB |
./js/beta |
beta.js |
initial | 2.1 KB |
./react |
index.js |
initial | 431 KB |
./react |
tslib |
initial | 2.1 KB |
./react |
apache-arrow |
lazy | 49 KB |
./react/beta |
beta.js |
initial | 4.9 KB |
Signed-off-by: ditadi <victordperd@gmail.com> # Conflicts: # packages/appkit/src/database/tooling/migrate.ts # packages/appkit/src/database/tooling/naming.ts # packages/appkit/src/database/tooling/tests/guard.test.ts # packages/appkit/src/database/tooling/tests/naming.test.ts # packages/appkit/src/database/tooling/tests/targets.test.ts
init still checked its planned branch against the readDeployBranches list that the deploy boundary replaced. It now asks deployRefusal, like every other guard, so a binding the checkout's files cannot resolve refuses init before any API call or .env write. readDeployTarget reads the default target from the same bundle model: its first resolved app binding, else its postgres_branch and postgres_database variables. The shared CLI test mocks the beta tooling path. Signed-off-by: ditadi <victordperd@gmail.com>
Signed-off-by: ditadi <victordperd@gmail.com>
clean drops the branch's migration journal, and init runs clean, migrate or introspect after its own checks, so another appkit db command could run in between. runClean now holds the checkout's history lock, and init holds one lock for its whole run and hands it to cleanHolding, migrateHolding and introspectHolding. init --schema none changes no history, so it takes no lock and creates no config/database. Signed-off-by: ditadi <victordperd@gmail.com>
init --schema none still handed the app schema to the developer, which deletes the branch copy of the role that owns it, in apps that may have no database schema contract at all. It now leaves the schema and its owner as the fork copied them. Schema public is never handed off either: it belongs to the database (pg_database_owner on PostgreSQL 15 and later, the bootstrap superuser before), so AppKit never deletes its owner or reassigns its objects. Signed-off-by: ditadi <victordperd@gmail.com>
Regenerated with pnpm clean && pnpm build && pnpm size:baseline. Against the previous baseline the @databricks/appkit packed tarball grows from 1364290 to 1448119 bytes (+83829, +6.14%), over the 5% budget. The growth is the CLI-only @databricks/appkit/beta/database-tooling entry (45 KB gzipped, from 28 KB) with the introspect fixes and init, clean and history lock code it ships. @databricks/appkit-ui is unchanged at 406741 bytes. Signed-off-by: ditadi <victordperd@gmail.com>
The re-run test ran with --schema none, which skips the hand-off, so no test reached the check that keeps init from deleting your own role. It now runs the default migrate start and asserts that the owner query ran for schema app and no role was deleted. Signed-off-by: ditadi <victordperd@gmail.com>
init --schema none hands off no schema and starts none, but it still loaded schema.ts for the schema name, so a half-edited file stopped a branch-only init. It now loads schema.ts only when the hand-off and the start use it. Signed-off-by: ditadi <victordperd@gmail.com>
…e lock withHistoryLock creates config/database for its lock file, and init and clean checked for schema.ts only after taking it, so a refused init or clean left an empty config/database behind. Both now check first, as runMigrate does. Signed-off-by: ditadi <victordperd@gmail.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🥞 Stacked PR (generated by Stack)
Use this link to review incremental changes.
Stacked on #670. The design is #677.
What did you change, and why?
Each checkout needs its own Lakebase branch for local development, set up without prompts so an agent or a script can run it. This PR adds
appkit db init,appkit db cleanandappkit db seed.appkit db inituses yourdev-<you>-<hash>branch, or with--sessionasession-<user hash>-<id>branch that expires after 7 days (--ttlchanges that). It forks a new branch from the project's default branch. It makes sure the branch has a read-write endpoint that suspends after 5 idle minutes and your Postgres role withDATABRICKS_SUPERUSER, and points.envat the branch. It hands you the app schema when the fork copied it owned by another Lakebase role, such as the app's service principal.Then init starts the schema. The default is migrate with
schema.tsand introspect without it, and--schema cleanand--schema noneare the other starts. When migrate or introspect needs drizzle-kit and the app lacks it, init installs the pinned version first. init refuses the project's default branch, protected branches and any branch the deploy boundary covers, before it changes anything.cleandrops the app schema, migration journal included, in one transaction. Onpublicit drops only what your role owns.clean --delete-branchdeletes this checkout's session branch.seedrunsconfig/database/seed.sqlin one transaction.cleanandseedrun only on your dev or session branch..envis written with mode 0600 through a temporary file, and a symlinked.envis refused.This revision changes these behaviors:
databricks.ymlreference the checkout's files cannot resolve refuses init before any API call or.envwrite.cleanholds the lock too.clean, and init with--schema migrateor--schema clean, refuse a missingschema.tsbefore taking the lock, so a refused run leaves no emptyconfig/database.init --schema nonereads noschema.ts, takes no lock, and hands off nothing. The schema and its owner stay as the fork copied them.publicis never handed off. It belongs to the database, so AppKit never deletes its owner or reassigns its objects.bundle-size-baseline.jsonis regenerated. The packed tarball grows from 1,364,290 to 1,448,119 bytes (+6.14%), over the 5% budget, because./beta/database-toolinggrows from 28 KB to 45 KB gzipped.Session branch names carry a hash of your user name (#666). init treats
.envas this checkout's session branch only when the name matches your hash, so a.envcopied from another developer never leads init to their branch.appkit dbstays hidden fromappkit --help.How do you know it works?
init.test.tsrunsrunInitagainst an in-memory Lakebase. It covers branch creation and reuse, session TTLs, a 403, a 409, the branch limit, and deploy-target and unresolved refusals before any API call. It also covers the hand-off and its failures,--schema none,public, and one lock across init's clean and migrate.env-file.test.ts,clean-seed.test.tsand the CLI'sinit-clean-seed.test.tscover the.envwriter, the clean and seed refusals, the confirmations and the exit codes.clean.pg.test.tsandhand-off.pg.test.tsrun against Postgres. They check what CASCADE takes outside the app schema, apublicclean, and the objects and grants that block a role delete.dbtests passed against a local PostgreSQL 14, typecheck passed, and a clean build matched the new size baseline. The full vitest suite passed at an earlier revision of this PR and at the top of the stack (feat(appkit): add appkit db check #678). The packed tarballs export the same root and./betanames as main, and./beta/database-toolingadds only init, clean, seed and session-branch deletion. CI runs the full suite on this PR.publicon a real Lakebase branch was not observed.