Skip to content

Commit d2bf920

Browse files
committed
Add validate_dependencies flag to pipeline upload
Add test for pipeline upload params
1 parent 3634750 commit d2bf920

File tree

4 files changed

+86
-17
lines changed

4 files changed

+86
-17
lines changed

agent/pipeline_uploader_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package agent_test
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"fmt"
78
"net/http"
@@ -17,6 +18,66 @@ import (
1718
"github.com/stretchr/testify/assert"
1819
)
1920

21+
func TestPipelineUploadParameters(t *testing.T) {
22+
t.Parallel()
23+
24+
ctx := context.Background()
25+
l := logger.NewBuffer()
26+
27+
jobID := api.NewUUID()
28+
stepUploadUUID := api.NewUUID()
29+
pipelineStr := `---
30+
steps:
31+
- command: "echo Hello"`
32+
33+
pipeline, err := pipeline.Parse(strings.NewReader(pipelineStr))
34+
assert.NoError(t, err)
35+
36+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
37+
switch req.URL.Path {
38+
case fmt.Sprintf("/jobs/%s/pipelines", jobID):
39+
var pipelineUpload map[string]any
40+
if err := json.NewDecoder(req.Body).Decode(&pipelineUpload); err != nil {
41+
http.Error(rw, "Error decoding pipeline", http.StatusInternalServerError)
42+
return
43+
}
44+
assert.Equal(t, pipelineUpload["validate_dependencies"], true)
45+
assert.Equal(t, pipelineUpload["replace"], true)
46+
47+
if req.Method == "POST" {
48+
rw.Header().Add("Location", fmt.Sprintf("/jobs/%s/pipelines/%s", jobID, stepUploadUUID))
49+
rw.WriteHeader(http.StatusAccepted)
50+
return
51+
}
52+
case fmt.Sprintf("/jobs/%s/pipelines/%s", jobID, stepUploadUUID):
53+
if req.Method == "GET" {
54+
_, _ = fmt.Fprintf(rw, `{"state": "%s"}`, "applied")
55+
return
56+
}
57+
}
58+
t.Errorf("Unknown endpoint %s %s", req.Method, req.URL.Path)
59+
http.Error(rw, "Not found", http.StatusNotFound)
60+
}))
61+
defer server.Close()
62+
63+
uploader := &agent.PipelineUploader{
64+
Client: api.NewClient(logger.Discard, api.Config{
65+
Endpoint: server.URL,
66+
Token: "llamas",
67+
}),
68+
JobID: jobID,
69+
Change: &api.PipelineChange{
70+
UUID: stepUploadUUID,
71+
Pipeline: pipeline,
72+
Replace: true,
73+
ValidateDependencies: true,
74+
},
75+
}
76+
77+
err = uploader.Upload(ctx, l)
78+
assert.NoError(t, err)
79+
}
80+
2081
func TestAsyncPipelineUpload(t *testing.T) {
2182
t.Parallel()
2283

api/pipelines.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import (
99
type PipelineChange struct {
1010
// UUID identifies this pipeline change. We keep this constant during
1111
// retry loops so that work is not repeated on the API server
12-
UUID string `json:"uuid"`
13-
Pipeline any `json:"pipeline"`
14-
Replace bool `json:"replace,omitempty"`
12+
UUID string `json:"uuid"`
13+
Pipeline any `json:"pipeline"`
14+
Replace bool `json:"replace,omitempty"`
15+
ValidateDependencies bool `json:"validate_dependencies,omitempty"`
1516
}
1617

1718
type PipelineUploadStatus struct {

clicommand/pipeline_upload.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,15 @@ type PipelineUploadConfig struct {
7474
GlobalConfig
7575
APIConfig
7676

77-
FilePath string `cli:"arg:0" label:"upload paths"`
78-
Replace bool `cli:"replace"`
79-
Job string `cli:"job"` // required, but not in dry-run mode
80-
DryRun bool `cli:"dry-run"`
81-
DryRunFormat string `cli:"format"`
82-
NoInterpolation bool `cli:"no-interpolation"`
83-
RedactedVars []string `cli:"redacted-vars" normalize:"list"`
84-
RejectSecrets bool `cli:"reject-secrets"`
77+
FilePath string `cli:"arg:0" label:"upload paths"`
78+
Replace bool `cli:"replace"`
79+
Job string `cli:"job"` // required, but not in dry-run mode
80+
DryRun bool `cli:"dry-run"`
81+
DryRunFormat string `cli:"format"`
82+
NoInterpolation bool `cli:"no-interpolation"`
83+
RedactedVars []string `cli:"redacted-vars" normalize:"list"`
84+
RejectSecrets bool `cli:"reject-secrets"`
85+
ValidateDependencies bool `cli:"validate-dependencies"`
8586

8687
// Used for if_changed processing
8788
ApplyIfChanged bool `cli:"apply-if-changed"`
@@ -142,7 +143,11 @@ var PipelineUploadCommand = cli.Command{
142143
Value: "origin/main",
143144
EnvVar: "BUILDKITE_GIT_DIFF_BASE,BUILDKITE_PULL_REQUEST_BASE_BRANCH",
144145
},
145-
146+
cli.BoolFlag{
147+
Name: "validate-dependencies",
148+
Usage: "When true, validates the dependencies of each step when uploading.",
149+
EnvVar: "BUILDKITE_PIPELINE_VALIDATE_DEPENDENCIES",
150+
},
146151
// Note: changes to these environment variables need to be reflected in the environment created
147152
// in the job runner. At the momenet, that's at agent/job_runner.go:500-507
148153
cli.StringFlag{
@@ -381,9 +386,10 @@ var PipelineUploadCommand = cli.Command{
381386
Client: api.NewClient(l, loadAPIClientConfig(cfg, "AgentAccessToken")),
382387
JobID: cfg.Job,
383388
Change: &api.PipelineChange{
384-
UUID: api.NewUUID(),
385-
Replace: cfg.Replace,
386-
Pipeline: result,
389+
UUID: api.NewUUID(),
390+
Replace: cfg.Replace,
391+
Pipeline: result,
392+
ValidateDependencies: cfg.ValidateDependencies,
387393
},
388394
RetrySleepFunc: time.Sleep,
389395
}

clicommand/pipeline_upload_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ func TestSearchForSecrets(t *testing.T) {
1818
t.Parallel()
1919

2020
cfg := &PipelineUploadConfig{
21-
RedactedVars: []string{"SEKRET", "SSH_KEY"},
22-
RejectSecrets: true,
21+
RedactedVars: []string{"SEKRET", "SSH_KEY"},
22+
RejectSecrets: true,
23+
ValidateDependencies: false,
2324
}
2425

2526
plainPipeline := &pipeline.Pipeline{

0 commit comments

Comments
 (0)