fix(gh-workflows): handle tree-level merge conflicts in upstream sync - #98
Merged
Merged
Conversation
The upstream sync workflow failed on the last 2 runs because set -e killed the script before the fallback conflict resolution could run, and the fallback only detected content-level conflicts (--diff-filter=U) missing tree-level conflicts (rename/rename, modify/delete, rename/delete) in litellm/proxy/_experimental/out/ (Next.js build artifacts). Fix: capture merge exit code with || pattern to survive set -e, and use git ls-files --unmerged to detect all conflict types. Resolve each by checking MERGE_HEAD: accept upstream version or remove if deleted. Co-authored-by: Claude <noreply@anthropic.com>
Collaborator
Author
|
/gemini review |
…alidation Capture merge output for conflict type classification (rename/rename, modify/delete, rename/delete, content) and group unmerged files by directory using collapsible ::group:: blocks for cleaner CI logs. Add post-resolution validation that verifies no unmerged files remain after conflict resolution, failing the job early if something was missed rather than creating a broken merge commit. Include conflict type counts in the merge commit message for traceability. Co-authored-by: Claude <noreply@anthropic.com>
mateo-di
marked this pull request as ready for review
March 16, 2026 19:57
3 tasks
3 tasks
3 tasks
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the upstream sync workflow (
carto-upstream-sync-main.yml) which has failed on the last 2 runs due to unhandled tree-level merge conflicts in Next.js build artifacts.What Changed
Modified:
.github/workflows/carto-upstream-sync-main.yml— Merge + conflict resolution logic in thesync-main-branchjobRoot Cause
Two compounding bugs:
set -eukills the fallback — Thegit mergecommand was a standalone statement, so when it returned non-zero,set -eterminated the script immediately. The conflict resolution fallback on theelsebranch was dead code that never executed.Fallback only detected content conflicts — Even if it ran,
git diff --name-only --diff-filter=Uonly captures content-level (both-modified) conflicts. The actual conflicts were tree-level types that-X theirscannot resolve:rename/rename(3) — Next.js build hash directories renamed differently on both sidesrename/delete(8) — JS chunks renamed in HEAD but deleted in upstreammodify/delete(11) — Files modified on one side, deleted on the otherAll 22 conflicts were in
litellm/proxy/_experimental/out/(generated Next.js static build output).Fix
Commit 1: Core bug fix
Capture merge exit code safely — Use
git merge ... || MERGE_RESULT=$?pattern. The||makes this a compound command, soset -edoesn't trigger on the left side's failure.Detect all conflict types — Replace
git diff --diff-filter=Uwithgit ls-files --unmerged | awk '{print $4}' | sort -u, which captures every unmerged entry regardless of conflict type.Resolve per-file — For each unmerged path, check if it exists at
MERGE_HEAD(the upstream tag):git checkout MERGE_HEAD -- "$file"(accept upstream version)git rm -f "$file"(remove from tree)git add -Ato clean up orphaned rename artifactsCommit 2: Observability & safety improvements
Conflict classification — Capture merge output and parse
CONFLICT (type)lines to produce a typed summary (rename/rename, modify/delete, rename/delete, content) with collapsible::group::blocks.Directory grouping — Group unmerged files by top-level directory (3 path components) for at-a-glance understanding.
Post-resolution validation — After resolving all conflicts, verify
git ls-files --unmergedreturns 0 entries before committing. Fails the job if anything was missed.Commit message traceability — Include conflict type counts in the merge commit message.
Failed Runs (evidence)
v1.81.14-stable_experimental/out/v1.82.0-stableLocal Dry-Run Test Results
Ran the exact script against the real
v1.82.0-stabletag on an isolated local branch (never pushed). Results:Script Execution: PASSED
The merge failed as expected (same 22 CONFLICT lines as CI), then the fallback resolved all conflicts automatically.
Conflict Classification: PASSED
Resolution Actions
Post-Resolution Validation: PASSED
git ls-files --unmergedreturned 0 entries.File Integrity: PASSED
organizations/index.htmlrestoredteams/index.htmlrestoredtools/mcp-servers/index.htmlrestoredFNzcPu...removedC_XKHL...(HEAD rename) removedU_YrOO...presentpyproject.tomlversion1.82.0Productive Branches: UNTOUCHED
carto/main6452946origin/maineccba906Downstream Workflow Impact: NONE
Deep-dive analysis of all 6 upstream sync workflows confirmed no interference:
carto-upstream-sync-resolver.yml) — merges in opposite direction (carto/main into sync branch), unaffected.gitattributesor the specific conflict resolution method used insync-main-branchArchitectural Context
EAD: N/A - small change
Review Focus Areas
Critical areas:
.github/workflows/carto-upstream-sync-main.yml:162-264— The new merge + fallback logic. Verify the|| MERGE_RESULT=$?pattern is safe withset -eu, and thatgit ls-files --unmerged+git cat-file -e MERGE_HEAD:pathcorrectly handles all conflict types.Safe to skip: No other files changed.
Deployment Impact
Migration & Breaking Changes
Security Considerations
Performance Impact
Tests
Dependencies
How to Validate
carto/mainworkflow_dispatch)sync-main-branchjob succeeds and resolves tree-level conflicts automaticallyAI-Generated Code Notice
git ls-files --unmergedoutput parsing andgit cat-file -e MERGE_HEAD:pathbehave as expected for all conflict typesChecklist