@@ -103,88 +103,206 @@ jobs:
103103 sync_branch="sync-main-to-${{ matrix.target_branch }}-$(date +%Y%m%d-%H%M%S)"
104104 git checkout -b "$sync_branch" ${{ matrix.target_branch }}
105105
106- # Get the commits that need to be applied
107- commits_to_apply=$(git log "${{ matrix.target_branch }}..main" --oneline --no-merges | cut -d' ' -f1 | tac)
108-
109- if [ -n "$commits_to_apply" ]; then
110- echo "📋 Applying commits: $commits_to_apply"
106+ # Get ALL commits that need to be applied (including merge commits)
107+ # First, get the merge base to ensure we have the correct starting point
108+ merge_base=$(git merge-base ${{ matrix.target_branch }} main)
109+ echo "📍 Merge base: $merge_base"
110+
111+ # Get all commits in main that are not in target branch (including merges)
112+ # Store commits in a temp file to avoid subshell issues
113+ git log "$merge_base..main" --format="%H" --reverse > /tmp/commits_to_apply.txt
114+
115+ # Also get commits using the simpler range (as fallback)
116+ if [ ! -s /tmp/commits_to_apply.txt ]; then
117+ git log "${{ matrix.target_branch }}..main" --format="%H" --reverse > /tmp/commits_to_apply.txt
118+ fi
111119
120+ if [ -s /tmp/commits_to_apply.txt ]; then
121+ echo "📋 Found commits to apply:"
122+ while read commit; do
123+ commit_msg=$(git log -1 --format="%s" "$commit")
124+ echo " - $commit: $commit_msg"
125+ done < /tmp/commits_to_apply.txt
126+
127+ # Track failed commits for reporting
128+ failed_commits_file="/tmp/failed_commits.txt"
129+ touch "$failed_commits_file"
130+ successful_count=0
131+ failed_count=0
132+
112133 # Cherry-pick each commit individually to avoid merge conflicts
113- for commit in $commits_to_apply; do
114- echo "🍒 Cherry-picking $commit..."
115- if git cherry-pick --no-commit "$commit"; then
134+ while read commit; do
135+ commit_msg=$(git log -1 --format="%s" "$commit")
136+ echo "🍒 Cherry-picking $commit: $commit_msg"
137+
138+ # Try cherry-pick with conflict resolution
139+ if git cherry-pick --no-commit "$commit" 2>&1; then
116140 echo "✅ Cherry-pick successful for $commit"
141+ successful_count=$((successful_count + 1))
117142 else
118- echo "⚠️ Cherry-pick failed for $commit, skipping..."
119- git cherry-pick --abort || true
120- git reset --hard HEAD
143+ # Check if it's already applied (empty commit)
144+ if git status --porcelain | grep -q "^UU"; then
145+ # Has conflicts
146+ echo "⚠️ Conflicts detected for $commit, will include via merge"
147+ git cherry-pick --abort || true
148+ echo "$commit" >> "$failed_commits_file"
149+ failed_count=$((failed_count + 1))
150+ elif git diff --cached --quiet && git diff --quiet; then
151+ # Empty commit, already applied
152+ echo "ℹ️ Commit $commit already applied (empty), skipping..."
153+ git cherry-pick --abort || true
154+ else
155+ # Other error, try to continue
156+ echo "⚠️ Cherry-pick had issues for $commit, attempting to continue..."
157+ git add -A || true
158+ if git cherry-pick --continue 2>&1; then
159+ echo "✅ Resolved and applied $commit"
160+ successful_count=$((successful_count + 1))
161+ else
162+ echo "❌ Could not resolve $commit, will include in merge"
163+ git cherry-pick --abort || true
164+ echo "$commit" >> "$failed_commits_file"
165+ failed_count=$((failed_count + 1))
166+ fi
167+ fi
121168 fi
122- done
123-
124- # Reset .csproj files to target branch versions
125- echo "📝 Resetting .csproj files to ${{ matrix.target_branch }} versions..."
126- find . -name "*.csproj" -type f -exec git checkout ${{ matrix.target_branch }} -- {} \;
127-
128- # Update version and target framework in Directory.Build.props
129- dotnet_version=$(echo "${{ matrix.target_branch }}" | sed 's/[^0-9]*//g')
130- echo "dotnet_version=$dotnet_version" >> $GITHUB_ENV
131- if [ -f "src/Directory.Build.props" ]; then
132- echo "🔄 Updating version and target framework to .NET $dotnet_version..."
133- # Update version number (9.0.x → 8.0.x)
134- sed -i "s/<Version>9\.0\./<Version>$dotnet_version.0./g" src/Directory.Build.props
135- # Update target framework (net9.0 → net8.0)
136- sed -i "s/<TargetFramework>net9\.0</<TargetFramework>net$dotnet_version.0</g" src/Directory.Build.props
137- fi
138-
139- # Stage all changes
169+ done < /tmp/commits_to_apply.txt
170+
171+ # If we have failed commits OR want to ensure all changes are included, do a merge
172+ # This ensures ALL changes from main are included, even if cherry-pick missed some
173+ echo "🔄 Ensuring all changes from main are included..."
174+
175+ # First, check what files differ between our current state and main
140176 git add -A
141-
142- # Check if there are changes to commit
143- if git diff --cached --quiet; then
144- echo "ℹ️ No changes to commit after processing"
145- git checkout main
146- git branch -D "$sync_branch"
147- exit 0
177+ current_diff=$(git diff --cached --name-only)
178+
179+ # Now merge main to get ALL changes (this is a safety net)
180+ if git merge --no-commit --no-ff main -m "Merge main to include all missing commits" 2>&1; then
181+ echo "✅ Merge successful, all commits from main are now included"
182+ else
183+ # Merge has conflicts, resolve by keeping target branch files where specified
184+ echo "⚠️ Merge has conflicts, will resolve by keeping target branch files where needed"
185+ # Conflicts will be resolved in the file reset section below
148186 fi
149-
150- # Commit the changes
151- git commit -m "Sync changes from main to ${{ matrix.target_branch }} - Applied recent commits, updated versions & framework, preserved .csproj files"
152-
153- echo "📤 Attempting to push sync branch: $sync_branch"
154187
155- # Try to push to origin, if it fails try to push to a fork
156- if git push origin "$sync_branch" 2>/dev/null; then
157- echo "✅ Pushed to origin successfully"
158- PUSH_REPO="${{ github.repository }}"
188+ echo "📊 Summary: $successful_count successful cherry-picks, $failed_count failed (included via merge)"
189+ else
190+ # Even if no commits found via log, check if there are file differences
191+ echo "ℹ️ No commits found via log, checking for file differences..."
192+
193+ # Check if there are any differences between branches
194+ if git diff --quiet ${{ matrix.target_branch }} main; then
195+ echo "✅ No differences found, branches are in sync"
196+ git checkout main
197+ git branch -D "$sync_branch" 2>/dev/null || true
198+ exit 0
159199 else
160- echo "⚠️ Cannot push to origin, trying fork approach..."
200+ echo "⚠️ Found file differences despite no commits in log"
201+ echo "This might indicate missing changes. Attempting merge to include them..."
161202
162- # Check if we have a fork configured
163- FORK_OWNER="${{ vars.FORK_OWNER || 'arcenox' }}"
164- FORK_URL="https://${{ secrets.PAT_TOKEN }}@github.com/${FORK_OWNER}/TickerQ.git"
165-
166- # Add fork as remote if not exists
167- git remote add fork "$FORK_URL" 2>/dev/null || git remote set-url fork "$FORK_URL"
168-
169- # Push to fork
170- if git push fork "$sync_branch"; then
171- echo "✅ Pushed to fork: ${FORK_OWNER}/TickerQ"
172- PUSH_REPO="${FORK_OWNER}/TickerQ"
203+ # Try a merge to catch any missing changes
204+ if git merge --no-commit --no-ff main -m "Merge main to include missing changes" 2>&1; then
205+ echo "✅ Merge successful, missing changes included"
173206 else
174- echo "❌ Failed to push to both origin and fork"
175- exit 1
207+ echo "⚠️ Merge has conflicts, will resolve"
176208 fi
177209 fi
210+ fi
211+
212+ # Reset files that should stay as they are in the target branch
213+ # (This runs for both the if and else branches above)
214+ echo "📝 Processing configuration files..."
215+
216+ # Reset all .csproj files
217+ find . -name "*.csproj" -type f -exec git checkout ${{ matrix.target_branch }} -- {} \;
218+
219+ # Get Directory.Build.props from main and update it for net8
220+ if [ -f "src/Directory.Build.props" ]; then
221+ echo "📝 Getting Directory.Build.props from main and updating for ${{ matrix.target_branch }}..."
222+
223+ # Explicitly get the file from main branch
224+ git checkout main -- src/Directory.Build.props
225+
226+ # Get the target .NET version
227+ dotnet_version=$(echo "${{ matrix.target_branch }}" | sed 's/[^0-9]*//g')
228+
229+ # Show current state from main
230+ echo "Directory.Build.props from main (before update):"
231+ grep -E "<Version>|<TargetFramework>" src/Directory.Build.props
232+
233+ # Update version (9.x.x → 8.x.x) keeping the same minor/patch/suffix
234+ current_version=$(grep -oP '<Version>\K[^<]+' src/Directory.Build.props)
235+ new_version=$(echo "$current_version" | sed "s/^9\./$dotnet_version./")
236+ sed -i "s|<Version>$current_version</Version>|<Version>$new_version</Version>|g" src/Directory.Build.props
237+
238+ # Update target framework (net9.0 → net8.0)
239+ sed -i "s|<TargetFramework>net9\.0</TargetFramework>|<TargetFramework>net$dotnet_version.0</TargetFramework>|g" src/Directory.Build.props
240+
241+ echo "Directory.Build.props after update:"
242+ grep -E "<Version>|<TargetFramework>" src/Directory.Build.props
243+ fi
244+
245+ # Reset workflow files to avoid including workflow changes in the PR
246+ echo "📝 Resetting workflow files to ${{ matrix.target_branch }} version..."
247+ if [ -d ".github/workflows" ]; then
248+ git checkout ${{ matrix.target_branch }} -- .github/workflows/ || true
249+ fi
178250
179- # Store branch name and repo for PR creation
180- echo "sync_branch=$sync_branch" >> $GITHUB_ENV
181- echo "push_repo=$PUSH_REPO" >> $GITHUB_ENV
182- else
183- echo "ℹ️ No commits to apply"
251+
252+ # Stage all changes
253+ git add -A
254+
255+ # Show what files have changes
256+ echo "📋 Files with changes after cherry-pick and reset:"
257+ git diff --cached --name-status
258+
259+ # Show actual changes
260+ echo "📝 Actual changes to be committed:"
261+ git diff --cached --stat
262+
263+ # Check if there are changes to commit
264+ if git diff --cached --quiet; then
265+ echo "ℹ️ No changes to commit after processing"
266+ echo "This means all changes from main are already in ${{ matrix.target_branch }}"
267+ echo "or only affected .csproj/Directory.Build.props files which we reset."
184268 git checkout main
269+ git branch -D "$sync_branch"
185270 exit 0
186271 fi
187272
273+ # Commit the changes
274+ git commit -m "Sync changes from main to ${{ matrix.target_branch }} - Applied recent commits, updated versions & framework, preserved .csproj files"
275+
276+ echo "📤 Attempting to push sync branch: $sync_branch"
277+
278+ # Try to push to origin, if it fails try to push to a fork
279+ if git push origin "$sync_branch" 2>/dev/null; then
280+ echo "✅ Pushed to origin successfully"
281+ PUSH_REPO="${{ github.repository }}"
282+ else
283+ echo "⚠️ Cannot push to origin, trying fork approach..."
284+
285+ # Check if we have a fork configured
286+ FORK_OWNER="${{ vars.FORK_OWNER || 'arcenox' }}"
287+ FORK_URL="https://${{ secrets.PAT_TOKEN }}@github.com/${FORK_OWNER}/TickerQ.git"
288+
289+ # Add fork as remote if not exists
290+ git remote add fork "$FORK_URL" 2>/dev/null || git remote set-url fork "$FORK_URL"
291+
292+ # Push to fork
293+ if git push fork "$sync_branch"; then
294+ echo "✅ Pushed to fork: ${FORK_OWNER}/TickerQ"
295+ PUSH_REPO="${FORK_OWNER}/TickerQ"
296+ else
297+ echo "❌ Failed to push to both origin and fork"
298+ exit 1
299+ fi
300+ fi
301+
302+ # Store branch name and repo for PR creation
303+ echo "sync_branch=$sync_branch" >> $GITHUB_ENV
304+ echo "push_repo=$PUSH_REPO" >> $GITHUB_ENV
305+
188306 - name : Ensure labels exist
189307 if : steps.check_merge.outputs.needs_merge == 'true'
190308 run : |
0 commit comments