@cellajs/cli 0.4.2 → 0.6.0
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/README.md +171 -113
- package/dist/config.d.ts +15 -11
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/index.js +1471 -818
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @cellajs/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Upgrade your app with upstream [cella template](https://github.com/cellajs/cella) changes while preserving your
|
|
4
4
|
customizations.
|
|
5
5
|
|
|
6
6
|
## Usage
|
|
@@ -9,7 +9,7 @@ From your monorepo root, run `pnpm cella` for the interactive menu, or call a se
|
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
pnpm cella analyze
|
|
12
|
-
pnpm cella
|
|
12
|
+
pnpm cella upgrade
|
|
13
13
|
pnpm cella audit
|
|
14
14
|
```
|
|
15
15
|
|
|
@@ -17,12 +17,12 @@ pnpm cella audit
|
|
|
17
17
|
|
|
18
18
|
| Service | Description |
|
|
19
19
|
|---------|-------------|
|
|
20
|
-
| `analyze` | Dry run to see what would change on
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
20
|
+
| `analyze` | Dry run to see what would change on upgrade. It leaves your files and branches alone but updates git metadata: it fetches upstream and writes `refs/cella/last-upgrade` and a graft for the upgrade base |
|
|
21
|
+
| `upgrade` | Merge upstream changes onto a fresh branch, merge package.json and open a squash-merge PR into `main` |
|
|
22
|
+
| `align` | List the upstream alignments this app has not handled yet, read them, run their codemods, record them |
|
|
23
23
|
| `audit` | Update outdated packages and runtime pins, then rebuild the security overrides from a fresh audit; report the security fixes this machine's Node, pnpm and gh miss |
|
|
24
24
|
| `stats` | Count files by category and workspace package; with `--since <ref>`, count what the current branch changed, by kind of file |
|
|
25
|
-
| `forks` * | Run
|
|
25
|
+
| `forks` * | Run the upgrade inside local fork repositories |
|
|
26
26
|
| `contributions` * | Pull and adopt changes from local forks |
|
|
27
27
|
|
|
28
28
|
\* `forks` and `contributions` only appear when you have `forks` configured in `cella.config.ts`.
|
|
@@ -37,9 +37,9 @@ Per-service help: `pnpm cella <service> --help`.
|
|
|
37
37
|
|
|
38
38
|
| Service | Useful options |
|
|
39
39
|
|---------|----------------|
|
|
40
|
-
| analyze | `--list`, `--json`, `--scope <all\|risk\|protected>`, `--track <release\|branch>`, `--ref <ref>`, `--unpinned` |
|
|
41
|
-
|
|
|
42
|
-
|
|
|
40
|
+
| analyze | `--list`, `--json`, `--scope <all\|risk\|protected>`, `--all`, `--track <release\|branch>`, `--ref <ref>`, `--unpinned` |
|
|
41
|
+
| upgrade | `--track <release\|branch>`, `--ref <ref>`, `--keep-config`, `--unpinned` |
|
|
42
|
+
| align | `--all`, `--json`, `--show <id>`, `--extract <id>`, `--run <id> [-- <codemod args>]`, `--mark <ids...>` |
|
|
43
43
|
| audit | `--list` |
|
|
44
44
|
| forks | `--fork <name>`, `--keep-config` |
|
|
45
45
|
| contributions | `--fork <name>`, `--json` |
|
|
@@ -52,10 +52,10 @@ Per-service help: `pnpm cella <service> --help`.
|
|
|
52
52
|
|
|
53
53
|
## Configuration
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
Upgrade behavior lives in `cella.config.ts` at your monorepo root (a sensible default ships with new
|
|
56
56
|
apps). To deviate files or folders from the template:
|
|
57
57
|
|
|
58
|
-
- **`ignored`**: files completely excluded from
|
|
58
|
+
- **`ignored`**: files completely excluded from upgrades (existing and new)
|
|
59
59
|
- **`pinned`**: full fork control, existing, modified, or deleted files are preserved
|
|
60
60
|
|
|
61
61
|
An `ignored` entry may name a path your app does not have, to keep it from arriving (a file upstream
|
|
@@ -69,42 +69,42 @@ to upstream, which only drops upstream's next change to it.
|
|
|
69
69
|
|
|
70
70
|
## Upstream tracking
|
|
71
71
|
|
|
72
|
-
The
|
|
72
|
+
The CLI tracks upstream cella one of two ways, set via `settings.upstreamTrack`:
|
|
73
73
|
|
|
74
74
|
| Mode | Behavior | For |
|
|
75
75
|
|------|----------|-----|
|
|
76
|
-
| `release` (default) |
|
|
76
|
+
| `release` (default) | Upgrade to the latest cella release tag. Stable and reviewable: each bump maps to a changelog. | Most forks |
|
|
77
77
|
| `branch` | Follow the bleeding-edge tip of `settings.upstreamBranch`. | cella maintainers, active development |
|
|
78
78
|
|
|
79
79
|
For a one-off run that ignores the configured mode, pass `--track`:
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
|
-
pnpm cella
|
|
82
|
+
pnpm cella upgrade --track branch # follow the tip once, without editing config
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
To
|
|
85
|
+
To upgrade to one specific upstream point, pin it with `--ref` (it wins over `--track`): a commit sha,
|
|
86
86
|
a release tag or an upstream branch name, resolved on the upstream remote (`main` is upstream's
|
|
87
87
|
`main`, not yours). The ref must be on `settings.upstreamBranch` or in an upstream release; a
|
|
88
|
-
release tag
|
|
88
|
+
release tag upgrades as that release, anything else is recorded like branch tracking.
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
|
-
pnpm cella
|
|
91
|
+
pnpm cella upgrade --ref 4f7d87c # upgrade up to this upstream commit
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
A run never
|
|
95
|
-
went past the latest release, release tracking ends with a `nothing to
|
|
96
|
-
release exists, instead of reverting what the app already has. A `--ref` behind the last
|
|
94
|
+
A run never upgrades to a point behind the last upgrade: when an earlier `--ref` or `--track branch` run
|
|
95
|
+
went past the latest release, release tracking ends with a `nothing to upgrade` message until a newer
|
|
96
|
+
release exists, instead of reverting what the app already has. A `--ref` behind the last upgrade is
|
|
97
97
|
refused. Either way the run changes nothing and leaves you on the branch you started from.
|
|
98
98
|
|
|
99
|
-
##
|
|
99
|
+
## Upgrade workflow
|
|
100
100
|
|
|
101
|
-
`pnpm cella
|
|
101
|
+
`pnpm cella upgrade` never commits to `main` directly.
|
|
102
102
|
|
|
103
103
|
```
|
|
104
|
-
main ──▶ cella/
|
|
104
|
+
main ──▶ cella/upgrade/<stamp> ──(3-way merge)──▶ PR ──(squash)──▶ main
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
It runs a real git 3-way merge. `
|
|
107
|
+
It runs a real git 3-way merge. `upgrade` is **idempotent and staged**: each run advances the upgrade
|
|
108
108
|
one stage, and the run that commits never ships: the pause on the committed branch is where
|
|
109
109
|
drift triage (`pnpm cella analyze` diffs committed HEAD) and follow-up commits happen.
|
|
110
110
|
|
|
@@ -112,86 +112,136 @@ drift triage (`pnpm cella analyze` diffs committed HEAD) and follow-up commits h
|
|
|
112
112
|
are reconciled (`pnpm install` + `pnpm check`), everything is staged, and the delta is
|
|
113
113
|
committed; then the run stops on the branch. A conflicted merge stops earlier so you can
|
|
114
114
|
resolve in your IDE (`git add` the resolved files) and re-run to commit.
|
|
115
|
-
2. **Final re-run `pnpm cella
|
|
116
|
-
opens a PR into `main` (via `gh`) titled like the
|
|
115
|
+
2. **Final re-run `pnpm cella upgrade`** on the committed branch ships it: pushes to `origin`,
|
|
116
|
+
opens a PR into `main` (via `gh`) titled like the upgrade commit, even with follow-up commits on
|
|
117
117
|
top, and switches you back to `main`.
|
|
118
118
|
|
|
119
119
|
Before the merge starts, a first run checks that it can go ahead, and stops without changing
|
|
120
120
|
anything when it cannot: the temporary branch is removed again and you are back on the branch you
|
|
121
121
|
started from. It stops when upstream needs a newer `@cellajs/cli` than the one running, and when
|
|
122
|
-
upstream changed its own
|
|
123
|
-
[Upstream changes that never
|
|
122
|
+
upstream changed its own CLI config in ways yours does not follow (see
|
|
123
|
+
[Upstream changes that never merge](#upstream-changes-that-never-merge)).
|
|
124
124
|
|
|
125
|
-
`
|
|
126
|
-
never switches to `main`. It compares `main` with `origin/main` by ref and cuts the
|
|
125
|
+
`upgrade` also runs from a linked git worktree while another worktree has `main` checked out: it
|
|
126
|
+
never switches to `main`. It compares `main` with `origin/main` by ref and cuts the upgrade branch
|
|
127
127
|
from `main`; when `main` is behind and checked out elsewhere, it cuts from `origin/main` instead
|
|
128
128
|
and leaves `main` as it is. After shipping, the worktree detaches at `main` instead of switching
|
|
129
129
|
to it.
|
|
130
130
|
|
|
131
131
|
When the commit stage runs, the in-progress merge state (`MERGE_HEAD`) is discarded, so the staged delta
|
|
132
|
-
collapses into a **single-parent commit** (`chore:
|
|
132
|
+
collapses into a **single-parent commit** (`chore: upgrade cella to <sha>`). This keeps the PR
|
|
133
133
|
to one clean commit with the incremental diff; a two-parent merge commit would instead list the
|
|
134
134
|
upstream branch's entire history, because the fork doesn't share pushed ancestry with upstream
|
|
135
135
|
and the local `git replace` graft that makes merges incremental is never pushed. Ancestry lives
|
|
136
|
-
in `refs/cella/last-
|
|
136
|
+
in `refs/cella/last-upgrade` (and the committed `cella.manifest.json` for fresh clones), so
|
|
137
137
|
`git merge-base` keeps working across throwaway branches; each is safe to delete once its PR
|
|
138
138
|
lands. The three-segment name can't collide with git's ref namespacing.
|
|
139
139
|
|
|
140
|
-
If conflicts remain when you re-run, `
|
|
140
|
+
If conflicts remain when you re-run, `upgrade` lists them and stops (never starting a second cycle
|
|
141
141
|
mid-merge). If `pnpm check`, the push, or `gh` fails, it degrades gracefully, reporting the
|
|
142
142
|
issue and printing the remaining manual steps:
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
|
-
git push -u origin cella/
|
|
146
|
-
gh pr create --base main --head cella/
|
|
145
|
+
git push -u origin cella/upgrade/<stamp>
|
|
146
|
+
gh pr create --base main --head cella/upgrade/<stamp> --fill
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
-
##
|
|
149
|
+
## Analyze output
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
`pnpm cella analyze` prints its file sections in the order they need you: what merges on its own
|
|
152
|
+
first (`behind`, `diverged`), then pinned files, drifted files, and the upstream changes the upgrade
|
|
153
|
+
leaves out (`protected but behind upstream`). The summary and `next steps` close the run, so the
|
|
154
|
+
last lines are the ones to act on. A file row is its path, linked per `fileLinkMode`, with a count
|
|
155
|
+
and a short age (`3h`, `2d`, `3mo`) in columns.
|
|
155
156
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
Large groups collapse: more than 15 behind files become one row per folder, more than 8 pinned files
|
|
158
|
+
keep the ones missing 10 or more upstream lines, and five or more protected files of one kind under
|
|
159
|
+
one override entry become one row (`backend/drizzle/ · 42 × snapshot.json`). `--all` lists every
|
|
160
|
+
path.
|
|
160
161
|
|
|
161
|
-
|
|
162
|
+
Analyze and upgrade both end with `next steps`, numbered in the order you take them: the review page,
|
|
163
|
+
the command to run next, and the alignments the upgrade brings or that are still open.
|
|
162
164
|
|
|
163
165
|
```
|
|
164
|
-
|
|
166
|
+
next steps
|
|
167
|
+
────────────────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
1 review file:///Users/you/app/.git/cella-diff/analyze-review.html
|
|
170
|
+
22 diffs in 3 sections · 42 listed without a diff
|
|
171
|
+
2 upgrade pnpm cella upgrade
|
|
172
|
+
commits on a fresh branch, a rerun opens the PR · 36 update, 2 merge
|
|
173
|
+
3 align 1 alignment arrives with this upgrade
|
|
174
|
+
○ Migration notes become alignments · manual · not breaking
|
|
175
|
+
after the upgrade: pnpm cella align
|
|
165
176
|
```
|
|
166
177
|
|
|
167
|
-
|
|
168
|
-
|
|
178
|
+
Without a terminal (piped, or read by an agent) each alignment row also gets its id, for
|
|
179
|
+
`pnpm cella align --show <id>`.
|
|
180
|
+
|
|
181
|
+
## Alignments
|
|
182
|
+
|
|
183
|
+
Upstream ships an alignment for every change that app code has to follow, in
|
|
184
|
+
`cella/alignments/<id>/`: a README (frontmatter, title, summary, then the steps) and sometimes a
|
|
185
|
+
codemod. Alignments stay upstream. The upgrade never brings that folder into the app and removes a
|
|
186
|
+
copy it finds (also of `cella/migrations/`, the migration notes upstream deleted when it started
|
|
187
|
+
the alignments); `align` reads them from the upstream commit the app last upgraded to, which the upgrade
|
|
188
|
+
already fetched.
|
|
189
|
+
|
|
190
|
+
The frontmatter says what the change asks of the app: `breaking`, `clientCacheBump`,
|
|
191
|
+
`caughtBy` (`compiler`, `tests` or `nothing`: what catches app code the change leaves behind),
|
|
192
|
+
`generate` (the change needs `pnpm generate`), `grep` (words app code may still use) and, beside a
|
|
193
|
+
codemod, its `roots`.
|
|
194
|
+
|
|
195
|
+
The app keeps one small record, `cella/cella.alignments.json`, listing the alignments it has not
|
|
196
|
+
handled yet. The upgrade adds the ones that arrive with it, `align --mark` removes them, and the file
|
|
197
|
+
is deleted once the list is empty. No file means nothing is pending, so a new app starts without
|
|
198
|
+
one.
|
|
199
|
+
|
|
200
|
+
Alignments are information, never a gate. `analyze` and each upgrade run list them under
|
|
201
|
+
[`next steps`](#analyze-output): by title, with their kind, at most five. In `analyze` the ones in
|
|
202
|
+
the upgrade range *arrive with this upgrade*; they become open once the upgrade lands, which is when
|
|
203
|
+
`pnpm cella align` lists them. `pnpm cella align` itself ends with one line:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
alignments: 94 of 97 handled · 3 open: pnpm cella align
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The upgrade PR lists the open alignments with links. Handle them in the upgrade PR or later; they
|
|
210
|
+
stay listed until marked.
|
|
169
211
|
|
|
170
212
|
```bash
|
|
171
|
-
pnpm cella
|
|
172
|
-
pnpm cella
|
|
173
|
-
pnpm cella
|
|
174
|
-
pnpm cella
|
|
175
|
-
pnpm cella
|
|
176
|
-
pnpm cella
|
|
213
|
+
pnpm cella align # open alignments, with summary and links
|
|
214
|
+
pnpm cella align --show <id> # one alignment's README and what git tells about it
|
|
215
|
+
pnpm cella align --run <id> # run its codemod, report only
|
|
216
|
+
pnpm cella align --run <id> -- rewrite frontend/src # run it with your own arguments
|
|
217
|
+
pnpm cella align --extract <id> # its folder under node_modules/.cache/cella/alignments/<id>/
|
|
218
|
+
pnpm cella align --mark <id> [...] # record alignments as handled
|
|
177
219
|
```
|
|
178
220
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
221
|
+
Next to its README, each alignment shows what git can tell about it: the upstream commit and PR
|
|
222
|
+
that added it, the other alignments of that commit, the files of that commit the app pins, ignores
|
|
223
|
+
or changed, and the lines of app code that hold one of its `grep` words. Only files that differ
|
|
224
|
+
from the upstream commit of the last upgrade count, so a template file the app never touched is
|
|
225
|
+
never a hit. Two or more open alignments with `generate` get one line: work their code steps first, then
|
|
226
|
+
generate once. `--show` reads an alignment the last upgrade does not have yet from the fetched
|
|
227
|
+
upstream branch, so it works before the upgrade that brings it.
|
|
228
|
+
|
|
229
|
+
`--run` extracts the alignment and runs its codemod with `tsx` from your app root. Everything after
|
|
230
|
+
`--` goes to the codemod as given; without it the codemod gets `inventory` and the alignment's
|
|
231
|
+
`roots`, the report-only run.
|
|
182
232
|
|
|
183
233
|
A codemod's roots cover template-owned files too, and a file that is identical to upstream already
|
|
184
234
|
is the way upstream wants it: upstream may have changed it after writing the codemod, so a rewrite
|
|
185
235
|
there only creates drift. Before the codemod starts, `--run` notes which files are byte-identical
|
|
186
|
-
to the
|
|
187
|
-
staged
|
|
236
|
+
to the upstream commit of the last upgrade (`upstream.commit` in `cella/cella.manifest.json`,
|
|
237
|
+
during a staged upgrade the incoming commit). After the run, each of those files the codemod changed gets its
|
|
188
238
|
upstream content back, and the run prints how many it restored. Files your app changed keep the
|
|
189
239
|
codemod's rewrite. The codemod's own report still counts the restored files, in a report-only run
|
|
190
240
|
too. A codemod run by hand from the `--extract` folder has no such protection.
|
|
191
241
|
|
|
192
|
-
##
|
|
242
|
+
## Merge rules
|
|
193
243
|
|
|
194
|
-
For each file, `
|
|
244
|
+
For each file, `upgrade` compares fork and upstream **content** (blob comparison) and resolves it
|
|
195
245
|
per the table below. Unconfigured files converge on upstream; `ignored` and `pinned` let you opt
|
|
196
246
|
out:
|
|
197
247
|
|
|
@@ -203,72 +253,77 @@ out:
|
|
|
203
253
|
| Deleted in upstream | ✅ Keep | ✅ Keep | 🗑️ Delete |
|
|
204
254
|
| Only in your app | ✅ Keep | ✅ Keep | ✅ Keep |
|
|
205
255
|
|
|
206
|
-
**Choosing an override:** `ignored` = file never
|
|
256
|
+
**Choosing an override:** `ignored` = file never merges and is fully hidden (app-specific docs,
|
|
207
257
|
assets, config you own). `pinned` = your version always wins but stays visible (files you
|
|
208
|
-
customize). Unconfigured =
|
|
258
|
+
customize). Unconfigured = merges automatically. Run `pnpm cella analyze` first to preview.
|
|
209
259
|
|
|
210
260
|
## Status indicators
|
|
211
261
|
|
|
212
|
-
During analysis and
|
|
262
|
+
During analysis and upgrade, files are displayed with status indicators:
|
|
213
263
|
|
|
214
264
|
| Symbol | Label | Meaning | Action |
|
|
215
265
|
|:------:|-------|---------|--------|
|
|
216
266
|
| ◇ | `managed` | Package/config file changed | Handled separately by cella |
|
|
217
|
-
| ⨂ | `ignored` | Protected by ignored config | Excluded from
|
|
267
|
+
| ⨂ | `ignored` | Protected by ignored config | Excluded from upgrades |
|
|
218
268
|
| ✓ | `identical` | Fork matches upstream | No action needed |
|
|
219
269
|
| ↑ | `ahead` | Fork changed (pinned), upstream did not | Protected, keeping fork |
|
|
220
270
|
| ! | `drifted` | Fork changed, not protected | At risk, consider pinning |
|
|
221
|
-
| ↓ | `behind` | Upstream has changes | Will
|
|
271
|
+
| ↓ | `behind` | Upstream has changes | Will update from upstream |
|
|
222
272
|
| ⇅ | `diverged` | Both sides changed | Will merge from upstream |
|
|
223
273
|
| ⨀ | `pinned` | Both changed, fork wins | Protected, keeping fork: review, see below |
|
|
224
274
|
| + | `local` | Only in fork, never in upstream | No action needed |
|
|
225
275
|
|
|
226
276
|
### Protected but behind upstream
|
|
227
277
|
|
|
228
|
-
A pinned or ignored file wins whole-file: when upstream also changed it since the last
|
|
278
|
+
A pinned or ignored file wins whole-file: when upstream also changed it since the last upgrade,
|
|
229
279
|
upstream's hunks are dropped, not merged. That is easy to miss (a pinned stylesheet quietly
|
|
230
|
-
missing new upstream utilities that
|
|
280
|
+
missing new upstream utilities that merged components rely on), so both commands call it out:
|
|
231
281
|
|
|
232
282
|
- `analyze` lists them in a `⚠ protected but behind upstream` section (pinned files as ⨀,
|
|
233
|
-
ignored as ⨂) with the number of lines upstream changed
|
|
234
|
-
|
|
235
|
-
|
|
283
|
+
ignored as ⨂) with the number of lines upstream changed, together with the ignored files only
|
|
284
|
+
upstream changed (tagged `new` or `deleted`, see below). New files come first, then the most
|
|
285
|
+
changed; generated output the fork regenerates itself (`sdk/gen`, `*.gen.*` files) is left out.
|
|
286
|
+
`--list`/`--json` include them in `--scope all` and `--scope protected` (`--json` adds
|
|
287
|
+
`upstreamChanged` and `upstreamChangedLines`).
|
|
288
|
+
- `upgrade` prints the same list at the end of its summary, right when the drop happens.
|
|
236
289
|
|
|
237
290
|
```
|
|
238
291
|
⚠ 3 protected files kept the fork version, dropping upstream changes:
|
|
239
292
|
⨀ frontend/src/styling/tailwind.css · 21 lines changed upstream
|
|
240
293
|
⨂ shared/config/default.ts · 4 lines changed upstream
|
|
241
294
|
⨂ shared/config/staging.ts · 2 lines changed upstream
|
|
242
|
-
pinned/ignored files where upstream also changed since the last
|
|
295
|
+
pinned/ignored files where upstream also changed since the last upgrade; the fork side wins on conflict, so review what upstream changed and adopt what you need.
|
|
243
296
|
```
|
|
244
297
|
|
|
245
|
-
The [review page](#review-page) shows what upstream changed in each of them since the last
|
|
246
|
-
The check is relative to the last
|
|
247
|
-
up as plain `ahead` afterwards. For that case the `↑ protected in fork` section
|
|
248
|
-
|
|
249
|
-
tips, `--json`: `upstreamLinesAbsent`). That is upstream content the fork never received,
|
|
298
|
+
The [review page](#review-page) shows what upstream changed in each of them since the last upgrade.
|
|
299
|
+
The check is relative to the last upgrade: a drop that happened in an earlier upgrade only shows
|
|
300
|
+
up as plain `ahead` afterwards. For that case the `↑ protected in fork` section counts the
|
|
301
|
+
`upstream lines absent` from each pinned file (lines upstream has that the fork lacks, compared at
|
|
302
|
+
the tips, `--json`: `upstreamLinesAbsent`). That is upstream content the fork never received,
|
|
250
303
|
deliberately or not: the review page shows the difference, so you can decide. Ignored files are
|
|
251
304
|
not annotated.
|
|
252
305
|
|
|
253
|
-
To pull upstream into every pinned file at once, run `
|
|
306
|
+
To pull upstream into every pinned file at once, run `upgrade --unpinned`: pins are lifted for that
|
|
254
307
|
run (managed files stay pinned) and the merge uses the full upstream history, so changes earlier
|
|
255
|
-
|
|
308
|
+
upgrades dropped come back too. Review the staged merge in your editor and keep what you want;
|
|
256
309
|
`analyze --unpinned` previews it.
|
|
257
310
|
|
|
258
|
-
### Upstream changes that never
|
|
311
|
+
### Upstream changes that never merge
|
|
259
312
|
|
|
260
|
-
Two more kinds of upstream change never reach the fork on their own. `analyze`
|
|
261
|
-
|
|
313
|
+
Two more kinds of upstream change never reach the fork on their own. `analyze` lists the first in
|
|
314
|
+
`protected but behind upstream` and prints the second after its file sections; `upgrade` prints both
|
|
315
|
+
after its merge summary:
|
|
262
316
|
|
|
263
317
|
- **Ignored paths changed upstream.** Upstream changed, added or deleted a file under an `ignored`
|
|
264
318
|
entry (app-owned module folders included) and the fork left it untouched. No conflict marks it,
|
|
265
|
-
so this is where new config keys and version bumps under `shared/config` show up.
|
|
266
|
-
entry gets one line with a file count, and the [review page](#review-page) shows
|
|
319
|
+
so this is where new config keys and version bumps under `shared/config` show up. In `upgrade`
|
|
320
|
+
each `ignored` entry gets one line with a file count, and the [review page](#review-page) shows
|
|
321
|
+
the diffs. Files
|
|
267
322
|
both sides changed stay in the section above, and generated output the fork regenerates itself
|
|
268
323
|
(`sdk/gen`, `*.gen.*` files) is left out. `--list`/`--json` include these
|
|
269
324
|
files in `--scope all` and `--scope protected` (`--json`: `upstreamOnly`).
|
|
270
|
-
- **Upstream
|
|
271
|
-
its own `overrides.pinned` or `overrides.ignored`, and keys it adds to `settings.
|
|
325
|
+
- **Upstream CLI config changes.** `cella/cella.config.ts` never merges, so entries upstream adds to
|
|
326
|
+
its own `overrides.pinned` or `overrides.ignored`, and keys it adds to `settings.packageJsonKeys`
|
|
272
327
|
(the template your config started from), never arrive. The report names each entry upstream added
|
|
273
328
|
that your config lacks (`+`) and each entry upstream dropped that your config still has (`−`). It
|
|
274
329
|
reads upstream's config without running it and never edits yours. `--json` puts the lists on the
|
|
@@ -277,76 +332,79 @@ its summary, and `sync` after its merge summary:
|
|
|
277
332
|
```
|
|
278
333
|
⚠ ignored paths changed upstream · 1 file under 1 entry
|
|
279
334
|
⨂ frontend/src/modules/marketing · 1 file
|
|
280
|
-
the fork left these untouched and ignored paths never
|
|
335
|
+
the fork left these untouched and ignored paths never merge: review and adopt what you need.
|
|
281
336
|
|
|
282
|
-
⚠ upstream changed its
|
|
337
|
+
⚠ upstream changed its CLI config · 2 entries to review
|
|
283
338
|
+ pinned: backend/src/bundle-config.ts
|
|
284
|
-
+
|
|
285
|
-
cella/cella.config.ts never
|
|
339
|
+
+ packageJsonKeys: exports
|
|
340
|
+
cella/cella.config.ts never merges: add or drop these by hand where they fit your app.
|
|
286
341
|
```
|
|
287
342
|
|
|
288
|
-
`analyze` only reports these. `
|
|
343
|
+
`analyze` only reports these. `upgrade` checks the CLI config before a new merge and stops when it
|
|
289
344
|
finds entries: the merge runs on your config, so with a list that is behind, a path upstream now
|
|
290
|
-
ignores or pins would arrive as an ordinary
|
|
345
|
+
ignores or pins would arrive as an ordinary merged file (upstream renamed an ignored folder, your
|
|
291
346
|
list still names the old one). Nothing has changed at that point. Add or drop the entries that fit
|
|
292
347
|
your app in `cella/cella.config.ts`, commit and rerun, or pass `--keep-config` to merge with your
|
|
293
348
|
config as it stands; the report then follows the merge summary as before. The rerun that commits an
|
|
294
349
|
already staged merge never stops for this.
|
|
295
350
|
|
|
296
351
|
```bash
|
|
297
|
-
pnpm cella
|
|
352
|
+
pnpm cella upgrade --keep-config # merge although upstream changed its CLI config
|
|
298
353
|
```
|
|
299
354
|
|
|
300
355
|
### Review page
|
|
301
356
|
|
|
302
357
|
The terminal lists files; the review page shows their diffs, side by side and highlighted, on one
|
|
303
|
-
page in your browser under the same section titles. `analyze` and `
|
|
304
|
-
has files, and
|
|
358
|
+
page in your browser under the same section titles. `analyze` and `upgrade` write it whenever a list
|
|
359
|
+
has files, and list it first under [`next steps`](#analyze-output):
|
|
305
360
|
|
|
306
361
|
```
|
|
307
|
-
|
|
308
|
-
|
|
362
|
+
1 review file:///Users/you/app/.git/cella-diff/upgrade-review.html
|
|
363
|
+
3 diffs of upstream changes that did not arrive · opened in the browser
|
|
309
364
|
```
|
|
310
365
|
|
|
311
|
-
| Section | `analyze` | `
|
|
366
|
+
| Section | `analyze` | `upgrade` | The diff shows |
|
|
312
367
|
| --- | --- | --- | --- |
|
|
313
|
-
| protected but behind upstream (
|
|
314
|
-
| ignored paths changed upstream | ✓ | ✓ | what upstream changed since the last
|
|
315
|
-
| pinned files that match the previous upstream | ✓ | ✓ | what upstream changed since the last
|
|
368
|
+
| protected but behind upstream (upgrade: protected files kept the fork version) | ✓ | ✓ | what upstream changed since the last upgrade |
|
|
369
|
+
| ignored paths changed upstream (analyze: under protected but behind upstream) | ✓ | ✓ | what upstream changed since the last upgrade |
|
|
370
|
+
| pinned files that match the previous upstream | ✓ | ✓ | what upstream changed since the last upgrade |
|
|
316
371
|
| protected in fork, upstream lines absent | ✓ | | the fork against upstream, both as they are now |
|
|
317
|
-
| drifted from upstream | ✓ | | what the fork changed since the last
|
|
372
|
+
| drifted from upstream | ✓ | | what the fork changed since the last upgrade |
|
|
318
373
|
|
|
319
|
-
`
|
|
320
|
-
changes the merge did not bring in, and the committed
|
|
321
|
-
`analyze` only
|
|
374
|
+
`upgrade` opens the page in your browser when it runs in a terminal: the files on it are upstream
|
|
375
|
+
changes the merge did not bring in, and the committed upgrade branch is where you adopt them.
|
|
376
|
+
`analyze` only lists the page, since you run it often and pinned files keep their absent lines.
|
|
322
377
|
The page lives in the git dir, so it never shows up in `git status`, and each run overwrites it. It
|
|
323
|
-
|
|
378
|
+
renders at most 50 diffs and 15,000 diff lines, and a single diff over 2,000 lines is listed
|
|
379
|
+
instead (a rendered line costs about 0.6 KB of page). Sections take turns, one file each, so every
|
|
380
|
+
section gets diffs before one fills the page. The rest, and files without a text diff, are listed
|
|
381
|
+
by path.
|
|
324
382
|
|
|
325
|
-
## Package.json
|
|
383
|
+
## Package.json merge
|
|
326
384
|
|
|
327
|
-
`
|
|
385
|
+
`packageJsonKeys` controls which package.json sections merge from upstream:
|
|
328
386
|
|
|
329
387
|
```typescript
|
|
330
|
-
|
|
388
|
+
packageJsonKeys: ['dependencies', 'devDependencies', 'scripts']
|
|
331
389
|
```
|
|
332
390
|
|
|
333
391
|
**Supported keys:** `dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`, `scripts`, `engines`, `packageManager`, `overrides`, `exports`, `pnpm`
|
|
334
392
|
|
|
335
393
|
Each section merges three-way against the merge-base package.json (upstream as of your last
|
|
336
|
-
|
|
394
|
+
upgrade). An entry your fork never touched follows upstream: it is **added**, **updated** (a rewritten
|
|
337
395
|
script, a changed range) or **removed** when upstream dropped it. An entry your fork added or
|
|
338
396
|
changed stays as it is; only a strictly higher upstream version still bumps it, and never for
|
|
339
397
|
`scripts`. An entry your fork removed is not re-added. A dependency or script upstream dropped
|
|
340
398
|
stays while your own code still uses it: files that differ from upstream and scripts your fork
|
|
341
399
|
added or changed are searched for an import of the package, a run of its CLI, or a package manager
|
|
342
|
-
command that runs the script. The
|
|
400
|
+
command that runs the script. The upgrade lists every change and warns about each entry it kept this
|
|
343
401
|
way, so you can remove it once your code no longer needs it. `exports` are add-only: an entry your fork
|
|
344
402
|
already defines is never rewritten, and `exports` only merges when both sides are subpath maps
|
|
345
|
-
(`{ ".": …, "./config": … }`). A workspace upstream added since your last
|
|
403
|
+
(`{ ".": …, "./config": … }`). A workspace upstream added since your last upgrade arrives with its
|
|
346
404
|
package.json copied verbatim. A merged section is sorted alphabetically, except `scripts`: they
|
|
347
405
|
keep upstream's order, and a script only your fork has stays after the one it follows.
|
|
348
406
|
|
|
349
|
-
`type` always
|
|
407
|
+
`type` always merges, whatever `packageJsonKeys` lists: it follows upstream where your fork kept the
|
|
350
408
|
previous value, and a package.json without `type` gets upstream's. Set it yourself (for example
|
|
351
409
|
`"commonjs"`) to keep your own.
|
|
352
410
|
|
package/dist/config.d.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* schema, and the internal types the services share.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
declare const
|
|
7
|
-
/** Valid package.json keys that can
|
|
8
|
-
type
|
|
6
|
+
declare const PACKAGE_JSON_KEYS: readonly ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies", "scripts", "engines", "packageManager", "overrides", "exports", "pnpm"];
|
|
7
|
+
/** Valid package.json keys that can merge from upstream */
|
|
8
|
+
type PackageJsonKey = (typeof PACKAGE_JSON_KEYS)[number];
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Settings: all configurable options for the cella CLI.
|
|
11
11
|
* Hover over each property for documentation.
|
|
12
12
|
*/
|
|
13
13
|
interface SyncSettings {
|
|
@@ -20,21 +20,25 @@ interface SyncSettings {
|
|
|
20
20
|
upstreamBranch?: string;
|
|
21
21
|
/**
|
|
22
22
|
* How to track upstream cella. Defaults to 'release'.
|
|
23
|
-
* - 'release' (default):
|
|
23
|
+
* - 'release' (default): upgrade to a published cella release tag (`0.18.1`, with or without `v`). Stable and
|
|
24
24
|
* reviewable: each bump maps to a changelog. Uses the latest release.
|
|
25
25
|
* - 'branch': follow the bleeding-edge tip of `upstreamBranch`. For cella
|
|
26
26
|
* maintainers and forks doing active development on top of unreleased changes.
|
|
27
27
|
*/
|
|
28
28
|
upstreamTrack?: 'release' | 'branch';
|
|
29
29
|
/**
|
|
30
|
-
* Trunk branch that `pnpm cella
|
|
30
|
+
* Trunk branch that `pnpm cella upgrade` cuts the temporary branch from and that you open the
|
|
31
31
|
* squash-merge PR into. Defaults to 'main'. Cutting fresh from trunk each cycle keeps every
|
|
32
32
|
* PR limited to that cycle's upstream delta (no accumulation) and `main` linear.
|
|
33
33
|
*/
|
|
34
34
|
releaseBase?: string;
|
|
35
|
-
/** Which package.json keys
|
|
36
|
-
|
|
37
|
-
/**
|
|
35
|
+
/** Which package.json keys merge from upstream (default: ['dependencies', 'devDependencies']). `type` always merges. */
|
|
36
|
+
packageJsonKeys?: PackageJsonKey[];
|
|
37
|
+
/** Merge the `packageJsonKeys` of every package.json after the upgrade merge (default: true). */
|
|
38
|
+
mergePackageJson?: boolean;
|
|
39
|
+
/** @deprecated Renamed to `packageJsonKeys`. */
|
|
40
|
+
packageJsonSync?: PackageJsonKey[];
|
|
41
|
+
/** @deprecated Renamed to `mergePackageJson`. */
|
|
38
42
|
syncWithPackages?: boolean;
|
|
39
43
|
/**
|
|
40
44
|
* How to link files in CLI output.
|
|
@@ -48,7 +52,7 @@ interface SyncSettings {
|
|
|
48
52
|
*
|
|
49
53
|
* Cella is the upstream/source-of-truth. For each fork it can:
|
|
50
54
|
* - pull contributions FROM the fork's `pullBranch` (contributions service)
|
|
51
|
-
* - run the normal temporary-branch
|
|
55
|
+
* - run the normal temporary-branch upgrade flow inside the fork (forks service)
|
|
52
56
|
*/
|
|
53
57
|
interface ForkConfig {
|
|
54
58
|
/** Display name for the fork (also used as the contrib/<name> branch slug) */
|
|
@@ -102,4 +106,4 @@ interface CellaCliConfig {
|
|
|
102
106
|
*/
|
|
103
107
|
declare function defineConfig(config: CellaCliConfig): CellaCliConfig;
|
|
104
108
|
|
|
105
|
-
export { type CellaCliConfig, type
|
|
109
|
+
export { type CellaCliConfig, type PackageJsonKey, defineConfig };
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/config/types.ts
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
var
|
|
3
|
+
var PACKAGE_JSON_KEYS = [
|
|
4
4
|
"dependencies",
|
|
5
5
|
"devDependencies",
|
|
6
6
|
"peerDependencies",
|
|
@@ -21,7 +21,9 @@ var cellaConfigSchema = z.object({
|
|
|
21
21
|
upstreamBranch: z.string().min(1).optional(),
|
|
22
22
|
upstreamTrack: z.enum(["release", "branch"]).optional(),
|
|
23
23
|
releaseBase: z.string().min(1).optional(),
|
|
24
|
-
|
|
24
|
+
packageJsonKeys: z.array(z.enum(PACKAGE_JSON_KEYS)).optional(),
|
|
25
|
+
mergePackageJson: z.boolean().optional(),
|
|
26
|
+
packageJsonSync: z.array(z.enum(PACKAGE_JSON_KEYS)).optional(),
|
|
25
27
|
syncWithPackages: z.boolean().optional(),
|
|
26
28
|
fileLinkMode: z.enum(["commit", "file"]).optional()
|
|
27
29
|
}).strict(),
|