Sync Flywheel Upstream #51
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
| name: Sync Flywheel Upstream | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' # Daily at midnight | |
| workflow_dispatch: | |
| concurrency: | |
| group: upstream-sync | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| sync: | |
| runs-on: ubuntu-latest | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PUSH_TOKEN: ${{ secrets.UPSTREAM_SYNC_TOKEN }} | |
| MAIN_BRANCH: main | |
| TARGET_BRANCH: local-desktop-installation-support | |
| SYNC_BRANCH: upstream-sync | |
| UPSTREAM_URL: https://github.com/Dicklesworthstone/agentic_coding_flywheel_setup.git | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ env.MAIN_BRANCH }} | |
| token: ${{ secrets.UPSTREAM_SYNC_TOKEN != '' && secrets.UPSTREAM_SYNC_TOKEN || secrets.GITHUB_TOKEN }} | |
| - name: Warn if mirror token is missing | |
| if: env.PUSH_TOKEN == '' | |
| run: | | |
| echo "::warning::UPSTREAM_SYNC_TOKEN is not configured. Pushes that update .github/workflows may be rejected." | |
| - name: Configure Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: latest | |
| - name: Add and Fetch Upstream | |
| run: | | |
| if git remote get-url upstream >/dev/null 2>&1; then | |
| git remote set-url upstream "$UPSTREAM_URL" | |
| else | |
| git remote add upstream "$UPSTREAM_URL" | |
| fi | |
| git fetch upstream | |
| # Step 1: Sync fork's main branch with upstream/main (Pure Mirror) | |
| - name: Sync Main Branch with Upstream | |
| run: | | |
| echo "Syncing fork's main branch with upstream/main..." | |
| # Hard reset main to match upstream/main exactly | |
| git checkout "$MAIN_BRANCH" | |
| git reset --hard upstream/main | |
| # Force push to update the fork's main branch | |
| git push -f origin "$MAIN_BRANCH" | |
| echo "✅ Fork's main branch is now a pure mirror of upstream/main" | |
| # Step 2: Merge main into local-desktop-installation-support | |
| - name: Prepare Integration Branch | |
| run: | | |
| # Checkout the integration branch | |
| git checkout "$TARGET_BRANCH" | |
| # Create/reset sync branch from target for the merge | |
| git checkout -B "$SYNC_BRANCH" "$TARGET_BRANCH" | |
| - name: Merge Main into Integration Branch | |
| id: merge | |
| continue-on-error: true | |
| run: | | |
| # Attempt to merge main (which is now synced with upstream) into the integration branch | |
| if git merge "$MAIN_BRANCH" --no-edit; then | |
| echo "merge_status=success" >> "$GITHUB_OUTPUT" | |
| echo "Merge successful." | |
| else | |
| echo "merge_status=conflict" >> "$GITHUB_OUTPUT" | |
| echo "Merge conflict detected." | |
| fi | |
| - name: Handle Conflicts | |
| if: steps.merge.outputs.merge_status == 'conflict' | |
| run: | | |
| echo "Committing conflict markers..." | |
| # Add all files with conflict markers | |
| git add . | |
| git commit -m "Merge main into $TARGET_BRANCH (with conflicts)" | |
| - name: Push Sync Branch | |
| run: | | |
| git push -f origin "$SYNC_BRANCH" | |
| - name: Ensure Labels Exist | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Ensure labels exist to prevent errors during PR creation | |
| gh label create upstream-sync --repo ${{ github.repository }} --description "Syncs changes from upstream" --color 1d76db || true | |
| gh label create conflict --repo ${{ github.repository }} --description "Merge conflicts detected" --color b60205 || true | |
| # Step 3: Handle result based on merge status | |
| - name: Push Clean Merge Directly | |
| if: steps.merge.outputs.merge_status == 'success' | |
| run: | | |
| echo "Clean merge - pushing directly to $TARGET_BRANCH..." | |
| git push origin "$SYNC_BRANCH:$TARGET_BRANCH" | |
| echo "✅ Successfully synced to $TARGET_BRANCH" | |
| - name: Create Pull Request for Conflicts | |
| if: steps.merge.outputs.merge_status == 'conflict' | |
| run: | | |
| # Check if PR already exists | |
| existing_pr=$(gh pr list --repo ${{ github.repository }} --head "$SYNC_BRANCH" --base "$TARGET_BRANCH" --json number -q '.[0].number') | |
| if [[ -z "$existing_pr" ]]; then | |
| echo "Creating new PR for conflict resolution..." | |
| TITLE="⚠️ Upstream Sync (Conflicts Detected)" | |
| BODY="This PR syncs changes from upstream. **Conflicts were detected and committed with markers.** Please review and resolve them." | |
| PR_URL=$(gh pr create \ | |
| --repo ${{ github.repository }} \ | |
| --title "$TITLE" \ | |
| --body "$BODY" \ | |
| --head "$SYNC_BRANCH" \ | |
| --base "$TARGET_BRANCH" \ | |
| --label "upstream-sync" \ | |
| --label "conflict") | |
| echo "PR_URL=$PR_URL" >> "$GITHUB_ENV" | |
| else | |
| echo "Updating existing PR #$existing_pr..." | |
| echo "PR_URL=https://github.com/${{ github.repository }}/pull/$existing_pr" >> "$GITHUB_ENV" | |
| gh pr edit "$existing_pr" --repo ${{ github.repository }} \ | |
| --title "⚠️ Upstream Sync (Conflicts Detected)" \ | |
| --add-label "conflict" \ | |
| --body "Updates from upstream. Conflicts detected." | |
| fi | |
| - name: Analyze Conflicts with AI | |
| if: steps.merge.outputs.merge_status == 'conflict' && env.OPENAI_API_KEY != '' | |
| run: | | |
| echo "Analyzing conflicts..." | |
| # Run the analysis script | |
| bun run ./scripts/analyze-conflicts.ts "${{ env.PR_URL }}" |