1313 contents : write
1414 id-token : write
1515 attestations : write
16+ outputs :
17+ version : ${{ steps.version.outputs.version }}
18+ release_tag : ${{ steps.release.outputs.tag }}
1619
1720 steps :
1821 - name : Harden the runner (Audit all outbound calls)
8588 - name : Install cosign
8689 uses : sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
8790
88- - name : Build MSIs (x64 + arm64)
89- # WiX 4 runs on .NET, so we install it on the same ubuntu-latest
90- # runner. Output: dist/stepsecurity-dev-machine-guard-<v>-x64.msi
91- # and the arm64 counterpart. Both wrap the goreleaser-produced
92- # .exe and embed it via CAB compression. No PowerShell anywhere.
93- run : |
94- dotnet tool install --global wix --version 4.0.5
95- export PATH="$PATH:$HOME/.dotnet/tools"
96- wix --version
97-
98- version="${{ steps.version.outputs.version }}"
99-
100- win_amd64_exe=$(find dist -type f -name '*.exe' -path '*windows_amd64*' | head -1)
101- win_arm64_exe=$(find dist -type f -name '*.exe' -path '*windows_arm64*' | head -1)
102- if [ ! -f "$win_amd64_exe" ] || [ ! -f "$win_arm64_exe" ]; then
103- echo "::error::Windows .exe artifacts not found under dist/"
104- find dist -type f -name '*.exe'
105- exit 1
106- fi
107-
108- wix build packaging/windows/Product.wxs \
109- -arch x64 \
110- -d Arch=x64 \
111- -d Version="$version" \
112- -d BinaryPath="$PWD/$win_amd64_exe" \
113- -out "dist/stepsecurity-dev-machine-guard-${version}-x64.msi"
114-
115- wix build packaging/windows/Product.wxs \
116- -arch arm64 \
117- -d Arch=arm64 \
118- -d Version="$version" \
119- -d BinaryPath="$PWD/$win_arm64_exe" \
120- -out "dist/stepsecurity-dev-machine-guard-${version}-arm64.msi"
121-
12291 - name : Locate binaries and packages
12392 id : binaries
12493 run : |
@@ -133,10 +102,7 @@ jobs:
133102 RPM_AMD64=$(find dist -type f -name '*-amd64.rpm' | head -1)
134103 RPM_ARM64=$(find dist -type f -name '*-arm64.rpm' | head -1)
135104
136- MSI_X64=$(find dist -type f -name '*-x64.msi' | head -1)
137- MSI_ARM64=$(find dist -type f -name '*-arm64.msi' | head -1)
138-
139- for label in "darwin:${DARWIN}" "windows_amd64:${WIN_AMD64}" "windows_arm64:${WIN_ARM64}" "linux_amd64:${LINUX_AMD64}" "linux_arm64:${LINUX_ARM64}" "deb_amd64:${DEB_AMD64}" "deb_arm64:${DEB_ARM64}" "rpm_amd64:${RPM_AMD64}" "rpm_arm64:${RPM_ARM64}" "msi_x64:${MSI_X64}" "msi_arm64:${MSI_ARM64}"; do
105+ for label in "darwin:${DARWIN}" "windows_amd64:${WIN_AMD64}" "windows_arm64:${WIN_ARM64}" "linux_amd64:${LINUX_AMD64}" "linux_arm64:${LINUX_ARM64}" "deb_amd64:${DEB_AMD64}" "deb_arm64:${DEB_ARM64}" "rpm_amd64:${RPM_AMD64}" "rpm_arm64:${RPM_ARM64}"; do
140106 name="${label%%:*}"
141107 path="${label#*:}"
142108 if [ -z "$path" ] || [ ! -f "$path" ]; then
@@ -155,8 +121,6 @@ jobs:
155121 echo "deb_arm64=$DEB_ARM64" >> "$GITHUB_OUTPUT"
156122 echo "rpm_amd64=$RPM_AMD64" >> "$GITHUB_OUTPUT"
157123 echo "rpm_arm64=$RPM_ARM64" >> "$GITHUB_OUTPUT"
158- echo "msi_x64=$MSI_X64" >> "$GITHUB_OUTPUT"
159- echo "msi_arm64=$MSI_ARM64" >> "$GITHUB_OUTPUT"
160124
161125 - name : Sign artifacts with Sigstore
162126 shell : bash
@@ -195,19 +159,6 @@ jobs:
195159 "${{ steps.binaries.outputs.rpm_amd64 }}.bundle"
196160 sign_with_retry "${{ steps.binaries.outputs.rpm_arm64 }}" \
197161 "${{ steps.binaries.outputs.rpm_arm64 }}.bundle"
198- sign_with_retry "${{ steps.binaries.outputs.msi_x64 }}" \
199- "${{ steps.binaries.outputs.msi_x64 }}.bundle"
200- sign_with_retry "${{ steps.binaries.outputs.msi_arm64 }}" \
201- "${{ steps.binaries.outputs.msi_arm64 }}.bundle"
202-
203- - name : Upload MSIs to draft release
204- env :
205- GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
206- run : |
207- gh release upload "${{ steps.release.outputs.tag }}" \
208- "${{ steps.binaries.outputs.msi_x64 }}" \
209- "${{ steps.binaries.outputs.msi_arm64 }}" \
210- --clobber
211162
212163 - name : Upload cosign bundles
213164 env :
@@ -223,8 +174,6 @@ jobs:
223174 "${{ steps.binaries.outputs.deb_arm64 }}.bundle" \
224175 "${{ steps.binaries.outputs.rpm_amd64 }}.bundle" \
225176 "${{ steps.binaries.outputs.rpm_arm64 }}.bundle" \
226- "${{ steps.binaries.outputs.msi_x64 }}.bundle" \
227- "${{ steps.binaries.outputs.msi_arm64 }}.bundle" \
228177 --clobber
229178
230179 - name : Attest build provenance
@@ -240,5 +189,119 @@ jobs:
240189 ${{ steps.binaries.outputs.deb_arm64 }}
241190 ${{ steps.binaries.outputs.rpm_amd64 }}
242191 ${{ steps.binaries.outputs.rpm_arm64 }}
243- ${{ steps.binaries.outputs.msi_x64 }}
244- ${{ steps.binaries.outputs.msi_arm64 }}
192+
193+ build-msi :
194+ name : Build & Sign MSIs
195+ needs : release
196+ runs-on : windows-latest
197+ permissions :
198+ contents : write
199+ id-token : write
200+ attestations : write
201+
202+ steps :
203+ - name : Harden the runner (Audit all outbound calls)
204+ uses : step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
205+ with :
206+ egress-policy : audit
207+
208+ - name : Checkout repository
209+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
210+
211+ - name : Install WiX 4
212+ # WiX 4 ships as a .NET global tool. windows-latest has the .NET SDK
213+ # preinstalled, so this resolves quickly. We pin to a known-working
214+ # version. Linux/macOS hosts have WiX 4 issues with Directory/@Name
215+ # path validation — we always build the MSI on Windows.
216+ shell : pwsh
217+ run : |
218+ dotnet tool install --global wix --version 4.0.5
219+ wix --version
220+
221+ - name : Download Windows .exe assets from draft release
222+ env :
223+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
224+ shell : pwsh
225+ run : |
226+ $tag = "${{ needs.release.outputs.release_tag }}"
227+ New-Item -ItemType Directory -Path dist -Force | Out-Null
228+ # Goreleaser produces archive names like:
229+ # stepsecurity-dev-machine-guard-<version>-windows_amd64.exe
230+ # We download them by exact pattern to dist/.
231+ gh release download "$tag" `
232+ -R "${{ github.repository }}" `
233+ -p "*-windows_amd64.exe" `
234+ -p "*-windows_arm64.exe" `
235+ -D dist
236+ Get-ChildItem dist | Format-Table Name, Length
237+
238+ - name : Build MSIs (x64 + arm64)
239+ shell : pwsh
240+ run : |
241+ $version = "${{ needs.release.outputs.version }}"
242+ $amd64 = Get-ChildItem dist -Filter "*-windows_amd64.exe" | Select-Object -First 1
243+ $arm64 = Get-ChildItem dist -Filter "*-windows_arm64.exe" | Select-Object -First 1
244+ if (-not $amd64 -or -not $arm64) {
245+ Write-Error "Windows .exe assets missing under dist/"
246+ exit 1
247+ }
248+
249+ wix build packaging/windows/Product.wxs `
250+ -arch x64 `
251+ -d Arch=x64 `
252+ -d "Version=$version" `
253+ -d "BinaryPath=$($amd64.FullName)" `
254+ -out "dist/stepsecurity-dev-machine-guard-$version-x64.msi"
255+
256+ wix build packaging/windows/Product.wxs `
257+ -arch arm64 `
258+ -d Arch=arm64 `
259+ -d "Version=$version" `
260+ -d "BinaryPath=$($arm64.FullName)" `
261+ -out "dist/stepsecurity-dev-machine-guard-$version-arm64.msi"
262+
263+ Get-ChildItem dist -Filter "*.msi" | Format-Table Name, Length
264+
265+ - name : Install cosign
266+ uses : sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
267+
268+ - name : Sign MSIs with Sigstore
269+ shell : bash
270+ run : |
271+ set -euo pipefail
272+ version="${{ needs.release.outputs.version }}"
273+ for arch in x64 arm64; do
274+ msi="dist/stepsecurity-dev-machine-guard-${version}-${arch}.msi"
275+ bundle="${msi}.bundle"
276+ for attempt in 1 2 3; do
277+ if cosign sign-blob "$msi" --bundle "$bundle" --yes; then
278+ echo "Signed $msi"
279+ break
280+ fi
281+ echo "::warning::Sign attempt $attempt failed for $msi, retrying in 10s..."
282+ sleep 10
283+ done
284+ test -f "$bundle" || { echo "::error::Failed to sign $msi"; exit 1; }
285+ done
286+
287+ - name : Upload MSIs and bundles to draft release
288+ env :
289+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
290+ shell : bash
291+ run : |
292+ set -euo pipefail
293+ tag="${{ needs.release.outputs.release_tag }}"
294+ version="${{ needs.release.outputs.version }}"
295+ gh release upload "$tag" \
296+ "dist/stepsecurity-dev-machine-guard-${version}-x64.msi" \
297+ "dist/stepsecurity-dev-machine-guard-${version}-arm64.msi" \
298+ "dist/stepsecurity-dev-machine-guard-${version}-x64.msi.bundle" \
299+ "dist/stepsecurity-dev-machine-guard-${version}-arm64.msi.bundle" \
300+ --clobber
301+
302+ - name : Attest MSI build provenance
303+ uses : actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
304+ with :
305+ subject-path : |
306+ dist/stepsecurity-dev-machine-guard-${{ needs.release.outputs.version }}-x64.msi
307+ dist/stepsecurity-dev-machine-guard-${{ needs.release.outputs.version }}-arm64.msi
0 commit comments