forked from astral-sh/python-build-standalone
-
Notifications
You must be signed in to change notification settings - Fork 0
179 lines (157 loc) · 6.47 KB
/
sync.yml
File metadata and controls
179 lines (157 loc) · 6.47 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
name: sync
on:
schedule:
- cron: '0 2 * * *' # daily at 02:00 UTC
workflow_dispatch:
pull_request:
permissions:
contents: write
pull-requests: write
# Strategy: create sync branch from main, merge the upstream tag INTO it,
# then PR back to main.
jobs:
sync:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GH_PYSTANDALONE_SYNC_TOKEN }}
GH_REPO: ${{ github.repository }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
token: ${{ secrets.GH_PYSTANDALONE_SYNC_TOKEN }}
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Fetch upstream
run: |
git remote add upstream https://github.com/astral-sh/python-build-standalone.git
git fetch upstream --tags --no-recurse-submodules
- name: Detect latest upstream tag
id: detect
run: |
# Upstream uses date-format tags (e.g. 20260310).
UPSTREAM_TAG=$(git tag -l --sort=-version:refname | head -n 1)
LOCAL_TAG=$(git tag -l --sort=-version:refname --merged origin/main | head -n 1)
echo "upstream=${UPSTREAM_TAG}" >> "$GITHUB_OUTPUT"
echo "local=${LOCAL_TAG}" >> "$GITHUB_OUTPUT"
echo "Upstream latest: ${UPSTREAM_TAG} Fork synced to: ${LOCAL_TAG}"
if [ -z "${UPSTREAM_TAG}" ]; then
echo "::error::No upstream tags found"
exit 1
fi
if [ "${UPSTREAM_TAG}" = "${LOCAL_TAG}" ]; then
echo "needs_sync=false" >> "$GITHUB_OUTPUT"
echo "Already up-to-date."
else
echo "needs_sync=true" >> "$GITHUB_OUTPUT"
fi
- name: Check for existing PR
if: steps.detect.outputs.needs_sync == 'true'
id: pr_check
env:
TAG: ${{ steps.detect.outputs.upstream }}
run: |
BRANCH="sync/${TAG}"
EXISTING=$(gh pr list --head "${BRANCH}" --state all --json number --jq '.[0].number // ""')
if [ -n "${EXISTING}" ]; then
echo "::notice::PR #${EXISTING} already exists for ${BRANCH}"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Create sync branch and merge upstream tag
if: steps.detect.outputs.needs_sync == 'true' && steps.pr_check.outputs.skip == 'false'
id: sync
env:
TAG: ${{ steps.detect.outputs.upstream }}
LOCAL_TAG: ${{ steps.detect.outputs.local }}
run: |
BRANCH="sync/${TAG}"
# Branch from main, then merge the upstream tag into it.
# This preserves upstream commit SHAs as merge parents.
git checkout -b "${BRANCH}" origin/main
if git merge --no-edit "refs/tags/${TAG}"; then
echo "conflicts=false" >> "$GITHUB_OUTPUT"
else
# Commit with conflict markers so they're visible in the PR diff.
# VS Code can resolve these with its merge conflict UI.
CONFLICTING=$(git diff --name-only --diff-filter=U | sort)
echo "::warning::Merge conflicts in: ${CONFLICTING//$'\n'/, }"
git add -A
git commit --no-edit -m "Merge upstream tag ${TAG} (conflicts — see PR)"
echo "conflicts=true" >> "$GITHUB_OUTPUT"
{
echo "CONFLICTING_FILES<<EOF"
echo "${CONFLICTING}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
fi
git push origin "HEAD:refs/heads/${BRANCH}"
echo "branch=${BRANCH}" >> "$GITHUB_OUTPUT"
- name: Ensure sync label exists
if: steps.detect.outputs.needs_sync == 'true' && steps.pr_check.outputs.skip == 'false'
run: gh label create "sync" --color "0075ca" --description "Automated upstream sync" || true
- name: Open pull request
if: steps.detect.outputs.needs_sync == 'true' && steps.pr_check.outputs.skip == 'false'
env:
TAG: ${{ steps.detect.outputs.upstream }}
LOCAL_TAG: ${{ steps.detect.outputs.local }}
BRANCH: ${{ steps.sync.outputs.branch }}
CONFLICTS: ${{ steps.sync.outputs.conflicts }}
CONFLICTING_FILES: ${{ steps.sync.outputs.CONFLICTING_FILES }}
run: |
COMMIT_COUNT=$(git rev-list --count "refs/tags/${LOCAL_TAG}..refs/tags/${TAG}" 2>/dev/null || echo "?")
if [ "${CONFLICTS}" = "true" ]; then
{
echo "> [!WARNING]"
echo "> Merge conflicts detected when merging upstream tag **${TAG}** into main."
echo "> The conflict markers have been committed so they are visible in the PR diff."
echo ""
echo "### Conflicting files"
echo ""
echo '```'
echo "${CONFLICTING_FILES}"
echo '```'
echo ""
echo "### Resolution"
echo ""
echo '```bash'
echo "git fetch origin"
echo "git checkout ${BRANCH}"
echo "# Resolve conflict markers"
echo "git add -A && git commit -m \"Resolve merge conflicts for ${TAG}\""
echo "git push origin ${BRANCH}"
echo '```'
} > /tmp/pr-body.md
else
{
echo "Automated merge of upstream tag **${TAG}** (${COMMIT_COUNT} new upstream commits since **${LOCAL_TAG}**)."
} > /tmp/pr-body.md
fi
DRAFT_FLAG=""
if [ "${CONFLICTS}" = "true" ]; then
DRAFT_FLAG="--draft"
fi
gh pr create \
--title "Sync upstream tag ${TAG}" \
--body-file /tmp/pr-body.md \
--head "${BRANCH}" \
--base main \
--label "sync" \
${DRAFT_FLAG}
check-conflicts:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Check for conflict markers
run: |
# Search tracked files for conflict markers.
if git grep -rlE '^<{7} |^>{7} ' -- . ':!.github/workflows/sync.yml'; then
echo "::error::Conflict markers found in the files listed above."
exit 1
fi
echo "No conflict markers found."