Skip to content

Commit 8bb7ff6

Browse files
committed
test(cli): enumeration pin for apply's drop gates, and the changeset
The pin discovers apply's drop-gate refusals from its source and holds plan and apply to naming each gate's command for a held drop. The two gate refusal tests' fixtures spell the drift entry's finding as `message`, the key ManagedDriftEntry declares. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
1 parent 420c3fe commit 8bb7ff6

5 files changed

Lines changed: 528 additions & 5 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/cli': patch
3+
---
4+
5+
fix(cli): `os migrate plan` and `os migrate apply` name the command each held drop waits for, never `--allow-destructive`, for every drop `apply` refuses (#24958)
6+
7+
Clause-②: no
8+
9+
`os migrate apply --allow-destructive` refuses the whole run, whatever flag is passed, while it would drop one of three columns before its precondition holds: `sys_account.issuer` while its retirement pre-flight finds `(provider_id, account_id)` keys held by more than one row (or cannot read `sys_account`), `sys_comment.reactions` while no verified run of `os migrate comment-reactions --apply` is recorded, and an `organization_id` column while the organization-ownership ceremony has not verified. Yet `os migrate plan` offered `--allow-destructive` for the first two, and `os migrate apply` without the flag listed all three with `"os migrate apply --allow-destructive" to drop it.` and closed with `N destructive change(s) will be SKIPPED (re-run with --allow-destructive to include them).` and `Skipped N destructive change(s) (re-run with --allow-destructive to include them).` That re-run was refused, exit 1.
10+
11+
- **Now.** Each such drop is still listed and counted as destructive drift, in both commands. Its line names what it waits for: the ceremony, `os migrate comment-reactions`, or the retirement pre-flight `os migrate account-issuer`.
12+
- **The footer.** One line per gate that holds a drop names that gate's commands and says `--allow-destructive` is refused until they have run. `os migrate plan` offers `--allow-destructive` for nothing while a drop is held. `os migrate apply` prints `N destructive change(s) will be SKIPPED, and a re-run with --allow-destructive cannot include them yet:` before those lines, and `Skipped N destructive change(s); a re-run with --allow-destructive cannot include them yet (see above).` after the apply.
13+
- **Unchanged.** A database with no held drop prints what it printed before, byte for byte, in both commands. The `--json` documents, the exit codes and every refusal of `os migrate apply --allow-destructive` (its rule and its text) are unchanged.
14+
15+
**What to do.** Nothing. Follow the footer: run the command each held drop names, then re-run `os migrate plan`.

‎packages/cli/src/commands/migrate/apply.account-issuer-json-refusal.test.ts‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ const ISSUER_DROP = {
6969
table: 'sys_account',
7070
column: 'issuer',
7171
op: { type: 'drop_column', column: 'issuer' },
72-
description: 'sys_account.issuer: column exists in the database but not in metadata (orphaned)',
72+
// The differ's `message` (`ManagedDriftEntry`), remedy sentence included: the
73+
// listing above the gate reads it (#24958).
74+
message: 'sys_account.issuer: column exists in the database but not in metadata (orphaned) — "os migrate apply --allow-destructive" to drop it.',
7375
};
7476

7577
const COLLISIONS = {
@@ -188,7 +190,10 @@ describe('controls', () => {
188190
const { exit } = await runApply(ARGV);
189191

190192
expect(exit).toBe(1);
191-
// Refused by the pre-flight, not by anything earlier on the human face.
193+
// Refused by the pre-flight, not by anything earlier on the human face:
194+
// its refusal printed, and the pre-flight read once — the listing above
195+
// the gate shares the gate's read (#24958).
196+
expect(log.mock.calls.map((c: unknown[]) => c.map(String).join(' ')).some((l: string) => l.includes('Refusing to drop sys_account.issuer'))).toBe(true);
192197
expect(mocks.probeAccountIdentityCollisions).toHaveBeenCalledTimes(1);
193198
expect(applyMigrationEntries).not.toHaveBeenCalled();
194199
}, RUN_TIMEOUT);

‎packages/cli/src/commands/migrate/apply.organization-ownership-refusal.test.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ const ORGANIZATION_DROP = {
6464
table: 'sys_platform_setting',
6565
column: 'organization_id',
6666
op: { type: 'drop_column', column: 'organization_id' },
67-
description: 'sys_platform_setting.organization_id: column exists in the database but not in metadata (orphaned)',
67+
// The differ's `message` (`ManagedDriftEntry`), remedy sentence included: the
68+
// listing above the gate reads it (#24958).
69+
message: 'sys_platform_setting.organization_id: column exists in the database but not in metadata (orphaned) — "os migrate apply --allow-destructive" to drop it.',
6870
};
6971

7072
/** The ceremony's two steps, as the refusal prescribes them. */

‎packages/cli/src/utils/apply-drop-gates.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ export const APPLY_DROP_GATES: readonly ApplyDropGate[] = [
170170
id: 'sys_comment.reactions',
171171
judges: isCommentReactionsDrop,
172172
holds: async (reads, engine) => ((await reads.commentReactionsConversion(engine)).verified ? null : {}),
173-
entry: 'a drop that waits for "os migrate comment-reactions" to carry the reactions stored in it into '
173+
entry: 'a drop that waits for "os migrate comment-reactions" to carry any reactions stored in it into '
174174
+ 'sys_comment_reaction records, and no verified run is recorded on this database (see below).',
175175
footer: (_held, waiting) =>
176-
'sys_comment.reactions above holds the reactions stored before they became sys_comment_reaction records, and no '
176+
'sys_comment.reactions above is where reactions were stored before they became sys_comment_reaction records, and no '
177177
+ `verified run of "os migrate comment-reactions --apply" is recorded on this database, so ${REFUSES} one is`
178178
+ `${andTheOthers(waiting)}. Run "os migrate comment-reactions" to preview, then "os migrate comment-reactions `
179179
+ '--apply"; it carries them into records and records the run verified.',

0 commit comments

Comments
 (0)