Skip to content

build-soda

build-soda #213

Workflow file for this run

name: build-soda
on:
push:
branches:
- 'soda'
workflow_dispatch:
inputs:
recovery_run:
description: 'Run with completed Wine builds and package tests'
required: false
type: string
architecture:
description: 'Candidate architecture'
required: true
type: choice
options:
- x86_64
- aarch64
default: x86_64
pgo:
description: 'Build a PGO candidate'
required: true
type: boolean
default: false
baseline_run_id:
description: 'Run ID containing the baseline artifact'
required: false
type: string
permissions:
actions: read
contents: read
env:
WINE_VERSION: '11.0'
REVISION: '28-experimental'
RELEASE_CODENAME: 'Windows Escape'
WINE_TKG_COMMIT: '04ddf86c96817d2f8bb45aefc04c9ad3871ca740'
VALVE_WINE_TAG: 'experimental-wine-bleeding-edge-11.0-428201-20260904-pdf1645-w0509a0-dd7ac25-v35bdee'
VALVE_WINE_COMMIT: '0509a0b64a4852741364c95bcdc67ae8f74ef11d'
PROTON_COMMIT: 'b7a763327f0cb76e9e0bd53dc4de95dee0d4c3b7'
FEX_COMMIT: '1cc4b93e7a71c883ec021b71359f136394dc1f3c'
OPENXR_SDK_COMMIT: '8899a91c17ce9618f565f42408b47db1d6e9ccc7'
PGO_BASELINE_RUN_ID: '33972726566'
BUILD_TOOLS_COMMIT: 'fcba104217c6daddddebe69d2dc2e39bc9025848'
MONADO_VERSION: '21.0.0+git2905.e26a272c1~dfsg1-2build2'
WINE_MONO_VERSION: '10.4.1'
WINE_MONO_SHA256: '071f4b2887e1c97a11d791ff3d65be9429eed6dec4c2708888bfd546ba358e23'
RELEASE_NOTES: |-
<img src="https://raw.githubusercontent.com/bottlesdevs/data/main/logo/soda-logo.svg" width="64" />
This is a Wine TKG build based on Valve's Wine (experimental bleeding edge) source code.
Soda 11.0-28 Experimental fixes LDAP initialization with empty or padded host lists and Direct2D command lists after their storage grows. It adds Vector3 keyframe animation interfaces and InteractionTracker close support used by Office's UI.
Eagle keeps the bottle's DLL overrides, follows the loaded binaries for symbol lookup and finishes a trace when only Wine's built-in desktop services remain. Mutex tracing skips unrelated handle closes.
The identity bridge now handles long socket paths. Use the latest Bottles main build for both sides of this fix.
Enable Eagle Tracing in the bottle's Preferences to collect per-launch logs in logs/runs. Review them before sharing. Eagle is included in the x86_64 runner for x86 and x64 apps; it is not included in the ARM64 runner. Matching application symbols are required for source names and lines. Console input/output is disconnected during tracing.
Other Office startup, sign-in and document crashes remain under investigation.
jobs:
patches:
if: inputs.recovery_run == ''
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: check Soda patches
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
git clone --filter=blob:none --no-checkout --depth=1 --branch "$VALVE_WINE_TAG" https://github.com/ValveSoftware/wine.git /tmp/valve-wine
git -C /tmp/valve-wine checkout --detach "$VALVE_WINE_COMMIT"
test "$(git -C /tmp/valve-wine rev-parse HEAD)" = "$VALVE_WINE_COMMIT"
git clone --filter=blob:none --no-checkout https://github.com/ValveSoftware/Proton.git /tmp/proton
git -C /tmp/proton sparse-checkout set --no-cone /wineopenxr
git -C /tmp/proton checkout --detach "$PROTON_COMMIT"
test "$(git -C /tmp/proton rev-parse HEAD)" = "$PROTON_COMMIT"
.github/import-msicu.sh /tmp/valve-wine
.github/import-wineopenxr.sh /tmp/valve-wine /tmp/proton/wineopenxr
for patch in "$GITHUB_WORKSPACE"/wine-tkg-userpatches/*.mypatch; do
git -C /tmp/valve-wine apply --check "$patch"
git -C /tmp/valve-wine apply "$patch"
done
grep -F '@ stdcall SLLoadApplicationPolicies(ptr ptr long ptr)' /tmp/valve-wine/dlls/sppc/sppc.spec
grep -F 'HRESULT WINAPI SLLoadApplicationPolicies' /tmp/valve-wine/dlls/sppc/sppc.c
for symbol in SL_I_OOB_GRACE_PERIOD SL_E_APPLICATION_POLICIES_MISSING SL_E_AUTHN_CHALLENGE_NOT_SET SL_E_AUTHN_CANT_VERIFY; do
grep -F "#define $symbol" /tmp/valve-wine/include/slerror.h
done
grep -F '@ stdcall GetDispatcherQueueForCurrentThread(ptr)' /tmp/valve-wine/dlls/coremessaging/coremessaging.spec
grep -F '@ stdcall CalculatePopupWindowPosition(ptr ptr long ptr ptr)' /tmp/valve-wine/dlls/user32/user32.spec
grep -F '@ stdcall -syscall NtUserCalculatePopupWindowPosition(ptr ptr long ptr ptr)' /tmp/valve-wine/dlls/win32u/win32u.spec
build:
needs: patches
if: github.event_name == 'push' || inputs.architecture == 'x86_64'
runs-on: ubuntu-24.04
outputs:
archive_name: ${{ steps.identity.outputs.archive_name }}
component_name: ${{ steps.identity.outputs.component_name }}
pgo: ${{ steps.identity.outputs.pgo }}
publish: ${{ steps.identity.outputs.publish }}
prerelease: ${{ steps.identity.outputs.prerelease }}
steps:
- uses: actions/checkout@v7
- name: define build identity
id: identity
run: |
version="$WINE_VERSION-$REVISION"
pgo=false
publish=false
prerelease=false
if [[ "$GITHUB_EVENT_NAME" == "push" && "$GITHUB_REF" == "refs/heads/soda" ]]; then
pgo=true
publish=true
if [[ "$REVISION" == *-experimental ]]; then
prerelease=true
fi
else
version="$version-${GITHUB_SHA::7}"
if [[ "${{ inputs.pgo }}" == "true" ]]; then
pgo=true
version="$version-pgo"
fi
fi
component_name="soda-$version-x86_64"
echo "archive_name=$component_name.tar.xz" >> "$GITHUB_OUTPUT"
echo "component_name=$component_name" >> "$GITHUB_OUTPUT"
echo "pgo=$pgo" >> "$GITHUB_OUTPUT"
echo "publish=$publish" >> "$GITHUB_OUTPUT"
echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT"
- name: setup
working-directory: /home/runner/work/
run: |
mkdir -p /home/runner/.config/frogminer/
sudo apt purge -y ubuntu-advantage-tools python3-update-manager
sudo dpkg --add-architecture i386 && sudo apt update
sudo apt-mark hold grub-common grub-efi-amd64-bin python3 python3-apt shim-signed
sudo apt install aptitude
sudo aptitude remove -y '?narrow(?installed,?version(deb.sury.org))'
sudo apt install -f
sudo apt-get install -y -o Dpkg::Options::="--force-overwrite" libpcap-dev:amd64 libpcap-dev:i386
sudo apt-get install -y libglib2.0-dev-bin libglib2.0-dev:amd64
sudo aptitude install -y -o Dpkg::Options::="--force-overwrite" \
libglib2.0-dev-bin:amd64 \
libgudev-1.0-dev:amd64 \
libgudev-1.0-dev:i386 \
libvulkan-dev:amd64 \
libvulkan-dev:i386
sudo apt-get install -y -o Dpkg::Options::="--force-overwrite" libpcsclite-dev:amd64 libpcsclite-dev:i386
sudo apt-get install -y libsecret-1-dev:amd64 libsecret-1-0:i386
bash "$GITHUB_WORKSPACE/.github/soda-secret-headers.sh" "$GITHUB_WORKSPACE/.soda-secret-amd64" amd64
bash "$GITHUB_WORKSPACE/.github/soda-secret-headers.sh" "$GITHUB_WORKSPACE/.soda-secret-i386" i386
sudo apt-get install -y \
g++ \
cmake \
file \
g++-mingw-w64-i686 \
g++-mingw-w64-x86-64 \
libopenxr-dev:amd64 \
"libopenxr1-monado=$MONADO_VERSION" \
mesa-vulkan-drivers \
"monado-service=$MONADO_VERSION" \
ninja-build \
xvfb
sudo apt-get check
- name: clone wine-tkg-git repo
working-directory: /home/runner/work/
run: |
git clone https://github.com/Frogging-Family/wine-tkg-git.git
cd wine-tkg-git/wine-tkg-git
git checkout "$WINE_TKG_COMMIT"
sed -i "s/_LOCAL_PRESET=\"\"/_LOCAL_PRESET=\"valve-exp-bleeding\"/g" customization.cfg
sed -i "s|^_bleeding_tag=.*|_bleeding_tag=\"$VALVE_WINE_TAG\"|" wine-tkg-profiles/wine-tkg-valve-exp-bleeding.cfg
sed -i '/^ubuntu_pkgs_64=/ s/libgstreamer-plugins-base1.0-dev/libgstreamer-plugins-base1.0-dev:amd64/' wine-tkg-scripts/deps
cp "$GITHUB_WORKSPACE"/wine-tkg-userpatches/*.mypatch wine-tkg-userpatches/
git clone --filter=blob:none --no-checkout https://github.com/ValveSoftware/Proton.git /tmp/proton
git -C /tmp/proton sparse-checkout set --no-cone /OpenXR-SDK /wineopenxr
git -C /tmp/proton checkout --detach "$PROTON_COMMIT"
test "$(git -C /tmp/proton rev-parse HEAD)" = "$PROTON_COMMIT"
git -C /tmp/proton submodule update --init --depth=1 OpenXR-SDK
test "$(git -C /tmp/proton/OpenXR-SDK rev-parse HEAD)" = "$OPENXR_SDK_COMMIT"
sed -i '/ _source_cleanup/a\ "$GITHUB_WORKSPACE/.github/import-msicu.sh" "${srcdir}/${_winesrcdir}"\n "$GITHUB_WORKSPACE/.github/import-wineopenxr.sh" "${srcdir}/${_winesrcdir}" "/tmp/proton/wineopenxr"' non-makepkg-build.sh
- name: get/set the soda recipe
working-directory: /home/runner/.config/frogminer/
run: |
git clone https://github.com/bottlesdevs/build-tools.git /tmp/build-tools
git -C /tmp/build-tools checkout "$BUILD_TOOLS_COMMIT"
cp /tmp/build-tools/runners/vaniglia/wine-tkg-valve.cfg wine-tkg.cfg
sed -i '$a_NOLIB32="false"' wine-tkg.cfg
sed -i "\$a_configure_userargs64=\"SECRET_CFLAGS=-I$GITHUB_WORKSPACE/.soda-secret-amd64/include SECRET_LIBS=-L$GITHUB_WORKSPACE/.soda-secret-amd64/lib\"" wine-tkg.cfg
sed -i "\$a_configure_userargs32=\"--disable-wineopenxr SECRET_CFLAGS=-I$GITHUB_WORKSPACE/.soda-secret-i386/include SECRET_LIBS=-L$GITHUB_WORKSPACE/.soda-secret-i386/lib\"" wine-tkg.cfg
if [[ "${{ steps.identity.outputs.pgo }}" == "true" ]]; then
mkdir -p /tmp/soda-pgo/profiles /tmp/soda-pgo/evidence
sed -i '$a_GCC_FLAGS="-O2 -pipe -msse3 -mfpmath=sse -ftree-vectorize -Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types -fprofile-generate=/tmp/soda-pgo/profiles -fprofile-update=prefer-atomic -fprofile-exclude-files=preloader"' wine-tkg.cfg
sed -i '$a_LD_FLAGS="-Wl,-O1,--sort-common,--as-needed -fprofile-generate=/tmp/soda-pgo/profiles"' wine-tkg.cfg
fi
cat wine-tkg.cfg
- name: build PGO training programs
if: steps.identity.outputs.pgo == 'true'
run: |
x86_64-w64-mingw32-gcc .github/soda-pgo-training.c \
-O2 -municode -ladvapi32 -lgdi32 -o /tmp/soda-pgo/training64.exe
i686-w64-mingw32-gcc .github/soda-pgo-training.c \
-O2 -municode -ladvapi32 -lgdi32 -o /tmp/soda-pgo/training32.exe
- name: build ICU smoke programs
run: |
mkdir -p /tmp/soda-icu
x86_64-w64-mingw32-gcc .github/soda-icu-smoke.c \
-O2 -Wall -Wextra -Werror -o /tmp/soda-icu/smoke64.exe
i686-w64-mingw32-gcc .github/soda-icu-smoke.c \
-O2 -Wall -Wextra -Werror -o /tmp/soda-icu/smoke32.exe
- name: start build
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
env:
GITHUB_TOKEN: ${{ github.token }}
run: yes|./non-makepkg-build.sh
- name: verify packaged Unix runtime
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
for arch in i386 x86_64; do
unix_dir="$runner_dir/lib/wine/$arch-unix"
test -f "$unix_dir/ntdll.so"
test -f "$unix_dir/win32u.so"
test -f "$unix_dir/winebus.so"
test -f "$unix_dir/winevulkan.so"
test -f "$unix_dir/winex11.so"
if ! grep -aFq 'org.winehq.Soda.Identity' "$unix_dir/windows.security.authentication.onlineid.so"; then
printf 'Missing %s identity credential backend\n' "$arch" >&2
exit 1
fi
module_count="$(find "$unix_dir" -maxdepth 1 -type f -name '*.so' | wc -l)"
test "$module_count" -ge 30
printf '%s Unix modules: %s\n' "$arch" "$module_count"
done
- name: train PGO build
if: steps.identity.outputs.pgo == 'true'
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
env:
BASELINE_RUN_ID: ${{ inputs.baseline_run_id || env.PGO_BASELINE_RUN_ID }}
GH_TOKEN: ${{ github.token }}
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
test -n "$BASELINE_RUN_ID"
export SODA_RUNNER_DIR="$PWD/$runner_dir"
mkdir -p /tmp/soda-pgo/training-baseline /tmp/soda-pgo/training-baseline-extracted
gh run download "$BASELINE_RUN_ID" --repo "$GITHUB_REPOSITORY" \
--dir /tmp/soda-pgo/training-baseline
baseline_archive="$(find /tmp/soda-pgo/training-baseline -type f \
-name 'soda-*-x86_64.tar.xz' -print -quit)"
test -n "$baseline_archive"
tar -C /tmp/soda-pgo/training-baseline-extracted -xJf "$baseline_archive"
baseline_runner="$(find /tmp/soda-pgo/training-baseline-extracted \
-mindepth 1 -maxdepth 1 -type d -name 'soda-*-x86_64' -print -quit)"
test -n "$baseline_runner"
export BASELINE_RUNNER="$baseline_runner"
printf 'Preparing PGO win64 prefix with baseline runner\n'
timeout 5m xvfb-run -a bash -c '
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-pgo/prefix64
export WINEARCH=win64
mkdir -p "$WINEPREFIX"
"$BASELINE_RUNNER/bin/wineboot" -u
"$BASELINE_RUNNER/bin/wineserver" -w
'
printf 'Training PGO win64 runner\n'
timeout 10m xvfb-run -a bash -c '
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-pgo/prefix64
export WINEARCH=win64
"$SODA_RUNNER_DIR/bin/wine" reg add "HKCU\Software\SodaPGO" /v Architecture /d win64 /f
"$SODA_RUNNER_DIR/bin/wine" cmd /c ver
"$SODA_RUNNER_DIR/bin/wine" /tmp/soda-pgo/training64.exe
wineserver_status=0
"$SODA_RUNNER_DIR/bin/wineserver" -w || wineserver_status=$?
test "$wineserver_status" -le 1
'
printf 'Preparing PGO win32 prefix with baseline runner\n'
timeout 5m xvfb-run -a bash -c '
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-pgo/prefix32
export WINEARCH=win32
mkdir -p "$WINEPREFIX"
"$BASELINE_RUNNER/bin/wineboot" -u
"$BASELINE_RUNNER/bin/wineserver" -w
'
printf 'Training PGO win32 runner\n'
timeout 10m xvfb-run -a bash -c '
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-pgo/prefix32
export WINEARCH=win32
"$SODA_RUNNER_DIR/bin/wine" reg add "HKCU\Software\SodaPGO" /v Architecture /d win32 /f
"$SODA_RUNNER_DIR/bin/wine" cmd /c ver
"$SODA_RUNNER_DIR/bin/wine" /tmp/soda-pgo/training32.exe
wineserver_status=0
"$SODA_RUNNER_DIR/bin/wineserver" -w || wineserver_status=$?
test "$wineserver_status" -le 1
'
find /tmp/soda-pgo/profiles -type f -name '*conftest*.gcda' \
-print -delete | sort \
> /tmp/soda-pgo/evidence/excluded-configure-profiles.txt
test -s /tmp/soda-pgo/evidence/excluded-configure-profiles.txt
find /tmp/soda-pgo/profiles -type f -name '*.gcda' -size +0c \
-printf '%s %p\n' | sort > /tmp/soda-pgo/evidence/profile-inventory.txt
profile_count="$(wc -l < /tmp/soda-pgo/evidence/profile-inventory.txt)"
test "$profile_count" -gt 0
grep -E '[#/]+server[#/]+' /tmp/soda-pgo/evidence/profile-inventory.txt
first_profile="$(find /tmp/soda-pgo/profiles -type f -name '*.gcda' -size +0c -print -quit)"
gcov-dump -l "$first_profile" > /tmp/soda-pgo/evidence/profile-dump.txt
grep -Eq 'runs=[1-9]|sum_max=[1-9]' /tmp/soda-pgo/evidence/profile-dump.txt
- name: rebuild with PGO profiles
if: steps.identity.outputs.pgo == 'true'
working-directory: /home/runner/work/
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
build_root=/home/runner/work/wine-tkg-git
test "$PWD" = /home/runner/work
test -f "$build_root/wine-tkg-git/non-makepkg-build.sh"
find "$build_root" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
git clone https://github.com/Frogging-Family/wine-tkg-git.git
cd wine-tkg-git/wine-tkg-git
git checkout "$WINE_TKG_COMMIT"
sed -i "s/_LOCAL_PRESET=\"\"/_LOCAL_PRESET=\"valve-exp-bleeding\"/g" customization.cfg
sed -i "s|^_bleeding_tag=.*|_bleeding_tag=\"$VALVE_WINE_TAG\"|" wine-tkg-profiles/wine-tkg-valve-exp-bleeding.cfg
sed -i '/^ubuntu_pkgs_64=/ s/libgstreamer-plugins-base1.0-dev/libgstreamer-plugins-base1.0-dev:amd64/' wine-tkg-scripts/deps
cp "$GITHUB_WORKSPACE"/wine-tkg-userpatches/*.mypatch wine-tkg-userpatches/
sed -i '/ _source_cleanup/a\ "$GITHUB_WORKSPACE/.github/import-msicu.sh" "${srcdir}/${_winesrcdir}"\n "$GITHUB_WORKSPACE/.github/import-wineopenxr.sh" "${srcdir}/${_winesrcdir}" "/tmp/proton/wineopenxr"' non-makepkg-build.sh
recipe=/home/runner/.config/frogminer/wine-tkg.cfg
sed -i '/^_GCC_FLAGS=/d; /^_LD_FLAGS=/d' "$recipe"
sed -i '$a_GCC_FLAGS="-O2 -pipe -msse3 -mfpmath=sse -ftree-vectorize -Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types -Wno-missing-profile -fprofile-use=/tmp/soda-pgo/profiles -fprofile-correction -fprofile-partial-training -fprofile-exclude-files=preloader"' "$recipe"
sed -i '$a_LD_FLAGS="-Wl,-O1,--sort-common,--as-needed -fprofile-use=/tmp/soda-pgo/profiles"' "$recipe"
find /tmp/soda-pgo/profiles -type f -name '*.gcda' -exec touch -a -d @1 {} +
touch /tmp/soda-pgo/profile-use-start
set +o pipefail
yes | ./non-makepkg-build.sh 2>&1 | tee /tmp/soda-pgo/evidence/profile-use-build.log
build_status="${PIPESTATUS[1]}"
set -o pipefail
test "$build_status" -eq 0
find /tmp/soda-pgo/profiles -type f -name '*.gcda' \
-anewer /tmp/soda-pgo/profile-use-start -printf '%p\n' \
> /tmp/soda-pgo/evidence/consumed-profiles.txt
consumed_count="$(wc -l < /tmp/soda-pgo/evidence/consumed-profiles.txt)"
test "$consumed_count" -gt 0
grep -E '[#/]+server[#/]+' /tmp/soda-pgo/evidence/consumed-profiles.txt
- name: verify packaged PGO Unix runtime
if: steps.identity.outputs.pgo == 'true'
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
for arch in i386 x86_64; do
unix_dir="$runner_dir/lib/wine/$arch-unix"
test -f "$unix_dir/ntdll.so"
test -f "$unix_dir/win32u.so"
test -f "$unix_dir/winebus.so"
test -f "$unix_dir/winevulkan.so"
test -f "$unix_dir/winex11.so"
if ! grep -aFq 'org.winehq.Soda.Identity' "$unix_dir/windows.security.authentication.onlineid.so"; then
printf 'Missing %s identity credential backend\n' "$arch" >&2
exit 1
fi
module_count="$(find "$unix_dir" -maxdepth 1 -type f -name '*.so' | wc -l)"
test "$module_count" -ge 30
printf '%s PGO Unix modules: %s\n' "$arch" "$module_count"
done
- name: bundle Wine Mono
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
mono_file="wine-mono-$WINE_MONO_VERSION-x86.msi"
mono_url="https://github.com/wine-mono/wine-mono/releases/download/wine-mono-$WINE_MONO_VERSION/$mono_file"
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
grep -F "#define MONO_VERSION \"$WINE_MONO_VERSION\"" src/ValveSoftware-winegit/dlls/appwiz.cpl/addons.c
grep -F "#define MONO_SHA \"$WINE_MONO_SHA256\"" src/ValveSoftware-winegit/dlls/appwiz.cpl/addons.c
curl --fail --location --retry 3 --output "/tmp/$mono_file" "$mono_url"
echo "$WINE_MONO_SHA256 /tmp/$mono_file" | sha256sum --check -
install -Dm644 "/tmp/$mono_file" "$runner_dir/share/wine/mono/$mono_file"
- name: upload pre-test runner
if: steps.identity.outputs.prerelease == 'true' || steps.identity.outputs.publish == 'false'
uses: actions/upload-artifact@v7
with:
name: pre-test-${{ steps.identity.outputs.component_name }}
path: /home/runner/work/wine-tkg-git/wine-tkg-git/non-makepkg-builds/wine-tkg-*
if-no-files-found: error
- name: verify prefix username
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-prefix
export WINEARCH=win64
export USER=soda-ci
unset WINEUSERNAME
runtime_log=/tmp/soda-username.log
mkdir -p "$WINEPREFIX"
if ! WINEDEBUG=err+all xvfb-run -a "$runner_dir/bin/wineboot" -u >"$runtime_log" 2>&1; then
cat "$runtime_log"
exit 1
fi
username_output="$(xvfb-run -a "$runner_dir/bin/wine" cmd /c echo '%USERNAME%' | tr -d '\r')"
username="$(printf '%s\n' "$username_output" | sed -n '/^soda-ci$/p' | tail -1)"
if [[ "$username" != soda-ci ]]; then
printf 'Expected username soda-ci, got:\n%s\n' "$username_output" >&2
exit 1
fi
printf 'Windows username: %s\nWindows profile directories:\n' "$username"
find "$WINEPREFIX/drive_c/users" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort
test -d "$WINEPREFIX/drive_c/users/soda-ci"
test ! -e "$WINEPREFIX/drive_c/users/steamuser"
"$runner_dir/bin/wineserver" -w
- name: verify pure 32-bit prefix
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-win32-prefix
export WINEARCH=win32
mkdir -p "$WINEPREFIX"
xvfb-run -a "$runner_dir/bin/wineboot" -u
architecture_output="$(xvfb-run -a "$runner_dir/bin/wine" cmd /c echo '%PROCESSOR_ARCHITECTURE%' | tr -d '\r')"
architecture="$(printf '%s\n' "$architecture_output" | sed -n '/^x86$/p' | tail -1)"
if [[ "$architecture" != x86 ]]; then
printf 'Expected x86, got:\n%s\n' "$architecture_output" >&2
exit 1
fi
grep -F '#arch=win32' "$WINEPREFIX/system.reg"
"$runner_dir/bin/wineserver" -w
- name: verify Office WinRT classes
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
for arch in i386 x86_64; do
test -f "$runner_dir/lib/wine/$arch-windows/windows.applicationmodel.dll"
test -f "$runner_dir/lib/wine/$arch-windows/windows.networking.dll"
test -f "$runner_dir/lib/wine/$arch-windows/windows.security.enterprisedata.dll"
test -f "$runner_dir/lib/wine/$arch-windows/windows.security.authentication.onlineid.dll"
test -f "$runner_dir/lib/wine/$arch-windows/twinapi.appcore.dll"
test -f "$runner_dir/lib/wine/$arch-unix/windows.security.authentication.onlineid.so"
grep -aFq 'org.winehq.Soda.Identity' "$runner_dir/lib/wine/$arch-unix/windows.security.authentication.onlineid.so"
done
x86_64-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-office-winrt-smoke.c" \
-O2 -Wall -Wextra -Werror -lole32 -lruntimeobject \
-o "$RUNNER_TEMP/soda-office-winrt-smoke64.exe"
i686-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-office-winrt-smoke.c" \
-O2 -Wall -Wextra -Werror -lole32 -lruntimeobject \
-o "$RUNNER_TEMP/soda-office-winrt-smoke32.exe"
x86_64-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-ldap-smoke.c" \
-O2 -Wall -Wextra -Werror -o "$RUNNER_TEMP/soda-ldap-smoke64.exe"
i686-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-ldap-smoke.c" \
-O2 -Wall -Wextra -Werror -o "$RUNNER_TEMP/soda-ldap-smoke32.exe"
run_smoke() {
local arch="$1"
local executable="$2"
local ldap_executable="$3"
local log="$RUNNER_TEMP/soda-office-winrt-$arch.log"
export WINEDEBUG=-all
export WINEPREFIX="$RUNNER_TEMP/soda-office-winrt-prefix-$arch"
export WINEARCH="$arch"
mkdir -p "$WINEPREFIX"
xvfb-run -a "$runner_dir/bin/wineboot" -u
xvfb-run -a "$runner_dir/bin/wine" "$executable" | tr -d '\r' | tee "$log"
grep -Fx 'core_application:00000000' "$log"
grep -Fx 'message_websocket:00000000' "$log"
grep -Fx 'protection_policy:00000000' "$log"
grep -Fx 'retail_info:00000000' "$log"
grep -Fx 'web_authentication_manager:00000000' "$log"
grep -Fx 'composition_effect_source_parameter:00000000' "$log"
xvfb-run -a "$runner_dir/bin/wine" reg add \
"HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\\$(basename "$ldap_executable")" \
/v GlobalFlag /t REG_DWORD /d 112 /f
xvfb-run -a "$runner_dir/bin/wine" "$ldap_executable" \
| tr -d '\r' | tee "$log.ldap"
grep -Fx 'ldap_init_checks:1024 failures:0' "$log.ldap"
"$runner_dir/bin/wineserver" -w
}
run_smoke win64 "$RUNNER_TEMP/soda-office-winrt-smoke64.exe" "$RUNNER_TEMP/soda-ldap-smoke64.exe"
run_smoke win32 "$RUNNER_TEMP/soda-office-winrt-smoke32.exe" "$RUNNER_TEMP/soda-ldap-smoke32.exe"
- name: verify MS-ICU runtime
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
export TZ=America/Denver
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-icu-prefix64
export WINEARCH=win64
mkdir -p "$WINEPREFIX"
xvfb-run -a "$runner_dir/bin/wineboot" -u
xvfb-run -a "$runner_dir/bin/wine" /tmp/soda-icu/smoke64.exe \
| tr -d '\r' | tee /tmp/soda-icu/runtime64.log
grep -F 'ICU 72.1 timezone=America/Denver' /tmp/soda-icu/runtime64.log
"$runner_dir/bin/wineserver" -w
export WINEPREFIX=/tmp/soda-icu-prefix32
export WINEARCH=win32
mkdir -p "$WINEPREFIX"
xvfb-run -a "$runner_dir/bin/wineboot" -u
xvfb-run -a "$runner_dir/bin/wine" /tmp/soda-icu/smoke32.exe \
| tr -d '\r' | tee /tmp/soda-icu/runtime32.log
grep -F 'ICU 72.1 timezone=America/Denver' /tmp/soda-icu/runtime32.log
"$runner_dir/bin/wineserver" -w
- name: verify compatibility fixes
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
Xvfb :97 -screen 0 1024x768x24 >/tmp/soda-compatibility-xvfb.log 2>&1 &
xvfb_pid=$!
trap 'kill "$xvfb_pid" 2>/dev/null || true' EXIT
export DISPLAY=:97
for attempt in {1..100}; do
test ! -S /tmp/.X11-unix/X97 || break
sleep 0.1
done
test -S /tmp/.X11-unix/X97
kill -0 "$xvfb_pid"
grep -F 'winebrowser.exe"" ""%1' src/ValveSoftware-winegit/loader/wine.inf.in
grep -F 'toplevel == hwnd && NtUserGetPresentRect' src/ValveSoftware-winegit/dlls/winex11.drv/init.c
x86_64-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-compatibility-smoke.c" \
-O2 -municode -lshell32 -o /tmp/soda-compatibility-smoke.exe
mkdir /tmp/soda-browser-bin
printf '%s\n' '#!/bin/sh' 'printf "%s" "$1" > /tmp/soda-browser-url' > /tmp/soda-browser-bin/xdg-open
chmod +x /tmp/soda-browser-bin/xdg-open
export PATH="/tmp/soda-browser-bin:$PATH"
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-url-prefix
export WINEARCH=win64
mkdir -p "$WINEPREFIX"
"$runner_dir/bin/wineboot" -u
"$runner_dir/bin/wine" reg add 'HKCU\Software\Wine\WineBrowser' /v Browsers /t REG_SZ /d xdg-open /f
long_url="https://soda.invalid/$(printf 'a%.0s' {1..1024})"
"$runner_dir/bin/wine" /tmp/soda-compatibility-smoke.exe "$long_url"
for attempt in {1..50}; do
test ! -f /tmp/soda-browser-url || break
sleep 0.1
done
test "$(cat /tmp/soda-browser-url)" = "$long_url"
"$runner_dir/bin/wineserver" -w
export WINEPREFIX=/tmp/soda-topology-prefix
export WINE_CPU_TOPOLOGY=2
mkdir -p "$WINEPREFIX"
"$runner_dir/bin/wineboot" -u
cpu_output="$("$runner_dir/bin/wine" cmd /c echo '%NUMBER_OF_PROCESSORS%' | tr -d '\r')"
cpu_count="$(printf '%s\n' "$cpu_output" | sed -n '/^[0-9][0-9]*$/p' | tail -1)"
if [[ "$cpu_count" != 2 ]]; then
printf 'Expected 2 processors, got:\n%s\n' "$cpu_output" >&2
exit 1
fi
"$runner_dir/bin/wineserver" -w
unset WINE_CPU_TOPOLOGY WINEDEBUG
export WINEPREFIX=/tmp/soda-heroes-vii-prefix
mkdir -p "$WINEPREFIX"
cp "$runner_dir/lib/wine/x86_64-windows/cmd.exe" /tmp/MMH7Game-Win64-Shipping.exe
"$runner_dir/bin/wineboot" -u
"$runner_dir/bin/wine" /tmp/MMH7Game-Win64-Shipping.exe /c echo '%NUMBER_OF_PROCESSORS%' \
>/tmp/soda-heroes-vii-cpus 2>/tmp/soda-heroes-vii.log
grep -F 'HACK: limiting Heroes VII CPU topology to ' /tmp/soda-heroes-vii.log
cpu_count="$(tr -d '\r' </tmp/soda-heroes-vii-cpus | sed -n '/^[0-9][0-9]*$/p' | tail -1)"
test -n "$cpu_count"
test "$cpu_count" -le 8
"$runner_dir/bin/wineserver" -w
export WINEDEBUG=-all
export WINE_CPU_TOPOLOGY=2
cpu_output="$("$runner_dir/bin/wine" /tmp/MMH7Game-Win64-Shipping.exe /c echo '%NUMBER_OF_PROCESSORS%' | tr -d '\r')"
cpu_count="$(printf '%s\n' "$cpu_output" | sed -n '/^[0-9][0-9]*$/p' | tail -1)"
if [[ "$cpu_count" != 2 ]]; then
printf 'Expected 2 processors, got:\n%s\n' "$cpu_output" >&2
exit 1
fi
"$runner_dir/bin/wineserver" -w
kill "$xvfb_pid"
trap - EXIT
- name: verify file security mappings
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
x86_64-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-file-security-smoke.c" \
-O2 -Wall -Wextra -Werror -ladvapi32 -o /tmp/soda-file-security-smoke.exe
export WINEDEBUG=-all
export WINEPREFIX=/tmp/soda-file-security-prefix
export WINEARCH=win64
mkdir -p "$WINEPREFIX"
xvfb-run -a "$runner_dir/bin/wineboot" -u
xvfb-run -a "$runner_dir/bin/wine" /tmp/soda-file-security-smoke.exe \
| tr -d '\r' | tee /tmp/soda-file-security-smoke.log
grep -Fx 'reopen:ok' /tmp/soda-file-security-smoke.log
"$runner_dir/bin/wineserver" -w
- name: verify OpenXR outside Steam
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: |
runner_dir="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
runner_dir="$PWD/$runner_dir"
mkdir -p /tmp/soda-openxr/app /tmp/soda-openxr/runtime /tmp/soda-openxr/xdg/openxr/1
chmod 700 /tmp/soda-openxr/runtime
cmake -S /tmp/proton/OpenXR-SDK -B /tmp/soda-openxr/loader-build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
-DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
-DBUILD_API_LAYERS=OFF \
-DBUILD_CONFORMANCE_TESTS=OFF \
-DBUILD_LOADER=ON \
-DBUILD_TESTS=OFF \
-DBUILD_WITH_SYSTEM_JSONCPP=OFF \
-DDYNAMIC_LOADER=ON
cmake --build /tmp/soda-openxr/loader-build --target openxr_loader --parallel 2
loader_dll="$(find /tmp/soda-openxr/loader-build -type f -iname '*openxr_loader.dll' -print -quit)"
test -n "$loader_dll"
cp "$loader_dll" /tmp/soda-openxr/app/openxr_loader.dll
for dll in libgcc_s_seh-1.dll libstdc++-6.dll libwinpthread-1.dll; do
source="$(x86_64-w64-mingw32-g++ -print-file-name="$dll")"
test ! -f "$source" || cp "$source" "/tmp/soda-openxr/app/$dll"
done
x86_64-w64-mingw32-gcc "$GITHUB_WORKSPACE/.github/soda-openxr-smoke.c" \
-I /tmp/proton/OpenXR-SDK/include -O2 -o /tmp/soda-openxr/app/soda-openxr-smoke.exe
monado_manifest=/usr/share/openxr/1/openxr_monado.json
lavapipe_manifest="$(find /usr/share/vulkan/icd.d -type f -name '*lvp*.json' -print -quit)"
test -f "$monado_manifest"
test -n "$lavapipe_manifest"
ln -s "$monado_manifest" /tmp/soda-openxr/xdg/openxr/1/active_runtime.json
export XDG_CONFIG_HOME=/tmp/soda-openxr/xdg
export XDG_RUNTIME_DIR=/tmp/soda-openxr/runtime
export VK_ICD_FILENAMES="$lavapipe_manifest"
export SIMULATED_ENABLE=1
export XRT_COMPOSITOR_NULL=1
export XRT_LOG=info
test -z "${XR_RUNTIME_JSON:-}"
mkfifo /tmp/soda-openxr/monado-input
exec 3<>/tmp/soda-openxr/monado-input
monado-service </tmp/soda-openxr/monado-input >/tmp/soda-openxr/monado.log 2>&1 &
monado_pid=$!
trap 'kill "$monado_pid" 2>/dev/null || true; exec 3>&-' EXIT
for attempt in {1..100}; do
test ! -S "$XDG_RUNTIME_DIR/monado_comp_ipc" || break
sleep 0.1
done
test -S "$XDG_RUNTIME_DIR/monado_comp_ipc"
unset SteamAppId SteamGameId SteamOverlayGameId STEAM_COMPAT_CLIENT_INSTALL_PATH STEAM_COMPAT_DATA_PATH
for process in steam steamwebhelper vrcompositor vrserver; do
if pgrep -x "$process"; then
exit 1
fi
done
export WINEPREFIX=/tmp/soda-openxr/prefix
export WINEARCH=win64
export SODA_OPENXR_RUNTIME=host
export WINEDEBUG=+openxr
mkdir -p "$WINEPREFIX"
xvfb-run -a "$runner_dir/bin/wineboot" -u
install -Dm644 /tmp/proton/wineopenxr/wineopenxr64.json \
"$WINEPREFIX/drive_c/openxr/wineopenxr64.json"
xvfb-run -a "$runner_dir/bin/wine" reg query 'HKLM\Software\Khronos\OpenXR\1' \
/v ActiveRuntime >/tmp/soda-openxr/registry.log
grep -F 'C:\openxr\wineopenxr64.json' /tmp/soda-openxr/registry.log
(
cd /tmp/soda-openxr/app
xvfb-run -a "$runner_dir/bin/wine" soda-openxr-smoke.exe
) >/tmp/soda-openxr/application.log 2>&1
grep -F 'runtime=Monado' /tmp/soda-openxr/application.log
grep -F 'system=Monado: Simulated HMD' /tmp/soda-openxr/application.log
"$runner_dir/bin/wineserver" -w
- name: verify Valve Wine source
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
run: test "$(git -C src/ValveSoftware-winegit rev-parse HEAD)" = "$VALVE_WINE_COMMIT"
- name: benchmark PGO candidate
if: steps.identity.outputs.pgo == 'true'
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/
env:
BASELINE_RUN_ID: ${{ inputs.baseline_run_id || env.PGO_BASELINE_RUN_ID }}
GH_TOKEN: ${{ github.token }}
run: |
test -n "$BASELINE_RUN_ID"
pgo_runner="$(find non-makepkg-builds -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$pgo_runner"
pgo_runner="$PWD/$pgo_runner"
mkdir -p /tmp/soda-pgo/baseline /tmp/soda-pgo/baseline-extracted
gh run download "$BASELINE_RUN_ID" --repo "$GITHUB_REPOSITORY" --dir /tmp/soda-pgo/baseline
baseline_archive="$(find /tmp/soda-pgo/baseline -type f -name 'soda-*-x86_64.tar.xz' -print -quit)"
test -n "$baseline_archive"
tar -C /tmp/soda-pgo/baseline-extracted -xJf "$baseline_archive"
baseline_runner="$(find /tmp/soda-pgo/baseline-extracted -mindepth 1 -maxdepth 1 -type d -name 'soda-*-x86_64' -print -quit)"
test -n "$baseline_runner"
export WINEDEBUG=-all
export WINEARCH=win64
Xvfb :99 -screen 0 1024x768x24 >/tmp/soda-pgo/evidence/xvfb.log 2>&1 &
xvfb_pid=$!
trap 'kill "$xvfb_pid" 2>/dev/null || true' EXIT
export DISPLAY=:99
mkdir -p /tmp/soda-pgo/benchmark-baseline /tmp/soda-pgo/benchmark-pgo
WINEPREFIX=/tmp/soda-pgo/benchmark-baseline "$baseline_runner/bin/wineboot" -u
WINEPREFIX=/tmp/soda-pgo/benchmark-pgo "$pgo_runner/bin/wineboot" -u
measure() {
local label="$1"
local runner="$2"
local prefix="$3"
local sample
sample="$(WINEPREFIX="$prefix" "$runner/bin/wine" \
/tmp/soda-pgo/training64.exe --benchmark | tr -d '\r' | \
sed -n '/^[0-9][0-9]*$/p' | tail -1)"
test -n "$sample"
printf '%s\n' "$sample" >> "/tmp/soda-pgo/evidence/$label-samples.txt"
}
for trial in {1..9}; do
if ((trial % 2)); then
measure baseline "$baseline_runner" /tmp/soda-pgo/benchmark-baseline
measure pgo "$pgo_runner" /tmp/soda-pgo/benchmark-pgo
else
measure pgo "$pgo_runner" /tmp/soda-pgo/benchmark-pgo
measure baseline "$baseline_runner" /tmp/soda-pgo/benchmark-baseline
fi
done
WINEPREFIX=/tmp/soda-pgo/benchmark-baseline "$baseline_runner/bin/wineserver" -w
WINEPREFIX=/tmp/soda-pgo/benchmark-pgo "$pgo_runner/bin/wineserver" -w
baseline_median="$(sort -n /tmp/soda-pgo/evidence/baseline-samples.txt | sed -n '5p')"
pgo_median="$(sort -n /tmp/soda-pgo/evidence/pgo-samples.txt | sed -n '5p')"
median_change="$(awk -v baseline="$baseline_median" -v pgo="$pgo_median" \
'BEGIN { printf "%.2f", (pgo - baseline) * 100 / baseline }')"
paste /tmp/soda-pgo/evidence/baseline-samples.txt \
/tmp/soda-pgo/evidence/pgo-samples.txt \
| awk '{ printf "%.6f\n", ($2 - $1) * 100 / $1 }' \
| sort -n > /tmp/soda-pgo/evidence/paired-change-samples.txt
paired_change_median="$(sed -n '5p' /tmp/soda-pgo/evidence/paired-change-samples.txt)"
printf 'baseline_median_us=%s\npgo_median_us=%s\nmedian_change_percent=%s\npaired_change_median_percent=%s\n' \
"$baseline_median" "$pgo_median" "$median_change" "$paired_change_median" \
> /tmp/soda-pgo/evidence/benchmark.txt
printf 'PGO benchmark: baseline %s us, candidate %s us, median change %s%%, paired change %s%%\n' \
"$baseline_median" "$pgo_median" "$median_change" "$paired_change_median" \
>> "$GITHUB_STEP_SUMMARY"
awk -v median="$median_change" -v paired="$paired_change_median" \
'BEGIN { exit !(median <= 2 && paired <= 5) }'
- name: Upload prepare.log on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: failure-logs
path: |
/home/runner/work/wine-tkg-git/wine-tkg-git/prepare.log
/home/runner/work/wine-tkg-git/wine-tkg-git/src/*-build/config.log
/tmp/soda-pgo/evidence
/tmp/soda-*.log
/tmp/soda-openxr/*.log
if-no-files-found: ignore
- name: package
working-directory: /home/runner/work/wine-tkg-git/wine-tkg-git/non-makepkg-builds/
env:
ARCHIVE_NAME: ${{ steps.identity.outputs.archive_name }}
COMPONENT_NAME: ${{ steps.identity.outputs.component_name }}
run: |
runner_dir="$(find . -mindepth 1 -maxdepth 1 -type d -name 'wine-tkg-*' -print -quit)"
test -n "$runner_dir"
test -f "$runner_dir/lib/wine/x86_64-unix/winegstreamer.so"
test -f "$runner_dir/lib/wine/i386-unix/winegstreamer.so"
test -f "$runner_dir/lib/wine/i386-windows/winegstreamer.dll"
test -f "$runner_dir/lib/wine/x86_64-unix/winscard.so"
test -f "$runner_dir/lib/wine/i386-unix/winscard.so"
test -f "$runner_dir/lib/wine/x86_64-windows/winscard.dll"
test -f "$runner_dir/lib/wine/i386-windows/winscard.dll"
for arch in i386 x86_64; do
test -f "$runner_dir/lib/wine/$arch-windows/windows.security.authentication.onlineid.dll"
test -f "$runner_dir/lib/wine/$arch-windows/twinapi.appcore.dll"
test -f "$runner_dir/lib/wine/$arch-unix/windows.security.authentication.onlineid.so"
done
test -x "$runner_dir/bin/wine"
file "$runner_dir/bin/wine" | grep -F 'x86-64'
file "$runner_dir/lib/wine/x86_64-windows/ntdll.dll" | grep -F 'x86-64'
file "$runner_dir/lib/wine/i386-windows/ntdll.dll" | grep -F 'Intel 80386'
test -f "$runner_dir/lib/wine/x86_64-windows/wineopenxr.dll"
test -f "$runner_dir/lib/wine/x86_64-unix/wineopenxr.so"
install -Dm644 /tmp/proton/wineopenxr/wineopenxr64.json "$runner_dir/share/openxr/wineopenxr64.json"
xvfb-run -a sh "$GITHUB_WORKSPACE/.github/build-eagle.sh" "$runner_dir" "$HOME/artifacts/Soda-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
mv "$runner_dir" "$COMPONENT_NAME"
tar cJvf "$ARCHIVE_NAME" "$COMPONENT_NAME"
mv "$ARCHIVE_NAME" "/tmp/$ARCHIVE_NAME"
- name: upload Eagle test logs
if: always()
uses: actions/upload-artifact@v7
with:
name: eagle-test-logs-${{ github.sha }}
path: |
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/32/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/64/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/p32/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/p64/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/c32/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/c64/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/s32/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/s64/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/d/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/t/*.log
/home/runner/artifacts/Soda-${{ github.run_id }}-${{ github.run_attempt }}/tests/e/*.log
if-no-files-found: ignore
- name: upload
uses: actions/upload-artifact@v7
with:
name: ${{ steps.identity.outputs.component_name }}
path: /tmp/${{ steps.identity.outputs.archive_name }}
if-no-files-found: error
- name: upload PGO evidence
if: steps.identity.outputs.pgo == 'true'
uses: actions/upload-artifact@v7
with:
name: pgo-evidence-${{ github.sha }}
path: /tmp/soda-pgo/evidence/*.txt
if-no-files-found: error
arm64:
needs: patches
if: github.event_name == 'push' || inputs.architecture == 'aarch64'
runs-on: ubuntu-24.04-arm
timeout-minutes: 360
outputs:
archive_name: ${{ steps.identity.outputs.archive_name }}
component_name: ${{ steps.identity.outputs.component_name }}
steps:
- uses: actions/checkout@v7
- name: define build identity
id: identity
run: |
version="$WINE_VERSION-$REVISION"
if [[ "$GITHUB_EVENT_NAME" != "push" || "$GITHUB_REF" != "refs/heads/soda" ]]; then
version="$version-${GITHUB_SHA::7}"
fi
component_name="soda-$version-aarch64"
echo "archive_name=$component_name.tar.xz" >> "$GITHUB_OUTPUT"
echo "component_name=$component_name" >> "$GITHUB_OUTPUT"
- name: setup
run: |
test "$(uname -m)" = aarch64
sudo apt-get update
sudo apt-get install -y \
g++ \
file \
gcc-mingw-w64-i686 \
gcc-mingw-w64-x86-64 \
xvfb \
xz-utils
command -v docker
sudo systemctl start docker
docker version
- name: prepare sources
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
git clone --filter=blob:none --no-checkout https://github.com/ValveSoftware/Proton.git /tmp/proton
git -C /tmp/proton checkout "$PROTON_COMMIT"
test "$(git -C /tmp/proton rev-parse HEAD)" = "$PROTON_COMMIT"
git -C /tmp/proton submodule update --init --recursive wine OpenXR-SDK FEX
test "$(git -C /tmp/proton/FEX rev-parse HEAD)" = "$FEX_COMMIT"
test "$(git -C /tmp/proton/OpenXR-SDK rev-parse HEAD)" = "$OPENXR_SDK_COMMIT"
git -C /tmp/proton/wine fetch --no-tags origin "$VALVE_WINE_TAG"
git -C /tmp/proton/wine checkout --detach "$VALVE_WINE_COMMIT"
test "$(git -C /tmp/proton/wine rev-parse HEAD)" = "$VALVE_WINE_COMMIT"
.github/import-msicu.sh /tmp/proton/wine
for patch in "$GITHUB_WORKSPACE"/wine-tkg-userpatches/*.mypatch; do
if [[ "$patch" == *wineopenxr-host-runtime.mypatch ]]; then
continue
fi
git -C /tmp/proton/wine apply --check "$patch"
git -C /tmp/proton/wine apply "$patch"
done
git -C /tmp/proton/wineopenxr apply --check "$GITHUB_WORKSPACE/.github/wineopenxr-host-runtime-proton.mypatch"
git -C /tmp/proton/wineopenxr apply "$GITHUB_WORKSPACE/.github/wineopenxr-host-runtime-proton.mypatch"
- name: build ICU and Office smoke programs
run: |
mkdir -p /tmp/soda-icu
x86_64-w64-mingw32-gcc .github/soda-icu-smoke.c \
-O2 -Wall -Wextra -Werror -o /tmp/soda-icu/smoke64.exe
i686-w64-mingw32-gcc .github/soda-icu-smoke.c \
-O2 -Wall -Wextra -Werror -o /tmp/soda-icu/smoke32.exe
mkdir -p "$RUNNER_TEMP/soda-office-winrt"
x86_64-w64-mingw32-gcc .github/soda-office-winrt-smoke.c \
-O2 -Wall -Wextra -Werror -lole32 -lruntimeobject \
-o "$RUNNER_TEMP/soda-office-winrt/smoke64.exe"
i686-w64-mingw32-gcc .github/soda-office-winrt-smoke.c \
-O2 -Wall -Wextra -Werror -lole32 -lruntimeobject \
-o "$RUNNER_TEMP/soda-office-winrt/smoke32.exe"
x86_64-w64-mingw32-gcc .github/soda-ldap-smoke.c \
-O2 -Wall -Wextra -Werror -o "$RUNNER_TEMP/soda-office-winrt/ldap64.exe"
i686-w64-mingw32-gcc .github/soda-ldap-smoke.c \
-O2 -Wall -Wextra -Werror -o "$RUNNER_TEMP/soda-office-winrt/ldap32.exe"
- name: prepare identity SDK
run: |
docker build --file .github/soda-arm64-sdk.Dockerfile --tag soda-arm64-sdk .github
- name: configure
run: |
mkdir /tmp/proton-build
cd /tmp/proton-build
/tmp/proton/configure.sh --build-name=soda-arm64 --target-arch=arm64 \
--container-engine=docker --proton-sdk-image=soda-arm64-sdk
- name: build Wine and FEX
working-directory: /tmp/proton-build
run: |
make WINE_DEPENDS= WINE_aarch64_DEPENDS= wine
make WINE_DEPENDS= WINE_aarch64_DEPENDS= fex
make WINE_DEPENDS= WINE_aarch64_DEPENDS= fex_unixlib
make WINE_DEPENDS= WINE_aarch64_DEPENDS= wineopenxr
- name: package
env:
ARCHIVE_NAME: ${{ steps.identity.outputs.archive_name }}
COMPONENT_NAME: ${{ steps.identity.outputs.component_name }}
run: |
runner_dir="/tmp/$COMPONENT_NAME"
proton_files=/tmp/proton-build/dist/files
test -x "$proton_files/bin-arm64/wine"
test -x "$proton_files/bin-arm64/wineserver"
mkdir "$runner_dir"
cp -a "$proton_files"/. "$runner_dir"/
mv "$runner_dir/bin-arm64" "$runner_dir/bin"
install -Dm644 /tmp/proton/FEX_Config.json "$runner_dir/share/fex-emu/Config.json"
install -Dm644 /tmp/proton/wineopenxr/wineopenxr64.json "$runner_dir/share/openxr/wineopenxr64.json"
mono_file="wine-mono-$WINE_MONO_VERSION-x86.msi"
mono_url="https://github.com/wine-mono/wine-mono/releases/download/wine-mono-$WINE_MONO_VERSION/$mono_file"
curl --fail --location --retry 3 --output "/tmp/$mono_file" "$mono_url"
echo "$WINE_MONO_SHA256 /tmp/$mono_file" | sha256sum --check -
install -Dm644 "/tmp/$mono_file" "$runner_dir/share/wine/mono/$mono_file"
required_files=(
lib/wine/aarch64-unix/ntdll.so
lib/wine/aarch64-windows/ntdll.dll
lib/wine/x86_64-windows/ntdll.dll
lib/wine/i386-windows/icu.dll
lib/wine/x86_64-windows/icu.dll
lib/wine/aarch64-windows/icu.dll
lib/wine/aarch64-windows/libarm64ecfex.dll
lib/wine/aarch64-windows/libwow64fex.dll
lib/wine/aarch64-unix/libarm64ecfex.so
lib/wine/aarch64-unix/libwow64fex.so
lib/wine/aarch64-windows/wineopenxr.dll
lib/wine/x86_64-windows/wineopenxr.dll
lib/wine/i386-windows/windows.security.authentication.onlineid.dll
lib/wine/x86_64-windows/windows.security.authentication.onlineid.dll
lib/wine/aarch64-windows/windows.security.authentication.onlineid.dll
lib/wine/aarch64-unix/windows.security.authentication.onlineid.so
lib/wine/i386-windows/twinapi.appcore.dll
lib/wine/x86_64-windows/twinapi.appcore.dll
lib/wine/aarch64-windows/twinapi.appcore.dll
)
for required_file in "${required_files[@]}"; do
if ! test -f "$runner_dir/$required_file"; then
echo "Missing required ARM64 runner file: $required_file" >&2
exit 1
fi
done
grep -aFq 'org.winehq.Soda.Identity' \
"$runner_dir/lib/wine/aarch64-unix/windows.security.authentication.onlineid.so"
file "$runner_dir/bin/wine" | grep -F 'ARM aarch64'
if ldd "$runner_dir/bin/wine" | grep -F 'not found'; then
exit 1
fi
tar -C /tmp -cJf "/tmp/$ARCHIVE_NAME" "$COMPONENT_NAME"
- name: upload
uses: actions/upload-artifact@v7
with:
name: ${{ steps.identity.outputs.component_name }}
path: /tmp/${{ steps.identity.outputs.archive_name }}
if-no-files-found: error
- name: verify Windows architectures
env:
COMPONENT_NAME: ${{ steps.identity.outputs.component_name }}
run: |
set -o pipefail
runner_dir="/tmp/$COMPONENT_NAME"
export FEX_APP_CONFIG="$runner_dir/share/fex-emu/Config.json"
export FEX_APP_CONFIG_LOCATION="$runner_dir/share/fex-emu"
export WINEARCH=win64
export WINEDEBUG=+module,+process
export WINEPREFIX=/tmp/soda-arm64-prefix
runtime_log=/tmp/soda-arm64-runtime.log
mkdir -p "$WINEPREFIX"
if ! xvfb-run -a "$runner_dir/bin/wine" wineboot -u >"$runtime_log" 2>&1; then
cat "$runtime_log"
exit 1
fi
if ! native_arch="$(xvfb-run -a "$runner_dir/bin/wine" cmd /c echo '%PROCESSOR_ARCHITECTURE%' 2>>"$runtime_log" | tr -d '\r' | grep -E '^(ARM64|AMD64|x86)$' | tail -1)"; then
cat "$runtime_log"
exit 1
fi
if [[ "$native_arch" != ARM64 ]]; then
printf 'Expected ARM64, got: %s\n' "$native_arch" >&2
cat "$runtime_log"
exit 1
fi
x64_cmd="$runner_dir/lib/wine/x86_64-windows/cmd.exe"
test -f "$x64_cmd"
if ! x64_arch="$(xvfb-run -a "$runner_dir/bin/wine" "$x64_cmd" /c echo '%PROCESSOR_ARCHITECTURE%' 2>>"$runtime_log" | tr -d '\r' | grep -E '^(ARM64|AMD64|x86)$' | tail -1)"; then
cat "$runtime_log"
exit 1
fi
if [[ "$x64_arch" != AMD64 ]]; then
printf 'Expected AMD64, got: %s\n' "$x64_arch" >&2
cat "$runtime_log"
exit 1
fi
x86_cmd="$runner_dir/lib/wine/i386-windows/cmd.exe"
test -f "$x86_cmd"
if ! x86_arch="$(xvfb-run -a "$runner_dir/bin/wine" "$x86_cmd" /c echo '%PROCESSOR_ARCHITECTURE%' 2>>"$runtime_log" | tr -d '\r' | grep -E '^(ARM64|AMD64|x86)$' | tail -1)"; then
cat "$runtime_log"
exit 1
fi
if [[ "$x86_arch" != x86 ]]; then
printf 'Expected x86, got: %s\n' "$x86_arch" >&2
cat "$runtime_log"
exit 1
fi
printf 'Windows architectures: native=%s, x64=%s, x86=%s\n' \
"$native_arch" "$x64_arch" "$x86_arch" | tee -a "$GITHUB_STEP_SUMMARY"
export TZ=America/Denver
export WINEDEBUG=-all
"$runner_dir/bin/wine" /tmp/soda-icu/smoke64.exe \
| tr -d '\r' | tee /tmp/soda-icu/runtime64.log
grep -F 'ICU 72.1 timezone=America/Denver' /tmp/soda-icu/runtime64.log
"$runner_dir/bin/wine" /tmp/soda-icu/smoke32.exe \
| tr -d '\r' | tee /tmp/soda-icu/runtime32.log
grep -F 'ICU 72.1 timezone=America/Denver' /tmp/soda-icu/runtime32.log
for arch in 64 32; do
"$runner_dir/bin/wine" "$RUNNER_TEMP/soda-office-winrt/smoke$arch.exe" \
| tr -d '\r' | tee "$RUNNER_TEMP/soda-office-winrt/runtime$arch.log"
for factory in core_application message_websocket protection_policy retail_info web_authentication_manager composition_effect_source_parameter; do
grep -Fx "$factory:00000000" "$RUNNER_TEMP/soda-office-winrt/runtime$arch.log"
done
"$runner_dir/bin/wine" reg add \
"HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ldap$arch.exe" \
/v GlobalFlag /t REG_DWORD /d 112 /f
"$runner_dir/bin/wine" "$RUNNER_TEMP/soda-office-winrt/ldap$arch.exe" \
| tr -d '\r' | tee "$RUNNER_TEMP/soda-office-winrt/ldap$arch.log"
grep -Fx 'ldap_init_checks:1024 failures:0' "$RUNNER_TEMP/soda-office-winrt/ldap$arch.log"
done
"$runner_dir/bin/wineserver" -w
recovery:
if: >-
github.event_name == 'workflow_dispatch' &&
inputs.recovery_run != '' &&
github.ref == 'refs/heads/soda'
runs-on: ubuntu-24.04
permissions:
actions: read
contents: write
env:
GH_TOKEN: ${{ github.token }}
SOURCE_RUN: ${{ inputs.recovery_run }}
SOURCE_COMMIT: '348313d6426f58cd892fc33a975919c1200f403c'
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: verify completed builds
run: |
[[ "$SOURCE_RUN" =~ ^[0-9]+$ ]]
work="$HOME/artifacts/Soda-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
mkdir -p "$work/t" "$work/release" "$work/logs"
export TMPDIR="$work/t" TMP="$work/t" TEMP="$work/t"
echo "RECOVERY_WORK=$work" >> "$GITHUB_ENV"
echo "TMPDIR=$work/t" >> "$GITHUB_ENV"
echo "TMP=$work/t" >> "$GITHUB_ENV"
echo "TEMP=$work/t" >> "$GITHUB_ENV"
gh api "repos/$GITHUB_REPOSITORY/actions/runs/$SOURCE_RUN" > "$work/run.json"
gh api "repos/$GITHUB_REPOSITORY/actions/runs/$SOURCE_RUN/jobs" > "$work/jobs.json"
python3 - "$work" <<'PYCODE'
import json
import os
from pathlib import Path
import sys
work = Path(sys.argv[1])
run = json.loads((work / 'run.json').read_text())
jobs = json.loads((work / 'jobs.json').read_text())['jobs']
assert run['head_sha'] == os.environ['SOURCE_COMMIT']
assert run['head_branch'] == 'soda' and run['event'] == 'push'
assert run['status'] == 'completed' and run['conclusion'] == 'failure'
assert run['path'] == '.github/workflows/build-soda.yml'
for name in ('patches', 'arm64'):
assert next(job for job in jobs if job['name'] == name)['conclusion'] == 'success'
steps = next(job for job in jobs if job['name'] == 'build')['steps']
package = next(i for i, step in enumerate(steps) if step['name'] == 'package')
assert all(step['conclusion'] == 'success' or (step['name'] == 'Upload prepare.log on failure' and step['conclusion'] == 'skipped') for step in steps[:package + 1])
assert steps[package]['conclusion'] == 'success'
assert [step['name'] for step in steps if step['conclusion'] == 'failure'] == ['upload Eagle test logs']
print('Completed Wine builds and package tests verified; only log upload failed')
PYCODE
git merge-base --is-ancestor "$SOURCE_COMMIT" "$GITHUB_SHA"
test -z "$(git diff --name-only "$SOURCE_COMMIT" "$GITHUB_SHA" -- . ':(exclude).github/workflows/**')"
- name: setup
working-directory: /home/runner/work/
run: |
mkdir -p /home/runner/.config/frogminer/
sudo apt purge -y ubuntu-advantage-tools python3-update-manager
sudo dpkg --add-architecture i386 && sudo apt update
sudo apt-mark hold grub-common grub-efi-amd64-bin python3 python3-apt shim-signed
sudo apt install aptitude
sudo aptitude remove -y '?narrow(?installed,?version(deb.sury.org))'
sudo apt install -f
sudo apt-get install -y -o Dpkg::Options::="--force-overwrite" libpcap-dev:amd64 libpcap-dev:i386
sudo apt-get install -y libglib2.0-dev-bin libglib2.0-dev:amd64
sudo aptitude install -y -o Dpkg::Options::="--force-overwrite" \
libglib2.0-dev-bin:amd64 \
libgudev-1.0-dev:amd64 \
libgudev-1.0-dev:i386 \
libvulkan-dev:amd64 \
libvulkan-dev:i386
sudo apt-get install -y -o Dpkg::Options::="--force-overwrite" libpcsclite-dev:amd64 libpcsclite-dev:i386
sudo apt-get install -y libsecret-1-dev:amd64 libsecret-1-0:i386
sudo apt-get install -y libfreetype6:amd64 libfreetype6:i386 libfontconfig1:amd64 libfontconfig1:i386
bash "$GITHUB_WORKSPACE/.github/soda-secret-headers.sh" "$GITHUB_WORKSPACE/.soda-secret-amd64" amd64
bash "$GITHUB_WORKSPACE/.github/soda-secret-headers.sh" "$GITHUB_WORKSPACE/.soda-secret-i386" i386
sudo apt-get install -y \
g++ \
cmake \
file \
g++-mingw-w64-i686 \
g++-mingw-w64-x86-64 \
libopenxr-dev:amd64 \
"libopenxr1-monado=$MONADO_VERSION" \
mesa-vulkan-drivers \
"monado-service=$MONADO_VERSION" \
ninja-build \
xvfb
sudo apt-get check
- name: package verified Wine artifacts
run: |
work="$RECOVERY_WORK"
component="soda-$WINE_VERSION-$REVISION"
gh run download "$SOURCE_RUN" --repo "$GITHUB_REPOSITORY" \
--name "pre-test-$component-x86_64" --dir "$work/runner"
wine="$(find "$work/runner" -maxdepth 3 -type f -path '*/bin/wine' -print)"
test "$(printf '%s\n' "$wine" | wc -l)" = 1
test -n "$wine"
runner="${wine%/bin/wine}"
chmod +x "$runner"/bin/*
for name in msidb msiexec notepad regedit regsvr32 wineboot winecfg wineconsole winedbg winefile winemine winepath; do
cmp "$runner/bin/$name" "$runner/bin/wine"
ln -sf wine "$runner/bin/$name"
done
for name in winecpp wineg++; do
cmp "$runner/bin/$name" "$runner/bin/winegcc"
ln -sf winegcc "$runner/bin/$name"
done
install -d "$runner/share/openxr"
curl -fL "https://raw.githubusercontent.com/ValveSoftware/Proton/$PROTON_COMMIT/wineopenxr/wineopenxr64.json" \
-o "$runner/share/openxr/wineopenxr64.json"
file "$runner/bin/wine" | grep -F 'x86-64'
for arch in i386 x86_64; do
test -f "$runner/lib/wine/$arch-unix/winegstreamer.so"
test -f "$runner/lib/wine/$arch-unix/winscard.so"
test -f "$runner/lib/wine/$arch-unix/windows.security.authentication.onlineid.so"
done
test -f "$runner/lib/wine/x86_64-unix/wineopenxr.so"
xvfb-run -a sh "$GITHUB_WORKSPACE/.github/build-eagle.sh" "$runner" "$work/eagle"
mv "$runner" "$work/release/$component-x86_64"
tar -C "$work/release" -cJf "$work/release/$component-x86_64.tar.xz" "$component-x86_64"
gh run download "$SOURCE_RUN" --repo "$GITHUB_REPOSITORY" \
--name "$component-aarch64" --dir "$work/release"
cd "$work/release"
echo 'df670ae214ae7ac6c1934fbf2d4b25efc5753561a27a47cb48ba4a4663725f4a soda-11.0-27-experimental-aarch64.tar.xz' | sha256sum --check -
sha256sum "$component-x86_64.tar.xz" "$component-aarch64.tar.xz" > SHA256SUMS
- name: collect package test logs
if: always()
run: |
work="$RECOVERY_WORK"
for log in "$work"/eagle/tests/{32,64,p32,p64,c32,c64,d,t,e}/*.log; do
test -f "$log" || continue
directory="$(basename "$(dirname "$log")")"
cp "$log" "$work/logs/$directory-$(basename "$log")"
done
- name: upload package test logs
if: always()
uses: actions/upload-artifact@v7
with:
name: eagle-recovery-test-logs-${{ github.sha }}
path: ${{ env.RECOVERY_WORK }}/logs/*.log
if-no-files-found: error
- name: upload verified packages
uses: actions/upload-artifact@v7
with:
name: soda-package-recovery-${{ github.sha }}
path: |
${{ env.RECOVERY_WORK }}/release/*.tar.xz
${{ env.RECOVERY_WORK }}/release/SHA256SUMS
if-no-files-found: error
- name: release
env:
GH_REPO: ${{ github.repository }}
run: |
component="soda-$WINE_VERSION-$REVISION"
cd "$RECOVERY_WORK/release"
if gh release view "$component" >/dev/null 2>&1; then
echo "Release $component already exists." >&2
exit 1
fi
printf '%s\n' "$RELEASE_NOTES" > "$RECOVERY_WORK/notes.md"
gh release create "$component" "$component-x86_64.tar.xz" "$component-aarch64.tar.xz" SHA256SUMS \
--target "$GITHUB_SHA" --title "Soda $WINE_VERSION-$REVISION" \
--notes-file "$RECOVERY_WORK/notes.md" --prerelease
release:
needs:
- build
- arm64
if: needs.build.outputs.publish == 'true'
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
name: ${{ needs.build.outputs.component_name }}
- uses: actions/download-artifact@v8
with:
name: ${{ needs.arm64.outputs.component_name }}
- name: release
if: github.event_name == 'push' && github.ref == 'refs/heads/soda'
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
ARCHIVE_NAME: ${{ needs.build.outputs.archive_name }}
ARM64_ARCHIVE_NAME: ${{ needs.arm64.outputs.archive_name }}
run: |
tag="soda-$WINE_VERSION-$REVISION"
title="Soda $WINE_VERSION-$REVISION"
file="$ARCHIVE_NAME"
arm64_file="$ARM64_ARCHIVE_NAME"
release_flags=(--latest)
if [[ -n "$RELEASE_CODENAME" ]]; then
title="$title - $RELEASE_CODENAME"
fi
if [[ "${{ needs.build.outputs.prerelease }}" == "true" ]]; then
release_flags=(--prerelease)
fi
if gh release view "$tag" >/dev/null 2>&1; then
echo "Release $tag already exists." >&2
exit 1
fi
sha256sum "$file" "$arm64_file" > SHA256SUMS
gh release create "$tag" "$file" "$arm64_file" SHA256SUMS --target "$GITHUB_SHA" --title "$title" --notes "$RELEASE_NOTES" "${release_flags[@]}"