Skip to content

Commit 74fd411

Browse files
authored
inject preview deployments into nested stacks (#70)
1 parent eaf5a40 commit 74fd411

107 files changed

Lines changed: 3686 additions & 152 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/assets/Operator-Design.svg

Lines changed: 2 additions & 2 deletions
Loading

README.md

Lines changed: 183 additions & 78 deletions
Large diffs are not rendered by default.

go.mod

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ module github.com/0xSplits/kayron
22

33
go 1.24.0
44

5-
toolchain go1.24.6
6-
75
require (
86
github.com/0xSplits/otelgo v0.1.2
97
github.com/0xSplits/roghfs v0.1.0
10-
github.com/0xSplits/workit v0.6.0
8+
github.com/0xSplits/workit v0.7.0
119
github.com/aws/aws-sdk-go-v2 v1.39.0
1210
github.com/aws/aws-sdk-go-v2/config v1.31.8
1311
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.66.2
@@ -18,6 +16,7 @@ require (
1816
github.com/distribution/reference v0.6.0
1917
github.com/goccy/go-yaml v1.18.0
2018
github.com/google/go-cmp v0.7.0
19+
github.com/google/go-containerregistry v0.20.6
2120
github.com/google/go-github/v73 v73.0.0
2221
github.com/gorilla/mux v1.8.1
2322
github.com/joho/godotenv v1.5.1
@@ -58,10 +57,8 @@ require (
5857
github.com/docker/docker-credential-helpers v0.9.3 // indirect
5958
github.com/go-logr/logr v1.4.3 // indirect
6059
github.com/go-logr/stdr v1.2.2 // indirect
61-
github.com/google/go-containerregistry v0.20.6
6260
github.com/google/go-querystring v1.1.0 // indirect
6361
github.com/google/uuid v1.6.0 // indirect
64-
github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 // indirect
6562
github.com/inconshreveable/mousetrap v1.1.0 // indirect
6663
github.com/klauspost/compress v1.18.0 // indirect
6764
github.com/mitchellh/go-homedir v1.1.0 // indirect
@@ -71,20 +68,20 @@ require (
7168
github.com/pkg/errors v0.9.1 // indirect
7269
github.com/prometheus/client_model v0.6.2 // indirect
7370
github.com/prometheus/common v0.66.1 // indirect
74-
github.com/prometheus/otlptranslator v0.0.2 // indirect
71+
github.com/prometheus/otlptranslator v1.0.0 // indirect
7572
github.com/prometheus/procfs v0.17.0 // indirect
76-
github.com/puzpuzpuz/xsync/v4 v4.1.0 // indirect
73+
github.com/puzpuzpuz/xsync/v4 v4.2.0 // indirect
7774
github.com/sirupsen/logrus v1.9.3 // indirect
7875
github.com/spf13/pflag v1.0.10 // indirect
7976
github.com/vbatts/tar-split v0.12.1 // indirect
80-
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
77+
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
8178
go.opentelemetry.io/otel v1.38.0 // indirect
8279
go.opentelemetry.io/otel/exporters/prometheus v0.60.0 // indirect
8380
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
8481
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
8582
go.opentelemetry.io/otel/trace v1.38.0 // indirect
86-
go.yaml.in/yaml/v2 v2.4.2 // indirect
83+
go.yaml.in/yaml/v2 v2.4.3 // indirect
8784
golang.org/x/sync v0.17.0 // indirect
8885
golang.org/x/sys v0.36.0 // indirect
89-
google.golang.org/protobuf v1.36.8 // indirect
86+
google.golang.org/protobuf v1.36.9 // indirect
9087
)

go.sum

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ github.com/0xSplits/otelgo v0.1.2 h1:QjbUMNNQcUsnkOmZ35bc3Fbhz7u0PA611LYrh4aOpPk
22
github.com/0xSplits/otelgo v0.1.2/go.mod h1:YnmWxWUT7xaMQTF3FBmN8GuvIMafSJ/lYhlyIBlr99w=
33
github.com/0xSplits/roghfs v0.1.0 h1:E3BB8+w+X3g64ezuJ13FssmfNorqy/fx2RGWBFtVifw=
44
github.com/0xSplits/roghfs v0.1.0/go.mod h1:KVlXti9dNWj2YtskpRjZNFqccSKsh5K+UJs73GMXTJs=
5-
github.com/0xSplits/workit v0.6.0 h1:h2LrDdkOTuokSOwt0E3dt8N90fsMsoNd3CCsyI3U0f8=
6-
github.com/0xSplits/workit v0.6.0/go.mod h1:+SQ35oJXLBigYeA1VSrKkJNaX4KBLE+M4PuoBZT1xs0=
5+
github.com/0xSplits/workit v0.7.0 h1:kBa6bJ/9mjUIJYhi+MzBI5kY1iEfSyAYGH+H7wrSMoY=
6+
github.com/0xSplits/workit v0.7.0/go.mod h1:9vuuL6Lr+KfZuOKMihtymd11+8Yq5woBqRqra29gd6U=
77
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
88
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
99
github.com/aws/aws-sdk-go-v2 v1.39.0 h1:xm5WV/2L4emMRmMjHFykqiA4M/ra0DJVSWUkDyBjbg4=
@@ -88,8 +88,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
8888
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
8989
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
9090
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
91-
github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 h1:cLN4IBkmkYZNnk7EAJ0BHIethd+J6LqxFNw5mSiI2bM=
92-
github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
9391
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
9492
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
9593
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
@@ -122,14 +120,14 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
122120
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
123121
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
124122
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
125-
github.com/prometheus/otlptranslator v0.0.2 h1:+1CdeLVrRQ6Psmhnobldo0kTp96Rj80DRXRd5OSnMEQ=
126-
github.com/prometheus/otlptranslator v0.0.2/go.mod h1:P8AwMgdD7XEr6QRUJ2QWLpiAZTgTE2UYgjlu3svompI=
123+
github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos=
124+
github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM=
127125
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
128126
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
129-
github.com/puzpuzpuz/xsync/v4 v4.1.0 h1:x9eHRl4QhZFIPJ17yl4KKW9xLyVWbb3/Yq4SXpjF71U=
130-
github.com/puzpuzpuz/xsync/v4 v4.1.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
131-
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
132-
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
127+
github.com/puzpuzpuz/xsync/v4 v4.2.0 h1:dlxm77dZj2c3rxq0/XNvvUKISAmovoXF4a4qM6Wvkr0=
128+
github.com/puzpuzpuz/xsync/v4 v4.2.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo=
129+
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
130+
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
133131
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
134132
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
135133
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -154,8 +152,8 @@ github.com/xh3b4sd/logger v0.11.1 h1:aTK4ygh7aPv1jq54J8bx+zjH6A8RYdkKAgOZYw867C0
154152
github.com/xh3b4sd/logger v0.11.1/go.mod h1:MC7Dp7RC3tZ182KlvSulGcRQVX/D2l+WlCSGLF1mvO8=
155153
github.com/xh3b4sd/tracer v1.0.0 h1:mr9uYCx/Ry2w1wdJz0V0Kq71/KeF+hUQjbZQJCxm3Zw=
156154
github.com/xh3b4sd/tracer v1.0.0/go.mod h1:nfZeNH5RRfqE6ctQroIfY75b2NRlJHl2g+HP7ddvHrM=
157-
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
158-
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
155+
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
156+
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
159157
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
160158
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
161159
go.opentelemetry.io/otel/exporters/prometheus v0.60.0 h1:cGtQxGvZbnrWdC2GyjZi0PDKVSLWP/Jocix3QWfXtbo=
@@ -170,8 +168,8 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr
170168
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
171169
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
172170
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
173-
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
174-
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
171+
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
172+
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
175173
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
176174
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
177175
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -180,8 +178,8 @@ golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
180178
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
181179
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
182180
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
183-
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
184-
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
181+
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
182+
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
185183
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
186184
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
187185
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

pkg/cache/create.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func (c *Cache) Create(rel release.Slice) error {
2020
"docker", x.Docker.String(),
2121
"github", x.Github.String(),
2222
"deploy", x.Deploy.String(),
23+
"preview", x.Deploy.Preview.String(),
2324
"provider", x.Provider.String(),
2425
)
2526

pkg/cache/object.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,34 @@ type Object struct {
3030
kin kind
3131
}
3232

33+
// Domain returns the hash based testing domain for preview deployments, or an
34+
// empty string for any other main release and non-testing environment.
35+
func (o Object) Domain(env string) string {
36+
// Note that we filter the domain name creation by preview deployments,
37+
// because at the time of writing we do not have any convenient way to tell
38+
// whether this release artifact is exposed to the internet via DNS. Right now
39+
// we only know that for certain in case of preview deployments, because their
40+
// sole purpose is to be exposed to the internet.
41+
42+
if !bool(o.Release.Deploy.Preview) {
43+
return ""
44+
}
45+
46+
return fmt.Sprintf("%s.%s.%s.splits.org",
47+
o.Release.Labels.Hash.Lower(),
48+
49+
// Note that this is a dirty hack to make preview deployments work today for
50+
// existing services that already work using certain incosnistencies between
51+
// repository and domain names. E.g. we have "splits-lite" in Github, but
52+
// use just "lite.testing.splits.org". A better way of doing this would be
53+
// to allow for some kind of domain configuration in the release definition,
54+
// so that we can remove this magical string replacement below.
55+
strings.TrimPrefix(o.Release.Docker.String(), "splits-"),
56+
57+
env,
58+
)
59+
}
60+
3361
func (o Object) Name() string {
3462
if o.kin == Infrastructure {
3563
return o.Release.Github.String()

pkg/cache/previews.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cache
2+
3+
// Previews returns all cached service release artifacts that are defined as
4+
// preview deployments.
5+
func (c *Cache) Previews(doc string) []Object {
6+
{
7+
c.mut.Lock()
8+
defer c.mut.Unlock()
9+
}
10+
11+
var lis []Object
12+
13+
for _, x := range c.ser {
14+
if bool(x.Release.Deploy.Preview) && x.Release.Docker.String() == doc {
15+
lis = append(lis, x)
16+
}
17+
}
18+
19+
return lis
20+
}

pkg/cache/services.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package cache
22

3+
// Services returns all cached service release artifacts, including those of any
4+
// preview deployments.
35
func (c *Cache) Services() []Object {
46
{
57
c.mut.Lock()

pkg/cache/update.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ func (c *Cache) Update(obj Object) {
1212

1313
if obj.kin == Service {
1414
c.ser[obj.ind].Artifact = c.ser[obj.ind].Artifact.Merge(obj.Artifact)
15+
c.ser[obj.ind].Release.Deploy.Preview = obj.Release.Deploy.Preview
1516
}
1617
}

pkg/hash/hash.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package hash
2+
3+
import (
4+
"crypto/sha256"
5+
"encoding/hex"
6+
7+
"golang.org/x/text/cases"
8+
"golang.org/x/text/language"
9+
)
10+
11+
type Hash struct {
12+
// dsh is the dashed prefix version of Upp.
13+
//
14+
// -1D0FD508
15+
//
16+
dsh []byte
17+
// low is the lower case version of Upp.
18+
//
19+
// 1d0fd508
20+
//
21+
low []byte
22+
// upp is the upper case version of this hash.
23+
//
24+
// 1D0FD508
25+
//
26+
upp []byte
27+
}
28+
29+
func New(str string) Hash {
30+
var hsh string
31+
{
32+
hsh = newHsh(str)
33+
}
34+
35+
var low string
36+
var upp string
37+
{
38+
low = cases.Lower(language.English).String(hsh)
39+
upp = cases.Upper(language.English).String(hsh)
40+
}
41+
42+
return Hash{
43+
dsh: []byte("-" + upp),
44+
low: []byte(low),
45+
upp: []byte(upp),
46+
}
47+
}
48+
49+
func (h Hash) Dashed() string {
50+
return string(h.dsh)
51+
}
52+
53+
func (h Hash) Empty() bool {
54+
return h.dsh == nil && h.low == nil && h.upp == nil
55+
}
56+
57+
func (h Hash) Lower() string {
58+
return string(h.low)
59+
}
60+
61+
func (h Hash) Upper() string {
62+
return string(h.upp)
63+
}
64+
65+
func newHsh(str string) string {
66+
sum := sha256.Sum256([]byte(str))
67+
enc := hex.EncodeToString(sum[:])
68+
69+
return enc[:8]
70+
}

0 commit comments

Comments
 (0)