Skip to content

Commit

Permalink
jenkins: interpret 302,303 and all 2xx response codes as success
Browse files Browse the repository at this point in the history
The jenkins server responds with 302 when a build with the same
parameter is already scheduled.
According to https://plugins.jenkins.io/build-token-root/ it can also
return 303 for the same scenario.

Be more lenient and interpret 302,303 and all 2xx as successful
responses.
If an unexpected status code is returned a debug message is logged.
  • Loading branch information
fho committed Dec 3, 2024
1 parent 4ca7120 commit a72a132
Showing 1 changed file with 26 additions and 16 deletions.
42 changes: 26 additions & 16 deletions internal/jenkins/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package jenkins

import (
"context"
"errors"
"fmt"
"io"
"net/http"
Expand All @@ -11,13 +10,16 @@ import (
"time"

"github.com/simplesurance/directorius/internal/goorderr"

"go.uber.org/zap"
)

type Client struct {
url string
auth *basicAuth

clt *http.Client
clt *http.Client
logger *zap.Logger
}

type basicAuth struct {
Expand All @@ -32,9 +34,10 @@ const (

func NewClient(url, user, password string) *Client {
return &Client{
url: url,
auth: &basicAuth{user: user, password: password},
clt: &http.Client{Timeout: requestTimeout},
url: url,
auth: &basicAuth{user: user, password: password},
clt: &http.Client{Timeout: requestTimeout},
logger: zap.L().Named("jenkins_client"),
}
}

Expand Down Expand Up @@ -71,7 +74,24 @@ func (s *Client) Build(ctx context.Context, j *Job) error {
}()
}

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
switch code := resp.StatusCode; {
case code == http.StatusCreated:
// Jenkins returns 201 and sends in the Location header the URL of the queued item,
// it's url can be used to get the build id, query the status, cancel it, etc
// location := resp.Header.Get("Location")
return nil
case code == http.StatusSeeOther, code == http.StatusFound:
// build already exists, probably happens when triggering a job
// with the same parameters then one in the wait-queue
return nil

case code >= 200 && code < 300:
s.logger.Debug("server returned unexpected status code, interpreting it as success",
zap.Int("http.status_code", resp.StatusCode),
zap.String("http.request_url", req.URL.Redacted()),
)
return nil
default:
/* we simply almost always retry to make it resilient,
* requests can fail and succeed later e.g. on:
- 404 because the multibranch job was not created yet but is soonish,
Expand All @@ -83,18 +103,8 @@ func (s *Client) Build(ctx context.Context, j *Job) error {
etc
*/
return goorderr.NewRetryableAnytimeError(fmt.Errorf("server returned status code: %d", resp.StatusCode))
}

if resp.StatusCode != http.StatusCreated {
return errors.New("server returned status code %d, expecting 201")
}

// Jenkins returns 201 and sends in the Location header the URL of the queued item,
// it's url can be used to get the build id, query the status, cancel it, etc
// location := resp.Header.Get("Location")

// s.clt.Do(req)
return nil
}

func toRequestBody(j *Job) io.Reader {
Expand Down

0 comments on commit a72a132

Please sign in to comment.