Skip to content

Commit 75db6b8

Browse files
pgodwinclaude
andcommitted
Add -version flag to all client CLI tools, build Windows installer in CI, and add build-local script
- Add -version/version handling (buildinfo.Print) to csclient, csecho, csgetzones, csipxping, csmount, csnbp, csncpinfo, csnetsend, csnetview, and classicstackd for consistent build metadata reporting. - Add scripts/build-local.sh plus root package.json/package-lock.json (TypeScript devDependency) for local desktop builds. - Add an installer-windows CI job (Inno Setup via Chocolatey + packaging/windows/build.ps1) to pr-ci.yml and release-main.yml so the Windows ISCC installer is built and verified on every PR and attached to GitHub Releases. - Rebuild the Vite SPA asset bundle. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 9980461 commit 75db6b8

20 files changed

Lines changed: 683 additions & 3 deletions

File tree

.github/workflows/pr-ci.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,42 @@ jobs:
174174
OUTPUT: ${{ matrix.output }}
175175
run: ${{ matrix.script }}
176176

177+
installer-windows:
178+
name: Build Windows Installer (ISCC)
179+
runs-on: windows-latest
180+
steps:
181+
- name: Checkout
182+
uses: actions/checkout@v7
183+
with:
184+
submodules: recursive
185+
186+
- name: Setup Go
187+
uses: actions/setup-go@v7
188+
with:
189+
go-version-file: go.mod
190+
191+
- name: Setup SPA
192+
uses: ./.github/actions/setup-spa
193+
194+
- name: Install Inno Setup
195+
shell: pwsh
196+
run: |
197+
choco install innosetup --no-progress -y
198+
if (-not (Get-Command ISCC.exe -ErrorAction SilentlyContinue)) {
199+
throw "ISCC.exe not found on PATH after installing Inno Setup"
200+
}
201+
202+
- name: Build installer (bin + ISCC)
203+
shell: pwsh
204+
run: pwsh packaging/windows/build.ps1 -Version 0.0.0-pr.${{ github.run_number }}
205+
206+
- name: Upload installer artifact
207+
uses: actions/upload-artifact@v4
208+
with:
209+
name: classicstack-windows-installer-pr${{ github.event.pull_request.number }}
210+
path: packaging/windows/Output/ClassicStack-Setup-*.exe
211+
if-no-files-found: error
212+
177213
build-embedded:
178214
name: Build Embedded (TinyGo)
179215
runs-on: ubuntu-latest

.github/workflows/release-main.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,43 @@ jobs:
163163
BUILD_VARIANT: ${{ matrix.variant }}
164164
run: ${{ matrix.package_script }}
165165

166+
installer-windows:
167+
name: Build Windows Installer (ISCC)
168+
needs: version
169+
runs-on: windows-latest
170+
steps:
171+
- name: Checkout
172+
uses: actions/checkout@v7
173+
with:
174+
submodules: recursive
175+
176+
- name: Setup Go
177+
uses: actions/setup-go@v7
178+
with:
179+
go-version-file: go.mod
180+
181+
- name: Setup SPA
182+
uses: ./.github/actions/setup-spa
183+
184+
- name: Install Inno Setup
185+
shell: pwsh
186+
run: |
187+
choco install innosetup --no-progress -y
188+
if (-not (Get-Command ISCC.exe -ErrorAction SilentlyContinue)) {
189+
throw "ISCC.exe not found on PATH after installing Inno Setup"
190+
}
191+
192+
- name: Build installer (bin + ISCC)
193+
shell: pwsh
194+
run: pwsh packaging/windows/build.ps1 -Version ${{ needs.version.outputs.build_version }}
195+
196+
- name: Upload installer artifact
197+
uses: actions/upload-artifact@v4
198+
with:
199+
name: classicstack-windows-installer
200+
path: packaging/windows/Output/ClassicStack-Setup-*.exe
201+
if-no-files-found: error
202+
166203
build-embedded:
167204
name: Build And Package Embedded (TinyGo)
168205
needs: version
@@ -243,6 +280,7 @@ jobs:
243280
- version
244281
- build
245282
- build-embedded
283+
- installer-windows
246284
runs-on: ubuntu-latest
247285
steps:
248286
- name: Download all artifacts
@@ -261,3 +299,4 @@ jobs:
261299
files: |
262300
release-artifacts/**/*.zip
263301
release-artifacts/**/*.tar.gz
302+
release-artifacts/**/*.exe

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ app-darwin:
7676
# installer-windows builds every Windows binary into ./bin and compiles
7777
# packaging/windows/ClassicStack.iss into a Setup .exe (packaging/windows/Output).
7878
# Windows only: needs pwsh and ISCC (Inno Setup 6, https://jrsoftware.org/isinfo.php)
79-
# on PATH. Not part of CI release packaging; see packaging/windows/build.ps1 and
80-
# packaging/windows/redist/README.md (bundled Npcap/WinFsp installers).
79+
# on PATH. Also built in CI (installer-windows job in pr-ci.yml/release-main.yml,
80+
# uploaded/attached unsigned — no bundled Npcap/WinFsp there); see
81+
# packaging/windows/build.ps1 and packaging/windows/redist/README.md.
8182
installer-windows:
8283
pwsh packaging/windows/build.ps1
8384

adapter/control/http/spa/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1">
66
<title>ClassicStack</title>
7-
<script type="module" crossorigin src="/assets/index-DcQCXCoV.js"></script>
7+
<script type="module" crossorigin src="/assets/index-p4weJ1fe.js"></script>
88
<link rel="stylesheet" crossorigin href="/assets/index-BXtJzfA7.css">
99
</head>
1010
<body>

cmd/classicstackd/main_unix.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"syscall"
1717
"time"
1818

19+
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/buildinfo"
1920
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/cli"
2021
)
2122

@@ -52,6 +53,7 @@ Usage:
5253
classicstackd run -config <path> run in the foreground
5354
classicstackd install -config <path> [-log <p>] macOS: login item (LaunchAgent)
5455
classicstackd uninstall macOS: remove the LaunchAgent
56+
classicstackd version print version information
5557
`)
5658
}
5759

@@ -70,6 +72,9 @@ func dispatch(cmd string, args []string, version cli.Version) error {
7072
return cmdInstall(args)
7173
case "uninstall", "remove":
7274
return cmdUninstall(args)
75+
case "version":
76+
buildinfo.Print(os.Stdout, "classicstackd", version.Version, version.Commit, version.Date)
77+
return nil
7378
case "-h", "--help", "help":
7479
usage()
7580
return nil

cmd/csclient/main.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"strings"
3131

3232
"github.com/ObsoleteMadness/ClassicStack/client/trace"
33+
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/buildinfo"
3334
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/csconnect"
3435

3536
// Register the client schemes. Each blank import plugs a scheme into the registry.
@@ -39,6 +40,14 @@ import (
3940
_ "github.com/ObsoleteMadness/ClassicStack/client/smb"
4041
)
4142

43+
// Build metadata injected at link time via -ldflags
44+
// -X main.BuildVersion=... -X main.BuildCommit=... -X main.BuildDate=...
45+
var (
46+
BuildVersion = "0.0.0-dev"
47+
BuildCommit = "unknown"
48+
BuildDate = "unknown"
49+
)
50+
4251
func main() {
4352
os.Exit(run(os.Args[1:]))
4453
}
@@ -53,6 +62,10 @@ func run(args []string) int {
5362
// direct-IPX, NBIPX, NBF, NCP, EtherDFS) — one shared verbose toggle on the core/log
5463
// library, rendered to stderr.
5564
trace.SetVerbose(cfg.Verbose)
65+
if cfg.Version {
66+
buildinfo.Print(os.Stdout, "csfs", BuildVersion, BuildCommit, BuildDate)
67+
return 0
68+
}
5669
if cfg.ListIfaces {
5770
csconnect.PrintInterfaces(os.Stdout)
5871
return 0
@@ -119,6 +132,7 @@ Flags:
119132
-fork host fork container: appledouble | applesingle | macbinary | derez | native | nofork
120133
-v verbose: print the client wire-trace (NBP/ATP/ASP) to stderr
121134
-list-ifaces list the capturable pcap NICs (the names -iface accepts) and exit
135+
-version print version information and exit
122136
123137
URI grammar:
124138
<scheme>://[[user][:pass]@]<server>[,<transport>]/<volume>[/<path>]

cmd/csecho/main.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ import (
2323
"github.com/ObsoleteMadness/ClassicStack/client/atalk"
2424
"github.com/ObsoleteMadness/ClassicStack/client/trace"
2525
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/atlink"
26+
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/buildinfo"
27+
)
28+
29+
// Build metadata injected at link time via -ldflags
30+
// -X main.BuildVersion=... -X main.BuildCommit=... -X main.BuildDate=...
31+
var (
32+
BuildVersion = "0.0.0-dev"
33+
BuildCommit = "unknown"
34+
BuildDate = "unknown"
2635
)
2736

2837
func main() {
@@ -41,11 +50,17 @@ func run() error {
4150
timeout = flag.Duration("timeout", 2*time.Second, "per-request reply timeout")
4251
payload = flag.String("data", "ClassicStack csecho", "echo payload string")
4352
verbose = flag.Bool("v", false, "verbose wire trace to stderr")
53+
version = flag.Bool("version", false, "print version information and exit")
4454
)
4555
at := atlink.Flags(flag.CommandLine)
4656
flag.Parse()
4757
trace.SetVerbose(*verbose)
4858

59+
if *version {
60+
buildinfo.Print(os.Stdout, "csecho", BuildVersion, BuildCommit, BuildDate)
61+
return nil
62+
}
63+
4964
if at.ListIface {
5065
atlink.PrintInterfaces(os.Stdout)
5166
return nil

cmd/csgetzones/main.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,21 @@ import (
2525
"github.com/ObsoleteMadness/ClassicStack/client/atalk"
2626
"github.com/ObsoleteMadness/ClassicStack/client/trace"
2727
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/atlink"
28+
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/buildinfo"
2829
)
2930

3031
// broadcastNode is the DDP node id every node on the segment receives; with no known
3132
// router address, csgetzones broadcasts the request and answers come from any router.
3233
const broadcastNode = 0xFF
3334

35+
// Build metadata injected at link time via -ldflags
36+
// -X main.BuildVersion=... -X main.BuildCommit=... -X main.BuildDate=...
37+
var (
38+
BuildVersion = "0.0.0-dev"
39+
BuildCommit = "unknown"
40+
BuildDate = "unknown"
41+
)
42+
3443
func main() {
3544
if err := run(); err != nil {
3645
fmt.Fprintln(os.Stderr, "csgetzones:", err)
@@ -47,11 +56,17 @@ func run() error {
4756
local = flag.Bool("local", false, "GetLocalZones: only zones on our own network")
4857
myZone = flag.Bool("my", false, "GetMyZone: just the responding router's own zone")
4958
verbose = flag.Bool("v", false, "verbose wire trace to stderr")
59+
version = flag.Bool("version", false, "print version information and exit")
5060
)
5161
at := atlink.Flags(flag.CommandLine)
5262
flag.Parse()
5363
trace.SetVerbose(*verbose)
5464

65+
if *version {
66+
buildinfo.Print(os.Stdout, "csgetzones", BuildVersion, BuildCommit, BuildDate)
67+
return nil
68+
}
69+
5570
if at.ListIface {
5671
atlink.PrintInterfaces(os.Stdout)
5772
return nil

cmd/csipxping/main.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,21 @@ import (
2828

2929
"github.com/ObsoleteMadness/ClassicStack/adapter/link/pcap"
3030
clientlink "github.com/ObsoleteMadness/ClassicStack/client/link"
31+
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/buildinfo"
3132
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/csconnect"
3233
"github.com/ObsoleteMadness/ClassicStack/core/link"
3334
ipxproto "github.com/ObsoleteMadness/ClassicStack/core/protocol/ipx"
3435
"github.com/ObsoleteMadness/ClassicStack/core/protocol/ipx/diag"
3536
)
3637

38+
// Build metadata injected at link time via -ldflags
39+
// -X main.BuildVersion=... -X main.BuildCommit=... -X main.BuildDate=...
40+
var (
41+
BuildVersion = "0.0.0-dev"
42+
BuildCommit = "unknown"
43+
BuildDate = "unknown"
44+
)
45+
3746
// etherTypeIPX is the Ethernet II type for IPX; ethHdrLen is the Ethernet II header
3847
// length (dst MAC + src MAC + type). These match core/port/ipx's encapsulation.
3948
const (
@@ -61,9 +70,15 @@ func run() error {
6170
wait = flag.Duration("interval", 500*time.Millisecond, "delay between requests")
6271
macFlag = flag.String("mac", "", "source MAC for our virtual station (default: random locally-administered)")
6372
listIf = flag.Bool("list-ifaces", false, "list the capturable pcap NICs (the names -iface accepts) and exit")
73+
version = flag.Bool("version", false, "print version information and exit")
6474
)
6575
flag.Parse()
6676

77+
if *version {
78+
buildinfo.Print(os.Stdout, "csipxping", BuildVersion, BuildCommit, BuildDate)
79+
return nil
80+
}
81+
6782
if *listIf {
6883
clientlink.PrintInterfaces(os.Stdout)
6984
return nil

cmd/csmount/main.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"strings"
2222

2323
"github.com/ObsoleteMadness/ClassicStack/client/trace"
24+
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/buildinfo"
2425
"github.com/ObsoleteMadness/ClassicStack/cmd/internal/csconnect"
2526
"github.com/ObsoleteMadness/ClassicStack/core/fs"
2627

@@ -30,6 +31,14 @@ import (
3031
_ "github.com/ObsoleteMadness/ClassicStack/client/smb"
3132
)
3233

34+
// Build metadata injected at link time via -ldflags
35+
// -X main.BuildVersion=... -X main.BuildCommit=... -X main.BuildDate=...
36+
var (
37+
BuildVersion = "0.0.0-dev"
38+
BuildCommit = "unknown"
39+
BuildDate = "unknown"
40+
)
41+
3342
func main() { os.Exit(run(os.Args[1:])) }
3443

3544
func run(args []string) int {
@@ -44,6 +53,11 @@ func run(args []string) int {
4453
traceMount(os.Stderr)
4554
}
4655

56+
if cfg.Version {
57+
buildinfo.Print(os.Stdout, "csmount", BuildVersion, BuildCommit, BuildDate)
58+
return 0
59+
}
60+
4761
if cfg.ListIfaces {
4862
csconnect.PrintInterfaces(os.Stdout)
4963
return 0

0 commit comments

Comments
 (0)