diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6b96acc..a35587d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,17 +33,12 @@ jobs: password=$(sudo docker exec jenkins-master cat /var/jenkins_home/secrets/initialAdminPassword) version=$(sudo docker exec jenkins-master sh -c 'echo "$JENKINS_VERSION"') port=8080 - echo "::set-output name=url::http://${ip}:${port}/" - echo "::set-output name=user::admin" - echo "::set-output name=password::${password}" - echo "::set-output name=version::${version}" + echo "JENKINS_URL=http://${ip}:${port}/" >> $GITHUB_ENV + echo "JENKINS_USER=admin" >> $GITHUB_ENV + echo "JENKINS_PASSWORD=${password}" >> $GITHUB_ENV + echo "JENKINS_VERSION=${version}" >> $GITHUB_ENV - name: Run go test - env: - JENKINS_URL: ${{ steps.start-jenkins.outputs.url }} - JENKINS_USER: ${{ steps.start-jenkins.outputs.user }} - JENKINS_PASSWORD: ${{ steps.start-jenkins.outputs.password }} - JENKINS_VERSION: ${{ steps.start-jenkins.outputs.version }} run: make test - name: Upload coverage to Codecov diff --git a/item.go b/item.go index 7c85076..ac93ae9 100644 --- a/item.go +++ b/item.go @@ -6,6 +6,7 @@ import ( "io" "log" "net/http" + "net/url" "path" "regexp" "strconv" @@ -23,6 +24,26 @@ func NewItem(url, class string, jenkins *Jenkins) *Item { return &Item{URL: url, Class: parseClass(class), jenkins: jenkins} } +type ApiJsonOpts struct { + Tree string + Depth int +} + +func (o *ApiJsonOpts) Encode() string { + v := url.Values{} + if o.Tree != "" { + v.Add("tree", o.Tree) + } + v.Add("depth", strconv.Itoa(o.Depth)) + return v.Encode() +} + +// Bind jenkins JSON data to any type, +// +// // bind json data to map +// data := make(map[string]string) +// jenkins.ApiJson(&data, &ApiJsonOpts{"tree":"description"}) +// fmt.Println(data["description"]) func (i *Item) ApiJson(v any, opts *ApiJsonOpts) error { return unmarshalApiJson(i, v, opts) } diff --git a/jenkins.go b/jenkins.go index 0573c76..59e706e 100644 --- a/jenkins.go +++ b/jenkins.go @@ -8,7 +8,6 @@ import ( "net/http" "net/url" "path" - "strconv" "strings" ) @@ -21,8 +20,6 @@ type JenkinsOpts struct { type Jenkins struct { *Item - User string - Password string client *http.Client Header http.Header Crumb *Crumb @@ -102,13 +99,16 @@ func New(url, user, password string) (*Jenkins, error) { url = appendSlash(url) c := &Jenkins{Header: make(http.Header)} c.Item = NewItem(url, "Jenkins", c) - auth := user + ":" + password - c.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) + c.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", user, password)))) c.Header.Set("Accept", "application/json") c.Header.Set("Content-Type", "application/xml; charset=UTF-8") return c, nil } +func (j *Jenkins) SetClient(c *http.Client) { + j.client = c +} + func (j *Jenkins) Client() *http.Client { if j.client == nil { // disable redirect for Job.Rename() and Move() @@ -149,29 +149,6 @@ func (j *Jenkins) Queue() *QueueService { return j.queue } -// Set content type for request, default is 'application/json' -func (c *Jenkins) SetContentType(ctype string) { - if ctype == "" { - c.Header.Set("Accept", "application/json") - } else { - c.Header.Set("Accept", ctype) - } -} - -func (c *Jenkins) SetBasicAuth(username, password string) { - auth := username + ":" + password - c.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) -} - -// func (j *Jenkins) DoRequest(url, method string, body io.Reader) (*http.Response, error) { -// req, err := http.NewRequest(method, url, body) -// if err != nil { -// return nil, err -// } -// req.SetBasicAuth(j.User, j.Password) -// return j.client.Do(req) -// } - func (c *Jenkins) GetCrumb() (*Crumb, error) { if c.Crumb != nil { return c.Crumb, nil @@ -201,14 +178,6 @@ func (c *Jenkins) GetCrumb() (*Crumb, error) { return c.Crumb, nil } -// Send request to jenkins, -// -// // send request to get JSON data of jenkins -// jenkins.Request("GET", "api/json") -// func (c *Jenkins) Request(method, entry string, body io.Reader) (*http.Response, error) { -// return c.doRequest(method, c.URL+entry, body) -// } - func (c *Jenkins) doRequest(method, url string, body io.Reader) (*http.Response, error) { if _, err := c.GetCrumb(); err != nil { return nil, err @@ -284,14 +253,10 @@ func (c *Jenkins) CreateJob(fullName string, xml io.Reader) (*http.Response, err return folder.Create(shortName, xml) } -func (c *Jenkins) DeleteJob(fullName string) error { +func (c *Jenkins) DeleteJob(fullName string) (*http.Response, error) { return NewJobItem(c.Name2URL(fullName), "Job", c).Delete() } -// func (c *Jenkins) String() string { -// return fmt.Sprintf("", c.URL) -// } - func (c *Jenkins) resolveJob(fullName string) (*JobItem, string) { dir, name := path.Split(strings.Trim(fullName, "/")) url := c.Name2URL(dir) @@ -374,20 +339,6 @@ func (c *Jenkins) ReloadJCasC() (*http.Response, error) { return c.Request("POST", "configuration-as-code/reload", nil) } -type ApiJsonOpts struct { - Tree string - Depth int -} - -func (o *ApiJsonOpts) Encode() string { - v := url.Values{} - if o.Tree != "" { - v.Add("tree", o.Tree) - } - v.Add("depth", strconv.Itoa(o.Depth)) - return v.Encode() -} - // func (c *Jenkins) ExportJCasC(name string) error { // resp, err := c.Request("POST", "configuration-as-code/export") // if err != nil { @@ -396,16 +347,6 @@ func (o *ApiJsonOpts) Encode() string { // return resp.ToFile(name) // } -// Bind jenkins JSON data to interface, -// -// // bind json data to map -// data := make(map[string]string) -// jenkins.ApiJson(jenkins.ReqParams{"tree":"description"}, &data) -// fmt.Println(data["description"]) -// func (c *Jenkins) ApiJson(v any, opts *ApiJsonOpts) error { -// return unmarshalApiJson(c, v, opts) -// } - func unmarshalApiJson(r Requester, v any, opts *ApiJsonOpts) error { entry := "api/json" if opts != nil { diff --git a/jenkins_test.go b/jenkins_test.go index 778811d..5163840 100644 --- a/jenkins_test.go +++ b/jenkins_test.go @@ -194,11 +194,14 @@ func TestGetJob(t *testing.T) { } func TestDeleteJob(t *testing.T) { - assert.NotNil(t, jenkins.DeleteJob("")) - _, err := jenkins.CreateJob("folder/pipeline3", strings.NewReader(jobConf)) + _, err := jenkins.DeleteJob("") + assert.NotNil(t, err) + _, err = jenkins.CreateJob("folder/pipeline3", strings.NewReader(jobConf)) + assert.Nil(t, err) + _, err = jenkins.DeleteJob("folder/pipeline3") assert.Nil(t, err) - assert.Nil(t, jenkins.DeleteJob("folder/pipeline3")) - assert.NotNil(t, jenkins.DeleteJob("folder/pipeline3")) + _, err = jenkins.DeleteJob("folder/pipeline3") + assert.NotNil(t, err) } func TestListJobs(t *testing.T) { diff --git a/job.go b/job.go index 2f08d0f..45541d8 100644 --- a/job.go +++ b/job.go @@ -40,39 +40,44 @@ func (j *JobItem) Credentials() *CredentialService { return j.credentials } -func (j *JobItem) Rename(name string) error { +func (j *JobItem) Rename(name string) (*url.URL, error) { v := url.Values{} v.Add("newName", name) resp, err := j.Request("POST", "confirmRename?"+v.Encode(), nil) if err != nil { - return err + return nil, err + } + newUrl, err := resp.Location() + if err != nil { + return nil, err } - url, _ := resp.Location() - j.URL = appendSlash(url.String()) + j.URL = appendSlash(newUrl.String()) j.setName() - return nil + return newUrl, nil } -func (j *JobItem) Move(path string) error { +func (j *JobItem) Move(path string) (*url.URL, error) { v := url.Values{} v.Add("destination", "/"+strings.Trim(path, "/")) resp, err := j.Request("POST", "move/move?"+v.Encode(), nil) if err != nil { - return err + return nil, err + } + newUrl, err := resp.Location() + if err != nil { + return nil, err } - url, _ := resp.Location() - j.URL = appendSlash(url.String()) + j.URL = appendSlash(newUrl.String()) j.setName() - return nil + return newUrl, nil } -func (j *JobItem) Copy(src, dest string) error { +func (j *JobItem) Copy(src, dest string) (*http.Response, error) { v := url.Values{} v.Add("name", dest) v.Add("mode", "copy") v.Add("from", src) - _, err := j.Request("POST", "createItem?"+v.Encode(), nil) - return err + return j.Request("POST", "createItem?"+v.Encode(), nil) } func (j *JobItem) GetParent() (*JobItem, error) { @@ -124,11 +129,10 @@ func (j *JobItem) GetDescription() (string, error) { return data["description"], nil } -func (j *JobItem) SetDescription(description string) error { +func (j *JobItem) SetDescription(description string) (*http.Response, error) { v := url.Values{} v.Add("description", description) - _, err := j.Request("POST", "submitDescription?"+v.Encode(), nil) - return err + return j.Request("POST", "submitDescription?"+v.Encode(), nil) } func (j *JobItem) Build(param url.Values) (*OneQueueItem, error) { @@ -263,9 +267,8 @@ func (j *JobItem) GetBuildByName(name string) (*BuildItem, error) { return NewBuildItem(build.URL, build.Class, j.jenkins), nil } -func (j *JobItem) Delete() error { - _, err := j.Request("POST", "doDelete", nil) - return err +func (j *JobItem) Delete() (*http.Response, error) { + return j.Request("POST", "doDelete", nil) } func (j *JobItem) ListBuilds() ([]*BuildItem, error) { diff --git a/job_test.go b/job_test.go index 9d0d3a2..283c3b2 100644 --- a/job_test.go +++ b/job_test.go @@ -19,7 +19,7 @@ func TestName(t *testing.T) { } func TestRename(t *testing.T) { - err := pipeline.Rename("pipeline1") + _, err := pipeline.Rename("pipeline1") assert.Nil(t, err) newPipeline, err := folder.Get("pipeline1") assert.Nil(t, err) @@ -32,7 +32,7 @@ func TestRename(t *testing.T) { assert.Nil(t, old) // revert - err = pipeline.Rename("pipeline") + _, err = pipeline.Rename("pipeline") assert.Nil(t, err) } @@ -120,7 +120,8 @@ func TestSetDescription(t *testing.T) { assert.Nil(t, err) assert.Empty(t, description) msg := "testing job for go jenkins" - assert.Nil(t, pipeline.SetDescription(msg)) + _, err = pipeline.SetDescription(msg) + assert.Nil(t, err) description, err = pipeline.GetDescription() assert.Nil(t, err) assert.Equal(t, msg, description) @@ -150,7 +151,8 @@ func TestGetBuildFunctions(t *testing.T) { } func TestMove(t *testing.T) { - assert.Nil(t, pipeline.Move("/folder/folder1")) + _, err := pipeline.Move("/folder/folder1") + assert.Nil(t, err) job, err := jenkins.GetJob("folder/pipeline") assert.Nil(t, err) assert.Nil(t, job) @@ -159,11 +161,13 @@ func TestMove(t *testing.T) { assert.Contains(t, job.URL, "folder1/job/pipeline") //revert change - assert.Nil(t, pipeline.Move("folder")) + _, err = pipeline.Move("folder") + assert.Nil(t, err) } func TestCopy(t *testing.T) { - assert.Nil(t, folder.Copy("pipeline", "new_pipeline")) + _, err := folder.Copy("pipeline", "new_pipeline") + assert.Nil(t, err) job, err := jenkins.GetJob("folder/new_pipeline") assert.Nil(t, err) assert.Equal(t, job.Class, pipeline.Class) diff --git a/view.go b/view.go index 6db5f18..8e15f44 100644 --- a/view.go +++ b/view.go @@ -68,15 +68,6 @@ func (v *ViewService) List() ([]*View, error) { return jobJson.Views, nil } -// func (v *ViewService) bindViewAPIJson(name string, view interface{}) error { -// resp, err := v.Request("GET", "view/"+name+"/api/json") -// if err != nil { -// return err -// } -// defer resp.Body.Close() -// return unmarshalResponse(resp.Body, view) -// } - // func (v *ViewService) GetJobFromView(name, jobName string) (*JobItem, error) { // view := &View{} // if err := v.bindViewAPIJson(name, view); err != nil {