@rehearsal-db/core 0.1.0-rc.1 → 0.1.0-rc.2
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/CHANGELOG.md +23 -1
- package/README.md +36 -8
- package/dist/package.json +2 -2
- package/dist/src/project/configuration_contract.d.mts +1 -1
- package/dist/src/project/configuration_contract.mjs +1 -1
- package/dist/src/project/configuration_rendering.mjs +6 -4
- package/dist/src/runtime/plan.mjs +5 -2
- package/dist/src/targets/supabase.mjs +2 -0
- package/dist/src/targets/supabase_environment.d.mts +6 -1
- package/dist/src/targets/supabase_environment.mjs +25 -3
- package/docs/README.md +10 -2
- package/docs/configuration.md +14 -6
- package/docs/getting-started.md +1 -1
- package/docs/index.md +27 -8
- package/docs/runtime-lifecycle.md +99 -0
- package/docs/stability.md +5 -4
- package/docs/troubleshooting.md +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## [0.1.0-rc.2] - 2026-10-09
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Container-engine startup is now explicit by default. Rehearsal starts Colima only
|
|
13
|
+
when a project deliberately enables `containerRuntime.autoStartColima`, reports that
|
|
14
|
+
action, and never silently stops the shared engine.
|
|
15
|
+
- Package-managed Supabase containers use Docker's non-resuming restart policy after
|
|
16
|
+
each start, preventing stopped Rehearsal stacks from waking merely because Docker or
|
|
17
|
+
Colima restarts. Exact Supabase project labels keep the change inside the selected
|
|
18
|
+
disposable target.
|
|
19
|
+
- Runtime diagnostics and a new lifecycle guide explain which commands need Docker,
|
|
20
|
+
what remains running, and how to finish a low-memory local session without pruning or
|
|
21
|
+
deleting persistent data.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- A stopped Colima VM no longer restarts from a default Rehearsal configuration.
|
|
26
|
+
- Independent Test Lab acceptance now reaps exact workspace-owned interactive children
|
|
27
|
+
after success, failure, interruption, and timeout.
|
|
28
|
+
|
|
8
29
|
## [0.1.0-rc.1] - 2026-10-08
|
|
9
30
|
|
|
10
31
|
### Changed
|
|
@@ -554,7 +575,8 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
|
|
|
554
575
|
publication uses short-lived trusted OIDC, and every release tag must already exist on
|
|
555
576
|
protected `main`.
|
|
556
577
|
|
|
557
|
-
[Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-rc.
|
|
578
|
+
[Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-rc.2...HEAD
|
|
579
|
+
[0.1.0-rc.2]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-rc.1...v0.1.0-rc.2
|
|
558
580
|
[0.1.0-rc.1]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.18...v0.1.0-rc.1
|
|
559
581
|
[0.1.0-beta.18]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.17...v0.1.0-beta.18
|
|
560
582
|
[0.1.0-beta.17]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.16...v0.1.0-beta.17
|
package/README.md
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/Ddupasquier/rehearsal-db/main/docs/site/logo-mark.svg" width="104" height="104" alt="Rehearsal logo" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">Rehearsal</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center"><strong>Your migration passed on an empty database. Production will not be empty.</strong></p>
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/@rehearsal-db/core"><img alt="npm version" src="https://img.shields.io/npm/v/%40rehearsal-db%2Fcore?style=flat-square&logo=npm&logoColor=white&labelColor=1c2a34&color=287b5c" /></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/@rehearsal-db/core"><img alt="Monthly npm downloads" src="https://img.shields.io/npm/dm/%40rehearsal-db%2Fcore?style=flat-square&logo=npm&logoColor=white&label=downloads&labelColor=1c2a34&color=287b5c" /></a>
|
|
12
|
+
<a href="LICENSE"><img alt="MIT license" src="https://img.shields.io/npm/l/%40rehearsal-db%2Fcore?style=flat-square&labelColor=1c2a34&color=287b5c" /></a>
|
|
13
|
+
<a href="https://ddupasquier.github.io/rehearsal-db/"><img alt="Read the documentation" src="https://img.shields.io/badge/docs-read_the_guide-269fab?style=flat-square&labelColor=1c2a34" /></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://ddupasquier.github.io/rehearsal-db/">Read the documentation</a> ·
|
|
18
|
+
<a href="https://www.npmjs.com/package/@rehearsal-db/core">View on npm</a> ·
|
|
19
|
+
<a href="https://github.com/Ddupasquier/rehearsal-db/issues">Report a problem</a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
Most migration tests start with an empty database. Production does not.
|
|
23
|
+
|
|
24
|
+
Existing rows, relationships, authentication identities, stored files, and migration
|
|
25
|
+
history are where risky changes break. A migration can build successfully and still fail
|
|
26
|
+
against the data and application behavior you actually have.
|
|
27
|
+
|
|
28
|
+
**Rehearsal catches those problems before deployment.** It restores a reviewed,
|
|
29
|
+
sanitized baseline into a disposable local PostgreSQL or Supabase environment, applies
|
|
30
|
+
only the exact migrations you approve, and runs your application's own proof.
|
|
31
|
+
|
|
32
|
+
| An empty database cannot prove… | Rehearsal lets you verify… |
|
|
33
|
+
| ---------------------------------------------------- | ------------------------------------------------------------ |
|
|
34
|
+
| old rows still satisfy new constraints | the migration against a reviewed, production-shaped copy |
|
|
35
|
+
| relationships, identities, and stored files survive | database, Auth, and Storage behavior in one local sandbox |
|
|
36
|
+
| the application still works after the schema changes | your own tests and hands-on flows before anything is shipped |
|
|
10
37
|
|
|
11
38
|
Projects with a separate publication or read-model database can declare it as a
|
|
12
39
|
dependent target. Rehearsal then manages the complete isolated runtime stack.
|
|
@@ -17,7 +44,7 @@ it through a reviewed privacy policy, and retire the access again. It is never p
|
|
|
17
44
|
`run`, `reset`, `migrate`, or application launch. Rehearsal is not a backup system or a
|
|
18
45
|
production deployment tool.
|
|
19
46
|
|
|
20
|
-
>
|
|
47
|
+
> **Pre-1.0 safety note:** use Rehearsal on a branch and keep a working backup of your
|
|
21
48
|
> project.
|
|
22
49
|
|
|
23
50
|
## What you need
|
|
@@ -37,7 +64,7 @@ your migration is intended to change.
|
|
|
37
64
|
From your project directory:
|
|
38
65
|
|
|
39
66
|
```bash
|
|
40
|
-
npm install --save-dev @rehearsal-db/core
|
|
67
|
+
npm install --save-dev @rehearsal-db/core
|
|
41
68
|
npx rehearsal
|
|
42
69
|
```
|
|
43
70
|
|
|
@@ -145,6 +172,7 @@ Reference:
|
|
|
145
172
|
|
|
146
173
|
- [CLI commands](docs/commands.md)
|
|
147
174
|
- [Configuration](docs/configuration.md)
|
|
175
|
+
- [Container runtime lifecycle](docs/runtime-lifecycle.md) — keep Docker and Supabase use on demand
|
|
148
176
|
- [TypeScript types](docs/typescript.md)
|
|
149
177
|
- [Baselines](docs/baselines.md)
|
|
150
178
|
- [Sanitization](docs/sanitization.md)
|
package/dist/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rehearsal-db/core",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.2",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Catch PostgreSQL and Supabase migrations that pass on empty databases but fail on real data—before deploy.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/Ddupasquier/rehearsal-db.git"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const REHEARSAL_CONFIG_VERSION = 1;
|
|
3
3
|
export const REHEARSAL_DEFAULTS = Object.freeze({
|
|
4
4
|
baseline: Object.freeze({ artifactDirectory: ".rehearsal" }),
|
|
5
|
-
containerRuntime: Object.freeze({ autoStartColima:
|
|
5
|
+
containerRuntime: Object.freeze({ autoStartColima: false }),
|
|
6
6
|
cleanup: Object.freeze({ retainBaselineGenerations: 2 }),
|
|
7
7
|
runtime: Object.freeze({
|
|
8
8
|
applicationUrl: "http://localhost:5175",
|
|
@@ -61,9 +61,10 @@ export default defineRehearsalConfig({
|
|
|
61
61
|
// After setup, run: npx rehearsal identity connect
|
|
62
62
|
// identityPolicy: "infrastructure/rehearsal/identity-policy.json",
|
|
63
63
|
|
|
64
|
-
// Reuse any running Docker-compatible engine
|
|
64
|
+
// Reuse any running Docker-compatible engine. Keep startup explicit so a
|
|
65
|
+
// Rehearsal command cannot wake unrelated containers after Docker was stopped.
|
|
65
66
|
containerRuntime: {
|
|
66
|
-
autoStartColima:
|
|
67
|
+
autoStartColima: false,
|
|
67
68
|
},
|
|
68
69
|
|
|
69
70
|
// Keep this many baseline generations, always including the active one.
|
|
@@ -166,9 +167,10 @@ export default defineRehearsalConfig({
|
|
|
166
167
|
// After setup, run: npx rehearsal identity connect
|
|
167
168
|
// identityPolicy: "infrastructure/rehearsal/identity-policy.json",
|
|
168
169
|
|
|
169
|
-
// Reuse any running Docker-compatible engine
|
|
170
|
+
// Reuse any running Docker-compatible engine. Keep startup explicit so a
|
|
171
|
+
// Rehearsal command cannot wake unrelated containers after Docker was stopped.
|
|
170
172
|
containerRuntime: {
|
|
171
|
-
autoStartColima:
|
|
173
|
+
autoStartColima: false,
|
|
172
174
|
},
|
|
173
175
|
|
|
174
176
|
// Keep this many baseline generations, always including the active one.
|
|
@@ -94,6 +94,9 @@ const resultCheck = async ({ id, label, run, remediation, }) => {
|
|
|
94
94
|
}
|
|
95
95
|
};
|
|
96
96
|
const assertRuntimeConfigMatches = async ({ config, paths, }) => {
|
|
97
|
+
const startupPolicy = config.containerRuntime.autoStartColima
|
|
98
|
+
? "Colima auto-start is enabled and may wake shared Docker containers"
|
|
99
|
+
: "container-engine startup is explicit";
|
|
97
100
|
if (config.runtime.target === "postgresql") {
|
|
98
101
|
if (paths.rehearsalConfig !== null || paths.supabaseWorkdir !== null) {
|
|
99
102
|
throw new Error("The PostgreSQL target unexpectedly resolved Supabase paths.");
|
|
@@ -101,7 +104,7 @@ const assertRuntimeConfigMatches = async ({ config, paths, }) => {
|
|
|
101
104
|
if (!config.postgresql) {
|
|
102
105
|
throw new Error("The PostgreSQL target is missing its configuration.");
|
|
103
106
|
}
|
|
104
|
-
return `isolated PostgreSQL image ${config.postgresql.image} and a loopback database port are configured`;
|
|
107
|
+
return `isolated PostgreSQL image ${config.postgresql.image} and a loopback database port are configured; ${startupPolicy}`;
|
|
105
108
|
}
|
|
106
109
|
if (!paths.rehearsalConfig) {
|
|
107
110
|
throw new Error("The Supabase target is missing its runtime configuration.");
|
|
@@ -121,7 +124,7 @@ const assertRuntimeConfigMatches = async ({ config, paths, }) => {
|
|
|
121
124
|
if (/\blinked\s*=\s*true\b/iu.test(source)) {
|
|
122
125
|
throw new Error("Local Supabase config unexpectedly enables a linked target.");
|
|
123
126
|
}
|
|
124
|
-
return
|
|
127
|
+
return `isolated Supabase project and ports match the project contract; ${startupPolicy}`;
|
|
125
128
|
};
|
|
126
129
|
const assertBaselinePermissions = async ({ paths, }) => {
|
|
127
130
|
const details = await stat(paths.dataPath);
|
|
@@ -388,6 +388,7 @@ const resetRuntime = async () => {
|
|
|
388
388
|
exclude: ["edge-runtime", "logflare", "vector", "realtime"],
|
|
389
389
|
environment: serviceEnvironment,
|
|
390
390
|
autoStartColima: config.containerRuntime.autoStartColima,
|
|
391
|
+
projectId: config.runtime.projectId,
|
|
391
392
|
});
|
|
392
393
|
const structuralSchemaSha256 = await restoreProductionSchema(active);
|
|
393
394
|
await restoreBaselineRows(active);
|
|
@@ -446,6 +447,7 @@ const startRuntime = async () => {
|
|
|
446
447
|
exclude: ["edge-runtime", "logflare", "vector", "realtime"],
|
|
447
448
|
environment: serviceEnvironment,
|
|
448
449
|
autoStartColima: config.containerRuntime.autoStartColima,
|
|
450
|
+
projectId: config.runtime.projectId,
|
|
449
451
|
});
|
|
450
452
|
const projectRuntime = configureProjectRuntime({ environment, baseline });
|
|
451
453
|
await writeRuntimeEnvironment({
|
|
@@ -35,11 +35,16 @@ export declare const ensureLocalContainerRuntime: ({ cwd, autoStartColima, }?: {
|
|
|
35
35
|
cwd?: string | undefined;
|
|
36
36
|
autoStartColima?: boolean;
|
|
37
37
|
}) => void;
|
|
38
|
+
export declare const preventOwnedSupabaseAutoRestart: ({ cwd, projectId, }: {
|
|
39
|
+
cwd?: string | undefined;
|
|
40
|
+
projectId: string;
|
|
41
|
+
}) => readonly string[];
|
|
38
42
|
export declare const readLocalSupabaseEnvironment: ({ cwd, workdir, environment, }?: SupabaseCommandOptions) => LocalSupabaseEnvironment;
|
|
39
|
-
export declare const startLocalSupabase: ({ cwd, workdir, exclude, environment, applyMigrations, autoStartColima, }?: SupabaseCommandOptions & {
|
|
43
|
+
export declare const startLocalSupabase: ({ cwd, workdir, exclude, environment, applyMigrations, autoStartColima, projectId, }?: SupabaseCommandOptions & {
|
|
40
44
|
exclude?: readonly string[];
|
|
41
45
|
applyMigrations?: boolean;
|
|
42
46
|
autoStartColima?: boolean;
|
|
47
|
+
projectId?: string | undefined;
|
|
43
48
|
}) => LocalSupabaseEnvironment;
|
|
44
49
|
export declare const stopLocalSupabase: ({ cwd, workdir, environment, }?: SupabaseCommandOptions) => void;
|
|
45
50
|
export declare const removeLocalSupabaseProjectResources: ({ cwd, projectId, }?: {
|
|
@@ -90,22 +90,42 @@ export const localCommandSucceeds = (command, args, { cwd = process.cwd(), envir
|
|
|
90
90
|
env: createCleanProcessEnvironment({ overrides: environment }),
|
|
91
91
|
stdio: "ignore",
|
|
92
92
|
}).status === 0;
|
|
93
|
-
export const ensureLocalContainerRuntime = ({ cwd = process.cwd(), autoStartColima =
|
|
93
|
+
export const ensureLocalContainerRuntime = ({ cwd = process.cwd(), autoStartColima = false, } = {}) => {
|
|
94
94
|
if (localCommandSucceeds("docker", ["info"], { cwd }))
|
|
95
95
|
return;
|
|
96
96
|
if (autoStartColima && localCommandSucceeds("colima", ["version"], { cwd })) {
|
|
97
97
|
runLocalCommand("colima", ["start"], { cwd });
|
|
98
|
+
console.log("Started Colima because containerRuntime.autoStartColima is enabled. Rehearsal will not stop this shared Docker runtime automatically.");
|
|
98
99
|
}
|
|
99
100
|
if (!localCommandSucceeds("docker", ["info"], { cwd })) {
|
|
100
|
-
throw new Error(
|
|
101
|
+
throw new Error(autoStartColima
|
|
102
|
+
? "A local Docker-compatible runtime is required. Install Docker or Colima, then rerun the command."
|
|
103
|
+
: "A local Docker-compatible runtime is stopped or unavailable. Start Docker or Colima explicitly, or opt in with containerRuntime.autoStartColima: true.");
|
|
101
104
|
}
|
|
102
105
|
};
|
|
106
|
+
export const preventOwnedSupabaseAutoRestart = ({ cwd = process.cwd(), projectId, }) => {
|
|
107
|
+
if (!/^[a-z0-9][a-z0-9-]{1,62}$/u.test(projectId)) {
|
|
108
|
+
throw new Error("Refusing to change container restart policies without an exact safe Supabase project id.");
|
|
109
|
+
}
|
|
110
|
+
const label = `com.supabase.cli.project=${projectId}`;
|
|
111
|
+
const containers = runLocalCommand("docker", ["ps", "--all", "--filter", `label=${label}`, "--format", "{{.ID}}"], { capture: true, cwd })
|
|
112
|
+
.split("\n")
|
|
113
|
+
.map((value) => value.trim())
|
|
114
|
+
.filter(Boolean);
|
|
115
|
+
if (containers.length) {
|
|
116
|
+
runLocalCommand("docker", ["update", "--restart=no", ...containers], {
|
|
117
|
+
capture: true,
|
|
118
|
+
cwd,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return Object.freeze(containers);
|
|
122
|
+
};
|
|
103
123
|
const withWorkdir = (args, workdir) => (workdir ? [...args, "--workdir", workdir] : [...args]);
|
|
104
124
|
export const readLocalSupabaseEnvironment = ({ cwd, workdir, environment = {}, } = {}) => {
|
|
105
125
|
const output = runLocalCommand("supabase", withWorkdir(["status", "-o", "env"], workdir), { capture: true, cwd, environment });
|
|
106
126
|
return parseLocalSupabaseEnvironment(output);
|
|
107
127
|
};
|
|
108
|
-
export const startLocalSupabase = ({ cwd, workdir, exclude = [], environment = {}, applyMigrations = true, autoStartColima =
|
|
128
|
+
export const startLocalSupabase = ({ cwd, workdir, exclude = [], environment = {}, applyMigrations = true, autoStartColima = false, projectId, } = {}) => {
|
|
109
129
|
ensureLocalContainerRuntime({ cwd, autoStartColima });
|
|
110
130
|
const startArguments = withWorkdir(["start", ...(exclude.length ? ["--exclude", exclude.join(",")] : [])], workdir);
|
|
111
131
|
runLocalCommand("supabase", startArguments, {
|
|
@@ -113,6 +133,8 @@ export const startLocalSupabase = ({ cwd, workdir, exclude = [], environment = {
|
|
|
113
133
|
cwd,
|
|
114
134
|
environment,
|
|
115
135
|
});
|
|
136
|
+
if (projectId)
|
|
137
|
+
preventOwnedSupabaseAutoRestart({ cwd, projectId });
|
|
116
138
|
if (applyMigrations) {
|
|
117
139
|
runLocalCommand("supabase", withWorkdir(["migration", "up", "--local"], workdir), { capture: true, cwd, environment });
|
|
118
140
|
}
|
package/docs/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# Rehearsal documentation
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Most migration tests start with an empty database. Production does not. Existing rows,
|
|
4
|
+
relationships, authentication identities, stored files, and migration history are where
|
|
5
|
+
risky changes break.
|
|
6
|
+
|
|
7
|
+
Rehearsal restores a reviewed, sanitized baseline into a disposable local environment,
|
|
8
|
+
applies only the exact migrations you approve, and runs your application's own proof.
|
|
9
|
+
|
|
10
|
+
You do not need to read this documentation from top to bottom. Choose what you want to
|
|
11
|
+
accomplish and follow that path.
|
|
5
12
|
|
|
6
13
|
## Start here
|
|
7
14
|
|
|
@@ -24,6 +31,7 @@ want to accomplish and follow that path.
|
|
|
24
31
|
|
|
25
32
|
- [CLI commands](commands.md)
|
|
26
33
|
- [Configuration](configuration.md)
|
|
34
|
+
- [Container runtime lifecycle](runtime-lifecycle.md)
|
|
27
35
|
- [TypeScript](typescript.md)
|
|
28
36
|
- [Runtime and identity policies](runtime-policies.md)
|
|
29
37
|
- [Database adapters](adapters.md)
|
package/docs/configuration.md
CHANGED
|
@@ -4,7 +4,7 @@ An ordinary npm application install creates this file in the application root wh
|
|
|
4
4
|
root can be identified safely:
|
|
5
5
|
|
|
6
6
|
```bash
|
|
7
|
-
npm install --save-dev @rehearsal-db/core
|
|
7
|
+
npm install --save-dev @rehearsal-db/core
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
The install hook detects the database type, project name, migration folder,
|
|
@@ -82,7 +82,7 @@ export default defineRehearsalConfig({
|
|
|
82
82
|
// After setup, run: npx rehearsal identity connect
|
|
83
83
|
// identityPolicy: "infrastructure/rehearsal/identity-policy.json",
|
|
84
84
|
containerRuntime: {
|
|
85
|
-
autoStartColima:
|
|
85
|
+
autoStartColima: false,
|
|
86
86
|
},
|
|
87
87
|
cleanup: {
|
|
88
88
|
retainBaselineGenerations: 2,
|
|
@@ -227,7 +227,7 @@ SHA-256 receipts are tracked. See
|
|
|
227
227
|
|
|
228
228
|
```ts
|
|
229
229
|
containerRuntime: {
|
|
230
|
-
autoStartColima:
|
|
230
|
+
autoStartColima: false,
|
|
231
231
|
},
|
|
232
232
|
cleanup: {
|
|
233
233
|
retainBaselineGenerations: 2,
|
|
@@ -235,9 +235,17 @@ cleanup: {
|
|
|
235
235
|
```
|
|
236
236
|
|
|
237
237
|
Rehearsal uses whichever Docker-compatible engine already answers `docker info`. If none
|
|
238
|
-
is running and `autoStartColima` is `true`, Rehearsal may run `colima start`.
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
is running and `autoStartColima` is `true`, Rehearsal may run `colima start`. This is an
|
|
239
|
+
explicit opt-in because starting a shared Docker engine can also restart unrelated
|
|
240
|
+
containers whose restart policy is `always` or `unless-stopped`. Rehearsal respects the
|
|
241
|
+
user's Colima CPU, memory, and disk settings and never changes them. The generated default
|
|
242
|
+
is `false`: start Docker or Colima yourself before a mutating command. Rehearsal never
|
|
243
|
+
stops a shared container engine automatically.
|
|
244
|
+
|
|
245
|
+
After each Supabase start, Rehearsal changes only the exact target's containers to
|
|
246
|
+
Docker's `no` restart policy. Its database and Storage volumes remain intact,
|
|
247
|
+
`rehearsal start` can resume it, and restarting Docker does not silently wake stopped
|
|
248
|
+
Rehearsal stacks.
|
|
241
249
|
|
|
242
250
|
`retainBaselineGenerations` controls how many immutable baseline generations survive an
|
|
243
251
|
approved `rehearsal refresh` or `rehearsal cleanup`; it must be at least 1. Refresh shows
|
package/docs/getting-started.md
CHANGED
|
@@ -35,7 +35,7 @@ Rehearsal will use that image with downloads disabled.
|
|
|
35
35
|
Run these commands from the directory containing your project's `package.json`:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
npm install --save-dev @rehearsal-db/core
|
|
38
|
+
npm install --save-dev @rehearsal-db/core
|
|
39
39
|
npx rehearsal
|
|
40
40
|
```
|
|
41
41
|
|
package/docs/index.md
CHANGED
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
# Rehearsal documentation
|
|
2
2
|
|
|
3
|
+
## Why an empty database is not enough
|
|
4
|
+
|
|
5
|
+
Most migration tests start with an empty database. Production does not.
|
|
6
|
+
|
|
7
|
+
Existing rows, relationships, authentication identities, stored files, and migration
|
|
8
|
+
history are where risky changes break. A migration can build successfully and still fail
|
|
9
|
+
against the data and application behavior you actually have.
|
|
10
|
+
|
|
11
|
+
Rehearsal catches those problems before deployment. It restores a reviewed, sanitized
|
|
12
|
+
baseline into a disposable local PostgreSQL or Supabase environment, applies only the
|
|
13
|
+
exact migrations you approve, and runs your application's own proof.
|
|
14
|
+
|
|
15
|
+
| Empty-database tests miss… | Rehearsal exercises… |
|
|
16
|
+
| ------------------------------------------------- | --------------------------------------------------------- |
|
|
17
|
+
| old rows and edge cases | a reviewed, production-shaped baseline |
|
|
18
|
+
| relationships between data, identities, and files | database, Auth, and Storage in one local sandbox |
|
|
19
|
+
| whether the product still behaves correctly | your automated proof and hands-on application walkthrough |
|
|
20
|
+
|
|
3
21
|
## Pick the path that fits today
|
|
4
22
|
|
|
5
23
|
You do not need to read everything before your first rehearsal. Start with the outcome
|
|
6
24
|
you want, then follow the links when a term or safety check is new.
|
|
7
25
|
|
|
8
|
-
| I want to…
|
|
9
|
-
|
|
|
10
|
-
| Set up my own project
|
|
11
|
-
| Try Rehearsal without touching my app
|
|
12
|
-
| Understand what makes a copy safe
|
|
13
|
-
| Look up a command or setting
|
|
14
|
-
|
|
|
15
|
-
|
|
|
26
|
+
| I want to… | Go here |
|
|
27
|
+
| --------------------------------------- | ----------------------------------------------------------------- |
|
|
28
|
+
| Set up my own project | [Getting started](getting-started.md) |
|
|
29
|
+
| Try Rehearsal without touching my app | [Hands-on tutorial](tutorial.md) |
|
|
30
|
+
| Understand what makes a copy safe | [Baselines](baselines.md) and [Sanitization](sanitization.md) |
|
|
31
|
+
| Look up a command or setting | [CLI commands](commands.md) and [Configuration](configuration.md) |
|
|
32
|
+
| Reduce Docker and Supabase resource use | [Container runtime lifecycle](runtime-lifecycle.md) |
|
|
33
|
+
| Add editor and compiler type checks | [TypeScript](typescript.md) |
|
|
34
|
+
| Fix something that did not work | [Troubleshooting](troubleshooting.md) |
|
|
16
35
|
|
|
17
36
|
## The short version
|
|
18
37
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Container runtime lifecycle
|
|
2
|
+
|
|
3
|
+
Rehearsal uses a local Docker-compatible engine for disposable PostgreSQL and Supabase
|
|
4
|
+
targets. It owns the targets it creates; it does not own the shared engine or another
|
|
5
|
+
project's containers.
|
|
6
|
+
|
|
7
|
+
## What starts Docker?
|
|
8
|
+
|
|
9
|
+
Read-only commands such as `doctor`, `status`, `candidates`, `explain`, and `inspect` do
|
|
10
|
+
not start Docker. Commands that create or resume a database—such as `start`, `reset`,
|
|
11
|
+
`run`, and `open`—need an already-running engine.
|
|
12
|
+
|
|
13
|
+
Generated configurations keep startup explicit:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
containerRuntime: {
|
|
17
|
+
autoStartColima: false,
|
|
18
|
+
},
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
With the default, a stopped engine produces an actionable error. Start Docker Desktop,
|
|
22
|
+
Colima, Rancher Desktop, Podman with Docker compatibility, or another supported engine,
|
|
23
|
+
then repeat the command.
|
|
24
|
+
|
|
25
|
+
Setting `autoStartColima: true` is an explicit convenience opt-in. If Docker is
|
|
26
|
+
unavailable and the `colima` command exists, Rehearsal runs plain `colima start` and
|
|
27
|
+
reports it. Rehearsal does not resize Colima and does not stop the shared engine
|
|
28
|
+
automatically. Starting Docker can also wake unrelated containers that use Docker's
|
|
29
|
+
`always` or `unless-stopped` restart policy.
|
|
30
|
+
|
|
31
|
+
## What remains after a command?
|
|
32
|
+
|
|
33
|
+
- `run` stops the application proof process but keeps the database target available for
|
|
34
|
+
hands-on testing.
|
|
35
|
+
- `open` keeps the application and databases available until the application session is
|
|
36
|
+
interrupted. The database target remains available afterward.
|
|
37
|
+
- `stop` stops every configured Rehearsal target in reverse dependency order and retains
|
|
38
|
+
its local data.
|
|
39
|
+
- `start` resumes a stopped target, reusing compatible state.
|
|
40
|
+
- `reset` recreates the target from the active immutable baseline.
|
|
41
|
+
- `discard` removes the selected disposable target. It is the data-destructive runtime
|
|
42
|
+
operation and retains the immutable baseline.
|
|
43
|
+
|
|
44
|
+
After Supabase starts, Rehearsal changes only containers with the exact configured
|
|
45
|
+
Supabase project label to Docker's `no` restart policy. This does not remove containers
|
|
46
|
+
or volumes. It prevents a later Docker restart from silently waking stopped Rehearsal
|
|
47
|
+
stacks; `rehearsal start` still resumes them normally.
|
|
48
|
+
|
|
49
|
+
## A low-memory daily workflow
|
|
50
|
+
|
|
51
|
+
1. Start your Docker-compatible engine.
|
|
52
|
+
2. Run `rehearsal run` or `rehearsal open`.
|
|
53
|
+
3. When finished, run `rehearsal stop` from the project root.
|
|
54
|
+
4. Check other projects before stopping the shared engine:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
docker ps
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
5. If nothing else needs Docker, stop the engine using its own command, such as
|
|
61
|
+
`colima stop`.
|
|
62
|
+
|
|
63
|
+
Rehearsal intentionally does not infer that every running container belongs to it. It
|
|
64
|
+
also never runs a global Docker prune. Database and Storage volumes are not deleted by
|
|
65
|
+
`stop`.
|
|
66
|
+
|
|
67
|
+
## Choosing PostgreSQL or Supabase
|
|
68
|
+
|
|
69
|
+
Use the PostgreSQL target for migration, schema, trigger, privacy, and ordinary relational
|
|
70
|
+
data checks that do not require Supabase services. It uses one database container.
|
|
71
|
+
|
|
72
|
+
Use the Supabase target when the proof needs Auth, Storage, PostgREST, or the local API
|
|
73
|
+
gateway. Rehearsal already excludes Realtime, Edge Runtime, Analytics/Logflare, and Vector
|
|
74
|
+
from its Supabase stack. A future service-profile feature will make additional optional
|
|
75
|
+
services explicit; until then, do not trade away application fidelity merely to reduce a
|
|
76
|
+
container count.
|
|
77
|
+
|
|
78
|
+
## Diagnosing unexpected activity
|
|
79
|
+
|
|
80
|
+
Start with read-only checks:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
docker context show
|
|
84
|
+
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Label "com.supabase.cli.project"}}'
|
|
85
|
+
docker stats --no-stream
|
|
86
|
+
colima status
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
For each container, inspect its project ownership and restart policy before taking any
|
|
90
|
+
action:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
docker inspect --format '{{json .Config.Labels}} {{.HostConfig.RestartPolicy.Name}}' CONTAINER
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Do not remove anonymous volumes or old images based on names alone. Use `rehearsal
|
|
97
|
+
cleanup` for package-owned baseline retention and its reviewed, opt-in image cleanup.
|
|
98
|
+
Shared resource inventory and stale-environment cleanup are tracked separately; until
|
|
99
|
+
that lands, stopping a configured target from its own project is the safe path.
|
package/docs/stability.md
CHANGED
|
@@ -26,7 +26,7 @@ file names, and undocumented package paths are not compatibility promises.
|
|
|
26
26
|
|
|
27
27
|
## What blocks a release candidate
|
|
28
28
|
|
|
29
|
-
An issue blocks
|
|
29
|
+
An issue blocks the active release candidate when it can cause any of the following within a supported
|
|
30
30
|
configuration:
|
|
31
31
|
|
|
32
32
|
- data loss, credential exposure, hosted-system access, or mutation outside resources
|
|
@@ -47,12 +47,13 @@ release.
|
|
|
47
47
|
|
|
48
48
|
1. Ship beta.18 with only stability, release-safety, upgrade, and documentation work.
|
|
49
49
|
2. Freeze broad feature development on the release branch.
|
|
50
|
-
3. Publish
|
|
50
|
+
3. Publish a release candidate from protected `main` through the reviewed npm environment.
|
|
51
51
|
4. Run the complete Rehearsal Test Lab gate twice from clean isolated workspaces.
|
|
52
52
|
5. Perform one final package-only upgrade in a real consumer. The consumer must use the
|
|
53
53
|
published package rather than duplicate Rehearsal machinery.
|
|
54
|
-
6. Keep the candidate available for at least seven calendar days. Restart the
|
|
55
|
-
a blocking package change is required.
|
|
54
|
+
6. Keep the current candidate available for at least seven calendar days. Restart the
|
|
55
|
+
window if a blocking package change is required. The container-lifecycle correction
|
|
56
|
+
in `0.1.0-rc.2` restarts this observation window.
|
|
56
57
|
7. Publish `0.1.0` only when no blocking issue remains and the accepted registry artifact
|
|
57
58
|
matches the tested artifact exactly.
|
|
58
59
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -11,10 +11,10 @@ Doctor names each missing or unsafe item. If you still need help, run
|
|
|
11
11
|
|
|
12
12
|
## `npx rehearsal` cannot find the command
|
|
13
13
|
|
|
14
|
-
Confirm you are in the project directory and install the
|
|
14
|
+
Confirm you are in the project directory and install the current release locally:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install --save-dev @rehearsal-db/core
|
|
17
|
+
npm install --save-dev @rehearsal-db/core
|
|
18
18
|
npx rehearsal --help
|
|
19
19
|
```
|
|
20
20
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rehearsal-db/core",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.2",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Catch PostgreSQL and Supabase migrations that pass on empty databases but fail on real data—before deploy.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/Ddupasquier/rehearsal-db.git"
|