mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-13 18:14:13 +02:00
76ff69e912
Weekly cron replaced with a monthly run (1st of each month, 02:00 UTC) to reduce unnecessary CI load. retention-days raised from 14 to 40 across all six artifact uploads (Qt5 + Qt6 tracks) to cover the new monthly interval with a safety margin -- 14 days was shorter than the gap between two cron runs, so the latest build's artifacts could expire before the next one replaced them.
773 lines
30 KiB
YAML
773 lines
30 KiB
YAML
name: Windows Build
|
||
|
||
on:
|
||
schedule:
|
||
- cron: '0 2 1 * *' #
|
||
workflow_dispatch: # Manual trigger available at any time
|
||
|
||
concurrency:
|
||
group: ${{ github.workflow }}-${{ github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
jobs:
|
||
# =============================================================================
|
||
# Job 1: Qt5 build (stable track)
|
||
# =============================================================================
|
||
build-windows:
|
||
runs-on: windows-latest
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v7
|
||
with:
|
||
submodules: recursive
|
||
fetch-depth: 0
|
||
|
||
- name: Install MSYS2
|
||
uses: msys2/setup-msys2@v2
|
||
with:
|
||
msystem: UCRT64
|
||
update: true
|
||
cache: true
|
||
install: >-
|
||
git
|
||
mingw-w64-ucrt-x86_64-ccache
|
||
mingw-w64-ucrt-x86_64-gcc
|
||
mingw-w64-ucrt-x86_64-cmake
|
||
mingw-w64-ucrt-x86_64-ninja
|
||
mingw-w64-ucrt-x86_64-qt5-base
|
||
mingw-w64-ucrt-x86_64-qt5-svg
|
||
mingw-w64-ucrt-x86_64-qt5-tools
|
||
mingw-w64-ucrt-x86_64-qt5-translations
|
||
mingw-w64-ucrt-x86_64-qt5-pdf
|
||
mingw-w64-ucrt-x86_64-sqlite3
|
||
mingw-w64-ucrt-x86_64-pkg-config
|
||
mingw-w64-ucrt-x86_64-kwidgetsaddons
|
||
mingw-w64-ucrt-x86_64-kcoreaddons
|
||
mingw-w64-ucrt-x86_64-extra-cmake-modules
|
||
mingw-w64-ucrt-x86_64-nsis
|
||
mingw-w64-ucrt-x86_64-angleproject
|
||
|
||
- name: Cache ccache
|
||
uses: actions/cache@v5
|
||
with:
|
||
path: C:\Users\runneradmin\AppData\Local\ccache
|
||
key: ccache-windows-${{ github.ref_name }}-${{ github.sha }}
|
||
restore-keys: |
|
||
ccache-windows-${{ github.ref_name }}-
|
||
ccache-windows-
|
||
|
||
- name: Configure ccache
|
||
shell: msys2 {0}
|
||
run: |
|
||
/ucrt64/bin/ccache --set-config=max_size=500M
|
||
/ucrt64/bin/ccache --set-config=compression=true
|
||
/ucrt64/bin/ccache -z
|
||
echo "=== ccache config ==="
|
||
/ucrt64/bin/ccache -p
|
||
|
||
- name: Patch NSIS Welcome page — fix title font size
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
WELCOME_NSH=$(find /ucrt64 -path "*/Modern UI 2/Pages/Welcome.nsh" | head -1)
|
||
if [ -z "$WELCOME_NSH" ]; then
|
||
echo "WARNING: Welcome.nsh not found, skipping font patch"
|
||
else
|
||
echo "Patching: $WELCOME_NSH"
|
||
sed -i '/WelcomePage\.Title\.Font/s/"[0-9]\+" "700"/"10" "700"/' "$WELCOME_NSH"
|
||
grep 'WelcomePage.Title.Font' "$WELCOME_NSH"
|
||
echo " OK font size patched to 10"
|
||
fi
|
||
|
||
FINISH_NSH=$(find /ucrt64 -path "*/Modern UI 2/Pages/Finish.nsh" | head -1)
|
||
if [ -z "$FINISH_NSH" ]; then
|
||
echo "WARNING: Finish.nsh not found, skipping font patch"
|
||
else
|
||
echo "Patching: $FINISH_NSH"
|
||
sed -i '/FinishPage\.Title\.Font/s/"[0-9]\+" "700"/"10" "700"/' "$FINISH_NSH"
|
||
grep 'FinishPage.Title.Font' "$FINISH_NSH"
|
||
echo " OK font size patched to 10"
|
||
fi
|
||
|
||
- name: Force Qt5 — remove Qt6 cmake + tools
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
rm -rf /ucrt64/lib/cmake/Qt6
|
||
pacman -R --noconfirm mingw-w64-ucrt-x86_64-qt6-tools 2>/dev/null || true
|
||
echo "=== windeployqt binaries ==="
|
||
ls /ucrt64/bin/windeployqt* || echo "NO windeployqt found!"
|
||
|
||
- name: Build with cmake
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
cd "$GITHUB_WORKSPACE"
|
||
mkdir build && cd build
|
||
NPROC=$(nproc)
|
||
echo "Available CPUs: $NPROC"
|
||
|
||
cmake -G Ninja \
|
||
-DCMAKE_BUILD_TYPE=Release \
|
||
-DCMAKE_PREFIX_PATH=/ucrt64 \
|
||
-DQt5_DIR=/ucrt64/lib/cmake/Qt5 \
|
||
-DQT_VERSION_MAJOR=5 \
|
||
-DCMAKE_DISABLE_FIND_PACKAGE_Qt6=ON \
|
||
-DBUILD_TESTING=OFF \
|
||
-DCMAKE_POLICY_DEFAULT_CMP0077=NEW \
|
||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||
-DCMAKE_CXX_FLAGS="-DQET_EXPORT_PROJECT_DB" \
|
||
-DCMAKE_C_COMPILER_LAUNCHER=/ucrt64/bin/ccache \
|
||
-DCMAKE_CXX_COMPILER_LAUNCHER=/ucrt64/bin/ccache \
|
||
-DSQLite3_INCLUDE_DIR=/ucrt64/include \
|
||
-DSQLite3_LIBRARY=/ucrt64/lib/libsqlite3.dll.a \
|
||
..
|
||
ninja -j"$NPROC"
|
||
|
||
- name: Show ccache stats
|
||
shell: msys2 {0}
|
||
run: |
|
||
echo "=== ccache statistics ==="
|
||
/ucrt64/bin/ccache -s
|
||
|
||
- name: Verify exe was built
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
EXE=$(find "$GITHUB_WORKSPACE/build" -maxdepth 3 -iname "qelectrotech.exe" | head -1)
|
||
if [ -z "$EXE" ]; then
|
||
echo "ERROR: no qelectrotech.exe found in build/"
|
||
find "$GITHUB_WORKSPACE/build" -maxdepth 3 -name "*.exe" || true
|
||
exit 1
|
||
fi
|
||
SIZE=$(stat -c%s "$EXE")
|
||
echo "Exe found: $EXE ($SIZE bytes)"
|
||
[ "$SIZE" -gt 100000 ] || { echo "ERROR: exe too small"; exit 1; }
|
||
|
||
- name: Deploy — copy exe + windeployqt + DLLs
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
NSIS_ROOT="$GITHUB_WORKSPACE/nsis_root"
|
||
FILES="$NSIS_ROOT/files"
|
||
BIN="$FILES/bin"
|
||
mkdir -p "$BIN"
|
||
|
||
EXE=$(find "$GITHUB_WORKSPACE/build" -maxdepth 3 -iname "qelectrotech.exe" | head -1)
|
||
echo "Copying exe: $EXE -> $BIN/QElectroTech.exe"
|
||
cp "$EXE" "$BIN/QElectroTech.exe"
|
||
|
||
cd "$BIN"
|
||
/ucrt64/bin/windeployqt-qt5 \
|
||
--release \
|
||
--no-translations \
|
||
--no-compiler-runtime \
|
||
./QElectroTech.exe || true
|
||
|
||
echo "=== 3-pass transitive DLL scan ==="
|
||
set +e
|
||
for PASS in 1 2 3; do
|
||
echo "-- Pass $PASS --"
|
||
for bin_file in "$BIN"/*.dll "$BIN"/*.exe "$BIN"/sqldrivers/*.dll "$BIN"/platforms/*.dll "$BIN"/imageformats/*.dll; do
|
||
[ -f "$bin_file" ] || continue
|
||
while IFS= read -r line; do
|
||
dll_path=$(echo "$line" | awk '{print $3}')
|
||
[ -f "$dll_path" ] || continue
|
||
dll_name=$(basename "$dll_path")
|
||
dst="$BIN/$dll_name"
|
||
if [ ! -f "$dst" ]; then
|
||
cp "$dll_path" "$dst"
|
||
echo " Copied (pass $PASS): $dll_name"
|
||
fi
|
||
done < <(ldd "$bin_file" 2>/dev/null | grep -i '/ucrt64/bin/')
|
||
done
|
||
done
|
||
set -e
|
||
|
||
DLL_COUNT=$(find "$BIN" -name "*.dll" | wc -l)
|
||
echo "=== $DLL_COUNT DLLs present after scan ==="
|
||
ls -lh "$BIN/QElectroTech.exe" || { echo "ERROR: exe missing from bin/"; exit 1; }
|
||
[ "$DLL_COUNT" -gt 5 ] || { echo "ERROR: too few DLLs"; exit 1; }
|
||
cd "$GITHUB_WORKSPACE"
|
||
|
||
cp /ucrt64/bin/libgcc_s_seh-1.dll "$BIN/"
|
||
cp /ucrt64/bin/libstdc++-6.dll "$BIN/"
|
||
cp /ucrt64/bin/libwinpthread-1.dll "$BIN/"
|
||
SQLITE=$(find /ucrt64/bin -name "libsqlite3*.dll" | head -1)
|
||
if [ -n "$SQLITE" ]; then
|
||
cp "$SQLITE" "$BIN/"
|
||
echo "SQLite3 copied: $(basename $SQLITE)"
|
||
else
|
||
echo "WARNING: libsqlite3 not found in /ucrt64/bin/"
|
||
fi
|
||
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/QET64.nsi" "$NSIS_ROOT/"
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/lang_extra.nsh" "$NSIS_ROOT/"
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/lang_extra_fr.nsh" "$NSIS_ROOT/"
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/lang_extra_missing.nsh" "$NSIS_ROOT/"
|
||
cp -r "$GITHUB_WORKSPACE/build-aux/windows/nsis_base/." "$NSIS_ROOT/"
|
||
|
||
curl -fsSL \
|
||
"https://raw.githubusercontent.com/qelectrotech/qelectrotech-source-mirror/refs/heads/master/misc/Lancer%20QET.bat" \
|
||
-o "$FILES/Lancer QET.bat"
|
||
cp -r "$GITHUB_WORKSPACE/elements" "$FILES/elements" || true
|
||
cp -r "$GITHUB_WORKSPACE/titleblocks" "$FILES/titleblocks" || true
|
||
cp -r "$GITHUB_WORKSPACE/examples" "$FILES/examples" || true
|
||
cp -r "$GITHUB_WORKSPACE/fonts" "$FILES/fonts" || true
|
||
|
||
cp -r "$GITHUB_WORKSPACE/lang" "$FILES/lang" || true
|
||
find "$GITHUB_WORKSPACE/build" -name "*.qm" -exec cp {} "$FILES/lang/" \; 2>/dev/null || true
|
||
echo "=== .qm files in files/lang/ ==="
|
||
ls "$FILES/lang/"*.qm 2>/dev/null | wc -l || echo "0 .qm files"
|
||
|
||
for f in LICENSE ChangeLog CREDIT README ELEMENTS.LICENSE; do
|
||
cp "$GITHUB_WORKSPACE/$f" "$FILES/$f" 2>/dev/null || true
|
||
done
|
||
|
||
echo "=== Verification of key files in files/ ==="
|
||
for f in LICENSE ChangeLog CREDIT README ELEMENTS.LICENSE \
|
||
qet_uninstall_file_associations.reg register_filetypes.bat "Lancer QET.bat"; do
|
||
[ -f "$FILES/$f" ] \
|
||
&& echo " OK : $f" \
|
||
|| echo " MISSING: $f"
|
||
done
|
||
for d in ico elements lang titleblocks fonts examples bin; do
|
||
[ -d "$FILES/$d" ] \
|
||
&& echo " OK : $d/" \
|
||
|| echo " MISSING: $d/"
|
||
done
|
||
|
||
- name: Extract version for installer name
|
||
shell: msys2 {0}
|
||
id: qet_version
|
||
run: |
|
||
set -euo pipefail
|
||
|
||
GITCOMMIT=$(git -C "$GITHUB_WORKSPACE" rev-parse --short HEAD)
|
||
|
||
A=$(git -C "$GITHUB_WORKSPACE" rev-list HEAD --count)
|
||
HEAD=$(( A + 473 ))
|
||
|
||
VERSION=$(grep 'return QVersionNumber{' "$GITHUB_WORKSPACE/sources/qetversion.cpp" \
|
||
| head -1 \
|
||
| awk -F '{' '{ print $2 }' \
|
||
| awk -F '}' '{ print $1 }' \
|
||
| sed -e 's/,/./g' -e 's/ //g')
|
||
[ -z "$VERSION" ] && VERSION="dev"
|
||
|
||
FULL_VERSION="${VERSION}-r${HEAD}-${GITCOMMIT}_x86_64-win64"
|
||
echo "version=$FULL_VERSION" >> "$GITHUB_OUTPUT"
|
||
echo "base_version=$VERSION" >> "$GITHUB_OUTPUT"
|
||
echo "gitcommit=$GITCOMMIT" >> "$GITHUB_OUTPUT"
|
||
echo "head=$HEAD" >> "$GITHUB_OUTPUT"
|
||
echo "VERSION : $VERSION"
|
||
echo "GITCOMMIT : $GITCOMMIT"
|
||
echo "HEAD (rev) : $HEAD"
|
||
echo "FULL : $FULL_VERSION"
|
||
|
||
- name: Patch QET64.nsi — version + exe name + absolute paths
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
VERSION="${{ steps.qet_version.outputs.version }}"
|
||
NSI="$GITHUB_WORKSPACE/nsis_root/QET64.nsi"
|
||
FILES_WIN=$(cygpath -w "$GITHUB_WORKSPACE/nsis_root/files")
|
||
SCRIPT="$GITHUB_WORKSPACE/build-aux/windows/patch_nsi.py"
|
||
|
||
python3 "$SCRIPT" "$NSI" "$VERSION" "$FILES_WIN"
|
||
|
||
echo "=== Verification ==="
|
||
grep 'SOFT_VERSION' "$NSI" | head -1
|
||
grep -m2 'nsis_root' "$NSI" | head -2
|
||
echo "=== Contents of nsis_root/files/ ==="
|
||
ls "$GITHUB_WORKSPACE/nsis_root/files/"
|
||
|
||
- name: Build NSIS installer
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
NSIS_ROOT="$GITHUB_WORKSPACE/nsis_root"
|
||
cd "$NSIS_ROOT"
|
||
echo "=== CWD : $(pwd) ==="
|
||
MSYS2_ARG_CONV_EXCL="*" makensis /V4 QET64.nsi
|
||
RC=$?
|
||
echo "=== Contents of nsis_root after makensis ==="
|
||
ls "$NSIS_ROOT/"
|
||
[ $RC -eq 0 ] || { echo "ERROR: makensis failed (exit $RC)"; exit 1; }
|
||
|
||
- name: Move installer to dist/
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
mkdir -p "$GITHUB_WORKSPACE/dist"
|
||
INSTALLER=$(find "$GITHUB_WORKSPACE/nsis_root" -maxdepth 1 -iname "installer_*.exe" | head -1)
|
||
if [ -z "$INSTALLER" ]; then
|
||
echo "ERROR: no installer .exe found in nsis_root/"
|
||
ls "$GITHUB_WORKSPACE/nsis_root/"
|
||
exit 1
|
||
fi
|
||
echo "Moving: $INSTALLER -> dist/"
|
||
mv "$INSTALLER" "$GITHUB_WORKSPACE/dist/"
|
||
|
||
- name: Upload build logs on failure
|
||
if: failure()
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: build-logs
|
||
path: |
|
||
build/CMakeFiles/*.log
|
||
nsis_root/files/bin/
|
||
if-no-files-found: warn
|
||
|
||
- name: Zip portable (readytouse)
|
||
id: zip_portable
|
||
shell: pwsh
|
||
run: |
|
||
$version = "${{ steps.qet_version.outputs.base_version }}"
|
||
$head = "${{ steps.qet_version.outputs.head }}"
|
||
$zipName = "qelectrotech-${version}+git${head}-x86-win64-readytouse.zip"
|
||
$src = "$env:GITHUB_WORKSPACE\nsis_root\files"
|
||
$dst = "$env:GITHUB_WORKSPACE\dist\$zipName"
|
||
$7z = "C:\Program Files\7-Zip\7z.exe"
|
||
|
||
New-Item -ItemType Directory -Force -Path "$env:GITHUB_WORKSPACE\dist" | Out-Null
|
||
& $7z a -tzip -mx=5 -mmt=on $dst "$src\*"
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
$sizeMB = [math]::Round((Get-Item $dst).Length / 1MB, 1)
|
||
Write-Output "ZIP created: $zipName ($sizeMB MB)"
|
||
"zip_name=$zipName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||
|
||
- name: Upload portable (files/ without installer)
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: qelectrotech-${{ steps.qet_version.outputs.base_version }}+git${{ steps.qet_version.outputs.head }}-x86-win64-readytouse
|
||
path: dist/${{ steps.zip_portable.outputs.zip_name }}
|
||
retention-days: 40
|
||
|
||
- name: Upload NSIS installer
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: qelectrotech-windows-installer
|
||
path: dist/Installer_*.exe
|
||
retention-days: 40
|
||
|
||
- name: Upload portable (nom fixe pour le workflow MSI)
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: qelectrotech-windows-portable
|
||
path: nsis_root/files/
|
||
retention-days: 40
|
||
|
||
# =============================================================================
|
||
# Job 2: Qt6 build (EXPERIMENTAL track)
|
||
#
|
||
# Version label: the C++ source (sources/qetversion.cpp) intentionally stays
|
||
# Qt-agnostic — QT_VERSION-based detection inside the binary proved unreliable
|
||
# (see commit e1aa65f, reverting 608ca984). Here the CI job itself knows with
|
||
# certainty which Qt major version it configured (-DQT_VERSION_MAJOR=6), so it
|
||
# is safe to label the *package* "0.200.1" at this level, without touching
|
||
# QetVersion::currentVersion() or making the binary self-detect its Qt build.
|
||
# =============================================================================
|
||
build-windows-qt6:
|
||
runs-on: windows-latest
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v7
|
||
with:
|
||
submodules: recursive
|
||
fetch-depth: 0
|
||
|
||
- name: Install MSYS2
|
||
uses: msys2/setup-msys2@v2
|
||
with:
|
||
msystem: UCRT64
|
||
update: true
|
||
cache: true
|
||
install: >-
|
||
git
|
||
mingw-w64-ucrt-x86_64-ccache
|
||
mingw-w64-ucrt-x86_64-gcc
|
||
mingw-w64-ucrt-x86_64-cmake
|
||
mingw-w64-ucrt-x86_64-ninja
|
||
mingw-w64-ucrt-x86_64-qt6-base
|
||
mingw-w64-ucrt-x86_64-qt6-svg
|
||
mingw-w64-ucrt-x86_64-qt6-tools
|
||
mingw-w64-ucrt-x86_64-qt6-translations
|
||
mingw-w64-ucrt-x86_64-qt6-pdf
|
||
mingw-w64-ucrt-x86_64-sqlite3
|
||
mingw-w64-ucrt-x86_64-pkg-config
|
||
mingw-w64-ucrt-x86_64-nsis
|
||
mingw-w64-ucrt-x86_64-angleproject
|
||
|
||
- name: Cache ccache
|
||
uses: actions/cache@v5
|
||
with:
|
||
path: C:\Users\runneradmin\AppData\Local\ccache
|
||
key: ccache-windows-qt6-${{ github.ref_name }}-${{ github.sha }}
|
||
restore-keys: |
|
||
ccache-windows-qt6-${{ github.ref_name }}-
|
||
ccache-windows-qt6-
|
||
|
||
- name: Configure ccache
|
||
shell: msys2 {0}
|
||
run: |
|
||
/ucrt64/bin/ccache --set-config=max_size=500M
|
||
/ucrt64/bin/ccache --set-config=compression=true
|
||
/ucrt64/bin/ccache -z
|
||
echo "=== ccache config ==="
|
||
/ucrt64/bin/ccache -p
|
||
|
||
- name: Patch NSIS Welcome page — fix title font size
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
WELCOME_NSH=$(find /ucrt64 -path "*/Modern UI 2/Pages/Welcome.nsh" | head -1)
|
||
if [ -z "$WELCOME_NSH" ]; then
|
||
echo "WARNING: Welcome.nsh not found, skipping font patch"
|
||
else
|
||
echo "Patching: $WELCOME_NSH"
|
||
sed -i '/WelcomePage\.Title\.Font/s/"[0-9]\+" "700"/"10" "700"/' "$WELCOME_NSH"
|
||
grep 'WelcomePage.Title.Font' "$WELCOME_NSH"
|
||
echo " OK font size patched to 10"
|
||
fi
|
||
|
||
FINISH_NSH=$(find /ucrt64 -path "*/Modern UI 2/Pages/Finish.nsh" | head -1)
|
||
if [ -z "$FINISH_NSH" ]; then
|
||
echo "WARNING: Finish.nsh not found, skipping font patch"
|
||
else
|
||
echo "Patching: $FINISH_NSH"
|
||
sed -i '/FinishPage\.Title\.Font/s/"[0-9]\+" "700"/"10" "700"/' "$FINISH_NSH"
|
||
grep 'FinishPage.Title.Font' "$FINISH_NSH"
|
||
echo " OK font size patched to 10"
|
||
fi
|
||
|
||
- name: Build with cmake
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
cd "$GITHUB_WORKSPACE"
|
||
mkdir build && cd build
|
||
NPROC=$(nproc)
|
||
echo "Available CPUs: $NPROC"
|
||
|
||
cmake -G Ninja \
|
||
-DCMAKE_BUILD_TYPE=Release \
|
||
-DCMAKE_PREFIX_PATH=/ucrt64 \
|
||
-DQt6_DIR=/ucrt64/lib/cmake/Qt6 \
|
||
-DQT_VERSION_MAJOR=6 \
|
||
-DBUILD_WITH_KF5=OFF \
|
||
-DPACKAGE_TESTS=OFF \
|
||
-DCMAKE_POLICY_DEFAULT_CMP0077=NEW \
|
||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||
-DCMAKE_CXX_FLAGS="-DQET_EXPORT_PROJECT_DB" \
|
||
-DCMAKE_C_COMPILER_LAUNCHER=/ucrt64/bin/ccache \
|
||
-DCMAKE_CXX_COMPILER_LAUNCHER=/ucrt64/bin/ccache \
|
||
-DSQLite3_INCLUDE_DIR=/ucrt64/include \
|
||
-DSQLite3_LIBRARY=/ucrt64/lib/libsqlite3.dll.a \
|
||
..
|
||
ninja -j"$NPROC"
|
||
|
||
- name: Show ccache stats
|
||
shell: msys2 {0}
|
||
run: |
|
||
echo "=== ccache statistics ==="
|
||
/ucrt64/bin/ccache -s
|
||
|
||
- name: Verify exe was built
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
EXE=$(find "$GITHUB_WORKSPACE/build" -maxdepth 3 -iname "qelectrotech.exe" | head -1)
|
||
if [ -z "$EXE" ]; then
|
||
echo "ERROR: no qelectrotech.exe found in build/"
|
||
find "$GITHUB_WORKSPACE/build" -maxdepth 3 -name "*.exe" || true
|
||
exit 1
|
||
fi
|
||
SIZE=$(stat -c%s "$EXE")
|
||
echo "Exe found: $EXE ($SIZE bytes)"
|
||
[ "$SIZE" -gt 100000 ] || { echo "ERROR: exe too small"; exit 1; }
|
||
|
||
- name: Deploy — copy exe + windeployqt + DLLs
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
NSIS_ROOT="$GITHUB_WORKSPACE/nsis_root"
|
||
FILES="$NSIS_ROOT/files"
|
||
BIN="$FILES/bin"
|
||
mkdir -p "$BIN"
|
||
|
||
EXE=$(find "$GITHUB_WORKSPACE/build" -maxdepth 3 -iname "qelectrotech.exe" | head -1)
|
||
echo "Copying exe: $EXE -> $BIN/QElectroTech.exe"
|
||
cp "$EXE" "$BIN/QElectroTech.exe"
|
||
|
||
cd "$BIN"
|
||
/ucrt64/bin/windeployqt6 \
|
||
--release \
|
||
--no-translations \
|
||
--no-compiler-runtime \
|
||
./QElectroTech.exe || true
|
||
|
||
echo "=== 3-pass transitive DLL scan ==="
|
||
set +e
|
||
for PASS in 1 2 3; do
|
||
echo "-- Pass $PASS --"
|
||
for bin_file in "$BIN"/*.dll "$BIN"/*.exe "$BIN"/sqldrivers/*.dll "$BIN"/platforms/*.dll "$BIN"/imageformats/*.dll; do
|
||
[ -f "$bin_file" ] || continue
|
||
while IFS= read -r line; do
|
||
dll_path=$(echo "$line" | awk '{print $3}')
|
||
[ -f "$dll_path" ] || continue
|
||
dll_name=$(basename "$dll_path")
|
||
dst="$BIN/$dll_name"
|
||
if [ ! -f "$dst" ]; then
|
||
cp "$dll_path" "$dst"
|
||
echo " Copied (pass $PASS): $dll_name"
|
||
fi
|
||
done < <(ldd "$bin_file" 2>/dev/null | grep -i '/ucrt64/bin/')
|
||
done
|
||
done
|
||
set -e
|
||
|
||
DLL_COUNT=$(find "$BIN" -name "*.dll" | wc -l)
|
||
echo "=== $DLL_COUNT DLLs present after scan ==="
|
||
ls -lh "$BIN/QElectroTech.exe" || { echo "ERROR: exe missing from bin/"; exit 1; }
|
||
[ "$DLL_COUNT" -gt 5 ] || { echo "ERROR: too few DLLs"; exit 1; }
|
||
cd "$GITHUB_WORKSPACE"
|
||
|
||
cp /ucrt64/bin/libgcc_s_seh-1.dll "$BIN/"
|
||
cp /ucrt64/bin/libstdc++-6.dll "$BIN/"
|
||
cp /ucrt64/bin/libwinpthread-1.dll "$BIN/"
|
||
SQLITE=$(find /ucrt64/bin -name "libsqlite3*.dll" | head -1)
|
||
if [ -n "$SQLITE" ]; then
|
||
cp "$SQLITE" "$BIN/"
|
||
echo "SQLite3 copied: $(basename $SQLITE)"
|
||
else
|
||
echo "WARNING: libsqlite3 not found in /ucrt64/bin/"
|
||
fi
|
||
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/QET64.nsi" "$NSIS_ROOT/"
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/lang_extra.nsh" "$NSIS_ROOT/"
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/lang_extra_fr.nsh" "$NSIS_ROOT/"
|
||
cp "$GITHUB_WORKSPACE/build-aux/windows/lang_extra_missing.nsh" "$NSIS_ROOT/"
|
||
cp -r "$GITHUB_WORKSPACE/build-aux/windows/nsis_base/." "$NSIS_ROOT/"
|
||
|
||
curl -fsSL \
|
||
"https://raw.githubusercontent.com/qelectrotech/qelectrotech-source-mirror/refs/heads/master/misc/Lancer%20QET_qt6.bat" \
|
||
-o "$FILES/Lancer QET_qt6.bat"
|
||
cp -r "$GITHUB_WORKSPACE/elements" "$FILES/elements" || true
|
||
cp -r "$GITHUB_WORKSPACE/titleblocks" "$FILES/titleblocks" || true
|
||
cp -r "$GITHUB_WORKSPACE/examples" "$FILES/examples" || true
|
||
cp -r "$GITHUB_WORKSPACE/fonts" "$FILES/fonts" || true
|
||
|
||
cp -r "$GITHUB_WORKSPACE/lang" "$FILES/lang" || true
|
||
find "$GITHUB_WORKSPACE/build" -name "*.qm" -exec cp {} "$FILES/lang/" \; 2>/dev/null || true
|
||
echo "=== .qm files in files/lang/ ==="
|
||
ls "$FILES/lang/"*.qm 2>/dev/null | wc -l || echo "0 .qm files"
|
||
|
||
for f in LICENSE ChangeLog CREDIT README ELEMENTS.LICENSE; do
|
||
cp "$GITHUB_WORKSPACE/$f" "$FILES/$f" 2>/dev/null || true
|
||
done
|
||
|
||
echo "=== Verification of key files in files/ ==="
|
||
for f in LICENSE ChangeLog CREDIT README ELEMENTS.LICENSE \
|
||
qet_uninstall_file_associations.reg register_filetypes.bat "Lancer QET_qt6.bat"; do
|
||
[ -f "$FILES/$f" ] \
|
||
&& echo " OK : $f" \
|
||
|| echo " MISSING: $f"
|
||
done
|
||
for d in ico elements lang titleblocks fonts examples bin; do
|
||
[ -d "$FILES/$d" ] \
|
||
&& echo " OK : $d/" \
|
||
|| echo " MISSING: $d/"
|
||
done
|
||
|
||
- name: Extract version for installer name (Qt6 — labelled 0.200.1)
|
||
shell: msys2 {0}
|
||
id: qet_version
|
||
run: |
|
||
set -euo pipefail
|
||
|
||
GITCOMMIT=$(git -C "$GITHUB_WORKSPACE" rev-parse --short HEAD)
|
||
|
||
A=$(git -C "$GITHUB_WORKSPACE" rev-list HEAD --count)
|
||
HEAD=$(( A + 473 ))
|
||
|
||
# Deliberately NOT parsed from sources/qetversion.cpp: the CI job
|
||
# already knows for certain it configured Qt6 (-DQT_VERSION_MAJOR=6),
|
||
# so the "0.200.1" experimental-track label is set here explicitly
|
||
# rather than relying on in-binary Qt version detection.
|
||
VERSION="0.200.1"
|
||
|
||
FULL_VERSION="${VERSION}-qt6-r${HEAD}-${GITCOMMIT}_x86_64-win64"
|
||
BASE_VERSION="${VERSION}-qt6"
|
||
echo "version=$FULL_VERSION" >> "$GITHUB_OUTPUT"
|
||
echo "base_version=$BASE_VERSION" >> "$GITHUB_OUTPUT"
|
||
echo "gitcommit=$GITCOMMIT" >> "$GITHUB_OUTPUT"
|
||
echo "head=$HEAD" >> "$GITHUB_OUTPUT"
|
||
echo "VERSION : $VERSION"
|
||
echo "GITCOMMIT : $GITCOMMIT"
|
||
echo "HEAD (rev) : $HEAD"
|
||
echo "FULL : $FULL_VERSION"
|
||
|
||
- name: Patch QET64.nsi — version + exe name + absolute paths
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
VERSION="${{ steps.qet_version.outputs.version }}"
|
||
NSI="$GITHUB_WORKSPACE/nsis_root/QET64.nsi"
|
||
FILES_WIN=$(cygpath -w "$GITHUB_WORKSPACE/nsis_root/files")
|
||
SCRIPT="$GITHUB_WORKSPACE/build-aux/windows/patch_nsi.py"
|
||
|
||
python3 "$SCRIPT" "$NSI" "$VERSION" "$FILES_WIN"
|
||
|
||
echo "=== Verification ==="
|
||
grep 'SOFT_VERSION' "$NSI" | head -1
|
||
grep -m2 'nsis_root' "$NSI" | head -2
|
||
echo "=== Contents of nsis_root/files/ ==="
|
||
ls "$GITHUB_WORKSPACE/nsis_root/files/"
|
||
|
||
- name: Build NSIS installer
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
NSIS_ROOT="$GITHUB_WORKSPACE/nsis_root"
|
||
cd "$NSIS_ROOT"
|
||
echo "=== CWD : $(pwd) ==="
|
||
MSYS2_ARG_CONV_EXCL="*" makensis /V4 QET64.nsi
|
||
RC=$?
|
||
echo "=== Contents of nsis_root after makensis ==="
|
||
ls "$NSIS_ROOT/"
|
||
[ $RC -eq 0 ] || { echo "ERROR: makensis failed (exit $RC)"; exit 1; }
|
||
|
||
- name: Move installer to dist/
|
||
shell: msys2 {0}
|
||
run: |
|
||
set -euo pipefail
|
||
mkdir -p "$GITHUB_WORKSPACE/dist"
|
||
INSTALLER=$(find "$GITHUB_WORKSPACE/nsis_root" -maxdepth 1 -iname "installer_*.exe" | head -1)
|
||
if [ -z "$INSTALLER" ]; then
|
||
echo "ERROR: no installer .exe found in nsis_root/"
|
||
ls "$GITHUB_WORKSPACE/nsis_root/"
|
||
exit 1
|
||
fi
|
||
echo "Moving: $INSTALLER -> dist/"
|
||
mv "$INSTALLER" "$GITHUB_WORKSPACE/dist/"
|
||
|
||
- name: Upload build logs on failure
|
||
if: failure()
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: build-logs-qt6
|
||
path: |
|
||
build/CMakeFiles/*.log
|
||
nsis_root/files/bin/
|
||
if-no-files-found: warn
|
||
|
||
- name: Zip portable (readytouse)
|
||
id: zip_portable
|
||
shell: pwsh
|
||
run: |
|
||
$version = "${{ steps.qet_version.outputs.base_version }}"
|
||
$head = "${{ steps.qet_version.outputs.head }}"
|
||
$zipName = "qelectrotech-${version}+git${head}-x86-win64-readytouse.zip"
|
||
$src = "$env:GITHUB_WORKSPACE\nsis_root\files"
|
||
$dst = "$env:GITHUB_WORKSPACE\dist\$zipName"
|
||
$7z = "C:\Program Files\7-Zip\7z.exe"
|
||
|
||
New-Item -ItemType Directory -Force -Path "$env:GITHUB_WORKSPACE\dist" | Out-Null
|
||
& $7z a -tzip -mx=5 -mmt=on $dst "$src\*"
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
$sizeMB = [math]::Round((Get-Item $dst).Length / 1MB, 1)
|
||
Write-Output "ZIP created: $zipName ($sizeMB MB)"
|
||
"zip_name=$zipName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||
|
||
- name: Upload portable (files/ without installer)
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: qelectrotech-${{ steps.qet_version.outputs.base_version }}+git${{ steps.qet_version.outputs.head }}-x86-win64-readytouse
|
||
path: dist/${{ steps.zip_portable.outputs.zip_name }}
|
||
retention-days: 40
|
||
|
||
- name: Upload NSIS installer
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: qelectrotech-windows-installer-qt6
|
||
path: dist/Installer_*.exe
|
||
retention-days: 40
|
||
|
||
- name: Upload portable (nom fixe pour le workflow MSI)
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: qelectrotech-windows-portable-qt6
|
||
path: nsis_root/files/
|
||
retention-days: 40
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Job 3 : Publie les assets nightly (exe + zip, Qt5 et Qt6) sur la release
|
||
# Ne tourne que sur push master (pas sur les PRs)
|
||
# ---------------------------------------------------------------------------
|
||
publish-nightly-assets:
|
||
needs: [build-windows, build-windows-qt6]
|
||
runs-on: ubuntu-latest
|
||
if: github.event_name != 'pull_request'
|
||
permissions:
|
||
contents: write
|
||
|
||
steps:
|
||
- name: Download installer artifacts (Qt5 + Qt6)
|
||
uses: actions/download-artifact@v8
|
||
with:
|
||
pattern: qelectrotech-windows-installer*
|
||
path: downloaded/installer/
|
||
merge-multiple: true
|
||
|
||
- name: Download portable artifacts (Qt5 + Qt6)
|
||
uses: actions/download-artifact@v8
|
||
with:
|
||
pattern: qelectrotech-*-readytouse
|
||
path: downloaded/portable/
|
||
merge-multiple: true
|
||
|
||
- name: Delete old nightly assets (.exe and .zip)
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
REPO: ${{ github.repository }}
|
||
run: |
|
||
gh release view nightly --repo "$REPO" --json assets \
|
||
--jq '.assets[] | select(.name | test("\\.(exe|zip)$")) | .name' \
|
||
| while read -r name; do
|
||
echo "Deleting old asset: $name"
|
||
gh release delete-asset nightly "$name" --repo "$REPO" --yes
|
||
done
|
||
echo "Old .exe and .zip assets deleted."
|
||
|
||
- name: Update nightly release
|
||
uses: softprops/action-gh-release@v3
|
||
with:
|
||
tag_name: nightly
|
||
name: "Nightly Build – Windows"
|
||
body: |
|
||
🔧 **Automated nightly build** — may be unstable.
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Commit** | ${{ github.sha }} |
|
||
| **Run** | https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} |
|
||
| **Date** | ${{ github.event.head_commit.timestamp }} |
|
||
|
||
> ⚠️ This is a development version; it introduces new features you want, but may cause bugs that have not yet been identified yet.
|
||
> For stable releases, see the [Releases page](https://github.com/${{ github.repository }}/releases).
|
||
|
||
> 🧪 **Qt6 builds are experimental.** Files tagged `-qt6-` are built against Qt6 and are not yet
|
||
> as tested as the Qt5 track. Expect rough edges; report issues clearly labelled "Qt6".
|
||
prerelease: true
|
||
make_latest: false
|
||
files: |
|
||
downloaded/installer/*.exe
|
||
downloaded/portable/*.zip
|
||
token: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
# GitHub Pages is generated and deployed by windows-msi.yml
|
||
# after the MSI upload, so that all URLs (exe/zip/msi, Qt5+Qt6) are known.
|