Skip to content

Commit eaef7f9

Browse files
committed
build: ldflags version injection + WhyKnot YYYY.M.D.N tag scheme
Switches main.version from a hardcoded const to a var so the release workflow can stamp the family-standard YYYY.M.D.N(-XXXX) version into the binary via: go build -ldflags "-X main.version=$VERSION" ... The workflow extracts $VERSION from the tag (strips the leading 'v') and validates the shape before building. Tags that don't match the regex fail the build instead of shipping a malformed version. Drops the code-signing step entirely -- there is no cert. The release uploads the unsigned binary; SmartScreen reputation will build as downloads accumulate.
1 parent 8bea50c commit eaef7f9

2 files changed

Lines changed: 44 additions & 33 deletions

File tree

.github/workflows/release.yml

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
workflow_dispatch:
88
inputs:
99
tag:
10-
description: 'Tag to release (e.g. v0.1.0)'
10+
description: 'Tag to release (e.g. v2026.5.22.0)'
1111
required: true
1212

1313
permissions:
@@ -24,60 +24,67 @@ jobs:
2424
go-version: '1.22'
2525
cache: true
2626

27+
- name: Resolve version from tag
28+
id: ver
29+
shell: pwsh
30+
run: |
31+
$tag = "${{ github.event.inputs.tag }}"
32+
if (-not $tag) { $tag = "${{ github.ref_name }}" }
33+
# Strip leading 'v' from the tag to land the family YYYY.M.D.N
34+
# scheme into the binary version string. Tags MUST start with 'v'.
35+
if (-not $tag.StartsWith('v')) {
36+
throw "tag '$tag' does not start with 'v'"
37+
}
38+
$version = $tag.Substring(1)
39+
# Sanity-check the YYYY.M.D.N(-XXXX) shape so a fat-fingered
40+
# tag fails the release rather than shipping a broken version.
41+
if ($version -notmatch '^\d{4}\.\d+\.\d+\.\d+(-[A-Fa-f0-9]{4})?$') {
42+
throw "version '$version' does not match the YYYY.M.D.N(-XXXX) shape"
43+
}
44+
"tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
45+
"version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
46+
Write-Host "tag=$tag version=$version"
47+
2748
- name: Fetch picotool
2849
shell: pwsh
2950
run: |
3051
./scripts/fetch-picotool.ps1
3152
3253
- name: Build with embedded picotool
3354
shell: pwsh
55+
env:
56+
GOOS: windows
57+
GOARCH: amd64
58+
CGO_ENABLED: '0'
59+
HANDOFF_VERSION: ${{ steps.ver.outputs.version }}
3460
run: |
35-
$env:GOOS = 'windows'
36-
$env:GOARCH = 'amd64'
37-
$env:CGO_ENABLED = '0'
38-
go build -trimpath -ldflags="-s -w" -tags embed_picotool -o handoff.exe .
61+
go build -trimpath -ldflags="-s -w -X main.version=$env:HANDOFF_VERSION" -tags embed_picotool -o handoff.exe .
62+
./handoff.exe version
3963
40-
- name: Build sidecar version manifest
64+
- name: Write release manifest
65+
id: manifest
4166
shell: pwsh
67+
env:
68+
HANDOFF_VERSION: ${{ steps.ver.outputs.version }}
69+
HANDOFF_TAG: ${{ steps.ver.outputs.tag }}
4270
run: |
43-
$tag = "${{ github.event.inputs.tag }}"
44-
if (-not $tag) { $tag = "${{ github.ref_name }}" }
45-
$version = $tag.TrimStart('v')
4671
$sha = (Get-FileHash -Algorithm SHA256 handoff.exe).Hash.ToLower()
4772
$manifest = [ordered]@{
48-
version = $version
73+
version = $env:HANDOFF_VERSION
4974
sha256 = $sha
50-
url = "https://github.com/${{ github.repository }}/releases/download/$tag/handoff.exe"
51-
notes = "Release $tag"
75+
url = "https://github.com/${{ github.repository }}/releases/download/$env:HANDOFF_TAG/handoff.exe"
76+
notes = "Release $env:HANDOFF_TAG"
5277
}
5378
$manifest | ConvertTo-Json -Compress | Out-File -FilePath handoff-version.json -Encoding ASCII
5479
Get-Content handoff-version.json
5580
56-
- name: Code signing (disabled until cert is provisioned)
57-
if: ${{ env.SIGNING_CERT_BASE64 != '' }}
58-
env:
59-
SIGNING_CERT_BASE64: ${{ secrets.SIGNING_CERT_BASE64 }}
60-
SIGNING_CERT_PASSWORD: ${{ secrets.SIGNING_CERT_PASSWORD }}
61-
shell: pwsh
62-
run: |
63-
# Activate by setting the SIGNING_CERT_BASE64 and SIGNING_CERT_PASSWORD
64-
# repository secrets to a base64-encoded PFX and its password. The
65-
# block stays inert until both are set.
66-
$pfx = [Convert]::FromBase64String($env:SIGNING_CERT_BASE64)
67-
$tmp = Join-Path $env:RUNNER_TEMP 'handoff-sign.pfx'
68-
[IO.File]::WriteAllBytes($tmp, $pfx)
69-
$signtool = Get-ChildItem 'C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe' |
70-
Sort-Object -Descending FullName | Select-Object -First 1
71-
& $signtool.FullName sign /f $tmp /p $env:SIGNING_CERT_PASSWORD /fd sha256 /tr http://timestamp.digicert.com /td sha256 handoff.exe
72-
Remove-Item $tmp -Force
73-
7481
- name: Upload release assets
7582
uses: softprops/action-gh-release@v2
7683
with:
77-
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
84+
tag_name: ${{ steps.ver.outputs.tag }}
7885
files: |
7986
handoff.exe
8087
handoff-version.json
8188
generate_release_notes: true
8289
draft: false
83-
prerelease: ${{ contains(github.event.inputs.tag || github.ref_name, '-') }}
90+
prerelease: ${{ contains(steps.ver.outputs.version, '-') }}

main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import (
99
"github.com/RealWhyKnot/Handoff/cmd"
1010
)
1111

12-
const version = "0.1.0"
12+
// version is stamped by the release workflow via
13+
// -ldflags "-X main.version=<tag without v-prefix>"
14+
// per the WhyKnot family YYYY.M.D.N scheme. The "dev" default
15+
// covers local builds without ldflags.
16+
var version = "dev"
1317

1418
func main() {
1519
if len(os.Args) < 2 {

0 commit comments

Comments
 (0)