Files
2026-02-05 13:31:47 -03:00

333 lines
11 KiB
Markdown

# Upstream Merge Automation
Scripts for automating the merge of upstream opencode changes into Kilo.
## Quick Start
```bash
# Install dependencies (from script/upstream directory)
cd script/upstream
bun install
# List available upstream versions
bun run list-versions.ts
# Analyze changes for a specific version (without merging)
bun run analyze.ts --version v1.1.49
# Run the full merge process
bun run merge.ts --version v1.1.49
# Dry-run to preview what would happen
bun run merge.ts --version v1.1.49 --dry-run
# Use a different base branch (e.g., for incremental merges)
bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44
```
## Scripts
### Main Scripts
| Script | Description |
| ------------------ | --------------------------------------------- |
| `merge.ts` | Main orchestration script for upstream merges |
| `list-versions.ts` | List available upstream versions |
| `analyze.ts` | Analyze changes without merging |
### Transform Scripts
| Script | Description |
| -------------------------------------- | ----------------------------------------------------------- |
| `transforms/package-names.ts` | Transform opencode package names to kilo |
| `transforms/preserve-versions.ts` | Preserve Kilo's package versions |
| `transforms/keep-ours.ts` | Keep Kilo's version of specific files |
| `transforms/skip-files.ts` | Skip/remove files that shouldn't exist in Kilo |
| `transforms/transform-i18n.ts` | Transform i18n files with Kilo branding |
| `transforms/transform-take-theirs.ts` | Take upstream + apply Kilo branding for branding-only files |
| `transforms/transform-tauri.ts` | Transform Tauri/Desktop config files |
| `transforms/transform-package-json.ts` | Enhanced package.json with Kilo dependency injection |
| `transforms/transform-scripts.ts` | Transform script files with GitHub API references |
| `transforms/transform-extensions.ts` | Transform extension files (Zed, etc.) |
| `transforms/transform-web.ts` | Transform web/docs files (.mdx) |
### Codemods (AST-based)
| Script | Description |
| ------------------------------- | ------------------------------------------ |
| `codemods/transform-imports.ts` | Transform import statements using ts-morph |
| `codemods/transform-strings.ts` | Transform string literals |
## Merge Process
The merge automation follows this process, applying **all transformations BEFORE the merge** to minimize conflicts:
1. **Validate environment**
- Check for upstream remote
- Ensure working directory is clean
2. **Fetch upstream** and determine target version
3. **Generate conflict report** analyzing which files will conflict
4. **Create branches**
- `backup/<branch>-<timestamp>` - Backup of current state
- `<author>/kilo-opencode-<version>` - Merge target branch
- `<author>/opencode-<version>` - Transformed upstream branch
5. **Apply ALL transformations to upstream branch (PRE-MERGE)**:
- Transform package names (opencode-ai -> @kilocode/cli)
- Preserve Kilo's versions
- Transform i18n files with Kilo branding
- Transform branding-only files (UI components, configs)
- Transform Tauri/Desktop config files
- Transform package.json files (names, deps, Kilo injections)
- Transform script files (GitHub API references)
- Transform extension files (Zed, etc.)
- Transform web/docs files
- Reset Kilo-specific files
6. **Merge** transformed upstream into Kilo branch
- Since all branding transforms are applied pre-merge, conflicts should be minimal
- Remaining conflicts are files with actual code differences (kilocode_change markers)
7. **Auto-resolve** any remaining conflicts
- Skip files that shouldn't exist in Kilo
- Keep Kilo's version of specific files
- Fallback transforms for edge cases
8. **Push** and generate final report
## Configuration
Configuration is defined in `utils/config.ts`:
```typescript
{
// Package name mappings
packageMappings: [
{ from: "opencode-ai", to: "@kilocode/cli" },
{ from: "@opencode-ai/cli", to: "@kilocode/cli" },
// ...
],
// Files to always keep Kilo's version (never take upstream)
keepOurs: [
"README.md",
"CONTRIBUTING.md",
"AGENTS.md",
".github/workflows/publish.yml", // GitHub workflows - manual review
// ...
],
// Files to skip entirely (remove from merge)
skipFiles: [
"README.*.md", // Translated READMEs
"STATS.md",
".github/workflows/update-nix-hashes.yml",
// ...
],
// Files to take upstream + apply Kilo branding transforms
takeTheirsAndTransform: [
"packages/app/src/components/**/*.tsx",
"packages/app/src/context/**/*.tsx",
"packages/ui/src/**/*.tsx",
// ...
],
// Tauri/Desktop config files
tauriFiles: [
"packages/desktop/src-tauri/*.json",
"packages/desktop/src-tauri/src/*.rs",
// ...
],
// Kilo-specific directories (preserved)
kiloDirectories: [
"packages/opencode/src/kilocode",
"packages/kilo-gateway",
"packages/kilo-telemetry",
// ...
],
}
```
## Pre-Merge Transformation Strategy
**Key insight**: By applying all branding transforms to the upstream branch BEFORE merging, we eliminate most conflicts that would otherwise occur due to branding differences (OpenCode -> Kilo).
### Transform Order (Pre-Merge)
The following transforms are applied to the opencode branch before merging:
1. **Package names** - `opencode-ai` -> `@kilocode/cli`, etc.
2. **Versions** - Preserve Kilo's version numbers
3. **i18n files** - OpenCode -> Kilo in user-visible strings
4. **Branding files** - UI components, configs with branding only
5. **Tauri configs** - Desktop app identifiers, names
6. **package.json** - Names, dependencies, Kilo injections
7. **Scripts** - GitHub API references
8. **Extensions** - Zed, etc.
9. **Web/docs** - Documentation files
### Post-Merge Strategies
After merging, any remaining conflicts are handled based on file type:
| File Type | Strategy | Description |
| ----------------- | ----------------------- | ------------------------------------------------ |
| i18n files | `i18n-transform` | Take upstream, apply Kilo branding |
| App components | `take-theirs-transform` | Take upstream, apply branding (no logic changes) |
| Tauri configs | `tauri-transform` | Take upstream, transform identifiers/names |
| package.json | `package-transform` | Take upstream, transform names, inject Kilo deps |
| Script files | `script-transform` | Take upstream, transform GitHub references |
| Extensions | `extension-transform` | Take upstream, apply branding |
| Web/docs | `web-transform` | Take upstream, apply branding |
| README/docs | `keep-ours` | Keep Kilo's version |
| GitHub workflows | `keep-ours` | Keep Kilo's version (manual review) |
| Code with markers | `manual` | Has `kilocode_change` markers, needs review |
### Why This Reduces Conflicts
Previously, conflicts occurred because:
- Upstream had `OpenCode` branding
- Kilo had `Kilo` branding
- Git saw these as conflicting changes
Now:
- We transform upstream to `Kilo` branding BEFORE merge
- Both branches have the same branding
- Git sees no conflict for branding-only files
The only remaining conflicts are files with **actual code differences** - files with `kilocode_change` markers that contain Kilo-specific logic.
## CLI Options
### merge.ts
```
Options:
--version <version> Target upstream version (e.g., v1.1.49)
--commit <hash> Target upstream commit hash
--base-branch <name> Base branch to merge into (default: dev)
--dry-run Preview changes without applying them
--no-push Don't push branches to remote
--report-only Only generate conflict report
--verbose Enable verbose logging
--author <name> Author name for branch prefix
```
### analyze.ts
```
Options:
--version <version> Target upstream version
--commit <hash> Target commit hash
--base-branch <name> Base branch to analyze from (default: dev)
--output <file> Output file for report
```
## Using Custom Base Branches
By default, upstream merges start from the `dev` branch. However, you can use `--base-branch` to start from a different branch. This is useful for:
### Incremental Merges
When working on multiple upstream versions, you can create a chain of merge PRs:
```bash
# First merge: v1.1.44 into dev
bun run merge.ts --version v1.1.44
# Create PR: catrielmuller/kilo-opencode-v1.1.44 -> dev
# Second merge: v1.1.50 based on the previous PR (without waiting for approval)
bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44
# Create PR: catrielmuller/kilo-opencode-v1.1.50 -> catrielmuller/kilo-opencode-v1.1.44
# OR: catrielmuller/kilo-opencode-v1.1.50 -> dev (once first PR is merged)
```
### Benefits
- **Work in parallel**: Don't wait for PR approval to start the next merge
- **Isolation**: Each merge is independent and easier to review
- **Flexibility**: Can adjust the PR chain as needed
- **Cleaner history**: Related merges can be grouped together
### Example Workflow
```bash
# 1. Analyze next version from your WIP branch
bun run analyze.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44
# 2. Run the merge
bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.1.44
# 3. Create PR from catrielmuller/kilo-opencode-v1.1.50
# - Target: catrielmuller/kilo-opencode-v1.1.44 (if first PR not merged yet)
# - Target: dev (if first PR is already merged)
```
## Manual Conflict Resolution
After running the merge script, you may have remaining conflicts. To resolve:
1. Open each conflicted file
2. Look for `kilocode_change` markers to identify Kilo-specific code
3. Resolve conflicts, keeping Kilo-specific changes
4. Stage and commit:
```bash
git add -A
git commit -m "resolve merge conflicts"
```
## Rollback
If something goes wrong:
```bash
# Find your backup branch
git branch | grep backup
# Reset to backup
git checkout dev
git reset --hard backup/dev-<timestamp>
```
## Adding New Transformations
### String-based (simple)
Edit `transforms/package-names.ts` and add patterns to `PACKAGE_PATTERNS`.
### AST-based (robust)
1. Create a new file in `codemods/`
2. Use ts-morph for TypeScript AST manipulation
3. Export transform functions
4. Add to the merge orchestration if needed
## Troubleshooting
### "No upstream remote found"
```bash
git remote add upstream git@github.com:anomalyco/opencode.git
```
### "Working directory has uncommitted changes"
```bash
git stash
# or
git commit -am "WIP"
```
### Merge conflicts after auto-resolution
Some files require manual review. Check the generated report for guidance.