Cross-compiles 012 (CGO_ENABLED=0, -trimpath, version stamped with -X main.version) for darwin, linux and windows on amd64 and arm64 into dist/ as tar.gz and zip archives with SHA256SUMS. Nothing is uploaded. 012 version prints the stamped version, else the module version, and the VCS revision. docs/contributing/releasing.md holds the release checklist.
- commit
- 77fde551eae0f41488a3653066111378499b87cc
- parent
- 24d313d458adc9a8a0311d3deba8fb68ea2318f3
- author
- Dami <dami.etoile@gmail.com>
| M | .gitignore | 1 | + |
| M | Makefile | 8 | +++- |
| M | cmd/ | 6 | ++- |
| M | cmd/ | 12 | ++++++ |
| A | cmd/ | 43 | ++++++++++++++++++++ |
| M | docs/ | 1 | + |
| A | docs/ | 62 | ++++++++++++++++++++++++++++++ |
| A | scripts/ | 63 | ++++++++++++++++++++++++++++++ |
@@ -7,7 +7,7 @@ GHOSTTY_SRC := $(DEPS)/ghostty-src
77 GHOSTTY_OUT := $(DEPS)/ghostty88 GHOSTTY_STAMP := $(GHOSTTY_OUT)/.built-$(GHOSTTY_COMMIT)99 10-10+1111 1212 build:1313 CGO_ENABLED=0 go build -o bin/012 ./cmd/012@@ -15,6 +15,12 @@ build:
1515 run: build1616 ./bin/0121717 18+# Release archives: 012 cross-compiled (pure Go, -trimpath, stamped with19+# VERSION) for macOS, Linux and Windows on amd64 and arm64 into dist/,20+# with SHA256SUMS. Nothing is uploaded; see docs/contributing/releasing.md.21+dist:22+ VERSION=$(VERSION) scripts/dist.sh23+1824 test:1925 go test ./...2026 @@ -53,13 +53,17 @@ func usage() error {
5353 return errors.New("usage: 012 " + config.FlagUsage() + " [file]: a " + sheet.FileExt +5454 " sheet, or a .csv, .tsv, .xlsx, .sqlite, .parquet or .wk1 file to import\n" +5555 " 012 serve [flags] [dir]: serve sheets in dir over SSH (see docs/terminal/ssh.md)\n" +56- " 012 config [path|edit|default|themes|set-key|delete-key]")56+ " 012 config [path|edit|default|themes|set-key|delete-key]\n" +57+ " 012 version")5758 }5859 5960 func run(args []string, e env) error {6061 if len(args) > 0 && args[0] == "config" {6162 return runConfig(args[1:], e)6263 }64+ if len(args) > 0 && (args[0] == "version" || args[0] == "--version") {65+ return runVersion(e)66+ }6367 if len(args) > 0 && args[0] == "serve" {6468 // A file called serve opens as ./serve.6569 return runServe(args[1:], e)@@ -174,3 +174,15 @@ func TestRunWarnsOnConfig(t *testing.T) {
174174 t.Error("two files")175175 }176176 }177+178+func TestVersion(t *testing.T) {179+ e, out, _ := testEnv(t, nil)180+ version = "v9.8.7"181+ defer func() { version = "" }()182+ for _, arg := range []string{"version", "--version"} {183+ out.Reset()184+ if err := run([]string{arg}, e); err != nil || !strings.HasPrefix(out.String(), "012 v9.8.7") {185+ t.Errorf("%s: %v %q", arg, err, out)186+ }187+ }188+}@@ -0,0 +1,43 @@
1+package main2+3+import (4+ "fmt"5+ "runtime"6+ "runtime/debug"7+)8+9+// version is the release this binary was built as, set by make dist10+// with -ldflags "-X main.version=v1.2.3". Empty in other builds.11+var version string12+13+// buildVersion is what 012 version prints: the stamped release, else the14+// module version go install records (v1.2.3, or (devel) in a checkout),15+// with the VCS revision when the build has one.16+func buildVersion() string {17+ v, rev := version, ""18+ if info, ok := debug.ReadBuildInfo(); ok {19+ if v == "" {20+ v = info.Main.Version21+ }22+ for _, s := range info.Settings {23+ if s.Key == "vcs.revision" {24+ rev = s.Value25+ }26+ }27+ }28+ if v == "" {29+ v = "(devel)"30+ }31+ if len(rev) > 12 {32+ rev = rev[:12]33+ }34+ if rev != "" {35+ v += " (" + rev + ")"36+ }37+ return v38+}39+40+func runVersion(e env) error {41+ _, err := fmt.Fprintf(e.stdout, "012 %s %s %s/%s\n", buildVersion(), runtime.Version(), runtime.GOOS, runtime.GOARCH)42+ return err43+}@@ -16,5 +16,6 @@ in [CLAUDE.md](../../CLAUDE.md), then:
1616 | [Testing](testing.md) | Unit, end-to-end through libghostty, golden screens, the oracle, docs checks, demos |1717 | [Bounds of support](limits.md) | Measured bounds and known bottlenecks |1818 | [Observability](observability.md) | Event logs, OTLP export, DuckDB queries, the local telemetry stack |19+| [Releasing](releasing.md) | The release checklist and `make dist` |1920 2021 Plans are in the [roadmap](../../ROADMAP.md).@@ -0,0 +1,62 @@
1+---2+title: "Releasing"3+sidebar_position: 84+---5+6+# Releasing7+8+A release is an annotated version tag whose message is the release9+notes, and archives of the binaries built from it on a maintainer's10+machine. The GitHub repository only hosts the code: nothing builds or11+publishes there, and `make dist` uploads nothing.12+13+## Checklist14+15+1. **`make check`** passes on the commit to be tagged (see16+ [Testing](testing.md)), with the golden screens reviewed in the17+ gallery.18+2. **Stress** (optional for small releases): `make stress` on a quiet19+ machine, then `make stress-report`, which compares the run with the20+ last release's and exits non-zero on a regression past the threshold21+ (see [Observability](observability.md#stress-runs)).22+ Record the run on the release commit so the next release compares23+ against it.24+3. **XLSX in spreadsheet apps.** Export a workbook that uses what the25+ release touches (formats, notes, frozen panes, filters, validation,26+ conditional formats, charts' data) with File > Export, and open it in27+ Excel, LibreOffice Calc and Google Sheets: it opens without a repair28+ prompt, and values, formulas and formats read as they did in 012. The29+ automated checks read XLSX with excelize and 012's own reader only.30+4. **Tag** with the release notes as the message, what changed since the31+ previous tag for a user, with the install line last:32+33+ ```sh34+ git tag -a v1.2.3 # the editor opens for the notes35+ git push origin v1.2.336+ ```37+38+ The Go module proxy picks the tag up, so `go install39+ github.com/FelineStateMachine/012/cmd/012@v1.2.3` works from then on.40+5. **Binaries**: `make dist VERSION=v1.2.3` on the tagged commit.41+42+## make dist43+44+`make dist VERSION=v1.2.3` (`scripts/dist.sh`) cross-compiles 012 with45+`CGO_ENABLED=0` and `-trimpath` for macOS, Linux and Windows on amd6446+and arm64, stamping the version with `-ldflags -X main.version=...`, so47+`012 version` prints it. Each platform gets an archive in `dist/`48+(gitignored) holding the binary, `LICENSE`, `NOTICE` and `README.md`:49+50+```51+dist/012_1.2.3_darwin_arm64.tar.gz52+dist/012_1.2.3_linux_amd64.tar.gz53+dist/012_1.2.3_windows_amd64.zip54+...55+dist/SHA256SUMS56+```57+58+`PLATFORMS="darwin/arm64 linux/amd64"` narrows the list. The script59+refuses a version that isn't `vMAJOR.MINOR.PATCH` (with an optional60+`-suffix`) or that is tagged at another commit than the one checked61+out, and warns when the tree has uncommitted changes. The archives and62+`SHA256SUMS` are what a release attaches, wherever it is published.@@ -0,0 +1,63 @@
1+2+# dist.sh - what `make dist VERSION=v1.2.3` does: cross-compile 012 as3+# pure Go for each platform into dist/, stamped with the version, one4+# archive per platform (tar.gz, zip for Windows) and a SHA256SUMS file.5+# Nothing is uploaded. See docs/contributing/releasing.md.6+#7+# VERSION=v1.2.3 required, a semantic version tag8+# PLATFORMS="darwin/arm64 linux/amd64" narrow the list9+set -euo pipefail10+11+root=$(cd "$(dirname "$0")/.." && pwd)12+cd "$root"13+14+version=${VERSION:-}15+if ! [[ $version =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then16+ echo "dist: VERSION must be a version like v1.2.3 (got '${version}')" >&217+ exit 118+fi19+if [ -n "$(git status --porcelain --untracked-files=no 2>/dev/null)" ]; then20+ echo "dist: warning: the working tree has uncommitted changes; the binaries include them" >&221+fi22+if tag=$(git rev-parse -q --verify "refs/tags/$version^{commit}" 2>/dev/null) && [ "$tag" != "$(git rev-parse HEAD)" ]; then23+ echo "dist: $version is tagged at another commit; check out the tag first" >&224+ exit 125+fi26+platforms=${PLATFORMS:-"darwin/amd64 darwin/arm64 linux/amd64 linux/arm64 windows/amd64 windows/arm64"}27+28+out="$root/dist"29+rm -rf "$out"30+mkdir -p "$out"31+32+for p in $platforms; do33+ goos=${p%/*}34+ goarch=${p#*/}35+ name="012_${version#v}_${goos}_${goarch}"36+ dir="$out/$name"37+ exe=01238+ if [ "$goos" = windows ]; then39+ exe=012.exe40+ fi41+ mkdir -p "$dir"42+ echo "dist: $name"43+ CGO_ENABLED=0 GOOS=$goos GOARCH=$goarch go build -trimpath \44+ -ldflags "-s -w -X main.version=$version" -o "$dir/$exe" ./cmd/01245+ cp LICENSE NOTICE README.md "$dir/"46+ if [ "$goos" = windows ]; then47+ (cd "$out" && zip -qrX "$name.zip" "$name")48+ else49+ tar -C "$out" -czf "$out/$name.tar.gz" "$name"50+ fi51+ rm -rf "$dir"52+done53+54+(55+ cd "$out"56+ if command -v sha256sum >/dev/null 2>&1; then57+ sha256sum -- 012_* >SHA256SUMS58+ else59+ shasum -a 256 -- 012_* >SHA256SUMS60+ fi61+)62+echo "dist: $(find "$out" -type f | wc -l | tr -d ' ') files in dist/"63+cat "$out/SHA256SUMS"