Skip to content

Commit 4638f7e

Browse files
committed
ci(auto-sync): add upstream sync workflow for feat/copilot
Parameterized clone of auto-sync-upstream.yml that mirrors the upstream router-for-me/CLIProxyAPI:main into feat/copilot instead of remote-fix. Key differences from the existing workflow: - name: auto-sync-upstream-copilot - cron: '30 2 * * *' (offset 30m from auto-sync-upstream to avoid fighting over scheduler / log timing) - concurrency.group: auto-sync-upstream-copilot (isolated from the remote-fix sync; both can run in parallel safely) - TARGET_BRANCH=feat/copilot, PR_BRANCH=auto-sync/upstream-main-copilot - Downstream image build dispatched against ghcr-feat-copilot.yml - PR label: auto-sync-copilot (keeps copilot sync PRs distinct from the remote-fix sync stream) Lives only on the default branch (main); schedule events only fire from there, mirroring the existing precedent.
1 parent a8c44eb commit 4638f7e

1 file changed

Lines changed: 171 additions & 0 deletions

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: auto-sync-upstream-copilot
2+
3+
on:
4+
schedule:
5+
# daily at 02:30 UTC (10:30 Asia/Singapore) — offset 30m from auto-sync-upstream
6+
- cron: '30 2 * * *'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
pull-requests: write
12+
issues: write
13+
actions: write
14+
15+
concurrency:
16+
group: auto-sync-upstream-copilot
17+
cancel-in-progress: false
18+
19+
env:
20+
UPSTREAM_URL: https://github.com/router-for-me/CLIProxyAPI.git
21+
UPSTREAM_BRANCH: main
22+
TARGET_BRANCH: feat/copilot
23+
PR_BRANCH: auto-sync/upstream-main-copilot
24+
25+
jobs:
26+
sync:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout target branch
30+
uses: actions/checkout@v4
31+
with:
32+
ref: ${{ env.TARGET_BRANCH }}
33+
fetch-depth: 0
34+
35+
- name: Configure git identity
36+
run: |
37+
git config user.name "github-actions[bot]"
38+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
39+
40+
- name: Add upstream remote and fetch
41+
run: |
42+
git remote add upstream "$UPSTREAM_URL"
43+
git fetch upstream "$UPSTREAM_BRANCH"
44+
45+
- name: Check if behind upstream
46+
id: check
47+
run: |
48+
BEHIND=$(git rev-list --count "HEAD..upstream/${UPSTREAM_BRANCH}")
49+
echo "behind=$BEHIND" >> "$GITHUB_OUTPUT"
50+
if [ "$BEHIND" = "0" ]; then
51+
echo "Already up to date with upstream/${UPSTREAM_BRANCH}."
52+
else
53+
echo "$BEHIND new commits from upstream:"
54+
git log --oneline "HEAD..upstream/${UPSTREAM_BRANCH}"
55+
fi
56+
57+
- name: Build merge commit message
58+
if: steps.check.outputs.behind != '0'
59+
run: |
60+
{
61+
echo "Merge upstream/${UPSTREAM_BRANCH} (auto-sync feat/copilot)"
62+
echo
63+
git log --reverse --pretty=format:'- %h %s' "HEAD..upstream/${UPSTREAM_BRANCH}"
64+
echo
65+
} > /tmp/merge-msg.txt
66+
cat /tmp/merge-msg.txt
67+
68+
- name: Try clean merge
69+
if: steps.check.outputs.behind != '0'
70+
id: merge
71+
run: |
72+
set +e
73+
git merge --no-ff -F /tmp/merge-msg.txt "upstream/${UPSTREAM_BRANCH}"
74+
rc=$?
75+
if [ "$rc" = "0" ]; then
76+
echo "clean=true" >> "$GITHUB_OUTPUT"
77+
else
78+
echo "clean=false" >> "$GITHUB_OUTPUT"
79+
git merge --abort || true
80+
fi
81+
exit 0
82+
83+
- name: Set up Go
84+
if: steps.merge.outputs.clean == 'true'
85+
uses: actions/setup-go@v5
86+
with:
87+
go-version-file: go.mod
88+
cache: true
89+
90+
- name: Verify build
91+
if: steps.merge.outputs.clean == 'true'
92+
id: build
93+
run: |
94+
set +e
95+
go build -o /tmp/cli-proxy-api ./cmd/server
96+
rc=$?
97+
rm -f /tmp/cli-proxy-api
98+
if [ "$rc" = "0" ]; then
99+
echo "ok=true" >> "$GITHUB_OUTPUT"
100+
else
101+
echo "ok=false" >> "$GITHUB_OUTPUT"
102+
fi
103+
exit 0
104+
105+
- name: Push merged changes to target branch
106+
if: steps.merge.outputs.clean == 'true' && steps.build.outputs.ok == 'true'
107+
run: git push origin "${TARGET_BRANCH}"
108+
109+
- name: Trigger downstream image build
110+
if: steps.merge.outputs.clean == 'true' && steps.build.outputs.ok == 'true'
111+
env:
112+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
113+
run: gh workflow run ghcr-feat-copilot.yml --repo "${{ github.repository }}" --ref "${TARGET_BRANCH}"
114+
115+
- name: Prepare PR branch (build failure case)
116+
if: steps.merge.outputs.clean == 'true' && steps.build.outputs.ok != 'true'
117+
run: |
118+
# HEAD is the (clean) merge commit — push it as the PR branch so reviewers
119+
# see exactly what would land, and pr-test-build.yml runs against it.
120+
git push --force origin "HEAD:refs/heads/${PR_BRANCH}"
121+
122+
- name: Prepare PR branch (conflict case)
123+
if: steps.check.outputs.behind != '0' && steps.merge.outputs.clean != 'true'
124+
run: |
125+
# Reset working tree, then push raw upstream tip as the PR branch so GitHub
126+
# surfaces the conflict against feat/copilot and offers web-based resolution.
127+
git reset --hard "origin/${TARGET_BRANCH}"
128+
git checkout -B "${PR_BRANCH}" "upstream/${UPSTREAM_BRANCH}"
129+
git push --force origin "${PR_BRANCH}"
130+
131+
- name: Open or update sync PR
132+
if: steps.check.outputs.behind != '0' && (steps.merge.outputs.clean != 'true' || steps.build.outputs.ok != 'true')
133+
env:
134+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
135+
GH_REPO: ${{ github.repository }}
136+
run: |
137+
set -e
138+
139+
if [ "${{ steps.merge.outputs.clean }}" != "true" ]; then
140+
REASON='conflicts with `'"${TARGET_BRANCH}"'`'
141+
else
142+
REASON='merge clean but `go build` failed'
143+
fi
144+
145+
{
146+
echo "Auto-sync from \`upstream/${UPSTREAM_BRANCH}\` (router-for-me/CLIProxyAPI) into \`${TARGET_BRANCH}\`."
147+
echo
148+
echo "**Reason for manual review:** ${REASON}"
149+
echo
150+
echo "### New commits"
151+
git log --reverse --pretty=format:'- %h %s' "origin/${TARGET_BRANCH}..upstream/${UPSTREAM_BRANCH}"
152+
} > /tmp/pr-body.md
153+
154+
# Idempotently ensure the label exists.
155+
gh label create auto-sync-copilot --color FBCA04 --description "Automated upstream sync (feat/copilot)" || true
156+
157+
EXISTING=$(gh pr list --head "${PR_BRANCH}" --base "${TARGET_BRANCH}" --state open --json number --jq '.[0].number' || true)
158+
159+
TITLE="auto-sync(copilot): merge upstream/${UPSTREAM_BRANCH} (${REASON})"
160+
161+
if [ -n "$EXISTING" ]; then
162+
gh pr edit "$EXISTING" --title "$TITLE" --body-file /tmp/pr-body.md
163+
echo "Updated existing PR #$EXISTING"
164+
else
165+
gh pr create \
166+
--base "${TARGET_BRANCH}" \
167+
--head "${PR_BRANCH}" \
168+
--title "$TITLE" \
169+
--body-file /tmp/pr-body.md \
170+
--label auto-sync-copilot
171+
fi

0 commit comments

Comments
 (0)