From 59d78336682ad63813c9496320d2db36fde0ac5d Mon Sep 17 00:00:00 2001 From: jwinterm Date: Sun, 24 May 2026 19:00:10 -0400 Subject: [PATCH] Windows CI: revert SFX wrapper, ship as zip artifact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 7-Zip SFX wrapped HashBags.exe extracted to a fresh %TEMP%\7zS\ subdir on every launch. path_provider_windows derives the wallet storage dir from the .exe location — so each launch saw a brand new "app dir" with no prior wallets, failing with "keys corrupted" before hanging at the PIN prompt. The multi-file zip distribution doesn't have this problem because the .exe lives at a stable user-chosen path. Multi-file zip is also what Firefox Portable, VS Code Portable, OBS Portable, and ~every other Flutter Windows desktop app ship as. The fashion in Windows is "portable = no install / no registry," not "portable = one file." Single-file via Inno Setup installer or Enigma Virtual Box remains possible as a v1.1 follow-up. For v1, ship the zip. --- .github/workflows/build-windows.yml | 82 +++++++---------------------- 1 file changed, 18 insertions(+), 64 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index d43116d38..5b51548a7 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -319,76 +319,30 @@ jobs: run: | ls -la build/windows/x64/runner/Release/ - # ---- Build single-file portable HashBags.exe (7-Zip SFX) ------------- - # Goal: ship one .exe that users can double-click. The Flutter Windows - # build produces a directory tree (~500 files: hash_wallet.exe + - # plugin DLLs + data/ + locales/), but we want a single binary. - # 7-Zip's installer-mode SFX module (7zS.sfx) bundles the archive - # into a wrapper .exe that on launch extracts to %TEMP% and runs - # the configured RunProgram. Each launch re-extracts; subsequent - # launches are slower than a real install but the trade-off for - # "zero-touch portable" is acceptable for now. - - name: Create portable HashBags.exe (7-Zip SFX wrapper) + # ---- Package + upload as zip ----------------------------------------- + # The Flutter Windows build produces a directory tree (~500 files — + # HashWallet.exe + plugin DLLs + data/ + locales/ + bundled monero_c + # + MinGW runtime DLLs). Ship as a zip; users extract and run. + # + # Tried wrapping with 7-Zip SFX for a single-file "portable" .exe + # earlier but path_provider_windows computes the wallet storage dir + # from the .exe location, and SFX extracts to a different %TEMP% + # subdir on every launch — wallet keys couldn't be found across + # runs. Multi-file zip is what Firefox Portable / VS Code Portable + # / every other Flutter Windows desktop app does too. + - name: Create Hash Bags Windows release zip run: | set -x -e - SEVENZ_DIR="/c/Program Files/7-Zip" - - # The standalone Windows 7-Zip install ships 7z.sfx (GUI prompt) - # and 7zCon.sfx (console-mode extractor) but NOT the installer- - # mode SFX modules (7zSD.sfx, 7zS2.sfx) that do "extract to temp - # + auto-run RunProgram". Those used to live in "7-Zip Extra" - # but were moved into the LZMA SDK archive in 23.01 — under - # bin/. Fetch the SDK on demand. - EXTRA_DIR="$RUNNER_TEMP/7z-sfx" - if [[ ! -f "$EXTRA_DIR/7zSD.sfx" ]]; then - mkdir -p "$EXTRA_DIR" - curl -fsSL -o "$EXTRA_DIR/lzma-sdk.7z" "https://www.7-zip.org/a/lzma2301.7z" - # Extract only the SFX binaries we need — the SDK has ~700 - # files of mostly source code we don't want. - "$SEVENZ_DIR/7z.exe" x "$EXTRA_DIR/lzma-sdk.7z" -o"$EXTRA_DIR" -y 'bin/*.sfx' | tail -3 - rm "$EXTRA_DIR/lzma-sdk.7z" - # Flatten — copy out of bin/ for predictable paths - mv "$EXTRA_DIR/bin/"*.sfx "$EXTRA_DIR/" - fi - # 7zSD.sfx is the classic installer-mode SFX (config.txt with - # RunProgram). 7zS2.sfx is the newer variant (similar config - # syntax). Prefer 7zSD which is more widely documented. - for candidate in "$EXTRA_DIR/7zSD.sfx" "$EXTRA_DIR/7zS2.sfx"; do - if [[ -f "$candidate" ]]; then - SFX_MODULE="$candidate" - break - fi - done - if [[ -z "${SFX_MODULE:-}" ]]; then - echo "FATAL: no installer-mode SFX module after LZMA SDK extract" - ls "$EXTRA_DIR" - exit 1 - fi - echo "Using SFX module: $SFX_MODULE" - - # 1. Pack the Release dir into a single .7z cd build/windows/x64/runner/Release - "$SEVENZ_DIR/7z.exe" a -mx=9 -mmt=on "$GITHUB_WORKSPACE/HashBags-payload.7z" . | tail -20 + # PowerShell's Compress-Archive is in PATH; no extra deps needed. + powershell -NoProfile -Command "Compress-Archive -Path .\* -DestinationPath ..\..\..\..\..\HashBags-windows-${{ github.sha }}.zip -Force" cd "$GITHUB_WORKSPACE" + ls -la HashBags-windows-*.zip + echo "Size: $(du -h HashBags-windows-${{ github.sha }}.zip | cut -f1)" - # 2. SFX config — runtime behavior of the wrapper .exe. - # RunProgram is what fires after extraction. HashWallet is the - # BINARY_NAME baked into windows/CMakeLists.txt. - # Using printf instead of a heredoc because bash heredoc bodies - # have no indentation and break out of YAML's `run: |` block. - printf ';!@Install@!UTF-8!\nTitle="Hash Bags"\nBeginPrompt=""\nProgress="yes"\nRunProgram="HashWallet.exe"\n;!@InstallEnd@!\n' > sfx-config.txt - - # 3. Concatenate SFX module + config + payload → final .exe. - # Identical to the Windows "copy /b a + b + c" idiom; cat works - # fine for byte-exact concatenation in Git Bash. - OUT="HashBags-${{ github.sha }}.exe" - cat "$SFX_MODULE" sfx-config.txt HashBags-payload.7z > "$OUT" - ls -la "$OUT" - echo "Size: $(du -h "$OUT" | cut -f1)" - - - name: Upload portable HashBags.exe + - name: Upload Hash Bags Windows zip uses: actions/upload-artifact@v3 with: name: hash-bags-windows-${{ github.sha }} - path: HashBags-${{ github.sha }}.exe + path: HashBags-windows-${{ github.sha }}.zip retention-days: 14