Skip to content

Commit c7eded6

Browse files
committed
Add --no-cache flag
1 parent cc5ba18 commit c7eded6

File tree

8 files changed

+313
-17
lines changed

8 files changed

+313
-17
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ This function is implemented in the /build endpoint, and supports both POST and
241241
POST
242242

243243
The POST method expects the build request in the request's body as a JSON object.
244+
The optional "nocache" field can be set to true to force a rebuild bypassing the cache.
244245

245246
Example
246247

@@ -269,13 +270,29 @@ Example
269270
}
270271
}
271272

273+
Force a rebuild bypassing the cache:
274+
275+
curl -X POST http://localhost:8000/build -d \
276+
'{
277+
"k6":"v1.4.0",
278+
"dependencies":[
279+
{
280+
"name":"k6/x/kubernetes",
281+
"constraints":">v0.8.0"
282+
}
283+
],
284+
"platform":"linux/amd64",
285+
"nocache":true
286+
}' | jq .
287+
272288
GET
273289

274290
The GET method expects the build requests in the query parameters:
275291
- platform: platform to build the binary for (e.g. linux/arm64). This is required
276292
- k6: the k6 version constrains (e.g. k6=v1.2.0)
277293
- dep: a dependency in the form name:version (e.g. dep=k6/x/faker:v0.4.0).
278294
Multple dependencies can be defined in a request.
295+
- nocache: set to "true" to force a rebuild bypassing the cache (e.g. nocache=true)
279296

280297
Example
281298

@@ -294,6 +311,10 @@ Example
294311
}
295312
}
296313

314+
Force a rebuild bypassing the cache:
315+
316+
curl -X GET "http://localhost:8000/build?platform=linux/amd64&k6=v1.4.0&dep=k6/x/kubernetes:>v0.8.0&nocache=true" | jq .
317+
297318
Caching
298319

299320
The GET method can be used to allow caching the build results. This method returns the ETag header with the

cmd/server/server.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This function is implemented in the /build endpoint, and supports both POST and
4444
POST
4545
4646
The POST method expects the build request in the request's body as a JSON object.
47+
The optional "nocache" field can be set to true to force a rebuild bypassing the cache.
4748
4849
Example
4950
@@ -72,13 +73,29 @@ Example
7273
}
7374
}
7475
76+
Force a rebuild bypassing the cache:
77+
78+
curl -X POST http://localhost:8000/build -d \
79+
'{
80+
"k6":"v1.4.0",
81+
"dependencies":[
82+
{
83+
"name":"k6/x/kubernetes",
84+
"constraints":">v0.8.0"
85+
}
86+
],
87+
"platform":"linux/amd64",
88+
"nocache":true
89+
}' | jq .
90+
7591
GET
7692
7793
The GET method expects the build requests in the query parameters:
7894
- platform: platform to build the binary for (e.g. linux/arm64). This is required
7995
- k6: the k6 version constrains (e.g. k6=v1.2.0)
8096
- dep: a dependency in the form name:version (e.g. dep=k6/x/faker:v0.4.0).
8197
Multple dependencies can be defined in a request.
98+
- nocache: set to "true" to force a rebuild bypassing the cache (e.g. nocache=true)
8299
83100
Example
84101
@@ -97,6 +114,10 @@ Example
97114
}
98115
}
99116
117+
Force a rebuild bypassing the cache:
118+
119+
curl -X GET "http://localhost:8000/build?platform=linux/amd64&k6=v1.4.0&dep=k6/x/kubernetes:>v0.8.0&nocache=true" | jq .
120+
100121
Caching
101122
102123
The GET method can be used to allow caching the build results. This method returns the ETag header with the

pkg/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type BuildRequest struct {
2828
K6Constrains string `json:"k6,omitempty"`
2929
Dependencies []k6build.Dependency `json:"dependencies,omitempty"`
3030
Platform string `json:"platform,omitempty"`
31+
NoCache bool `json:"nocache,omitempty"`
3132
}
3233

3334
// BuildResponse defines the response for a BuildRequest

pkg/api/context.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package api
2+
3+
import "context"
4+
5+
type contextKey int
6+
7+
const (
8+
noCacheKey contextKey = iota
9+
)
10+
11+
// WithNoCache returns a context with the nocache flag set
12+
func WithNoCache(ctx context.Context, noCache bool) context.Context {
13+
return context.WithValue(ctx, noCacheKey, noCache)
14+
}
15+
16+
// NoCache returns the nocache flag from the context
17+
func NoCache(ctx context.Context) bool {
18+
v, _ := ctx.Value(noCacheKey).(bool)
19+
return v
20+
}

pkg/api/context_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"testing"
6+
)
7+
8+
func TestNoCache(t *testing.T) {
9+
t.Parallel()
10+
11+
testCases := []struct {
12+
title string
13+
setVal *bool // nil means don't set
14+
expected bool
15+
}{
16+
{
17+
title: "not set returns false",
18+
setVal: nil,
19+
expected: false,
20+
},
21+
{
22+
title: "set to true returns true",
23+
setVal: boolPtr(true),
24+
expected: true,
25+
},
26+
{
27+
title: "set to false returns false",
28+
setVal: boolPtr(false),
29+
expected: false,
30+
},
31+
}
32+
33+
for _, tc := range testCases {
34+
tc := tc
35+
t.Run(tc.title, func(t *testing.T) {
36+
t.Parallel()
37+
38+
ctx := context.Background()
39+
if tc.setVal != nil {
40+
ctx = WithNoCache(ctx, *tc.setVal)
41+
}
42+
got := NoCache(ctx)
43+
if got != tc.expected {
44+
t.Fatalf("expected %v, got %v", tc.expected, got)
45+
}
46+
})
47+
}
48+
}
49+
50+
func boolPtr(b bool) *bool {
51+
return &b
52+
}

pkg/builder/builder.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"time"
1717

1818
"github.com/grafana/k6build"
19+
"github.com/grafana/k6build/pkg/api"
1920
"github.com/grafana/k6build/pkg/catalog"
2021
"github.com/grafana/k6build/pkg/lock"
2122
"github.com/grafana/k6build/pkg/store"
@@ -171,23 +172,27 @@ func (b *Builder) Build( //nolint:funlen
171172
// Try to get the object, if not found, try to acquire a build lock.
172173
// If the build lock is not acquired, assume some other builder is building the binary.
173174
// Sleep and retry.
175+
// If nocache is set, skip the cache lookup and go straight to building.
176+
noCache := api.NoCache(ctx)
174177
var artifactObject store.Object
175178
for {
176-
artifactObject, err = b.store.Get(ctx, id)
177-
if err == nil {
178-
b.metrics.storeHitsCounter.Inc()
179-
180-
return k6build.Artifact{
181-
ID: id,
182-
Checksum: artifactObject.Checksum,
183-
URL: artifactObject.URL,
184-
Dependencies: resolvedVersions(resolved),
185-
Platform: platform,
186-
}, nil
187-
}
188-
189-
if !errors.Is(err, store.ErrObjectNotFound) {
190-
return k6build.Artifact{}, k6build.NewWrappedError(k6build.ErrAccessingArtifact, err)
179+
if !noCache {
180+
artifactObject, err = b.store.Get(ctx, id)
181+
if err == nil {
182+
b.metrics.storeHitsCounter.Inc()
183+
184+
return k6build.Artifact{
185+
ID: id,
186+
Checksum: artifactObject.Checksum,
187+
URL: artifactObject.URL,
188+
Dependencies: resolvedVersions(resolved),
189+
Platform: platform,
190+
}, nil
191+
}
192+
193+
if !errors.Is(err, store.ErrObjectNotFound) {
194+
return k6build.Artifact{}, k6build.NewWrappedError(k6build.ErrAccessingArtifact, err)
195+
}
191196
}
192197

193198
acquired, unlock, err := b.lock.Try(ctx, id)

pkg/server/server.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (a *APIServer) BuildPost(w http.ResponseWriter, r *http.Request) {
8080

8181
// BuildGet implements the request handler for the build request using get
8282
// the build arguments
83-
// /build?k6=version&platform=version&dep=name:constrains&dep=name:constrains
83+
// /build?k6=version&platform=version&dep=name:constrains&dep=name:constrains&nocache=true
8484
func (a *APIServer) BuildGet(w http.ResponseWriter, r *http.Request) {
8585
w.Header().Add("Content-Type", "application/json")
8686

@@ -91,6 +91,7 @@ func (a *APIServer) BuildGet(w http.ResponseWriter, r *http.Request) {
9191
name, constraints, _ := strings.Cut(dep, ":")
9292
req.Dependencies = append(req.Dependencies, k6build.Dependency{Name: name, Constraints: constraints})
9393
}
94+
req.NoCache = r.URL.Query().Get("nocache") == "true"
9495

9596
a.processBuildRequest(w, r, req)
9697
}
@@ -100,8 +101,13 @@ func (a *APIServer) processBuildRequest(w http.ResponseWriter, r *http.Request,
100101

101102
resp := api.BuildResponse{}
102103

104+
ctx := r.Context()
105+
if req.NoCache {
106+
ctx = api.WithNoCache(ctx, true)
107+
}
108+
103109
artifact, err := a.srv.Build(
104-
r.Context(),
110+
ctx,
105111
req.Platform,
106112
req.K6Constrains,
107113
req.Dependencies,

0 commit comments

Comments
 (0)