Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: return code in CompileAndPublish rather than handleError #1107

Merged
merged 5 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 23 additions & 56 deletions api/build/compile_publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"github.com/go-vela/server/queue"
"github.com/go-vela/server/queue/models"
"github.com/go-vela/server/scm"
"github.com/go-vela/server/util"
"github.com/go-vela/types/constants"
"github.com/go-vela/types/library"
"github.com/go-vela/types/pipeline"
Expand All @@ -43,14 +42,14 @@
// schedule processing, and API build creation.
//
//nolint:funlen,gocyclo // ignore function length due to comments, error handling, and general complexity of function
func CompileAndPublish(

Check failure on line 45 in api/build/compile_publish.go

View workflow job for this annotation

GitHub Actions / golangci

[golangci] api/build/compile_publish.go#L45

error-return: error should be the last type when returning multiple items (revive)
Raw output
api/build/compile_publish.go:45:1: error-return: error should be the last type when returning multiple items (revive)
func CompileAndPublish(
	c context.Context,
	cfg CompileAndPublishConfig,
	database database.Interface,
	scm scm.Service,
	compiler compiler.Engine,
	queue queue.Service,
) (*pipeline.Build, *models.Item, error, int) {
	logrus.Debugf("generating queue items for build %s/%d", cfg.Repo.GetFullName(), cfg.Build.GetNumber())

	// assign variables from form for readibility
	r := cfg.Repo
	u := cfg.Repo.GetOwner()
	b := cfg.Build
	baseErr := cfg.BaseErr

	// confirm current repo owner has at least write access to repo (needed for status update later)
	_, err := scm.RepoAccess(c, u.GetName(), u.GetToken(), r.GetOrg(), r.GetName())
	if err != nil {
		retErr := fmt.Errorf("unable to publish build to queue: repository owner %s no longer has write access to repository %s", u.GetName(), r.GetFullName())

		return nil, nil, retErr, http.StatusUnauthorized
	}

	// get pull request number from build if event is pull_request or issue_comment
	var prNum int
	if strings.EqualFold(b.GetEvent(), constants.EventPull) || strings.EqualFold(b.GetEvent(), constants.EventComment) {
		prNum, err = getPRNumberFromBuild(b)
		if err != nil {
			retErr := fmt.Errorf("%s: failed to get pull request number for %s: %w", baseErr, r.GetFullName(), err)

			return nil, nil, retErr, http.StatusBadRequest
		}
	}

	// if the event is issue_comment and the issue is a pull request,
	// call SCM for more data not provided in webhook payload
	if strings.EqualFold(cfg.Source, "webhook") && strings.EqualFold(b.GetEvent(), constants.EventComment) {
		commit, branch, baseref, headref, err := scm.GetPullRequest(c, r, prNum)
		if err != nil {
			retErr := fmt.Errorf("%s: failed to get pull request info for %s: %w", baseErr, r.GetFullName(), err)

			return nil, nil, retErr, http.StatusInternalServerError
		}

		b.SetCommit(commit)
		b.SetBranch(strings.ReplaceAll(branch, "refs/heads/", ""))
		b.SetBaseRef(baseref)
		b.SetHeadRef(headref)
	}

	// if the source is from a schedule, fetch the commit sha from schedule branch (same as build branch at this moment)
	if strings.EqualFold(cfg.Source, "schedule") {
		// send API call to capture the commit sha for the branch
		_, commit, err := scm.GetBranch(c, r, b.GetBranch())
		if err != nil {
			retErr := fmt.Errorf("failed to get commit for repo %s on %s branch: %w", r.GetFullName(), r.GetBranch(), err)

			return nil, nil, retErr, http.StatusInternalServerError
		}

		b.SetCommit(commit)
	}

	// create SQL filters for querying pending and running builds for repo
	filters := map[string]interface{}{
		"status": []string{constants.StatusPending, constants.StatusRunning},
	}

	// send API call to capture the number of pending or running builds for the repo
	builds, err := database.CountBuildsForRepo(c, r, filters)
	if err != nil {
		retErr := fmt.Errorf("%s: unable to get count of builds for repo %s", baseErr, r.GetFullName())

		return nil, nil, retErr, http.StatusInternalServerError
	}

	logrus.Debugf("currently %d builds running on repo %s", builds, r.GetFullName())

	// check if the number of pending and running builds exceeds the limit for the repo
	if builds >= r.GetBuildLimit() {
		retErr := fmt.Errorf("%s: repo %s has exceeded the concurrent build limit of %d", baseErr, r.GetFullName(), r.GetBuildLimit())

		return nil, nil, retErr, http.StatusTooManyRequests
	}

	// update fields in build object
	// this is necessary in case source is restart and the build is prepopulated with these values
	b.SetID(0)
	b.SetCreated(time.Now().UTC().Unix())
	b.SetEnqueued(0)
	b.SetStarted(0)
	b.SetFinished(0)
	b.SetStatus(constants.StatusPending)
	b.SetError("")
	b.SetHost("")
	b.SetRuntime("")
	b.SetDistribution("")

	// variable to store changeset files
	var files []string

	// check if the build event is not issue_comment or pull_request
	if !strings.EqualFold(b.GetEvent(), constants.EventComment) &&
		!strings.EqualFold(b.GetEvent(), constants.EventPull) &&
		!strings.EqualFold(b.GetEvent(), constants.EventDelete) {
		// send API call to capture list of files changed for the commit
		files, err = scm.Changeset(c, r, b.GetCommit())
		if err != nil {
			retErr := fmt.Errorf("%s: failed to get changeset for %s: %w", baseErr, r.GetFullName(), err)

			return nil, nil, retErr, http.StatusInternalServerError
		}
	}

	// check if the build event is a pull_request
	if strings.EqualFold(b.GetEvent(), constants.EventPull) && prNum > 0 {
		// send API call to capture list of files changed for the pull request
		files, err = scm.ChangesetPR(c, r, prNum)
		if err != nil {
			retErr := fmt.Errorf("%s: failed to get changeset for %s: %w", baseErr, r.GetFullName(), err)

			return nil, nil, retErr, http.StatusInternalServerError
		}
	}

	var (
		// variable to store the raw pipeline configuration
		pipelineFile []byte
		// variable to store executable pipeline
		p *pipeline.Build
		// variable to store pipeline configuration
		pipeline *library.Pipeline
		// variable to store the pipeline type for the repository
		pipelineType = r.GetPipelineType()
		// variable to store updated repository record
		repo *types.Repo
	)

	// implement a loop to process asynchronous operations with a retry limit
	//
	// Some operations taken during the webhook workflow can lead to race conditions
	// failing to successfully process the request. This logic ensures we attempt our
	// best efforts to handle these cases gracefully.
	for i := 0; i < cfg.Retries; i++ {
		logrus.Debugf("compilation loop - attempt %d", i+1)
		// check if we're on the first iteration of the loop
		if i > 0 {
			// incrementally sleep in between retries
			time.Sleep(time.Duration(i) * time.Second)
		}

		// send database call to attempt to capture the pipeline if we already processed it before
		pipeline, err = database.GetPipelineForRepo(c, b.GetCommit(), r)
		if err != nil { // assume the pipeline doesn't exist in the database yet
			// send API call to capture the pipeline configuration file
			pipelineFile, err = scm.ConfigBackoff(c, u, r, b.GetCommit())
			if err != nil {
				retErr := fmt.Errorf("%s: unable to get pipeline configuration for %s: %w", baseErr, r.GetFullName(), err)

				return nil, nil, retErr, http.StatusNotFound
			}
		} else {
			pipelineFile = pipeline.GetData()
		}

		// send API call to capture repo for the counter (grabbing repo again to ensure counter is correct)
		repo, err = database.GetRepoForOrg(c, r.GetOrg(), r.GetName())
		if err != nil {
			retErr := fmt.Errorf("%s: unable to get repo %s: %w", baseErr, r.GetFullName(), err)

			// check if the retry limit has been exceeded
			if i < cfg.Retries-1 {
				logrus.WithError(retErr).Warningf("retrying #%d", i+1)

				// continue to the next iteration of the loop
				continue
			}

			return nil, nil, retErr, http.StatusInternalServerError
		}

		// update DB record of repo (repo) with any changes captured from webhook payload (r)
		repo.SetTopics(r.GetTopics())
		repo.SetBranch(r.GetBranch())

		// update the build numbers based off repo counter
		inc := repo.GetCounter() + 1
		repo.SetCounter(inc)
		b.SetNumber(inc)

		// populate the build link if a web address is provided
		if len(cfg.Metadata.Vela.WebAddress) > 0 {
			b.SetLink(
				fmt.Sprintf("%s/%s/%d", cfg.Metadata.Vela.WebAddress, repo.GetFullName(), b.GetNumber()),
			)
		}

		// ensure we use the expected pipeline type when compiling
		//
		// The pipeline type for a repo can change at any time which can break compiling
		// existing pipelines in the system for that repo. To account for this, we update
		// the repo pipeline type to match what was defined for the existing pipeline
		// before compiling. After we're done compiling, we reset the pipeline type.
		if len(pipeline.GetType()) > 0 {
			repo.SetPipelineType(pipeline.GetType())
		}

		var compiled *library.Pipeline
		// parse and compile the pipeline configuration file
		p, compiled, err = compiler.
			Duplicate().
			WithBuild(b).
			WithComment(cfg.Comment).
			WithCommit(b.GetCommit()).
			WithFiles(files).
			WithMetadata(cfg.Metadata).
			WithRepo(repo).
			WithUser(u).
			WithLabels(cfg.Labels).
			Compile(pipelineFile)
		if err != nil {
			// format the error message with extra information
			err = fmt.Errorf("unable to compile pipeline configuration for %s: %w", repo.GetFullName(), err)

			// log the error for traceability
			logrus.Error(err.Error())

			return nil, nil, fmt.Errorf("%s: %w", baseErr, err), http.StatusInternalServerError
		}

		// reset the pipeline type for the repo
		//
		// The pipeline type for a repo can change at any time which can break compiling
		// existing pipelines in the system for that repo. To account for this, we update
		// the repo pipeline type to match what was defined for the existing pipeline
		// before compiling. After we're done compiling, we reset the pipeline type.
		repo.SetPipelineType(pipelineType)

		// skip the build if pipeline compiled to only the init and clone steps
		skip := SkipEmptyBuild(p)
		if skip != "" {
			// set build to successful status
			b.SetStatus(constants.StatusSkipped)

			// send API call to set the status on the commit
			err = scm.Status(c, u, b, repo.GetOrg(), repo.GetName())
			if err != nil {
				logrus.Errorf("unable to set commit status for %s/%d: %v", repo.GetFullName(), b.GetNumber(), err)
			}

			return nil,
				&models.Item{
					Build: b,
				},
				errors.New(skip),
				http.StatusOK
		}

		// check if the pipeline did not already exist in the database
		if pipeline == nil {
			pipeline = compiled
			pipeline.SetRepoID(repo.GetID())
			pipeline.SetCommit(b.GetCommit())
			pipeline.SetRef(b.GetRef())

			// send API call to create the pipeline
			pipeline, err = database.CreatePipeline(c, pipeline)
			if err != nil {
				retErr := fmt.Errorf("%s: failed to create pipeline for %s: %w", baseErr, repo.GetFullName(), err)

				// check if the retry limit has been exceeded
				if i < cfg.Retries-1 {
					logrus.WithError(retErr).Warningf("retrying #%d", i+1)

					// continue to the next iteration of the loop
					continue
				}

				return nil, nil, retErr, http.StatusInternalServerError
			}
		}

		b.SetPipelineID(pipeline.GetID())

		// create the objects from the pipeline in the database
		// TODO:
		// - if a build gets created and something else fails midway,
		//   the next loop will attempt to create the same build,
		//   using the same Number and thus create a constraint
		//   conflict; consider deleting the partially created
		//   build object in the database
		err = PlanBuild(c, database, scm, p, b, repo)
		if err != nil {
			retErr := fmt.Errorf("%s: %w", baseErr, err)

			// check if the retry limit has been exceeded
			if i < cfg.Retries-1 {
				logrus.WithError(retErr).Warningf("retrying #%d", i+1)

				// reset fields set by cleanBuild for retry
				b.SetError("")
				b.SetStatus(constants.StatusPending)
				b.SetFinished(0)

				// continue to the next iteration of the loop
				continue
			}

			return nil, nil, retErr, http.StatusInternalServerError
		}

		// break the loop because everything was successful
		break
	} // end of retry loop

	// send API call to update repo for ensuring counter is incremented
	repo, err = database.UpdateRepo(c, repo)
	if err != nil {
		retErr := fmt.Errorf("%s: failed to update repo %s: %w", baseErr, repo.GetFullName(), err)

		return nil, nil, retErr, http.StatusInternalServerError
	}

	// return error if pipeline didn't get populated
	if p == nil {
		retErr := fmt.Errorf("%s: failed to set pipeline for %s: %w", baseErr, repo.GetFullName(), err)

		return nil, nil, retErr, http.StatusInternalServerError
	}

	// return error if build didn't get populated
	if b == nil {
		retErr := fmt.Errorf("%s: failed to set build for %s: %w", baseErr, repo.GetFullName(), err)

		return nil, nil, retErr, http.StatusInternalServerError
	}

	// send API call to capture the triggered build
	b, err = database.GetBuildForRepo(c, repo, b.GetNumber())
	if err != nil {
		retErr := fmt.Errorf("%s: failed to get new build %s/%d: %w", baseErr, repo.GetFullName(), b.GetNumber(), err)

		return nil, nil, retErr, http.StatusInternalServerError
	}

	// determine queue route
	route, err := queue.Route(&p.Worker)
	if err != nil {
		retErr := fmt.Errorf("unable to set route for build %d for %s: %w", b.GetNumber(), r.GetFullName(), err)

		// error out the build
		CleanBuild(c, database, b, nil, nil, retErr)

		return nil, nil, retErr, http.StatusBadRequest
	}

	// temporarily set host to the route before it gets picked up by a worker
	b.SetHost(route)

	// publish the pipeline.Build to the build_executables table to be requested by a worker
	err = PublishBuildExecutable(c, database, p, b)
	if err != nil {
		retErr := fmt.Errorf("unable to publish build executable for %s/%d: %w", repo.GetFullName(), b.GetNumber(), err)

		return nil, nil, retErr, http.StatusInternalServerError
	}

	return p, models.ToItem(b, repo), nil, http.StatusCreated
}
c context.Context,
cfg CompileAndPublishConfig,
database database.Interface,
scm scm.Service,
compiler compiler.Engine,
queue queue.Service,
) (*pipeline.Build, *models.Item, error) {
) (*pipeline.Build, *models.Item, error, int) {

Check failure on line 52 in api/build/compile_publish.go

View workflow job for this annotation

GitHub Actions / golangci

[golangci] api/build/compile_publish.go#L52

ST1008: error should be returned as the last argument (stylecheck)
Raw output
api/build/compile_publish.go:52:35: ST1008: error should be returned as the last argument (stylecheck)
) (*pipeline.Build, *models.Item, error, int) {
                                  ^
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
logrus.Debugf("generating queue items for build %s/%d", cfg.Repo.GetFullName(), cfg.Build.GetNumber())

// assign variables from form for readibility
Expand All @@ -63,9 +62,8 @@
_, err := scm.RepoAccess(c, u.GetName(), u.GetToken(), r.GetOrg(), r.GetName())
if err != nil {
retErr := fmt.Errorf("unable to publish build to queue: repository owner %s no longer has write access to repository %s", u.GetName(), r.GetFullName())
util.HandleError(c, http.StatusUnauthorized, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusUnauthorized
}

// get pull request number from build if event is pull_request or issue_comment
Expand All @@ -74,28 +72,19 @@
prNum, err = getPRNumberFromBuild(b)
if err != nil {
retErr := fmt.Errorf("%s: failed to get pull request number for %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusBadRequest
}
}

// if the event is issue_comment and the issue is a pull request,
// call SCM for more data not provided in webhook payload
if strings.EqualFold(cfg.Source, "webhook") && strings.EqualFold(b.GetEvent(), constants.EventComment) {
if err != nil {
retErr := fmt.Errorf("%s: failed to get pull request number for %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
}

commit, branch, baseref, headref, err := scm.GetPullRequest(c, r, prNum)
if err != nil {
retErr := fmt.Errorf("%s: failed to get pull request info for %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

b.SetCommit(commit)
Expand All @@ -110,9 +99,8 @@
_, commit, err := scm.GetBranch(c, r, b.GetBranch())
if err != nil {
retErr := fmt.Errorf("failed to get commit for repo %s on %s branch: %w", r.GetFullName(), r.GetBranch(), err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

b.SetCommit(commit)
Expand All @@ -127,19 +115,17 @@
builds, err := database.CountBuildsForRepo(c, r, filters)
if err != nil {
retErr := fmt.Errorf("%s: unable to get count of builds for repo %s", baseErr, r.GetFullName())
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

logrus.Debugf("currently %d builds running on repo %s", builds, r.GetFullName())

// check if the number of pending and running builds exceeds the limit for the repo
if builds >= r.GetBuildLimit() {
retErr := fmt.Errorf("%s: repo %s has exceeded the concurrent build limit of %d", baseErr, r.GetFullName(), r.GetBuildLimit())
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusTooManyRequests
}

// update fields in build object
Expand All @@ -166,9 +152,8 @@
files, err = scm.Changeset(c, r, b.GetCommit())
if err != nil {
retErr := fmt.Errorf("%s: failed to get changeset for %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}
}

Expand All @@ -178,9 +163,8 @@
files, err = scm.ChangesetPR(c, r, prNum)
if err != nil {
retErr := fmt.Errorf("%s: failed to get changeset for %s: %w", baseErr, r.GetFullName(), err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}
}

Expand Down Expand Up @@ -218,9 +202,7 @@
if err != nil {
retErr := fmt.Errorf("%s: unable to get pipeline configuration for %s: %w", baseErr, r.GetFullName(), err)

util.HandleError(c, http.StatusNotFound, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusNotFound
}
} else {
pipelineFile = pipeline.GetData()
Expand All @@ -239,9 +221,7 @@
continue
}

util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

// update DB record of repo (repo) with any changes captured from webhook payload (r)
Expand Down Expand Up @@ -290,10 +270,7 @@
// log the error for traceability
logrus.Error(err.Error())

retErr := fmt.Errorf("%s: %w", baseErr, err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, fmt.Errorf("%s: %w", baseErr, err), http.StatusInternalServerError
}

// reset the pipeline type for the repo
Expand All @@ -320,7 +297,8 @@
&models.Item{
Build: b,
},
errors.New(skip)
errors.New(skip),
http.StatusOK
}

// check if the pipeline did not already exist in the database
Expand All @@ -343,9 +321,7 @@
continue
}

util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}
}

Expand Down Expand Up @@ -375,9 +351,7 @@
continue
}

util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

// break the loop because everything was successful
Expand All @@ -388,34 +362,30 @@
repo, err = database.UpdateRepo(c, repo)
if err != nil {
retErr := fmt.Errorf("%s: failed to update repo %s: %w", baseErr, repo.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

// return error if pipeline didn't get populated
if p == nil {
retErr := fmt.Errorf("%s: failed to set pipeline for %s: %w", baseErr, repo.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

// return error if build didn't get populated
if b == nil {
retErr := fmt.Errorf("%s: failed to set build for %s: %w", baseErr, repo.GetFullName(), err)
util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

// send API call to capture the triggered build
b, err = database.GetBuildForRepo(c, repo, b.GetNumber())
if err != nil {
retErr := fmt.Errorf("%s: failed to get new build %s/%d: %w", baseErr, repo.GetFullName(), b.GetNumber(), err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

// determine queue route
Expand All @@ -426,9 +396,7 @@
// error out the build
CleanBuild(c, database, b, nil, nil, retErr)

util.HandleError(c, http.StatusBadRequest, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusBadRequest
}

// temporarily set host to the route before it gets picked up by a worker
Expand All @@ -438,12 +406,11 @@
err = PublishBuildExecutable(c, database, p, b)
if err != nil {
retErr := fmt.Errorf("unable to publish build executable for %s/%d: %w", repo.GetFullName(), b.GetNumber(), err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return nil, nil, retErr
return nil, nil, retErr, http.StatusInternalServerError
}

return p, models.ToItem(b, repo), nil
return p, models.ToItem(b, repo), nil, http.StatusCreated
}

// getPRNumberFromBuild is a helper function to
Expand Down
27 changes: 16 additions & 11 deletions api/build/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package build
import (
"fmt"
"net/http"
"strings"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
Expand All @@ -19,7 +18,6 @@ import (
"github.com/go-vela/server/router/middleware/user"
"github.com/go-vela/server/scm"
"github.com/go-vela/server/util"
"github.com/go-vela/types/constants"
"github.com/go-vela/types/library"
)

Expand Down Expand Up @@ -51,24 +49,32 @@ import (
// - ApiKeyAuth: []
// responses:
// '200':
// description: Request processed but build was skipped
// description: Successfully received the webhook but build was skipped
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
// schema:
// type: string
// '201':
// description: Successfully created the build
// description: Successfully created the build from webhook
// type: json
// schema:
// "$ref": "#/definitions/Build"
// '400':
// description: Unable to create the build
// description: Malformed webhook payload or improper pipeline configuration
// schema:
// "$ref": "#/definitions/Error"
// '401':
// description: Repository owner does not have proper access
// schema:
// "$ref": "#/definitions/Error"
// '404':
// description: Unable to create the build
// description: Unable to receive the webhook
// schema:
// "$ref": "#/definitions/Error"
// '429':
// description: Concurrent build limit reached for repository
// schema:
// "$ref": "#/definitions/Error"
// '500':
// description: Unable to create the build
// description: Unable to receive the webhook or internal error while processing
// schema:
// "$ref": "#/definitions/Error"

Expand Down Expand Up @@ -123,7 +129,7 @@ func CreateBuild(c *gin.Context) {
Retries: 1,
}

_, item, err := CompileAndPublish(
_, item, err, code := CompileAndPublish(
c,
config,
database.FromContext(c),
Expand All @@ -133,15 +139,14 @@ func CreateBuild(c *gin.Context) {
)

// check if build was skipped
if err != nil && strings.EqualFold(item.Build.GetStatus(), constants.StatusSkipped) {
if err != nil && code == http.StatusOK {
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
c.JSON(http.StatusOK, err.Error())

return
}

// error handling done in CompileAndPublish
if err != nil {
return
util.HandleError(c, code, err)
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
}

c.JSON(http.StatusCreated, item.Build)
Expand Down
24 changes: 16 additions & 8 deletions api/build/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,32 @@ import (
// - ApiKeyAuth: []
// responses:
// '200':
// description: Request processed but build was skipped
// description: Successfully received the webhook but build was skipped
// schema:
// type: string
// '201':
// description: Successfully restarted the build
// description: Successfully created the build from webhook
// type: json
// schema:
// "$ref": "#/definitions/Build"
// '400':
// description: Unable to restart the build
// description: Malformed webhook payload or improper pipeline configuration
// schema:
// "$ref": "#/definitions/Error"
// '401':
// description: Repository owner does not have proper access
// schema:
// "$ref": "#/definitions/Error"
// '404':
// description: Unable to restart the build
// description: Unable to receive the webhook
// schema:
// "$ref": "#/definitions/Error"
// '429':
// description: Concurrent build limit reached for repository
// schema:
// "$ref": "#/definitions/Error"
// '500':
// description: Unable to restart the build
// description: Unable to receive the webhook or internal error while processing
// schema:
// "$ref": "#/definitions/Error"

Expand Down Expand Up @@ -120,7 +129,7 @@ func RestartBuild(c *gin.Context) {
}

// generate queue items
_, item, err := CompileAndPublish(
_, item, err, code := CompileAndPublish(
c,
config,
database.FromContext(c),
Expand All @@ -129,9 +138,8 @@ func RestartBuild(c *gin.Context) {
queue.FromContext(c),
)

// error handling done in CompileAndPublish
if err != nil {
return
util.HandleError(c, code, err)
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
}

c.JSON(http.StatusCreated, item.Build)
Expand Down
Loading
Loading