From 68a7445d7b2fe3c1d971b57888c73cbc14ae32c7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 27 Mar 2026 22:43:21 +0000 Subject: [PATCH 1/2] Auto-resolve known conflict categories in upstream sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the merge has conflicts, automatically resolve files that the fork never customizes: - docs/ — generated reference docs (take upstream, autofix CI regenerates) - .github/workflows/release.yml — deleted in fork (keep deleted) - packages/*/CHANGELOG.md — upstream changelogs (take upstream) - pnpm-lock.yaml — lockfile (take upstream) - examples/**/package.json — example deps (take upstream) If any conflicts remain outside these categories, the workflow aborts with a clear error listing the files that need manual intervention. Auto-resolved files are listed in the PR body for visibility. https://claude.ai/code/session_01QCPv9A7pkCeR42zoJ9fujU --- .github/workflows/sync-upstream.yml | 85 +++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 7e10c306a..e02380122 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -88,6 +88,7 @@ jobs: - name: Merge upstream into fork branch if: steps.compare.outputs.needs_sync == 'true' && steps.check_pr.outputs.pr_exists == 'false' + id: merge run: | VERSION=${{ steps.compare.outputs.upstream_version }} DATE=${{ steps.compare.outputs.date }} @@ -100,11 +101,75 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - # Merge upstream main into our branch + # Attempt the merge — allow failure so we can auto-resolve conflicts echo "Merging upstream/main into fork branch..." - git merge upstream/main -m "Merge upstream TanStack Pacer v${VERSION} into fork" + if git merge upstream/main -m "Merge upstream TanStack Pacer v${VERSION} into fork"; then + echo "Merge completed cleanly" + echo "auto_resolved=" >> "$GITHUB_OUTPUT" + git push origin "$BRANCH" + exit 0 + fi + + echo "Merge has conflicts — attempting auto-resolution..." + CONFLICTED=$(git diff --name-only --diff-filter=U) + + # ── Auto-resolution rules ───────────────────────────────────── + # Each rule handles a category of files that we never customize + # in the fork and can safely resolve automatically. + AUTO_RESOLVED="" + UNRESOLVED="" + + for FILE in $CONFLICTED; do + case "$FILE" in + # Generated docs — take upstream; autofix CI regenerates them + docs/*) + git checkout --theirs -- "$FILE" && git add "$FILE" + AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream — generated docs)\n" + ;; + # CI workflows deleted in fork (e.g. release.yml) — keep deleted + .github/workflows/release.yml) + git rm -f "$FILE" 2>/dev/null || true + AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (kept deleted — fork uses publish-fork.yml)\n" + ;; + # Upstream changelogs — take upstream; fork doesn't add entries + packages/*/CHANGELOG.md) + git checkout --theirs -- "$FILE" && git add "$FILE" + AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream — changelog)\n" + ;; + # Lockfile — take upstream; will be validated by CI + pnpm-lock.yaml) + git checkout --theirs -- "$FILE" && git add "$FILE" + AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream — lockfile)\n" + ;; + # Example app package.json — take upstream; fork doesn't modify examples + examples/*/package.json | examples/*/*/package.json) + git checkout --theirs -- "$FILE" && git add "$FILE" + AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream — example dep versions)\n" + ;; + # Everything else requires manual review + *) + UNRESOLVED="${UNRESOLVED} ${FILE}\n" + ;; + esac + done - # Push the branch + if [ -n "$AUTO_RESOLVED" ]; then + echo "Auto-resolved conflicts:" + echo -e "$AUTO_RESOLVED" + fi + + # If any conflicts remain that we can't auto-resolve, abort + REMAINING=$(git diff --name-only --diff-filter=U) + if [ -n "$REMAINING" ]; then + echo "::error::Unable to auto-resolve all conflicts. Manual intervention required:" + echo -e "$UNRESOLVED" + git merge --abort + exit 1 + fi + + # All conflicts resolved — complete the merge + git commit --no-edit + echo "auto_resolved=$(echo -e "$AUTO_RESOLVED" | base64 -w 0)" >> "$GITHUB_OUTPUT" git push origin "$BRANCH" - name: Create PR @@ -118,6 +183,18 @@ jobs: CHANGED=$(echo "${{ steps.compare.outputs.changed }}" | base64 -d) + AUTO_RESOLVED="" + if [ -n "${{ steps.merge.outputs.auto_resolved }}" ]; then + DECODED=$(echo "${{ steps.merge.outputs.auto_resolved }}" | base64 -d) + AUTO_RESOLVED="### Auto-resolved conflicts + + \`\`\` + ${DECODED} + \`\`\` + + " + fi + gh pr create \ --base main \ --head "$BRANCH" \ @@ -130,7 +207,7 @@ jobs: ${CHANGED} - ### After merging + ${AUTO_RESOLVED}### After merging The [publish-fork](${{ github.server_url }}/${{ github.repository }}/actions/workflows/publish-fork.yml) workflow will automatically publish any packages with changed versions. From 38a40f488ba9ad93ba2688f5e9d190cbdddbe5dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 27 Mar 2026 22:46:40 +0000 Subject: [PATCH 2/2] Reconcile lockfile with fork's package.json after conflict resolution After taking upstream's pnpm-lock.yaml during conflict resolution, run pnpm install --no-frozen-lockfile to incorporate any fork-specific dependencies from our root package.json. Adds the tanstack/config setup step so pnpm and Node are available for this. https://claude.ai/code/session_01QCPv9A7pkCeR42zoJ9fujU --- .github/workflows/sync-upstream.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index e02380122..e5bb1959d 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -86,6 +86,10 @@ jobs: echo "pr_exists=false" >> "$GITHUB_OUTPUT" fi + - name: Setup Tools + if: steps.compare.outputs.needs_sync == 'true' && steps.check_pr.outputs.pr_exists == 'false' + uses: tanstack/config/.github/setup@main + - name: Merge upstream into fork branch if: steps.compare.outputs.needs_sync == 'true' && steps.check_pr.outputs.pr_exists == 'false' id: merge @@ -136,10 +140,11 @@ jobs: git checkout --theirs -- "$FILE" && git add "$FILE" AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream — changelog)\n" ;; - # Lockfile — take upstream; will be validated by CI + # Lockfile — take upstream, then reconcile with fork's root package.json pnpm-lock.yaml) git checkout --theirs -- "$FILE" && git add "$FILE" - AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream — lockfile)\n" + AUTO_RESOLVED="${AUTO_RESOLVED} ${FILE} (took upstream + pnpm install to reconcile)\n" + NEEDS_LOCKFILE_RECONCILE=true ;; # Example app package.json — take upstream; fork doesn't modify examples examples/*/package.json | examples/*/*/package.json) @@ -167,6 +172,13 @@ jobs: exit 1 fi + # Reconcile lockfile if it was conflict-resolved + if [ "${NEEDS_LOCKFILE_RECONCILE:-}" = "true" ]; then + echo "Running pnpm install to reconcile lockfile with fork's package.json..." + pnpm install --no-frozen-lockfile + git add pnpm-lock.yaml + fi + # All conflicts resolved — complete the merge git commit --no-edit echo "auto_resolved=$(echo -e "$AUTO_RESOLVED" | base64 -w 0)" >> "$GITHUB_OUTPUT"