Skip to content

feat: ship Windows binaries and fix broken install instructions - #147

Open
husniadil wants to merge 1 commit into
securestart:mainfrom
husniadil:feat/release-windows-binaries
Open

feat: ship Windows binaries and fix broken install instructions#147
husniadil wants to merge 1 commit into
securestart:mainfrom
husniadil:feat/release-windows-binaries

Conversation

@husniadil

@husniadil husniadil commented Aug 2, 2026

Copy link
Copy Markdown

Two independent user-facing gaps, both about the path between "CI is green" and "a user can actually install this".

1. Windows is built by CI but never shipped

ci.yml has built windows/amd64 on windows-latest with CGO_ENABLED=1 on every PR, and it passes — for example run 30671147270, job Build (windows, amd64, windows-latest) | success.

release.yml does not contain the string windows at all. Its matrix has four entries; the latest release (v0.0.11) accordingly has four archives, none for Windows.

So everything needed for Windows already exists — internal/app/runner_windows.go, the danieljoos/wincred dependency, the Credential Manager keyring backend documented in SSO.md:161 and CONFIGURATION.md:808 — and CI proves it compiles. Only the release matrix was missing.

go install is not a workaround here: the whole binary requires cgo (bitwarden/sdk-go wraps a Rust static lib), so a Windows user would need a mingw-w64 toolchain installed. The Bitwarden SDK does bundle internal/cinterface/lib/windows-x64/libbitwarden_c.a, so this is purely a packaging gap.

Change: one matrix entry (windows-latest, binary_name: sstart.exe), and a Windows-only archive step.

Windows gets a .zip rather than a .tar.gz — it is what Windows users expect, and the publish job's collector already globs *.zip alongside *.tar.gz. The archive step is split by OS rather than made conditional inline, so the existing four targets keep their exact current code path and cannot regress. Compress-Archive is used because it is guaranteed present on the runner image, unlike zip(1).

2. Every install command in the README returns 404

This one is independent of Windows and affects everyone today:

sstart_Linux_x86_64.tar.gz    HTTP 404
sstart_Darwin_x86_64.tar.gz   HTTP 404
sstart_Darwin_arm64.tar.gz    HTTP 404

Correction to an earlier revision of this description: I first wrote that these URLs also pointed at the wrong repository. That was wrong, and I want to be precise since it changes the diagnosis.

dirathea/sstart is not a separate repository — it is a redirect. The repo was transferred into the securestart org and GitHub keeps the old path working (GET /repos/dirathea/sstart301full_name: securestart/sstart). My initial check used curl without -L, so the 301 body simply had no tag_name and I misread it as "no releases". Releases resolve fine through the redirect:

https://github.com/dirathea/sstart/releases/download/v0.0.11/sstart-0.0.11-linux-amd64.tar.gz   HTTP 200
https://github.com/dirathea/sstart/releases/latest/download/sstart_Linux_x86_64.tar.gz          HTTP 404

So there is exactly one cause, not two: the filenames are wrong. The README uses goreleaser-style names (sstart_Linux_x86_64.tar.gz); the workflow produces sstart-<version>-<os>-<arch>.tar.gz. The 404 reproduces against securestart directly, so the repo path was never the issue.

There is also a structural problem independent of naming: because asset names embed the version, releases/latest/download/<name> can never resolve for any filename. The instructions now read the latest tag first, then build the URL.

The README links are updated to securestart/sstart anyway — it is the canonical location and does not depend on a redirect being kept alive — but that part is cosmetic, not the fix.

linux-arm64 was also shipped but undocumented, so ARM users had no idea it existed. Now listed.

The go install line still points at dirathea/sstart — that is the Go module path and it resolves correctly (all tags v0.0.1–v0.0.11 are on the module proxy), so I left it alone. If the intent is to move the module path to securestart, that is a separate change.

Verification

The new bash snippet was extracted verbatim from the README and executed:

resolved: VERSION=0.0.11 OS=darwin ARCH=arm64
sstart version v0.0.11 (commit: 8fdfb86..., built: 2026-01-19T21:43:57.109Z)

An earlier draft of that snippet mis-parsed the tag; it was caught by running it, and the committed version is the one that works.

release.yml parses as valid YAML and each archive step carries exactly one branch of the OS condition, so no target is skipped or double-handled.

What I could not verify: the PowerShell archive step. release.yml only triggers on tag push, so nothing exercises it until an actual release, and I have no Windows/pwsh environment. I kept it deliberately plain for that reason — $ErrorActionPreference = 'Stop', explicit .FullName, no .NET type usage — but it deserves a careful read, or a throwaway tag on a fork to confirm before relying on it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Hmh2p2Bg6kmxxvzpFDW2WL

CI has built and verified windows/amd64 with CGO_ENABLED=1 on every PR
for a while, but the release workflow never shipped the result, so
Windows users had no binary to download. The provider code, signal
handling (runner_windows.go) and Credential Manager keyring backend were
already there and documented — only the release matrix was missing.

Windows ships a .zip rather than a .tar.gz because that is what Windows
users expect, and the publish job already collected *.zip. The archive
step is split per-OS so the existing four targets keep their exact
current code path.

Separately, every download command in the README returned 404. The cause
is the filenames: the README used goreleaser-style names
(sstart_Linux_x86_64.tar.gz) while the workflow produces
sstart-<version>-<os>-<arch>.tar.gz. Release assets embed the version,
so a stable latest/download/ URL cannot resolve for any filename; the
instructions now read the latest tag first, then build the URL.

The links also move to securestart/sstart. dirathea/sstart still works —
it is a redirect left over from the org transfer, not a separate repo —
but pointing at the canonical path avoids depending on that redirect
being kept alive. The go install line keeps the dirathea module path,
which is what go.mod declares.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hmh2p2Bg6kmxxvzpFDW2WL
@husniadil
husniadil force-pushed the feat/release-windows-binaries branch from 27ed183 to 44e7482 Compare August 2, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant