-
Notifications
You must be signed in to change notification settings - Fork 115
199 lines (170 loc) · 7.4 KB
/
Copy pathsync-alpha-from-main.yml
File metadata and controls
199 lines (170 loc) · 7.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
name: Sync Alpha from Main
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
concurrency:
group: sync-alpha-from-main
cancel-in-progress: false
jobs:
sync:
name: Rebase main into alpha
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Check if alpha is already up to date
id: check
run: |
MAIN_SHA="$(git rev-parse origin/main)"
ALPHA_SHA="$(git rev-parse origin/alpha)"
COMMIT_COUNT="$(git rev-list --count "${ALPHA_SHA}..${MAIN_SHA}")"
echo "main_sha=${MAIN_SHA}" >> "$GITHUB_OUTPUT"
echo "alpha_sha=${ALPHA_SHA}" >> "$GITHUB_OUTPUT"
echo "commit_count=${COMMIT_COUNT}" >> "$GITHUB_OUTPUT"
if [ "${COMMIT_COUNT}" -eq 0 ]; then
echo "needs_sync=false" >> "$GITHUB_OUTPUT"
echo "alpha is already up to date with main"
else
echo "needs_sync=true" >> "$GITHUB_OUTPUT"
echo "Commits in main not in alpha: ${COMMIT_COUNT}"
fi
- name: Check for existing open sync PR
if: steps.check.outputs.needs_sync == 'true'
id: existing_pr
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
EXISTING=$(gh pr list \
--base alpha \
--state open \
--json headRefName \
--jq '[.[] | select(.headRefName | startswith("chore/sync-alpha-from-main-"))] | length')
if [ "${EXISTING}" -gt 0 ]; then
echo "Open sync PR already exists — skipping"
echo "pr_exists=true" >> "$GITHUB_OUTPUT"
else
echo "pr_exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Create work branch off alpha
if: steps.check.outputs.needs_sync == 'true' && steps.existing_pr.outputs.pr_exists == 'false'
id: branch
run: |
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
WORK_BRANCH="chore/sync-alpha-from-main-${TIMESTAMP}"
echo "work_branch=${WORK_BRANCH}" >> "$GITHUB_OUTPUT"
git checkout -b "${WORK_BRANCH}" origin/alpha
echo "Created ${WORK_BRANCH} from origin/alpha"
- name: Attempt rebase of main onto work branch
if: steps.check.outputs.needs_sync == 'true' && steps.existing_pr.outputs.pr_exists == 'false'
id: rebase
env:
WORK_BRANCH: ${{ steps.branch.outputs.work_branch }}
MAIN_SHA: ${{ steps.check.outputs.main_sha }}
ALPHA_SHA: ${{ steps.check.outputs.alpha_sha }}
run: |
MERGE_BASE="$(git merge-base "${ALPHA_SHA}" "${MAIN_SHA}")"
git rebase --onto "${WORK_BRANCH}" "${MERGE_BASE}" origin/main && {
echo "rebase_clean=true" >> "$GITHUB_OUTPUT"
git checkout -B "${WORK_BRANCH}"
echo "Rebase completed cleanly"
} || {
echo "rebase_clean=false" >> "$GITHUB_OUTPUT"
git rebase --abort 2>/dev/null || true
echo "Rebase had conflicts — falling back to merge"
MERGE_MSG=$(cat <<'MSG'
chore: merge main into alpha (conflict resolution required)
Automated merge of origin/main into origin/alpha.
Rebase encountered conflicts; falling back to merge.
A human must resolve conflict markers before merging this PR.
MSG
)
git merge --no-ff --allow-unrelated-histories origin/main -m "${MERGE_MSG}" || {
git add -A
CONFLICT_MSG=$(cat <<'MSG'
chore: best-effort merge main into alpha (conflicts present)
Automated merge of origin/main into origin/alpha.
Both rebase and merge encountered conflicts. Conflict markers
are present and must be resolved before this PR can be merged.
MSG
)
git commit --no-verify -m "${CONFLICT_MSG}"
}
}
- name: Push work branch
if: steps.check.outputs.needs_sync == 'true' && steps.existing_pr.outputs.pr_exists == 'false'
env:
WORK_BRANCH: ${{ steps.branch.outputs.work_branch }}
run: |
git push origin "${WORK_BRANCH}"
- name: Open PR against alpha
if: steps.check.outputs.needs_sync == 'true' && steps.existing_pr.outputs.pr_exists == 'false'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WORK_BRANCH: ${{ steps.branch.outputs.work_branch }}
COMMIT_COUNT: ${{ steps.check.outputs.commit_count }}
REBASE_CLEAN: ${{ steps.rebase.outputs.rebase_clean }}
MAIN_SHA: ${{ steps.check.outputs.main_sha }}
ALPHA_SHA: ${{ steps.check.outputs.alpha_sha }}
run: |
if [ "${REBASE_CLEAN}" = "true" ]; then
CONFLICT_NOTE="Rebase completed cleanly — no conflicts detected. This PR can be merged directly."
else
CONFLICT_NOTE="⚠️ **Conflicts detected.** Rebase fell back to merge. Search for \`<<<<<<<\` conflict markers and resolve before merging."
fi
gh pr create \
--base alpha \
--head "${WORK_BRANCH}" \
--title "chore: sync alpha from main ($(date +%Y-%m-%d))" \
--body "## Summary
Automated sync of \`main\` into \`alpha\` triggered by push to \`main\`.
| | |
|---|---|
| Commits synced | ${COMMIT_COUNT} |
| origin/main | \`${MAIN_SHA:0:8}\` |
| origin/alpha | \`${ALPHA_SHA:0:8}\` |
## Status
${CONFLICT_NOTE}
## Review Instructions
1. Check for conflict markers (\`<<<<<<<\`) in changed files.
2. Resolve any conflicts and push to this branch.
3. Verify the build passes.
4. Merge into \`alpha\`.
---
*Auto-generated by \`.github/workflows/sync-alpha-from-main.yml\`*"
- name: Summary
if: always()
env:
NEEDS_SYNC: ${{ steps.check.outputs.needs_sync }}
PR_EXISTS: ${{ steps.existing_pr.outputs.pr_exists || 'false' }}
COMMIT_COUNT: ${{ steps.check.outputs.commit_count || '0' }}
REBASE_CLEAN: ${{ steps.rebase.outputs.rebase_clean || 'n/a' }}
JOB_STATUS: ${{ job.status }}
run: |
if [ "${NEEDS_SYNC}" = "false" ]; then
echo "## ✅ Already in sync" >> "$GITHUB_STEP_SUMMARY"
echo "alpha is up to date with main — nothing to do." >> "$GITHUB_STEP_SUMMARY"
elif [ "${PR_EXISTS}" = "true" ]; then
echo "## ℹ️ Sync PR already open" >> "$GITHUB_STEP_SUMMARY"
echo "An open sync PR already exists against alpha — skipped." >> "$GITHUB_STEP_SUMMARY"
elif [ "${JOB_STATUS}" = "failure" ]; then
echo "## ❌ Sync failed" >> "$GITHUB_STEP_SUMMARY"
echo "Check the logs above for details." >> "$GITHUB_STEP_SUMMARY"
elif [ "${REBASE_CLEAN}" = "true" ]; then
echo "## ✅ PR opened — clean rebase" >> "$GITHUB_STEP_SUMMARY"
echo "${COMMIT_COUNT} commits synced from main to alpha with no conflicts." >> "$GITHUB_STEP_SUMMARY"
else
echo "## ⚠️ PR opened — conflicts require resolution" >> "$GITHUB_STEP_SUMMARY"
echo "${COMMIT_COUNT} commits from main; rebase had conflicts. PR opened for human resolution." >> "$GITHUB_STEP_SUMMARY"
fi