Files
bsdaily/cmd/bsdaily/main.go
T
sneak 2cd390e62e Stamp the git tag or short commit into the binary (closes #4)
A plain `docker build .` now stamps the version into bsdaily: the
VERSION build argument when one is given, otherwise `git describe
--tags --always` of the .git in the build context. The build fails if
the context carries .git and no version comes out. A host `make` build
stamps the same `git describe` value, or dev when it yields nothing.
bsdaily logs the version on the first line of every run and prints it
with --version.

The new .dockerignore is the canonical copy, which keeps .git/config
out of the build context, plus this repo's host-built artifacts.
script/docker is replaced with the canonical copy, which passes the
version it derives on the host.

Model: opus-5-5
2026-10-02 08:38:33 +00:00

93 lines
2.6 KiB
Go

package main
import (
"fmt"
"log/slog"
"os"
"time"
"git.eeqj.de/sneak/bsdaily/internal/bsdaily"
"github.com/spf13/cobra"
)
// Version is the git tag or short commit, set at link time with -X by the
// Dockerfile and the Makefile, logged on the first line of every run and
// printed by --version. Builds that do not set it report dev.
var Version = "dev"
func main() {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
slog.SetDefault(logger)
var dateFlag string
var fromFlag string
var toFlag string
rootCmd := &cobra.Command{
Use: "bsdaily",
Short: "Extract a single day's data from the latest daily snapshot",
Version: Version,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
slog.Info("starting", "version", Version)
hasDate := dateFlag != ""
hasFrom := fromFlag != ""
hasTo := toFlag != ""
// Validate mutual exclusivity
if hasDate && (hasFrom || hasTo) {
return fmt.Errorf("--date and --from/--to are mutually exclusive")
}
if hasFrom != hasTo {
if hasFrom {
return fmt.Errorf("--from requires --to")
}
return fmt.Errorf("--to requires --from")
}
var targetDates []time.Time
if hasDate {
t, err := time.Parse("2006-01-02", dateFlag)
if err != nil {
return fmt.Errorf("invalid --date %q (expected YYYY-MM-DD): %w", dateFlag, err)
}
targetDates = []time.Time{t}
} else if hasFrom {
from, err := time.Parse("2006-01-02", fromFlag)
if err != nil {
return fmt.Errorf("invalid --from %q (expected YYYY-MM-DD): %w", fromFlag, err)
}
to, err := time.Parse("2006-01-02", toFlag)
if err != nil {
return fmt.Errorf("invalid --to %q (expected YYYY-MM-DD): %w", toFlag, err)
}
if from.After(to) {
return fmt.Errorf("--from %s is after --to %s", fromFlag, toFlag)
}
for d := from; !d.After(to); d = d.AddDate(0, 0, 1) {
targetDates = append(targetDates, d)
}
}
// else: targetDates remains nil → Run() defaults to snapshot date minus one
if err := bsdaily.Run(targetDates); err != nil {
return err
}
slog.Info("completed successfully")
return nil
},
}
rootCmd.Flags().StringVarP(&dateFlag, "date", "d", "", "target date to extract (YYYY-MM-DD); defaults to snapshot date minus one day")
rootCmd.Flags().StringVar(&fromFlag, "from", "", "start of date range to extract (YYYY-MM-DD, inclusive); use with --to")
rootCmd.Flags().StringVar(&toFlag, "to", "", "end of date range to extract (YYYY-MM-DD, inclusive); use with --from")
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}