Skip to content

Commit 85f35b8

Browse files
authored
Merge pull request #104 from ashishkurmi/swarit/fix/windows
fix(windows): stop console window flashes during scheduled scans
2 parents 0e007ef + 94624db commit 85f35b8

19 files changed

Lines changed: 548 additions & 76 deletions

File tree

.github/workflows/msi-smoke.yml

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
wix --version
5656
wix extension add --global WixToolset.Util.wixext/4.0.5
5757
58-
- name: Build Windows .exe
58+
- name: Build Windows .exes (agent + launcher)
5959
shell: pwsh
6060
run: |
6161
$env:GOOS = "windows"
@@ -64,7 +64,11 @@ jobs:
6464
go build -trimpath -ldflags "-s -w" `
6565
-o "$PWD\dmg-smoke.exe" `
6666
./cmd/stepsecurity-dev-machine-guard
67-
Get-Item "$PWD\dmg-smoke.exe" | Select-Object Name, Length
67+
go build -trimpath -ldflags "-s -w -H windowsgui" `
68+
-o "$PWD\dmg-smoke-task.exe" `
69+
./cmd/stepsecurity-dev-machine-guard-task
70+
Get-Item "$PWD\dmg-smoke.exe", "$PWD\dmg-smoke-task.exe" |
71+
Select-Object Name, Length
6872
6973
- name: Build MSI
7074
shell: pwsh
@@ -83,6 +87,7 @@ jobs:
8387
-d Arch=x64 `
8488
-d "Version=$version" `
8589
-d "BinaryPath=$PWD\dmg-smoke.exe" `
90+
-d "LauncherPath=$PWD\dmg-smoke-task.exe" `
8691
-out "dist\dmg-smoke.msi"
8792
Get-Item "dist\dmg-smoke.msi" | Select-Object Name, Length
8893
@@ -112,18 +117,28 @@ jobs:
112117
- name: Verify install artifacts
113118
shell: pwsh
114119
run: |
115-
$bin = "C:\Program Files\StepSecurity\stepsecurity-dev-machine-guard.exe"
116-
$cfg = "C:\ProgramData\StepSecurity\config.json"
117-
$task = "StepSecurity Dev Machine Guard"
120+
$bin = "C:\Program Files\StepSecurity\stepsecurity-dev-machine-guard.exe"
121+
$launcher = "C:\Program Files\StepSecurity\stepsecurity-dev-machine-guard-task.exe"
122+
$cfg = "C:\ProgramData\StepSecurity\config.json"
123+
$task = "StepSecurity Dev Machine Guard"
118124
119125
$checks = @()
120126
121-
# 1. Binary on disk
127+
# 1a. Agent binary on disk
122128
if (Test-Path $bin) {
123-
Write-Host "[OK] Binary present at $bin"
129+
Write-Host "[OK] Agent present at $bin"
124130
$checks += $true
125131
} else {
126-
Write-Host "::error::Binary missing: $bin"
132+
Write-Host "::error::Agent missing: $bin"
133+
$checks += $false
134+
}
135+
136+
# 1b. Launcher binary on disk
137+
if (Test-Path $launcher) {
138+
Write-Host "[OK] Launcher present at $launcher"
139+
$checks += $true
140+
} else {
141+
Write-Host "::error::Launcher missing: $launcher"
127142
$checks += $false
128143
}
129144
@@ -160,7 +175,8 @@ jobs:
160175
$checks += $false
161176
}
162177
163-
# 4. Scheduled task registered and runs as INTERACTIVE
178+
# 4. Scheduled task registered, runs as INTERACTIVE, and its
179+
# action points at the launcher (not the agent directly).
164180
$taskInfo = schtasks /query /tn $task /v /fo LIST 2>&1
165181
if ($LASTEXITCODE -eq 0) {
166182
$runAs = ($taskInfo | Select-String -Pattern '^\s*Run As User:').ToString()
@@ -171,6 +187,15 @@ jobs:
171187
Write-Host "::error::Run As User wrong: $runAs"
172188
$checks += $false
173189
}
190+
191+
$action = ($taskInfo | Select-String -Pattern '^\s*Task To Run:').ToString()
192+
if ($action -match 'stepsecurity-dev-machine-guard-task\.exe') {
193+
Write-Host "[OK] Task action points at GUI launcher"
194+
$checks += $true
195+
} else {
196+
Write-Host "::error::Task action does not point at launcher: $action"
197+
$checks += $false
198+
}
174199
} else {
175200
Write-Host "::error::schtasks /query failed: $taskInfo"
176201
$checks += $false
@@ -199,12 +224,17 @@ jobs:
199224
run: |
200225
$task = "StepSecurity Dev Machine Guard"
201226
202-
# Binary should be gone
203-
if (Test-Path "C:\Program Files\StepSecurity\stepsecurity-dev-machine-guard.exe") {
204-
Write-Host "::error::Binary still present after uninstall"
205-
exit 1
227+
# Both binaries should be gone
228+
foreach ($leftover in @(
229+
"C:\Program Files\StepSecurity\stepsecurity-dev-machine-guard.exe",
230+
"C:\Program Files\StepSecurity\stepsecurity-dev-machine-guard-task.exe"
231+
)) {
232+
if (Test-Path $leftover) {
233+
Write-Host "::error::File still present after uninstall: $leftover"
234+
exit 1
235+
}
206236
}
207-
Write-Host "[OK] Binary removed"
237+
Write-Host "[OK] Agent + launcher removed"
208238
209239
# Scheduled task should be gone. Capture the exit code into a
210240
# local — PowerShell uses $LASTEXITCODE from the last native call

.github/workflows/release.yml

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,13 @@ jobs:
9292
id: binaries
9393
run: |
9494
DARWIN=$(find dist -type f -name '*darwin_unnotarized' | head -1)
95-
WIN_AMD64=$(find dist -type f -name '*.exe' -path '*windows_amd64*' | head -1)
96-
WIN_ARM64=$(find dist -type f -name '*.exe' -path '*windows_arm64*' | head -1)
95+
# Filter agent vs launcher (-task) explicitly — both ship as
96+
# <name>-<version>-<os>_<arch>.exe so a bare *.exe glob would
97+
# match either.
98+
WIN_AMD64=$(find dist -type f -name 'stepsecurity-dev-machine-guard-*-windows_amd64.exe' ! -name '*-task-*' | head -1)
99+
WIN_ARM64=$(find dist -type f -name 'stepsecurity-dev-machine-guard-*-windows_arm64.exe' ! -name '*-task-*' | head -1)
100+
WIN_TASK_AMD64=$(find dist -type f -name 'stepsecurity-dev-machine-guard-task-*-windows_amd64.exe' | head -1)
101+
WIN_TASK_ARM64=$(find dist -type f -name 'stepsecurity-dev-machine-guard-task-*-windows_arm64.exe' | head -1)
97102
LINUX_AMD64=$(find dist -type f -name 'stepsecurity-dev-machine-guard' -path '*linux_amd64*' | head -1)
98103
LINUX_ARM64=$(find dist -type f -name 'stepsecurity-dev-machine-guard' -path '*linux_arm64*' | head -1)
99104
@@ -102,7 +107,7 @@ jobs:
102107
RPM_AMD64=$(find dist -type f -name '*-amd64.rpm' | head -1)
103108
RPM_ARM64=$(find dist -type f -name '*-arm64.rpm' | head -1)
104109
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
110+
for label in "darwin:${DARWIN}" "windows_amd64:${WIN_AMD64}" "windows_arm64:${WIN_ARM64}" "windows_task_amd64:${WIN_TASK_AMD64}" "windows_task_arm64:${WIN_TASK_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
106111
name="${label%%:*}"
107112
path="${label#*:}"
108113
if [ -z "$path" ] || [ ! -f "$path" ]; then
@@ -115,6 +120,8 @@ jobs:
115120
echo "darwin=$DARWIN" >> "$GITHUB_OUTPUT"
116121
echo "win_amd64=$WIN_AMD64" >> "$GITHUB_OUTPUT"
117122
echo "win_arm64=$WIN_ARM64" >> "$GITHUB_OUTPUT"
123+
echo "win_task_amd64=$WIN_TASK_AMD64" >> "$GITHUB_OUTPUT"
124+
echo "win_task_arm64=$WIN_TASK_ARM64" >> "$GITHUB_OUTPUT"
118125
echo "linux_amd64=$LINUX_AMD64" >> "$GITHUB_OUTPUT"
119126
echo "linux_arm64=$LINUX_ARM64" >> "$GITHUB_OUTPUT"
120127
echo "deb_amd64=$DEB_AMD64" >> "$GITHUB_OUTPUT"
@@ -147,6 +154,10 @@ jobs:
147154
"dist/stepsecurity-dev-machine-guard-windows_amd64.exe.bundle"
148155
sign_with_retry "${{ steps.binaries.outputs.win_arm64 }}" \
149156
"dist/stepsecurity-dev-machine-guard-windows_arm64.exe.bundle"
157+
sign_with_retry "${{ steps.binaries.outputs.win_task_amd64 }}" \
158+
"dist/stepsecurity-dev-machine-guard-task-windows_amd64.exe.bundle"
159+
sign_with_retry "${{ steps.binaries.outputs.win_task_arm64 }}" \
160+
"dist/stepsecurity-dev-machine-guard-task-windows_arm64.exe.bundle"
150161
sign_with_retry "${{ steps.binaries.outputs.linux_amd64 }}" \
151162
"dist/stepsecurity-dev-machine-guard-linux_amd64.bundle"
152163
sign_with_retry "${{ steps.binaries.outputs.linux_arm64 }}" \
@@ -168,6 +179,8 @@ jobs:
168179
dist/stepsecurity-dev-machine-guard-darwin_unnotarized.bundle \
169180
dist/stepsecurity-dev-machine-guard-windows_amd64.exe.bundle \
170181
dist/stepsecurity-dev-machine-guard-windows_arm64.exe.bundle \
182+
dist/stepsecurity-dev-machine-guard-task-windows_amd64.exe.bundle \
183+
dist/stepsecurity-dev-machine-guard-task-windows_arm64.exe.bundle \
171184
dist/stepsecurity-dev-machine-guard-linux_amd64.bundle \
172185
dist/stepsecurity-dev-machine-guard-linux_arm64.bundle \
173186
"${{ steps.binaries.outputs.deb_amd64 }}.bundle" \
@@ -183,6 +196,8 @@ jobs:
183196
${{ steps.binaries.outputs.darwin }}
184197
${{ steps.binaries.outputs.win_amd64 }}
185198
${{ steps.binaries.outputs.win_arm64 }}
199+
${{ steps.binaries.outputs.win_task_amd64 }}
200+
${{ steps.binaries.outputs.win_task_arm64 }}
186201
${{ steps.binaries.outputs.linux_amd64 }}
187202
${{ steps.binaries.outputs.linux_arm64 }}
188203
${{ steps.binaries.outputs.deb_amd64 }}
@@ -240,10 +255,15 @@ jobs:
240255
shell: pwsh
241256
run: |
242257
$version = "${{ needs.release.outputs.version }}"
243-
$amd64 = Get-ChildItem dist -Filter "*-windows_amd64.exe" | Select-Object -First 1
244-
$arm64 = Get-ChildItem dist -Filter "*-windows_arm64.exe" | Select-Object -First 1
245-
if (-not $amd64 -or -not $arm64) {
246-
Write-Error "Windows .exe assets missing under dist/"
258+
# Both agent and launcher .exes share the *-windows_<arch>.exe
259+
# suffix; filter on the -task- segment to tell them apart.
260+
$amd64 = Get-ChildItem dist -Filter "stepsecurity-dev-machine-guard-*-windows_amd64.exe" | Where-Object Name -NotLike '*-task-*' | Select-Object -First 1
261+
$arm64 = Get-ChildItem dist -Filter "stepsecurity-dev-machine-guard-*-windows_arm64.exe" | Where-Object Name -NotLike '*-task-*' | Select-Object -First 1
262+
$taskAmd64 = Get-ChildItem dist -Filter "stepsecurity-dev-machine-guard-task-*-windows_amd64.exe" | Select-Object -First 1
263+
$taskArm64 = Get-ChildItem dist -Filter "stepsecurity-dev-machine-guard-task-*-windows_arm64.exe" | Select-Object -First 1
264+
if (-not $amd64 -or -not $arm64 -or -not $taskAmd64 -or -not $taskArm64) {
265+
Write-Error "Windows .exe assets (agent + launcher, both arches) missing under dist/"
266+
Get-ChildItem dist | Format-Table Name
247267
exit 1
248268
}
249269
@@ -253,6 +273,7 @@ jobs:
253273
-d Arch=x64 `
254274
-d "Version=$version" `
255275
-d "BinaryPath=$($amd64.FullName)" `
276+
-d "LauncherPath=$($taskAmd64.FullName)" `
256277
-out "dist/stepsecurity-dev-machine-guard-$version-x64.msi"
257278
258279
wix build packaging/windows/Product.wxs `
@@ -261,6 +282,7 @@ jobs:
261282
-d Arch=arm64 `
262283
-d "Version=$version" `
263284
-d "BinaryPath=$($arm64.FullName)" `
285+
-d "LauncherPath=$($taskArm64.FullName)" `
264286
-out "dist/stepsecurity-dev-machine-guard-$version-arm64.msi"
265287
266288
Get-ChildItem dist -Filter "*.msi" | Format-Table Name, Length

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ stepsecurity-dev-machine-guard-linux
2828

2929
# Temporary files
3030
todo-remove/
31+
32+
# Agent runtime state. When the binary or its tests run from inside the
33+
# repo (working dir = a subpkg, HOME pointing under it, etc.), it drops
34+
# config.json, agent.error.log, ai-agent-hook-errors.jsonl, hooks-state.json
35+
# and friends here. Never artifacts we want to track.
36+
**/.stepsecurity/

.goreleaser.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,29 @@ builds:
2323
env:
2424
- CGO_ENABLED=0
2525

26+
# GUI-subsystem launcher invoked by Windows Task Scheduler so the
27+
# console-subsystem agent never gets a console window allocated.
28+
# -H windowsgui flips the PE subsystem; otherwise identical config.
29+
- id: stepsecurity-dev-machine-guard-task
30+
main: ./cmd/stepsecurity-dev-machine-guard-task
31+
binary: stepsecurity-dev-machine-guard-task
32+
goos:
33+
- windows
34+
goarch:
35+
- amd64
36+
- arm64
37+
mod_timestamp: "{{ .CommitTimestamp }}"
38+
flags:
39+
- -trimpath
40+
ldflags:
41+
- -s -w
42+
- -H windowsgui
43+
- -X github.com/step-security/dev-machine-guard/internal/buildinfo.GitCommit={{.FullCommit}}
44+
- -X github.com/step-security/dev-machine-guard/internal/buildinfo.ReleaseTag={{.Tag}}
45+
- -X github.com/step-security/dev-machine-guard/internal/buildinfo.ReleaseBranch={{.Branch}}
46+
env:
47+
- CGO_ENABLED=0
48+
2649
universal_binaries:
2750
- id: universal
2851
ids:
@@ -44,6 +67,13 @@ archives:
4467
- binary
4568
name_template: "stepsecurity-dev-machine-guard-{{ .Version }}-{{ .Os }}_{{ .Arch }}"
4669
allow_different_binary_count: true
70+
- id: windows-task
71+
ids:
72+
- stepsecurity-dev-machine-guard-task
73+
formats:
74+
- binary
75+
name_template: "stepsecurity-dev-machine-guard-task-{{ .Version }}-{{ .Os }}_{{ .Arch }}"
76+
allow_different_binary_count: true
4777

4878
nfpms:
4979
- id: linux-packages

Makefile

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,34 @@ LDFLAGS := -s -w \
99
-X $(MODULE)/internal/buildinfo.ReleaseTag=$(TAG) \
1010
-X $(MODULE)/internal/buildinfo.ReleaseBranch=$(BRANCH)
1111

12-
.PHONY: build build-windows build-windows-arm64 build-linux deploy-windows test lint clean smoke build-msi-amd64 build-msi-arm64
12+
.PHONY: build build-windows build-windows-task build-windows-arm64 build-windows-task-arm64 build-linux deploy-windows test lint clean smoke build-msi-amd64 build-msi-arm64
1313

1414
build:
1515
go build -trimpath -ldflags "$(LDFLAGS)" -o $(BINARY) ./cmd/stepsecurity-dev-machine-guard
1616

1717
build-windows:
1818
GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o $(BINARY).exe ./cmd/stepsecurity-dev-machine-guard
1919

20+
# GUI-subsystem launcher (see cmd/stepsecurity-dev-machine-guard-task).
21+
# `-H windowsgui` flips the PE subsystem so Windows doesn't allocate
22+
# a console when Task Scheduler launches it.
23+
build-windows-task:
24+
GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS) -H windowsgui" -o $(BINARY)-task.exe ./cmd/stepsecurity-dev-machine-guard-task
25+
2026
build-windows-arm64:
2127
GOOS=windows GOARCH=arm64 go build -trimpath -ldflags "$(LDFLAGS)" -o $(BINARY)-arm64.exe ./cmd/stepsecurity-dev-machine-guard
2228

29+
build-windows-task-arm64:
30+
GOOS=windows GOARCH=arm64 go build -trimpath -ldflags "$(LDFLAGS) -H windowsgui" -o $(BINARY)-task-arm64.exe ./cmd/stepsecurity-dev-machine-guard-task
31+
2332
build-linux:
2433
GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o $(BINARY)-linux ./cmd/stepsecurity-dev-machine-guard
2534

2635
# MSI builds. Require WiX 4 on PATH: `dotnet tool install --global wix --version 4.0.5`.
2736
# Output: dist/stepsecurity-dev-machine-guard-<version>-{x64,arm64}.msi
2837
# Reads Version from internal/buildinfo so MajorUpgrade semantics line up
2938
# with whatever the binary reports as `--version`.
30-
build-msi-amd64: build-windows
39+
build-msi-amd64: build-windows build-windows-task
3140
mkdir -p dist
3241
@wix extension list --global 2>/dev/null | grep -q "WixToolset.Util.wixext" || \
3342
wix extension add --global WixToolset.Util.wixext/4.0.5
@@ -37,9 +46,10 @@ build-msi-amd64: build-windows
3746
-d Arch=x64 \
3847
-d Version=$(VERSION) \
3948
-d BinaryPath=$(CURDIR)/$(BINARY).exe \
49+
-d LauncherPath=$(CURDIR)/$(BINARY)-task.exe \
4050
-out dist/stepsecurity-dev-machine-guard-$(VERSION)-x64.msi
4151

42-
build-msi-arm64: build-windows-arm64
52+
build-msi-arm64: build-windows-arm64 build-windows-task-arm64
4353
mkdir -p dist
4454
@wix extension list --global 2>/dev/null | grep -q "WixToolset.Util.wixext" || \
4555
wix extension add --global WixToolset.Util.wixext/4.0.5
@@ -49,6 +59,7 @@ build-msi-arm64: build-windows-arm64
4959
-d Arch=arm64 \
5060
-d Version=$(VERSION) \
5161
-d BinaryPath=$(CURDIR)/$(BINARY)-arm64.exe \
62+
-d LauncherPath=$(CURDIR)/$(BINARY)-task-arm64.exe \
5263
-out dist/stepsecurity-dev-machine-guard-$(VERSION)-arm64.msi
5364

5465
deploy-windows:
@@ -61,7 +72,7 @@ lint:
6172
golangci-lint run ./...
6273

6374
clean:
64-
rm -f $(BINARY) $(BINARY).exe $(BINARY)-arm64.exe $(BINARY)-linux
75+
rm -f $(BINARY) $(BINARY).exe $(BINARY)-task.exe $(BINARY)-arm64.exe $(BINARY)-task-arm64.exe $(BINARY)-linux
6576
rm -rf dist/
6677

6778
smoke: build

0 commit comments

Comments
 (0)