Skip to content

Commit e9d188b

Browse files
committed
docs(migrate): ACL orphan manual fix workflow in v1->v2 guide
1 parent 0afa13e commit e9d188b

1 file changed

Lines changed: 59 additions & 36 deletions

File tree

scripts/migrate/Migration-guide-v1-to-v2.md

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Configuration: `scripts/migrate/lib/config.js` and `scripts/migrate/lib/datastor
1313
## npm scripts
1414

1515
```bash
16-
npm run backup:urls
16+
npm run backup:urls
1717
npm run migrate:urls # repo URL normalization — dry-run
1818
npm run migrate:urls -- --apply # apply normalization
1919

@@ -37,10 +37,10 @@ npm run migrate:users
3737

3838
All scripts connect through `scripts/migrate/lib/datastore.js`.
3939

40-
| Backend | `--dbType` | When used |
41-
| ------- | ---------- | --------- |
42-
| MongoDB | `mongo` | **Default** if `--dbType` and `DB_TYPE` are unset |
43-
| File (neDB) | `fs` | Explicit: `--dbType fs` or `DB_TYPE=fs` |
40+
| Backend | `--dbType` | When used |
41+
| ----------- | ---------- | ------------------------------------------------- |
42+
| MongoDB | `mongo` | **Default** if `--dbType` and `DB_TYPE` are unset |
43+
| File (neDB) | `fs` | Explicit: `--dbType fs` or `DB_TYPE=fs` |
4444

4545
Priority: CLI `--dbType` → env `DB_TYPE``mongo` (no auto-detection).
4646

@@ -50,14 +50,14 @@ Collections / files: `users`, `repos`.
5050

5151
## Environment variables
5252

53-
| Variable | Required | Default | Purpose |
54-
| --------------- | -------- | ---------------------------------- | ------- |
55-
| `MONGO_URI` | no | `mongodb://localhost:27017` | MongoDB connection string (`dbType=mongo`) |
56-
| `DB_NAME` | no | `git-proxy` | MongoDB database name |
57-
| `DB_TYPE` | no | `mongo` | Backend: `mongo` or `fs` |
58-
| `USERS_DB_PATH` | no | `./.data/db/users.db` | neDB users file (`dbType=fs`), relative to **cwd** |
59-
| `REPOS_DB_PATH` | no | `./.data/db/repos.db` | neDB repos file (`dbType=fs`), relative to **cwd** |
60-
| `REPORTS_DIR` | no | `reports/<YYYY-MM-DD>-migration` | Directory where report files are written |
53+
| Variable | Required | Default | Purpose |
54+
| --------------- | -------- | -------------------------------- | -------------------------------------------------- |
55+
| `MONGO_URI` | no | `mongodb://localhost:27017` | MongoDB connection string (`dbType=mongo`) |
56+
| `DB_NAME` | no | `git-proxy` | MongoDB database name |
57+
| `DB_TYPE` | no | `mongo` | Backend: `mongo` or `fs` |
58+
| `USERS_DB_PATH` | no | `./.data/db/users.db` | neDB users file (`dbType=fs`), relative to **cwd** |
59+
| `REPOS_DB_PATH` | no | `./.data/db/repos.db` | neDB repos file (`dbType=fs`), relative to **cwd** |
60+
| `REPORTS_DIR` | no | `reports/<YYYY-MM-DD>-migration` | Directory where report files are written |
6161

6262
CLI overrides (same priority as above for connection): `--mongoUri`, `--dbName`, `--usersDbPath`, `--reposDbPath`.
6363

@@ -83,26 +83,26 @@ Reports are **action-oriented**: YAML/CSV list repos or users that need migratio
8383

8484
### Always written (when the script reaches report generation)
8585

86-
| File | Written by |
87-
| ---------------------- | ----------------------------------------------- |
86+
| File | Written by |
87+
| ------------------------- | ---------------------------------------------- |
8888
| `report-{timestamp}.yaml` | `migrate-urls`, `backup-urls`, `migrate-users` |
8989

9090
### Conditional CSV / JSON (created only if the relevant list is non-empty)
9191

92-
| File | Written by | Condition |
93-
| ---------------------------- | ----------------------------- | ---------------------------------- |
94-
| `report-{timestamp}.csv` | `migrate-urls`, `backup-urls` | `changes.length > 0` (URL pending) |
95-
| `url-issues-{timestamp}.csv` | `migrate-urls`, `backup-urls` | `issues.length > 0` (manual URL) |
96-
| `users-audit-{timestamp}.csv`| `migrate-users` | blocking email `users.issues` |
97-
| `acl-orphans-{timestamp}.csv`| `migrate-users` | `acl.orphans.length > 0` |
98-
| `email-changes-{timestamp}.csv` | `migrate-users` (--apply) | `apply.changes.length > 0` |
99-
| `backup-urls-{timestamp}.json` | `backup-urls` only | see backup-urls below |
92+
| File | Written by | Condition |
93+
| ------------------------------- | ----------------------------- | ---------------------------------- |
94+
| `report-{timestamp}.csv` | `migrate-urls`, `backup-urls` | `changes.length > 0` (URL pending) |
95+
| `url-issues-{timestamp}.csv` | `migrate-urls`, `backup-urls` | `issues.length > 0` (manual URL) |
96+
| `users-audit-{timestamp}.csv` | `migrate-users` | blocking email `users.issues` |
97+
| `acl-orphans-{timestamp}.csv` | `migrate-users` | `acl.orphans.length > 0` |
98+
| `email-changes-{timestamp}.csv` | `migrate-users` (--apply) | `apply.changes.length > 0` |
99+
| `backup-urls-{timestamp}.json` | `backup-urls` only | see backup-urls below |
100100

101101
### Backup-only extras
102102

103-
| File | Written by | Contents |
104-
| ---------------------------- | ---------------- | -------- |
105-
| `backup-users-{timestamp}.json` | `backup-users` | **All** users (password field excluded) |
103+
| File | Written by | Contents |
104+
| ------------------------------- | -------------- | -------------------------------------------------------- |
105+
| `backup-users-{timestamp}.json` | `backup-users` | **All** users (password field excluded) |
106106
| `users-email-{timestamp}.csv` | `backup-users` | **All** users as `username,email` template for CSV apply |
107107

108108
`backup-urls` does **not** dump every repo: the JSON array contains only documents that appear in `changes` (missing `.git`) or `issues` (blank / unsupported URL), each with `backupReason` metadata. If nothing needs migration and there are no URL issues, **no** `backup-urls-*.json` is created and the script exits 0.
@@ -123,18 +123,25 @@ CSV validation errors from `--apply --csv` are recorded in YAML (`report.csv.err
123123

124124
### Exit codes
125125

126-
| Script | Exit 0 when | Exit 1 when |
127-
| ---------------- | ----------- | ----------- |
128-
| `migrate-urls` | no apply errors and no URL issues | URL issues and/or apply errors |
129-
| `migrate-users` | no blocking email issues, no ACL orphans, apply OK, no post-apply email conflicts, no CSV errors | any of the above fail |
130-
| `backup-urls` | always (including “nothing to backup”) | fatal error only |
131-
| `backup-users` | success | fatal error only |
126+
| Script | Exit 0 when | Exit 1 when |
127+
| --------------- | ------------------------------------------------------------------------------------------------ | ------------------------------ |
128+
| `migrate-urls` | no apply errors and no URL issues | URL issues and/or apply errors |
129+
| `migrate-users` | no blocking email issues, no ACL orphans, apply OK, no post-apply email conflicts, no CSV errors | any of the above fail |
130+
| `backup-urls` | always (including “nothing to backup”) | fatal error only |
131+
| `backup-users` | success | fatal error only |
132132

133133
After a successful URL apply, a follow-up dry-run should show `reposNeedingUpdate: 0`, but exit code is still **1** if URL **issues** remain (blank or non-http(s) URLs).
134134

135-
### Manual test fixtures
135+
### Read-only issue reports (manual fix in the database)
136+
137+
Some CSV files are **audit output only** — no migration script reads them back as input:
136138

137-
Local MongoDB seed data and per-repo ACL/URL test-case tables: [`fixtures/README.md`](fixtures/README.md).
139+
| File | Meaning |
140+
| ------------------- | ---------------------------------------------------------------------------------------------------------------- |
141+
| `url-issues-*.csv` | Repos whose `url` is blank or not `http`/`https` — fix in the DB, then re-run `migrate:urls` |
142+
| `acl-orphans-*.csv` | Repo ACL entries whose username does not match any `users.username` — fix in the DB, then re-run `migrate:users` |
143+
144+
Only `migrate-users --apply --csv` consumes a CSV (`username,email` for `users.email`). `email-changes-*.csv` is an apply **log**, not a re-import format.
138145

139146
---
140147

@@ -157,15 +164,15 @@ npm run backup:urls
157164
npm run migrate:urls -- --apply
158165
```
159166

160-
Notes: trailing `/` is normalized (`.../repo/``.../repo.git`). Blank/non-http(s) URLs are reported as issues and require manual fixing.
167+
Notes: trailing `/` is normalized (`.../repo/``.../repo.git`). Blank/non-http(s) URLs are reported as issues and require **manual** correction in the database; `url-issues-*.csv` is a checklist only (see [Read-only issue reports](#read-only-issue-reports-manual-fix-in-the-database)).
161168

162169
Phase 1 report files: see [Report artifacts](#report-artifacts) (`report-*.yaml`, `report-*.csv`, `url-issues-*.csv`, `backup-urls-*.json`).
163170

164171
---
165172

166173
## Phase 2 — User emails & ACL audit
167174

168-
**Goal:** unblock v2 pushes: valid **unique** `users.email` (audit + CSV apply fallback); surface **ACL orphan** `username` strings for manual UI fix.
175+
**Goal:** unblock v2 pushes: valid **unique** `users.email` (audit + CSV apply fallback); surface **ACL orphan** entries that must be corrected **manually** in the database (scripts never rewrite repo ACL).
169176

170177
**migrate-urls vs migrate-users**
171178

@@ -177,12 +184,26 @@ Phase 1 report files: see [Report artifacts](#report-artifacts) (`report-*.yaml`
177184

178185
`backup-users.js` is separate (not invoked by `migrate-users`) and writes a **full** users JSON snapshot plus `users-email-*.csv` for all users (see [Report artifacts](#report-artifacts)).
179186

187+
### Recommended order (emails → ACL → verify)
188+
189+
1. **Emails** — run `npm run migrate:users` (dry-run). Resolve every blocking row in `users-audit-*.csv` / YAML `users.issues` (missing/invalid/duplicate email). Where CSV apply is appropriate, run `npm run migrate:users -- --apply --csv ./mappings.csv` and confirm `apply.ok` in the report.
190+
2. **ACL orphans** — while `acl.orphanCount` (console: `ACL orphans`) is greater than zero, fix each orphan listed in `acl-orphans-*.csv` or YAML `acl.orphans` in the database. Migration tools **do not** update `repos.users.canPush` or `repos.users.canAuthorise`.
191+
3. **Verify** — run `npm run migrate:users` (dry-run) again after each batch of fixes. Phase 2 is complete only when `blockingIssueCount` is **0**, `orphanCount` is **0**, and the process exits **0** (see [Exit codes](#exit-codes)).
192+
180193
```bash
181194
npm run migrate:users
182195
npm run backup:users
183196
npm run migrate:users -- --apply --csv ./mappings.csv
197+
# … manual ACL fixes in the database …
198+
npm run migrate:users # repeat until ACL orphans: 0 and exit 0
184199
```
185200

201+
### ACL orphans (manual fix required)
202+
203+
An **orphan** is a username string stored under a repo’s `users.canPush` or `users.canAuthorise` that does not match any document in `users` (match is trimmed, case-insensitive on `username`). These stale or mistyped ACL entries keep `migrate-users` in a failing state until they are removed or aligned with a real user record.
204+
205+
`acl-orphans-{timestamp}.csv` columns: `RepoID`, `RepoName`, `RepoURL`, `Field` (`canPush` / `canAuthorise`), `OrphanUsername`, `NormalizedOrphan`, `Index`. Like `url-issues-*.csv`, this file is **read-only** — it cannot be “loaded back” or applied by any script; use it as a work list, fix data in your environment, then re-run the dry-run (see [Read-only issue reports](#read-only-issue-reports-manual-fix-in-the-database)).
206+
186207
For **apply** (`migrate-users --apply --csv ...`): CSV header must be `username,email` (`lib/csv.js`). The command exits `1` on blocking email issues, ACL orphans, CSV/apply failures, or duplicate-email simulation (see [Exit codes](#exit-codes)).
187208

188209
CSV input: UTF‑8, one row per line, only those two columns; parser is minimal (quoted commas OK, **`""`** escapes inside fields not supported). Prefer export without BOM.
@@ -207,4 +228,6 @@ npm run migrate:urls # expect reposNeedingUpdate: 0; exit 1 if URL issues rema
207228
npm run migrate:users
208229
npm run backup:users
209230
npm run migrate:users -- --apply --csv ./mappings.csv
231+
# fix ACL orphans manually (acl-orphans-*.csv is not re-importable)
232+
npm run migrate:users # repeat until orphanCount: 0 and exit 0
210233
```

0 commit comments

Comments
 (0)