Skip to content

Commit ce33ab6

Browse files
committed
ci(sync): implement integration branch pattern for upstream sync
Refactor the upstream-sync workflow to maintain main as a pure mirror of upstream/main, then merge into the integration branch. Clean merges are now pushed directly to local-desktop-installation-support, while conflicts trigger a PR for manual resolution. Add comprehensive documentation explaining the fork workflow strategy, branch roles, and daily development protocol.
1 parent 52f78c9 commit ce33ab6

2 files changed

Lines changed: 119 additions & 31 deletions

File tree

.github/workflows/upstream-sync.yml

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
runs-on: ubuntu-latest
1616
env:
1717
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
MAIN_BRANCH: main
1819
TARGET_BRANCH: local-desktop-installation-support
1920
SYNC_BRANCH: upstream-sync
2021
UPSTREAM_URL: https://github.com/Dicklesworthstone/agentic_coding_flywheel_setup.git
@@ -25,7 +26,7 @@ jobs:
2526
uses: actions/checkout@v4
2627
with:
2728
fetch-depth: 0
28-
ref: ${{ env.TARGET_BRANCH }}
29+
ref: ${{ env.MAIN_BRANCH }}
2930

3031
- name: Configure Git
3132
run: |
@@ -42,17 +43,35 @@ jobs:
4243
git remote add upstream "$UPSTREAM_URL"
4344
git fetch upstream
4445
45-
- name: Prepare Sync Branch
46+
# Step 1: Sync fork's main branch with upstream/main (Pure Mirror)
47+
- name: Sync Main Branch with Upstream
4648
run: |
47-
# Reset sync branch to target branch to ensure a clean slate
49+
echo "Syncing fork's main branch with upstream/main..."
50+
51+
# Hard reset main to match upstream/main exactly
52+
git checkout "$MAIN_BRANCH"
53+
git reset --hard upstream/main
54+
55+
# Force push to update the fork's main branch
56+
git push -f origin "$MAIN_BRANCH"
57+
58+
echo "✅ Fork's main branch is now a pure mirror of upstream/main"
59+
60+
# Step 2: Merge main into local-desktop-installation-support
61+
- name: Prepare Integration Branch
62+
run: |
63+
# Checkout the integration branch
64+
git checkout "$TARGET_BRANCH"
65+
66+
# Create/reset sync branch from target for the merge
4867
git checkout -B "$SYNC_BRANCH" "$TARGET_BRANCH"
4968
50-
- name: Merge Upstream
69+
- name: Merge Main into Integration Branch
5170
id: merge
5271
continue-on-error: true
5372
run: |
54-
# Attempt to merge. If conflicts, this will fail (exit 1)
55-
if git merge upstream/main --no-edit; then
73+
# Attempt to merge main (which is now synced with upstream) into the integration branch
74+
if git merge "$MAIN_BRANCH" --no-edit; then
5675
echo "merge_status=success" >> "$GITHUB_OUTPUT"
5776
echo "Merge successful."
5877
else
@@ -66,7 +85,7 @@ jobs:
6685
echo "Committing conflict markers..."
6786
# Add all files with conflict markers
6887
git add .
69-
git commit -m "Merge upstream/main (with conflicts)"
88+
git commit -m "Merge main into $TARGET_BRANCH (with conflicts)"
7089
7190
- name: Push Sync Branch
7291
run: |
@@ -83,23 +102,25 @@ jobs:
83102
# Debug: List labels to verify visibility
84103
gh label list --repo ${{ github.repository }}
85104
86-
- name: Create Pull Request
87-
if: steps.merge.outputs.merge_status == 'success' || steps.merge.outputs.merge_status == 'conflict'
105+
# Step 3: Handle result based on merge status
106+
- name: Push Clean Merge Directly
107+
if: steps.merge.outputs.merge_status == 'success'
108+
run: |
109+
echo "Clean merge - pushing directly to $TARGET_BRANCH..."
110+
git push origin "$SYNC_BRANCH:$TARGET_BRANCH"
111+
echo "✅ Successfully synced to $TARGET_BRANCH"
112+
113+
- name: Create Pull Request for Conflicts
114+
if: steps.merge.outputs.merge_status == 'conflict'
88115
run: |
89116
# Check if PR already exists
90117
existing_pr=$(gh pr list --repo ${{ github.repository }} --head "$SYNC_BRANCH" --base "$TARGET_BRANCH" --json number -q '.[0].number')
91118
92119
if [[ -z "$existing_pr" ]]; then
93-
echo "Creating new PR..."
94-
if [[ "${{ steps.merge.outputs.merge_status }}" == "conflict" ]]; then
95-
TITLE="⚠️ Upstream Sync (Conflicts Detected)"
96-
BODY="This PR syncs changes from upstream. **Conflicts were detected and committed with markers.** Please review and resolve them."
97-
LABELS="upstream-sync,conflict"
98-
else
99-
TITLE="🔄 Upstream Sync (Clean)"
100-
BODY="This PR syncs changes from upstream. No conflicts detected."
101-
LABELS="upstream-sync"
102-
fi
120+
echo "Creating new PR for conflict resolution..."
121+
TITLE="⚠️ Upstream Sync (Conflicts Detected)"
122+
BODY="This PR syncs changes from upstream. **Conflicts were detected and committed with markers.** Please review and resolve them."
123+
LABELS="upstream-sync,conflict"
103124
104125
PR_URL=$(gh pr create \
105126
--repo ${{ github.repository }} \
@@ -114,23 +135,15 @@ jobs:
114135
echo "Updating existing PR #$existing_pr..."
115136
echo "PR_URL=https://github.com/${{ github.repository }}/pull/$existing_pr" >> "$GITHUB_ENV"
116137
117-
# Update comments/labels if status changed
118-
if [[ "${{ steps.merge.outputs.merge_status }}" == "conflict" ]]; then
119-
gh pr edit "$existing_pr" --repo ${{ github.repository }} --title "⚠️ Upstream Sync (Conflicts Detected)" --add-label "conflict" --body "Updates from upstream. Conflicts detected."
120-
else
121-
gh pr edit "$existing_pr" --repo ${{ github.repository }} --title "🔄 Upstream Sync (Clean)" --remove-label "conflict" --body "Updates from upstream. Clean merge."
122-
fi
138+
gh pr edit "$existing_pr" --repo ${{ github.repository }} \
139+
--title "⚠️ Upstream Sync (Conflicts Detected)" \
140+
--add-label "conflict" \
141+
--body "Updates from upstream. Conflicts detected."
123142
fi
124143
125144
- name: Analyze Conflicts with AI
126145
if: steps.merge.outputs.merge_status == 'conflict' && env.OPENAI_API_KEY != ''
127146
run: |
128147
echo "Analyzing conflicts..."
129-
# We need to install dependencies for the script if any
130-
# For now assuming simple script or checking for package.json
131-
132148
# Run the analysis script
133-
# Passing PR URL or Number potentially needed for the script to post comments
134-
# Actually, if we use gh cli in the script, we just need GH_TOKEN
135-
136149
bun run ./scripts/analyze-conflicts.ts "${{ env.PR_URL }}"

docs/fork-workflow-strategy.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Fork Workflow Strategy: "The Integration Branch Pattern"
2+
This guide outlines the optimal workflow for maintaining a long-lived fork that consumes upstream updates while developing local features.
3+
## The Goal
4+
1. **Consume Upstream**: Get daily updates from `Dicklesworthstone/agentic_coding_flywheel_setup`.
5+
2. **Develop Locally**: Build new features in isolation.
6+
3. **Integrate**: Combine both sources into a stable deployment branch.
7+
## The "Integration Branch" Pattern
8+
We use a specific branching strategy to keep streams of work clean.
9+
### Branches
10+
| Branch Name | Role | Source of Truth |
11+
| :--- | :--- | :--- |
12+
| `main` | **Pure Upstream Mirror** | ONLY upstream code. Never commit here directly. |
13+
| `feature/*` | **Your Work** | Your isolated feature development. |
14+
| `local-desktop-installation-support` | **Integration / Deployment** | The "Production" branch for your local install. Contains Upstream + Your Features. |
15+
### Visual Data Flow
16+
```mermaid
17+
graph TD
18+
subgraph Upstream Repo
19+
U[Upstream / main]
20+
end
21+
subgraph Your Fork
22+
M[main<br/>(Pure Copy)]
23+
F1[feature/my-cool-config]
24+
F2[feature/custom-scripts]
25+
I[local-desktop-installation-support<br/>(Integration Branch)]
26+
end
27+
%% Flows
28+
U -->|Action: Daily Sync| I
29+
F1 -->|PR: Merge| I
30+
F2 -->|PR: Merge| I
31+
32+
style I fill:#d4edda,stroke:#28a745,stroke-width:2px
33+
style U fill:#cce5ff,stroke:#004085,stroke-width:2px
34+
```
35+
## Daily Protocol
36+
### 1. The Automated Morning Sync
37+
Your GitHub Action `upstream-sync.yml` runs daily.
38+
- It pulls `upstream/main`.
39+
- It attempts to merge into `local-desktop-installation-support`.
40+
- **If Clean**: It pushes automatically. You wake up to a fresh, up-to-date repo.
41+
- **If Conflict**: It opens a PR with conflict markers. You must resolve it (see [Upstream Sync Guide](./upstream-sync.md)).
42+
### 2. Developing a New Feature (The "Right Way")
43+
**NEVER** work directly on `local-desktop-installation-support`. Always use a feature branch.
44+
#### Step 1: Start Fresh
45+
Always branch off the latest integration branch.
46+
```bash
47+
git checkout local-desktop-installation-support
48+
git pull origin local-desktop-installation-support
49+
git checkout -b feature/my-new-idea
50+
```
51+
#### Step 2: Hack & Commit
52+
Work as usual.
53+
```bash
54+
# code code code
55+
git add .
56+
git commit -m "Add my new idea"
57+
```
58+
#### Step 3: Merge back to Integration
59+
When ready, merge your feature into the integration branch.
60+
```bash
61+
git checkout local-desktop-installation-support
62+
git merge feature/my-new-idea
63+
git push origin local-desktop-installation-support
64+
```
65+
*Tip: If you want to use PRs for your own features to run tests, that's even better! Open a PR from `feature/my-new-idea` -> `local-desktop-installation-support`.*
66+
### 3. Handling Upstream "Gotchas"
67+
Sometimes upstream changes a file you also changed.
68+
1. **The Action fails to merge cleanly.**
69+
2. **You get a Notification.**
70+
3. **You Open the PR** created by the action.
71+
4. **You Resolve Conflicts** (locally or in UI) to decide: "Do I keep my custom config, or take their update?"
72+
## Summary Rules
73+
1. **Don't touch `main`**. Let the sync action handle upstream data.
74+
2. **Don't commit to `local-desktop-installation-support` directly** for big work. Use feature branches.
75+
3. **Treat `local-desktop-installation-support` as your "Personal Production"**. If it's in there, it's live on your machine.

0 commit comments

Comments
 (0)