Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 10 additions & 41 deletions .claude/commands/bump-alpha-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,40 +91,14 @@ Update dependencies in the following package.json files within semver-compatible

Run `pnpm install` to update the lockfile with new dependency versions.

### 6. Merge pnpm Branch Lockfiles
### 6. Verify Changes and Fix TypeScript Errors

This repository uses pnpm's `gitBranchLockfile` feature (see `pnpm-workspace.yaml`: `gitBranchLockfile: true` with `mergeGitBranchLockfilesBranchPattern: - main`). Feature branches accumulate per-branch lockfiles (`pnpm-lock.<branch-name>.yaml`) that must be periodically merged back into the main `pnpm-lock.yaml` so trunk stays consistent.

Run:

```bash
pnpm install --merge-git-branch-lockfiles
```

This command:

- Reads all `pnpm-lock.*.yaml` files at the repo root
- Merges their resolutions into the main `pnpm-lock.yaml`
- Deletes the per-branch lockfiles

After running, verify:

```bash
ls pnpm-lock*.yaml # should show only pnpm-lock.yaml
git status # confirm any removed branch lockfiles are staged for deletion
```

If there are no branch lockfiles present, this step is effectively a no-op and the main lockfile is left unchanged — still run the command to be safe.

### 7. Verify Changes and Fix TypeScript Errors

After updating dependencies and merging branch lockfiles, verify everything works correctly:
After updating dependencies, verify everything works correctly:

1. **Run `pnpm install`** to ensure no errors in dependency resolution
2. **Check all package.json files** have the correct version
3. **Confirm `pnpm-lock.*.yaml` branch lockfiles are gone** (only `pnpm-lock.yaml` should remain)
4. **Note any peer dependency warnings**
5. **Run TypeScript type checking** to detect any type errors caused by updated packages:
3. **Note any peer dependency warnings**
4. **Run TypeScript type checking** to detect any type errors caused by updated packages:

```bash
# Check TypeScript errors in react package
Expand All @@ -138,15 +112,15 @@ pnpm --prefix ./react exec tsc --noEmit
pnpm --prefix ./packages/backend.ai-ui exec tsc --noEmit
```

6. **If TypeScript errors occur**, fix them before proceeding:
5. **If TypeScript errors occur**, fix them before proceeding:
- Review the error messages to identify which updated packages caused the issue
- Common fixes include:
- Updating type definitions (`@types/*` packages)
- Adjusting code to match new API signatures
- Adding type assertions where needed
- Fix all errors before completing the version bump

7. **Run build to ensure everything compiles**:
6. **Run build to ensure everything compiles**:

```bash
pnpm run build
Expand All @@ -172,9 +146,6 @@ pnpm update --ignore-engines

# Install to update lockfile
pnpm install

# Merge per-branch lockfiles back into pnpm-lock.yaml
pnpm install --merge-git-branch-lockfiles
```

## Output Summary
Expand All @@ -184,9 +155,8 @@ After completion, provide a summary including:
1. **Version Update**: Old version -> New version
2. **Files Updated**: List of files modified by `make versiontag`
3. **Dependencies Updated**: Summary of updated packages with version changes
4. **Branch Lockfiles Merged**: List of `pnpm-lock.*.yaml` files removed (empty if none existed)
5. **Peer Dependency Warnings**: Any warnings encountered
6. **Next Steps**: Suggest committing changes if everything looks good
4. **Peer Dependency Warnings**: Any warnings encountered
5. **Next Steps**: Suggest committing changes if everything looks good

## Example Workflow

Expand All @@ -198,9 +168,8 @@ Claude:
2. Runs make versiontag
3. Updates dependencies in react/ and packages/backend.ai-ui/
4. Runs pnpm install
5. Runs pnpm install --merge-git-branch-lockfiles to fold stale branch lockfiles into pnpm-lock.yaml
6. Runs typecheck + build
7. Provides summary of all changes
5. Runs typecheck + build
6. Provides summary of all changes
```

## Notes
Expand Down
99 changes: 99 additions & 0 deletions .claude/rules/pnpm-lockfile-conflicts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
description: When resolving pnpm-lock.yaml merge/rebase conflicts, always take main's version and re-run pnpm install instead of hand-merging
---

# pnpm-lock.yaml Conflict Resolution Rule

When `pnpm-lock.yaml` conflicts during a merge, rebase, `gt sync`, or `gt restack`, **always take the main branch's version** rather than hand-merging the lockfile. Then run `pnpm install` to let pnpm reconcile any new dependencies from your branch's `package.json` / `pnpm-workspace.yaml`.

## Why

`pnpm-lock.yaml` is a large, auto-generated artifact. It is effectively a deterministic function of:

- `package.json` (in each workspace)
- `pnpm-workspace.yaml` (catalog, overrides, patched dependencies, minimum release age policy)
- pnpm's resolver

Hand-merging two versions of this file is error-prone — humans regularly miss transitive dependency mismatches, integrity hashes, or peer dependency notes, producing a lockfile that parses but doesn't correspond to a valid resolution state. CI then fails on `pnpm install --frozen-lockfile`, often in ways that point at the wrong root cause.

Since FR-2866 disabled `gitBranchLockfile`, every branch writes to the same canonical `pnpm-lock.yaml`. The cleanest resolution path is: take main's lockfile, then let pnpm re-resolve any new deps your branch added. pnpm will deterministically rewrite the file to match the post-merge `package.json` state — you don't lose your branch's dep changes, they're just re-derived.

## Pattern

### ✅ Recommended — `git restore --source=main` (context-independent)

```bash
# Works the same in merge, rebase, gt sync, gt restack
git restore --source=main pnpm-lock.yaml
pnpm install
git add pnpm-lock.yaml
# then continue: git rebase --continue / gt continue / git commit
```

`--source=main` explicitly names the source, so the command behaves identically whether you're in a merge or a rebase. Memorize this one form.

### ✅ Also correct — `git checkout --theirs` (during `git merge`)

```bash
# After: git merge main → conflict in pnpm-lock.yaml
git checkout --theirs pnpm-lock.yaml
pnpm install
git add pnpm-lock.yaml
git commit
```

In a **merge**, `--theirs` = the branch being merged in (main).

### ⚠️ Correct but reversed semantics — `git checkout --ours` (during rebase / `gt sync` / `gt restack`)

```bash
# After: gt sync, gt restack, or git rebase main → conflict in pnpm-lock.yaml
git checkout --ours pnpm-lock.yaml
pnpm install
git add pnpm-lock.yaml
git rebase --continue # or: gt continue
```

In a **rebase**, `--ours` and `--theirs` are swapped relative to merge: `--ours` = the base you're rebasing onto (main), `--theirs` = the commit being replayed (your branch). This is a well-known Git footgun. If you're unsure which context you're in, fall back to `git restore --source=main pnpm-lock.yaml` from the recommended pattern.

### ❌ Wrong — hand-merging the conflict markers

```yaml
# DO NOT do this
<<<<<<< HEAD
'@some/pkg':
version: 1.0.0
=======
'@some/pkg':
version: 1.1.0
>>>>>>> main
```

Lockfile conflict regions can span hundreds of lines and reference interconnected `packages:`, `snapshots:`, and `importers:` sections. Hand-editing them produces lockfiles that pass parsing but fail `pnpm install --frozen-lockfile` in CI.

### ❌ Wrong — taking main's lockfile and skipping `pnpm install`

```bash
git restore --source=main pnpm-lock.yaml
git add pnpm-lock.yaml
git commit # ← problem: if your branch added new deps to package.json,
# they aren't in main's lockfile yet, so CI will fail on
# pnpm install --frozen-lockfile.
```

Always run `pnpm install` after restoring. pnpm will re-resolve any new deps your branch introduced and write a coherent lockfile.

## Rules

1. **Default**: `git restore --source=main pnpm-lock.yaml` — same command for merge and rebase.
2. **Always follow up with `pnpm install`** so pnpm reconciles any new deps from your branch's `package.json` / `pnpm-workspace.yaml`.
3. **Never hand-merge `pnpm-lock.yaml`** — the file is auto-generated; let the tool that owns it (pnpm) regenerate it.
4. **Mind the rebase / merge swap** when using `--ours` / `--theirs`. In rebase, `--ours` is main; in merge, `--theirs` is main. When in doubt, use `--source=main`.
5. **Same rule applies during `gt sync` and `gt restack`** — both use rebase semantics under the hood. Resolve with `git restore --source=main pnpm-lock.yaml`, run `pnpm install`, then `gt continue`.
6. **Don't escalate routine lockfile conflicts** — they almost always resolve via this recipe. Escalate only if `pnpm install` itself fails after taking main's lockfile (which typically points at a real `package.json` / `pnpm-workspace.yaml` problem, not a lockfile problem).

## Related

- `pnpm-workspace.yaml` — the canonical source of truth for catalog, overrides, patched dependencies, and the `minimumReleaseAge` policy.
- FR-2866 (PR #7359) — disabled `gitBranchLockfile`, making `pnpm-lock.yaml` the single shared lockfile across all branches.
- pnpm docs on lockfile conflicts: <https://pnpm.io/git#dealing-with-merge-conflicts>
53 changes: 0 additions & 53 deletions .github/workflows/weekly-merge-branch-lockfiles.yml

This file was deleted.

2 changes: 0 additions & 2 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ catalog:
uuid: ^13.0.0
webpack: ^5.106.1

gitBranchLockfile: true

enableGlobalVirtualStore: true

minimumReleaseAge: 10080
Expand Down
Loading