Skip to content

Commit 395beba

Browse files
committed
ucrt64: add workflow that drives the MINGW64 -> UCRT64 transition
MSYS2 has deprecated MINGW64. Upstream no longer accepts new packages targeting that environment and is winding down updates for the ones we already ship, so anything we do not migrate is going to rot in place. UCRT64 is the supported successor for the x86_64 target, and Git for Windows therefore has to follow. Rather than spin up a separate `git-sdk-ucrt-64` repository just for the new environment, we want to keep everything in this repo and make the cutover happen on a `ucrt64` branch that eventually becomes `main`. To produce the converted tree without running `pacman` manually, many times, and committing the resulting churn, this commit adds a one-shot workflow that performs exactly that work inside the PR opened from the `ucrt64` branch: it installs the UCRT64 counterpart of every currently-installed MINGW64 package, then uninstalls every MINGW64 package, then uninstalls every MINGW32 package. Each phase becomes one giant commit like the ones produced by the `sync` workflow. This approach was brain-stormed and documented in git-for-windows/git#6018 (reply in thread). Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 1845df2 commit 395beba

1 file changed

Lines changed: 241 additions & 0 deletions

File tree

.github/workflows/ucrt64.yml

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
name: Convert to UCRT64
2+
3+
# One-shot workflow that performs the MINGW64 -> UCRT64 transition for this
4+
# SDK inside the PR opened from the `ucrt64` branch. It computes the UCRT64
5+
# counterparts of every installed MINGW64 package (skipping those that have
6+
# no UCRT64 equivalent in any configured Pacman repository, such as
7+
# `mingw-w64-cv2pdb` at the time of writing), installs them, then removes
8+
# all MINGW64 and finally all MINGW32 packages in three large commits and
9+
# pushes the resulting state back to the PR branch. The set of skipped
10+
# packages is reported as a PR comment for follow-up by a human.
11+
12+
on:
13+
pull_request:
14+
branches: [main]
15+
types: [opened, reopened, synchronize]
16+
workflow_dispatch:
17+
18+
permissions:
19+
contents: write
20+
pull-requests: write
21+
22+
env:
23+
GIT_CONFIG_PARAMETERS: "'user.name=Git for Windows Build Agent' 'user.email=ci@git-for-windows.build' 'windows.sdk64.path=${{ github.workspace }}' 'windows.sdk32.path=' 'http.sslbackend=schannel' 'core.autocrlf=false' 'checkout.workers=16'"
24+
HOME: "${{ github.workspace }}\\home\\git-ci"
25+
MSYSTEM: MSYS
26+
27+
jobs:
28+
convert:
29+
name: Convert MINGW64 to UCRT64 in-place
30+
if: |
31+
github.repository == 'git-for-windows/git-sdk-64' &&
32+
(
33+
(github.event_name == 'pull_request' &&
34+
github.head_ref == 'ucrt64' &&
35+
github.event.pull_request.head.repo.full_name == github.repository) ||
36+
(github.event_name == 'workflow_dispatch' &&
37+
github.ref_name == 'ucrt64')
38+
)
39+
runs-on: windows-latest
40+
steps:
41+
- name: clone git-sdk-64
42+
uses: actions/checkout@v6
43+
with:
44+
ref: ${{ github.head_ref || github.ref_name }}
45+
persist-credentials: true
46+
47+
- name: use git-sdk-64's Bash and git.exe
48+
run: "usr\\bin\\bash.exe -lc 'cygpath -aw /usr/bin >>$GITHUB_PATH && cygpath -aw /cmd >>$GITHUB_PATH'"
49+
50+
- name: compute UCRT64 package lists
51+
id: lists
52+
shell: bash
53+
run: |
54+
set -e
55+
workdir="$(cygpath -u "$RUNNER_TEMP")/ucrt64-conversion"
56+
mkdir -p "$workdir"
57+
echo "workdir=$workdir" >>"$GITHUB_OUTPUT"
58+
59+
# Refresh the package databases so the latest UCRT64 packages are
60+
# visible to `pacman -Sl`.
61+
pacman -Sy --noconfirm
62+
63+
# Names (without the architecture prefix) of all installed MINGW64
64+
# packages.
65+
pacman -Qq | sed -n 's/^mingw-w64-x86_64-//p' | sort -u \
66+
>"$workdir/mingw64-names.txt"
67+
68+
if ! test -s "$workdir/mingw64-names.txt"
69+
then
70+
echo 'No MINGW64 packages installed; conversion is already done.'
71+
echo 'skip=true' >>"$GITHUB_OUTPUT"
72+
exit 0
73+
fi
74+
75+
# Names (without prefix) of every available UCRT64 package across
76+
# all configured Pacman repositories (upstream `ucrt64` today,
77+
# plus `git-for-windows-ucrt-x86_64` once it exists).
78+
pacman -Sl | awk '{print $2}' \
79+
| sed -n 's/^mingw-w64-ucrt-x86_64-//p' | sort -u \
80+
>"$workdir/ucrt64-available.txt"
81+
82+
# The UCRT64 counterparts that exist and will be installed.
83+
comm -12 "$workdir/mingw64-names.txt" "$workdir/ucrt64-available.txt" \
84+
| sed 's/^/mingw-w64-ucrt-x86_64-/' \
85+
>"$workdir/ucrt64-to-install.txt"
86+
87+
# MINGW64 packages with no UCRT64 counterpart anywhere in the
88+
# configured repositories; these are skipped and reported via a
89+
# PR comment.
90+
comm -23 "$workdir/mingw64-names.txt" "$workdir/ucrt64-available.txt" \
91+
| sed 's/^/mingw-w64-x86_64-/' \
92+
>"$workdir/ucrt64-skipped.txt"
93+
94+
to_install_count=$(wc -l <"$workdir/ucrt64-to-install.txt")
95+
skipped_count=$(wc -l <"$workdir/ucrt64-skipped.txt")
96+
echo "::group::UCRT64 packages to install ($to_install_count)"
97+
cat "$workdir/ucrt64-to-install.txt"
98+
echo "::endgroup::"
99+
echo "::group::MINGW64 packages without UCRT64 counterpart ($skipped_count skipped)"
100+
cat "$workdir/ucrt64-skipped.txt"
101+
echo "::endgroup::"
102+
103+
- name: install UCRT64 counterparts of all MINGW64 packages
104+
if: steps.lists.outputs.skip != 'true'
105+
shell: bash
106+
run: |
107+
set -e
108+
workdir='${{ steps.lists.outputs.workdir }}'
109+
test -s "$workdir/ucrt64-to-install.txt" || {
110+
echo 'No UCRT64 counterparts available; nothing to install.'
111+
exit 0
112+
}
113+
xargs -a "$workdir/ucrt64-to-install.txt" \
114+
pacman -S --noconfirm --needed --overwrite='*'
115+
116+
- name: commit "Install UCRT64 counterparts of all MINGW64 packages"
117+
if: steps.lists.outputs.skip != 'true'
118+
shell: bash
119+
run: |
120+
set -e
121+
workdir='${{ steps.lists.outputs.workdir }}'
122+
{
123+
echo 'Install UCRT64 counterparts of all MINGW64 packages'
124+
echo
125+
if test -s "$workdir/ucrt64-to-install.txt"
126+
then
127+
echo 'Installed UCRT64 packages:'
128+
sed 's/^/ /' "$workdir/ucrt64-to-install.txt"
129+
fi
130+
if test -s "$workdir/ucrt64-skipped.txt"
131+
then
132+
echo
133+
echo 'No UCRT64 counterpart in the configured Pacman repositories (skipped):'
134+
sed 's/^/ /' "$workdir/ucrt64-skipped.txt"
135+
fi
136+
} >"$workdir/msg.txt"
137+
git add -A .
138+
git diff-index --quiet --cached HEAD -- \
139+
':(exclude)var/lib/pacman/sync/' \
140+
':(exclude)etc/rebase.db*' \
141+
|| git commit -s -q -F "$workdir/msg.txt"
142+
143+
- name: uninstall all MINGW64 packages
144+
if: steps.lists.outputs.skip != 'true'
145+
shell: bash
146+
run: |
147+
set -e
148+
workdir='${{ steps.lists.outputs.workdir }}'
149+
pacman -Qq | grep '^mingw-w64-x86_64-' \
150+
>"$workdir/mingw64-installed.txt" || true
151+
test -s "$workdir/mingw64-installed.txt" || {
152+
echo 'No MINGW64 packages left to remove.'
153+
exit 0
154+
}
155+
# -dd: skip dep checks (we are removing the whole stack at once and
156+
# they all depend on each other); --noscriptlet: do not run remove
157+
# scripts that themselves rely on the MINGW64 toolchain we are
158+
# about to delete.
159+
xargs -a "$workdir/mingw64-installed.txt" \
160+
pacman -Rdd --noscriptlet --noconfirm
161+
162+
- name: commit "Uninstall all MINGW64 packages"
163+
if: steps.lists.outputs.skip != 'true'
164+
shell: bash
165+
run: |
166+
set -e
167+
workdir='${{ steps.lists.outputs.workdir }}'
168+
test -s "$workdir/mingw64-installed.txt" || exit 0
169+
{
170+
echo 'Uninstall all MINGW64 packages'
171+
echo
172+
echo 'Removed MINGW64 packages:'
173+
sed 's/^/ /' "$workdir/mingw64-installed.txt"
174+
} >"$workdir/msg.txt"
175+
git add -A .
176+
git diff-index --quiet --cached HEAD -- \
177+
':(exclude)var/lib/pacman/sync/' \
178+
':(exclude)etc/rebase.db*' \
179+
|| git commit -s -q -F "$workdir/msg.txt"
180+
181+
- name: uninstall all MINGW32 packages
182+
if: steps.lists.outputs.skip != 'true'
183+
shell: bash
184+
run: |
185+
set -e
186+
workdir='${{ steps.lists.outputs.workdir }}'
187+
pacman -Qq | grep '^mingw-w64-i686-' \
188+
>"$workdir/mingw32-installed.txt" || true
189+
test -s "$workdir/mingw32-installed.txt" || {
190+
echo 'No MINGW32 packages left to remove.'
191+
exit 0
192+
}
193+
xargs -a "$workdir/mingw32-installed.txt" \
194+
pacman -Rdd --noscriptlet --noconfirm
195+
196+
- name: commit "Uninstall all MINGW32 packages"
197+
if: steps.lists.outputs.skip != 'true'
198+
shell: bash
199+
run: |
200+
set -e
201+
workdir='${{ steps.lists.outputs.workdir }}'
202+
test -s "$workdir/mingw32-installed.txt" || exit 0
203+
{
204+
echo 'Uninstall all MINGW32 packages'
205+
echo
206+
echo 'Removed MINGW32 packages:'
207+
sed 's/^/ /' "$workdir/mingw32-installed.txt"
208+
} >"$workdir/msg.txt"
209+
git add -A .
210+
git diff-index --quiet --cached HEAD -- \
211+
':(exclude)var/lib/pacman/sync/' \
212+
':(exclude)etc/rebase.db*' \
213+
|| git commit -s -q -F "$workdir/msg.txt"
214+
215+
- name: push converted branch
216+
if: steps.lists.outputs.skip != 'true'
217+
shell: bash
218+
env:
219+
TARGET_REF: ${{ github.head_ref || github.ref_name }}
220+
run: |
221+
set -e
222+
git push origin "HEAD:refs/heads/$TARGET_REF"
223+
224+
- name: comment on PR with skipped packages
225+
if: steps.lists.outputs.skip != 'true' && github.event_name == 'pull_request'
226+
uses: actions/github-script@v7
227+
env:
228+
SKIPPED_FILE: ${{ steps.lists.outputs.workdir }}/ucrt64-skipped.txt
229+
with:
230+
script: |
231+
const fs = require('fs');
232+
const list = fs.readFileSync(process.env.SKIPPED_FILE, 'utf8').trim();
233+
const body = list.length === 0
234+
? 'Every installed MINGW64 package has a UCRT64 counterpart in the configured Pacman repositories; nothing was skipped.'
235+
: 'The following MINGW64 packages have no UCRT64 counterpart in the configured Pacman repositories and were skipped:\n\n```\n' + list + '\n```';
236+
await github.rest.issues.createComment({
237+
owner: context.repo.owner,
238+
repo: context.repo.repo,
239+
issue_number: context.issue.number,
240+
body,
241+
});

0 commit comments

Comments
 (0)