From 7479a5bafb5cac80d8f6c4abd7e4705cd15b7a0d Mon Sep 17 00:00:00 2001 From: Kevin Tang <73975146+vt128@users.noreply.github.com> Date: Mon, 22 Jun 2026 14:21:29 +0800 Subject: [PATCH] [build] embed IANA tzdata so named time zones work in minimal images (STAR-57) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit starcli's time module resolves named zones (parse_time location=, in_location, is_valid_timezone) via time.LoadLocation, which needs the IANA tz database. The binary relied on the host's /usr/share/zoneinfo — fine on the ubuntu Docker image, but a slim binary or a scratch/distroless/alpine image has no tz data, so named zones would fail there. With v0.2 heading toward goreleaser binaries and minimal images, embed the database via `import _ "time/tzdata"` so the CLI is self-contained and "runs anywhere". Proof (linux/amd64 static binary in plain alpine, which has no zoneinfo): with the import -> is_valid_timezone("America/New_York") == True without it -> == False Cost: +400 KiB stripped (32.8 -> 33.2 MB), negligible against the existing size. - main.go: blank import of time/tzdata with the rationale. - e2e: two golden cases (is_valid_timezone + in_location conversion) guard that named zones keep resolving through the real binary. Full -race green; Docker golang:1.25 floor green; gofmt/vet clean. --- e2e/e2e_test.go | 4 ++++ main.go | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 64f9554..15c6410 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -86,6 +86,10 @@ func TestGolden(t *testing.T) { // --check validates without running: {name: "check valid does not run", args: []string{"--check", "-c", `print("RAN")`}, notOut: "RAN", wantExit: 0}, {name: "check invalid is non-zero", args: []string{"--check", "-c", `x =`}, wantExit: anyNonZero}, + // named time zones resolve via the embedded IANA tzdata (no host + // /usr/share/zoneinfo needed — see main.go's time/tzdata import): + {name: "named timezone is valid", args: []string{"-c", `load("time","is_valid_timezone"); print(is_valid_timezone("America/New_York"))`}, wantOut: "True\n", wantExit: 0}, + {name: "named timezone converts", args: []string{"-c", `load("time","parse_time"); print(parse_time("2021-03-22T12:00:00Z").in_location("America/New_York").hour)`}, wantOut: "8\n", wantExit: 0}, } for _, c := range cases { diff --git a/main.go b/main.go index fad87c9..d4eed8f 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,12 @@ package main import ( "os" + // Embed the IANA time-zone database into the binary so named zones + // (time.parse_time location=, in_location, is_valid_timezone) resolve even + // when the host has no /usr/share/zoneinfo — i.e. minimal/scratch/distroless + // containers and slimmed binaries. Costs ~450 KB; keeps the CLI portable + // ("runs anywhere") instead of depending on host tz data. + _ "time/tzdata" "bitbucket.org/neiku/hlog" "bitbucket.org/neiku/winornot"