Merge pull request #141 from sgotti/jsonnet_ctx
config: provide jsonnet context top level argument
This commit is contained in:
commit
ac1b0dcb73
|
@ -20,6 +20,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
itypes "agola.io/agola/internal/services/types"
|
||||
"agola.io/agola/internal/util"
|
||||
"agola.io/agola/services/types"
|
||||
|
||||
|
@ -645,11 +646,28 @@ func (r *Run) Task(taskName string) *Task {
|
|||
|
||||
var DefaultConfig = Config{}
|
||||
|
||||
func ParseConfig(configData []byte, format ConfigFormat) (*Config, error) {
|
||||
// ConfigContext is the context to pass to the config generator. Fields are not marked as omitempty since
|
||||
// we want to provide all of them with empty value if not existing in such context
|
||||
// (i.e. pull_request_id will be an empty string when not a pull request)
|
||||
type ConfigContext struct {
|
||||
RefType itypes.RunRefType `json:"ref_type"`
|
||||
Ref string `json:"ref"`
|
||||
Branch string `json:"branch"`
|
||||
Tag string `json:"tag"`
|
||||
PullRequestID string `json:"pull_request_id"`
|
||||
CommitSHA string `json:"commit_sha"`
|
||||
}
|
||||
|
||||
func ParseConfig(configData []byte, format ConfigFormat, configContext *ConfigContext) (*Config, error) {
|
||||
// Generate json from jsonnet
|
||||
if format == ConfigFormatJsonnet {
|
||||
// TODO(sgotti) support custom import files inside the configdir ???
|
||||
vm := jsonnet.MakeVM()
|
||||
cj, err := json.Marshal(configContext)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("failed to marshal config context: %w", err)
|
||||
}
|
||||
vm.TLACode("ctx", string(cj))
|
||||
out, err := vm.EvaluateSnippet("", string(configData))
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("failed to evaluate jsonnet config: %w", err)
|
||||
|
|
|
@ -58,7 +58,7 @@ func TestParseConfig(t *testing.T) {
|
|||
runs:
|
||||
- name: run01
|
||||
tasks:
|
||||
-
|
||||
-
|
||||
`,
|
||||
err: fmt.Errorf(`run "run01": task at index 0 is empty`),
|
||||
},
|
||||
|
@ -203,7 +203,7 @@ func TestParseConfig(t *testing.T) {
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if _, err := ParseConfig([]byte(tt.in), ConfigFormatJSON); err != nil {
|
||||
if _, err := ParseConfig([]byte(tt.in), ConfigFormatJSON, &ConfigContext{}); err != nil {
|
||||
if tt.err == nil {
|
||||
t.Fatalf("got error: %v, expected no error", err)
|
||||
}
|
||||
|
@ -593,7 +593,7 @@ func TestParseOutput(t *testing.T) {
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
out, err := ParseConfig([]byte(tt.in), ConfigFormatJSON)
|
||||
out, err := ParseConfig([]byte(tt.in), ConfigFormatJSON, &ConfigContext{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
|
|
@ -495,7 +495,17 @@ func (h *ActionHandler) CreateRuns(ctx context.Context, req *CreateRunRequest) e
|
|||
configFormat = config.ConfigFormatJSON
|
||||
|
||||
}
|
||||
config, err := config.ParseConfig([]byte(data), configFormat)
|
||||
|
||||
configContext := &config.ConfigContext{
|
||||
RefType: req.RefType,
|
||||
Ref: req.Ref,
|
||||
Branch: req.Branch,
|
||||
Tag: req.Tag,
|
||||
PullRequestID: req.PullRequestID,
|
||||
CommitSHA: req.CommitSHA,
|
||||
}
|
||||
|
||||
config, err := config.ParseConfig([]byte(data), configFormat, configContext)
|
||||
if err != nil {
|
||||
h.log.Errorf("failed to parse config: %+v", err)
|
||||
|
||||
|
|
|
@ -1680,3 +1680,189 @@ func TestPullRequest(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigContext(t *testing.T) {
|
||||
config := `
|
||||
function(ctx) {
|
||||
runs: [
|
||||
{
|
||||
name: 'run01',
|
||||
tasks: [
|
||||
{
|
||||
name: 'task01',
|
||||
runtime: {
|
||||
containers: [
|
||||
{
|
||||
image: 'alpine/git',
|
||||
},
|
||||
],
|
||||
},
|
||||
environment: {
|
||||
REF_TYPE: ctx.ref_type,
|
||||
REF: ctx.ref,
|
||||
BRANCH: ctx.branch,
|
||||
TAG: ctx.tag,
|
||||
PULL_REQUEST_ID: ctx.pull_request_id,
|
||||
COMMIT_SHA: ctx.commit_sha,
|
||||
},
|
||||
steps: [
|
||||
{ type: 'clone' },
|
||||
{ type: 'run', command: 'env' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
env map[string]string
|
||||
}{
|
||||
{
|
||||
name: "test direct run branch",
|
||||
env: map[string]string{
|
||||
"REF_TYPE": "branch",
|
||||
"REF": "refs/heads/master",
|
||||
"BRANCH": "master",
|
||||
"TAG": "",
|
||||
"PULL_REQUEST_ID": "",
|
||||
"COMMIT_SHA": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test direct run tag",
|
||||
args: []string{"--tag", "v0.1.0"},
|
||||
env: map[string]string{
|
||||
"REF_TYPE": "tag",
|
||||
"REF": "refs/tags/v0.1.0",
|
||||
"BRANCH": "",
|
||||
"TAG": "v0.1.0",
|
||||
"PULL_REQUEST_ID": "",
|
||||
"COMMIT_SHA": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test direct run with pr",
|
||||
args: []string{"--ref", "refs/pull/1/head"},
|
||||
env: map[string]string{
|
||||
"REF_TYPE": "pull_request",
|
||||
"REF": "refs/pull/1/head",
|
||||
"BRANCH": "",
|
||||
"TAG": "",
|
||||
"PULL_REQUEST_ID": "1",
|
||||
"COMMIT_SHA": "",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "agola")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
tetcd, tgitea, c := setup(ctx, t, dir)
|
||||
defer shutdownGitea(tgitea)
|
||||
defer shutdownEtcd(tetcd)
|
||||
|
||||
gwClient := gwclient.NewClient(c.Gateway.APIExposedURL, "admintoken")
|
||||
user, _, err := gwClient.CreateUser(ctx, &gwapitypes.CreateUserRequest{UserName: agolaUser01})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
t.Logf("created agola user: %s", user.UserName)
|
||||
|
||||
token := createAgolaUserToken(ctx, t, c)
|
||||
|
||||
// From now use the user token
|
||||
gwClient = gwclient.NewClient(c.Gateway.APIExposedURL, token)
|
||||
|
||||
directRun(t, dir, config, c.Gateway.APIExposedURL, token, tt.args...)
|
||||
|
||||
// TODO(sgotti) add an util to wait for a run phase
|
||||
_ = testutil.Wait(30*time.Second, func() (bool, error) {
|
||||
runs, _, err := gwClient.GetRuns(ctx, nil, nil, []string{path.Join("/user", user.ID)}, nil, "", 0, false)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if len(runs) != 1 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
run := runs[0]
|
||||
if run.Phase != rstypes.RunPhaseFinished {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
|
||||
runs, _, err := gwClient.GetRuns(ctx, nil, nil, []string{path.Join("/user", user.ID)}, nil, "", 0, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("runs: %s", util.Dump(runs))
|
||||
|
||||
if len(runs) != 1 {
|
||||
t.Fatalf("expected 1 run got: %d", len(runs))
|
||||
}
|
||||
|
||||
run, _, err := gwClient.GetRun(ctx, runs[0].ID)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if run.Phase != rstypes.RunPhaseFinished {
|
||||
t.Fatalf("expected run phase %q, got %q", rstypes.RunPhaseFinished, run.Phase)
|
||||
}
|
||||
if run.Result != rstypes.RunResultSuccess {
|
||||
t.Fatalf("expected run result %q, got %q", rstypes.RunResultSuccess, run.Result)
|
||||
}
|
||||
|
||||
var task *gwapitypes.RunResponseTask
|
||||
for _, t := range run.Tasks {
|
||||
if t.Name == "task01" {
|
||||
task = t
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := gwClient.GetLogs(ctx, run.ID, task.ID, false, 1, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
logs, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
curEnv, err := testutil.ParseEnvs(bytes.NewReader(logs))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
||||
// update commit sha from annotations since it will change at every test
|
||||
tt.env["COMMIT_SHA"] = run.Annotations["commit_sha"]
|
||||
|
||||
for n, e := range tt.env {
|
||||
if ce, ok := curEnv[n]; !ok {
|
||||
t.Fatalf("missing env var %s", n)
|
||||
} else {
|
||||
if ce != e {
|
||||
t.Fatalf("different env var %s value, want: %q, got %q", n, e, ce)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue