Skip to content

Commit 51c7446

Browse files
authored
chore: add Go template dependency sync command (#4)
Add a command for keeping the embedded Go template dependency files in sync with the generated Go example. The command copies examples/simple-go/go.mod and go.sum back to the corresponding template files and supports --check for CI drift detection. Refs hatchet-dev/hatchet#4107.
1 parent f9a2c29 commit 51c7446

2 files changed

Lines changed: 99 additions & 0 deletions

File tree

.github/workflows/validate.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ jobs:
1616
with:
1717
go-version-file: go.mod
1818

19+
- name: Go template dependencies are in sync
20+
run: go run ./cmd/sync-go-template-deps --check
21+
1922
- name: Generated examples are up to date
2023
run: go run ./cmd/generate-examples --check
2124

cmd/sync-go-template-deps/main.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Command sync-go-template-deps keeps the embedded Go template dependency files
2+
// in sync with the generated Go example.
3+
//
4+
// The Go template cannot hold a real go.mod, since it sits under the embedded
5+
// template tree, so it uses go.mod.embed and go.sum. This command keeps those
6+
// identical to examples/simple-go/go.mod and go.sum. It does not parse versions
7+
// and does not run go commands.
8+
//
9+
// Usage:
10+
//
11+
// go run ./cmd/sync-go-template-deps
12+
// go run ./cmd/sync-go-template-deps --check
13+
//
14+
// Run it from the repository root. Paths are relative to the working directory.
15+
package main
16+
17+
import (
18+
"bytes"
19+
"flag"
20+
"fmt"
21+
"os"
22+
"strings"
23+
)
24+
25+
type syncPair struct {
26+
src string
27+
dst string
28+
}
29+
30+
var pairs = []syncPair{
31+
{src: "examples/simple-go/go.mod", dst: "templates/go/go.mod.embed"},
32+
{src: "examples/simple-go/go.sum", dst: "templates/go/go.sum"},
33+
}
34+
35+
func main() {
36+
check := flag.Bool("check", false, "verify the template files match the generated Go example instead of writing them")
37+
flag.Parse()
38+
39+
if err := run(*check); err != nil {
40+
fmt.Fprintln(os.Stderr, "sync-go-template-deps:", err)
41+
os.Exit(1)
42+
}
43+
}
44+
45+
func run(check bool) error {
46+
if check {
47+
return runCheck()
48+
}
49+
return runSync()
50+
}
51+
52+
// runSync writes each example file onto its template counterpart, preserving
53+
// the destination's existing file mode.
54+
func runSync() error {
55+
for _, p := range pairs {
56+
content, err := os.ReadFile(p.src)
57+
if err != nil {
58+
return fmt.Errorf("reading %s: %w", p.src, err)
59+
}
60+
61+
mode := os.FileMode(0644)
62+
if info, err := os.Stat(p.dst); err == nil {
63+
mode = info.Mode().Perm()
64+
}
65+
66+
if err := os.WriteFile(p.dst, content, mode); err != nil {
67+
return fmt.Errorf("writing %s: %w", p.dst, err)
68+
}
69+
}
70+
return nil
71+
}
72+
73+
// runCheck reports any template file that does not match its example
74+
// counterpart byte-for-byte, leaving the working tree untouched.
75+
func runCheck() error {
76+
var stale []string
77+
for _, p := range pairs {
78+
srcContent, err := os.ReadFile(p.src)
79+
if err != nil {
80+
return fmt.Errorf("reading %s: %w", p.src, err)
81+
}
82+
dstContent, err := os.ReadFile(p.dst)
83+
if err != nil {
84+
return fmt.Errorf("reading %s: %w", p.dst, err)
85+
}
86+
if !bytes.Equal(srcContent, dstContent) {
87+
stale = append(stale, fmt.Sprintf("%s is out of sync with %s", p.dst, p.src))
88+
}
89+
}
90+
91+
if len(stale) > 0 {
92+
return fmt.Errorf("Go template dependency files are out of sync:\n %s\nrun `go run ./cmd/sync-go-template-deps` to update",
93+
strings.Join(stale, "\n "))
94+
}
95+
return nil
96+
}

0 commit comments

Comments
 (0)