From 5e3229d0f51b2afd461a2fe9f011929c3c8e262d Mon Sep 17 00:00:00 2001 From: Aurelien Gateau Date: Thu, 12 Feb 2026 12:55:42 +0100 Subject: [PATCH 1/4] feat: Add support for msi packages --- .github/workflows/build_release_assets.yml | 6 +++ .pre-commit-config.yaml | 1 + .../20260218_145052_aurelien.gateau_msi.md | 3 ++ doc/dev/os-packages.md | 11 ++++ scripts/build-os-packages/build-os-packages | 3 +- scripts/build-os-packages/ggshield.wxs | 52 +++++++++++++++++++ .../build-os-packages/windows-functions.bash | 46 ++++++++++++++++ 7 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 changelog.d/20260218_145052_aurelien.gateau_msi.md create mode 100644 scripts/build-os-packages/ggshield.wxs diff --git a/.github/workflows/build_release_assets.yml b/.github/workflows/build_release_assets.yml index f321a8207d..c960952ede 100644 --- a/.github/workflows/build_release_assets.yml +++ b/.github/workflows/build_release_assets.yml @@ -161,6 +161,11 @@ jobs: # Make it available cp rcodesign /usr/local/bin + - name: Install WiX Toolset + if: matrix.os == 'windows-2022' + shell: bash + run: dotnet tool install --global wix --version 4.0.4 + - name: Install dependencies shell: bash run: | @@ -274,6 +279,7 @@ jobs: packages/ggshield-*.rpm packages/ggshield_*.deb packages/ggshield.*.nupkg + packages/ggshield-*.msi # Run some basic tests, the goal is to verify the ggshield binary has all the # libraries it needs to run diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 36d4052cf2..bd38860600 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,6 +35,7 @@ repos: rev: v3.6.0 hooks: - id: prettier + exclude: \.wxs$ - repo: https://github.com/pycqa/isort rev: 5.13.2 diff --git a/changelog.d/20260218_145052_aurelien.gateau_msi.md b/changelog.d/20260218_145052_aurelien.gateau_msi.md new file mode 100644 index 0000000000..62643223c2 --- /dev/null +++ b/changelog.d/20260218_145052_aurelien.gateau_msi.md @@ -0,0 +1,3 @@ +### Added + +- ggshield is now available as a MSI package. diff --git a/doc/dev/os-packages.md b/doc/dev/os-packages.md index 26ec6b0adb..ffc78206c9 100644 --- a/doc/dev/os-packages.md +++ b/doc/dev/os-packages.md @@ -23,6 +23,7 @@ flowchart TD signing -->|no| create_archive sign --> create_archive --> pkg[/"pkg 🍏"/] create_archive --> zip[/"zip 🪟"/] + create_archive --> msi[/"msi 🪟"/] create_archive --> tar.gz[/"tar.gz 🐧"/] create_archive --> deb[/"deb 🐧"/] create_archive --> rpm[/"rpm 🐧"/] @@ -96,3 +97,13 @@ Note 2: `install-keylocker-tools` expects `$PATH` to already contain the install #### Building signed binaries Once all environment variables are set and DigiCert tools are installed, one can build signed Windows binaries using `build-os-packages --sign`. + +### MSI Package + +The build produces an MSI installer (`ggshield-VERSION-x86_64-pc-windows-msvc.msi`) using [WiX Toolset v4](https://wixtoolset.org/). The WiX source file is `scripts/build-os-packages/ggshield.wxs`. + +- **Install location**: `C:\Program Files\GitGuardian\ggshield\` +- **PATH**: The installer adds the install location to the system `PATH`. This is removed on uninstall. +- **Upgrades**: Installing a newer version automatically removes the previous one (via `MajorUpgrade`). +- **Silent install**: `msiexec /i ggshield-X.Y.Z-x86_64-pc-windows-msvc.msi /quiet` +- **Silent uninstall**: `msiexec /x ggshield-X.Y.Z-x86_64-pc-windows-msvc.msi /quiet` diff --git a/scripts/build-os-packages/build-os-packages b/scripts/build-os-packages/build-os-packages index 5508114ce1..6c326ea304 100755 --- a/scripts/build-os-packages/build-os-packages +++ b/scripts/build-os-packages/build-os-packages @@ -114,7 +114,7 @@ init_system_vars() { EXE_EXT=".exe" HUMAN_OS=Windows TARGET="$arch-pc-windows-msvc" - REQUIREMENTS="$REQUIREMENTS choco" + REQUIREMENTS="$REQUIREMENTS choco wix" ;; *) die "Unknown OS. uname printed '$out'" @@ -323,6 +323,7 @@ step_create_archive() { Windows) create_windows_packages test_chocolatey_package + test_msi_package ;; esac } diff --git a/scripts/build-os-packages/ggshield.wxs b/scripts/build-os-packages/ggshield.wxs new file mode 100644 index 0000000000..251c9d655a --- /dev/null +++ b/scripts/build-os-packages/ggshield.wxs @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/build-os-packages/windows-functions.bash b/scripts/build-os-packages/windows-functions.bash index 44b02286ab..63ebd1cafe 100644 --- a/scripts/build-os-packages/windows-functions.bash +++ b/scripts/build-os-packages/windows-functions.bash @@ -62,7 +62,53 @@ test_chocolatey_package() { popd } +windows_build_msi_package() { + # MSI only supports X.Y.Z version format, strip any suffix (e.g. +sha) + local msi_version="${VERSION%%[+]*}" + + local wxs_path + wxs_path=$(cygpath -w "$SCRIPT_DIR/ggshield.wxs") + + local source_dir + source_dir=$(cygpath -w "$PACKAGES_DIR/$ARCHIVE_DIR_NAME") + + local msi_path="$PACKAGES_DIR/$ARCHIVE_DIR_NAME.msi" + local msi_path_win + msi_path_win=$(cygpath -w "$msi_path") + + info "Building MSI package" + wix build "$wxs_path" \ + -arch x64 \ + -d Version="$msi_version" \ + -bindpath "SourceDir=$source_dir" \ + -o "$msi_path_win" + + if [ "$DO_SIGN" -eq 1 ] ; then + info "Signing MSI package" + smctl sign \ + --verbose \ + --exit-non-zero-on-fail \ + --fingerprint "$WINDOWS_CERT_FINGERPRINT" \ + --tool signtool \ + --input "$msi_path" + fi + + info "MSI package created in $msi_path" +} + +test_msi_package() { + local msi_path="$PACKAGES_DIR/$ARCHIVE_DIR_NAME.msi" + if [ ! -f "$msi_path" ] ; then + die "MSI package not found: $msi_path" + fi + if [ ! -s "$msi_path" ] ; then + die "MSI package is empty: $msi_path" + fi + info "MSI package OK: $msi_path" +} + create_windows_packages() { windows_create_archive windows_build_chocolatey_package + windows_build_msi_package } From 1077d3592aec8810ec304a885cae57cd7233760f Mon Sep 17 00:00:00 2001 From: Aurelien Gateau Date: Wed, 18 Feb 2026 16:45:06 +0100 Subject: [PATCH 2/4] fix(ci): upgrade WiX Toolset to v5 for Files element support WiX v4.0.4 does not support the element used in ggshield.wxs, causing the MSI build to fail with WIX0005. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/build_release_assets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_release_assets.yml b/.github/workflows/build_release_assets.yml index c960952ede..65c57d3300 100644 --- a/.github/workflows/build_release_assets.yml +++ b/.github/workflows/build_release_assets.yml @@ -164,7 +164,7 @@ jobs: - name: Install WiX Toolset if: matrix.os == 'windows-2022' shell: bash - run: dotnet tool install --global wix --version 4.0.4 + run: dotnet tool install --global wix --version 5.0.2 - name: Install dependencies shell: bash From b83fbaa21facb0696a7679b05309944835561f74 Mon Sep 17 00:00:00 2001 From: Aurelien Gateau Date: Wed, 18 Feb 2026 17:23:12 +0100 Subject: [PATCH 3/4] fix: move Files element out of Component in WiX source The element must be a direct child of , not . It auto-generates its own components. Co-Authored-By: Claude Opus 4.6 --- scripts/build-os-packages/ggshield.wxs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/scripts/build-os-packages/ggshield.wxs b/scripts/build-os-packages/ggshield.wxs index 251c9d655a..90a9a3d9df 100644 --- a/scripts/build-os-packages/ggshield.wxs +++ b/scripts/build-os-packages/ggshield.wxs @@ -21,12 +21,7 @@ - - - + - From 58ec934daeedd596fae9d1976cd71aea2c2728ef Mon Sep 17 00:00:00 2001 From: Aurelien Gateau Date: Wed, 18 Feb 2026 17:27:59 +0100 Subject: [PATCH 4/4] fix: use ComponentGroup for Files element in WiX source Files-generated components must belong to a Feature. Wrap the Files element in a ComponentGroup and reference it via ComponentGroupRef. Co-Authored-By: Claude Opus 4.6 --- scripts/build-os-packages/ggshield.wxs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/build-os-packages/ggshield.wxs b/scripts/build-os-packages/ggshield.wxs index 90a9a3d9df..042dab910d 100644 --- a/scripts/build-os-packages/ggshield.wxs +++ b/scripts/build-os-packages/ggshield.wxs @@ -21,8 +21,6 @@ - - + + + + +