feat(ci): add Windows build alongside Linux #21

Merged
David merged 1 commit from feat/ci-build-windows into main 2026-05-14 16:45:38 +02:00
Owner

Summary

Adds a Windows build alongside the existing Linux build. Cross-compiles yt.exe on the OpenSUSE runner via mingw, publishes the artifact to the existing youtrack-cli Generic Package slug. Naming follows the build-<artifact>.yml precedent set by da-os (which ships both build-linux.yml and build-windows.yml).

New files

  • .forgejo/workflows/build-windows.yml: same shape as build-linux.yml (get-tags via oci-build/get-tags.nu, latest + vX.Y.Z fan-out, DELETE-then-PUT against the Forgejo Generic Package API).
  • oci-build/Dockerfile.windows: cross-compile chain matching da-os: ghcr.io/niceguyit/rust-builder-glibc-windows base image, gcc-mingw-w64-x86-64 added at build time, Rust target x86_64-pc-windows-gnu, dummy-source dependency prime under the target triple, export stage emitting /yt.exe. Same YOUTRACK_CLI_GIT_HASH / YOUTRACK_CLI_BUILD_DATE / CARGO_BUILD_JOBS build args as the Linux Dockerfile so build.rs bakes identical metadata into the .exe.

Artifact / download URL

  • File: yt-windows-x86_64.exe.
  • Generic Package URL: https://dev.a8n.run/api/packages/<owner>/generic/youtrack-cli/<tag>/yt-windows-x86_64.exe. Parallel to the existing Linux URL.
  • Version-in-filename was deliberately NOT introduced: the Linux workflow uses a bare filename, and changing that here would create gratuitous Linux/Windows asymmetry. (da-os uses versioned filenames; we did not from the start.)

Drive-by tweak

Narrowed build-linux.yml's paths: filter from oci-build/** to the specific files it actually depends on (Dockerfile + get-tags.nu), so a Dockerfile.windows edit no longer redundantly triggers a Linux rebuild and vice versa. Same kind of tightening on the new build-windows.yml.

Out of scope (called out in CLAUDE.md)

The Linux Dockerfile is still bare oci-build/Dockerfile. With oci-build/Dockerfile.windows now alongside it, the bare name is asymmetric. Renaming it to Dockerfile.linux is left for a follow-up since it would also touch compose.yml, justfile, and build-linux.yml. Easy to do separately if you want it.

Verification

  • cargo fmt --check clean.
  • cargo clippy --all-targets -- -D warnings clean.
  • cargo test --all-targets: 160 tests pass (no source changes).
  • End-to-end docker buildx build --target export --file oci-build/Dockerfile.windows . was NOT exercised locally: the host runner is the only place with the rust-builder-glibc-windows image pinned, so the first CI run on this branch is the real smoke test.

Test plan

  • First push to main after merge: confirm Forgejo Actions UI shows both "Build Linux binary" and "Build Windows binary" running. Both should succeed.
  • Confirm the .exe lands at https://dev.a8n.run/api/packages/pandoras-box/generic/youtrack-cli/latest/yt-windows-x86_64.exe and download works.
  • Run the downloaded yt-windows-x86_64.exe --version on a Windows host: should print the expected version + git hash + build date.
  • Cut a release/v0.1.X PR: confirm both binaries land under the new version path alongside latest.
## Summary Adds a Windows build alongside the existing Linux build. Cross-compiles `yt.exe` on the OpenSUSE runner via mingw, publishes the artifact to the existing `youtrack-cli` Generic Package slug. Naming follows the `build-<artifact>.yml` precedent set by `da-os` (which ships both `build-linux.yml` and `build-windows.yml`). ## New files - `.forgejo/workflows/build-windows.yml`: same shape as `build-linux.yml` (get-tags via `oci-build/get-tags.nu`, latest + `vX.Y.Z` fan-out, DELETE-then-PUT against the Forgejo Generic Package API). - `oci-build/Dockerfile.windows`: cross-compile chain matching da-os: `ghcr.io/niceguyit/rust-builder-glibc-windows` base image, `gcc-mingw-w64-x86-64` added at build time, Rust target `x86_64-pc-windows-gnu`, dummy-source dependency prime under the target triple, `export` stage emitting `/yt.exe`. Same `YOUTRACK_CLI_GIT_HASH` / `YOUTRACK_CLI_BUILD_DATE` / `CARGO_BUILD_JOBS` build args as the Linux Dockerfile so `build.rs` bakes identical metadata into the .exe. ## Artifact / download URL - File: `yt-windows-x86_64.exe`. - Generic Package URL: `https://dev.a8n.run/api/packages/<owner>/generic/youtrack-cli/<tag>/yt-windows-x86_64.exe`. Parallel to the existing Linux URL. - Version-in-filename was deliberately NOT introduced: the Linux workflow uses a bare filename, and changing that here would create gratuitous Linux/Windows asymmetry. (da-os uses versioned filenames; we did not from the start.) ## Drive-by tweak Narrowed `build-linux.yml`'s `paths:` filter from `oci-build/**` to the specific files it actually depends on (`Dockerfile` + `get-tags.nu`), so a `Dockerfile.windows` edit no longer redundantly triggers a Linux rebuild and vice versa. Same kind of tightening on the new `build-windows.yml`. ## Out of scope (called out in CLAUDE.md) The Linux Dockerfile is still bare `oci-build/Dockerfile`. With `oci-build/Dockerfile.windows` now alongside it, the bare name is asymmetric. Renaming it to `Dockerfile.linux` is left for a follow-up since it would also touch `compose.yml`, `justfile`, and `build-linux.yml`. Easy to do separately if you want it. ## Verification - `cargo fmt --check` clean. - `cargo clippy --all-targets -- -D warnings` clean. - `cargo test --all-targets`: 160 tests pass (no source changes). - End-to-end `docker buildx build --target export --file oci-build/Dockerfile.windows .` was NOT exercised locally: the host runner is the only place with the `rust-builder-glibc-windows` image pinned, so the first CI run on this branch is the real smoke test. ## Test plan - [ ] First push to `main` after merge: confirm Forgejo Actions UI shows both "Build Linux binary" and "Build Windows binary" running. Both should succeed. - [ ] Confirm the .exe lands at `https://dev.a8n.run/api/packages/pandoras-box/generic/youtrack-cli/latest/yt-windows-x86_64.exe` and download works. - [ ] Run the downloaded `yt-windows-x86_64.exe --version` on a Windows host: should print the expected version + git hash + build date. - [ ] Cut a `release/v0.1.X` PR: confirm both binaries land under the new version path alongside `latest`.
feat(ci): add Windows build alongside Linux
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 8s
Create release / Create release from merged PR (pull_request) Has been skipped
2a1f047f5f
Mirrors the `build-linux.yml` + `Dockerfile` pair on the Linux side with a Windows counterpart. New `.forgejo/workflows/build-windows.yml` cross-compiles `yt.exe` on the OpenSUSE runner using `oci-build/Dockerfile.windows`, then publishes the artifact to the Forgejo Generic Package registry under the existing `youtrack-cli` package slug. Naming follows the `build-<artifact>.yml` precedent established by da-os.

The cross-compile chain matches da-os exactly: `ghcr.io/niceguyit/rust-builder-glibc-windows` base image, `gcc-mingw-w64-x86-64` added at build time, Rust target `x86_64-pc-windows-gnu`, dummy-source dependency prime under the target triple so cached layers stay warm. Build args mirror the Linux side (`YOUTRACK_CLI_GIT_HASH`, `YOUTRACK_CLI_BUILD_DATE`, `CARGO_BUILD_JOBS`) so `build.rs` bakes the same metadata into the .exe.

Artifact: `yt-windows-x86_64.exe`, uploaded with the same `latest` + version-tag fan-out the Linux workflow already uses. Download URL pattern: `https://dev.a8n.run/api/packages/<owner>/generic/youtrack-cli/<tag>/yt-windows-x86_64.exe`, parallel to the Linux URL. No version-in-filename to keep the Linux/Windows pair symmetric (da-os uses versioned filenames; we did not, and changing that now would break existing Linux download URLs).

While here, narrowed the Linux workflow's `paths:` filter from `oci-build/**` to the specific files it actually depends on (`Dockerfile` and `get-tags.nu`), so a `Dockerfile.windows` edit no longer triggers a redundant Linux rebuild and vice versa.

CLAUDE.md updated with the new files and a note that the bare `oci-build/Dockerfile` filename (Linux) is asymmetric with `Dockerfile.windows`; renaming it to `Dockerfile.linux` is left as a follow-up since it would also touch compose.yml, justfile, and build-linux.yml.

No Rust source changes; 160 tests still pass; clippy/fmt clean. End-to-end Docker build of `Dockerfile.windows` not exercised locally (the host runner is the only place with the required `rust-builder-glibc-windows` image); first CI run on this branch will be the smoke test.
David merged commit 84d7de4c59 into main 2026-05-14 16:45:38 +02:00
David deleted branch feat/ci-build-windows 2026-05-14 16:45:38 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/youtrack-cli!21
No description provided.