gateway: move create run to own action
* Move all run creation logic to the action handler. * Cleanup webhook to use it
This commit is contained in:
parent
5b22ebc2d3
commit
8242dc3a9d
|
@ -18,15 +18,52 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"github.com/sorintlab/agola/internal/config"
|
||||
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
||||
"github.com/sorintlab/agola/internal/runconfig"
|
||||
"github.com/sorintlab/agola/internal/services/common"
|
||||
rsapi "github.com/sorintlab/agola/internal/services/runservice/api"
|
||||
rstypes "github.com/sorintlab/agola/internal/services/runservice/types"
|
||||
"github.com/sorintlab/agola/internal/services/types"
|
||||
"github.com/sorintlab/agola/internal/util"
|
||||
|
||||
errors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultSSHPort = "22"
|
||||
|
||||
agolaDefaultConfigDir = ".agola"
|
||||
agolaDefaultJsonnetConfigFile = "config.jsonnet"
|
||||
agolaDefaultJsonConfigFile = "config.json"
|
||||
agolaDefaultYamlConfigFile = "config.yml"
|
||||
|
||||
// List of runs annotations
|
||||
AnnotationRunType = "run_type"
|
||||
AnnotationRefType = "ref_type"
|
||||
AnnotationProjectID = "projectid"
|
||||
AnnotationUserID = "userid"
|
||||
|
||||
AnnotationRunCreationTrigger = "run_creation_trigger"
|
||||
AnnotationWebhookEvent = "webhook_event"
|
||||
AnnotationWebhookSender = "webhook_sender"
|
||||
|
||||
AnnotationCommitSHA = "commit_sha"
|
||||
AnnotationRef = "ref"
|
||||
AnnotationMessage = "message"
|
||||
AnnotationCommitLink = "commit_link"
|
||||
AnnotationCompareLink = "compare_link"
|
||||
|
||||
AnnotationBranch = "branch"
|
||||
AnnotationBranchLink = "branch_link"
|
||||
AnnotationTag = "tag"
|
||||
AnnotationTagLink = "tag_link"
|
||||
AnnotationPullRequestID = "pull_request_id"
|
||||
AnnotationPullRequestLink = "pull_request_link"
|
||||
)
|
||||
|
||||
func (h *ActionHandler) GetRun(ctx context.Context, runID string) (*rsapi.RunResponse, error) {
|
||||
runResp, resp, err := h.runserviceClient.GetRun(ctx, runID, nil)
|
||||
if err != nil {
|
||||
|
@ -249,3 +286,270 @@ func (h *ActionHandler) RunTaskAction(ctx context.Context, req *RunTaskActionsRe
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateRunRequest struct {
|
||||
RunType types.RunType
|
||||
RefType types.RunRefType
|
||||
RunCreationTrigger types.RunCreationTriggerType
|
||||
|
||||
Project *types.Project
|
||||
User *types.User
|
||||
RepoPath string
|
||||
GitSource gitsource.GitSource
|
||||
CommitSHA string
|
||||
Message string
|
||||
Branch string
|
||||
Tag string
|
||||
Ref string
|
||||
PullRequestID string
|
||||
SSHPrivKey string
|
||||
SSHHostKey string
|
||||
SkipSSHHostKeyCheck bool
|
||||
CloneURL string
|
||||
|
||||
WebhookEvent string
|
||||
WebhookSender string
|
||||
|
||||
CommitLink string
|
||||
BranchLink string
|
||||
TagLink string
|
||||
PullRequestLink string
|
||||
|
||||
// CompareLink is provided only when triggered by a webhook and contains the
|
||||
// commit compare link
|
||||
CompareLink string
|
||||
}
|
||||
|
||||
func (h *ActionHandler) CreateRuns(ctx context.Context, req *CreateRunRequest) error {
|
||||
setupErrors := []string{}
|
||||
|
||||
if req.CommitSHA == "" {
|
||||
return util.NewErrBadRequest(errors.Errorf("empty commit SHA"))
|
||||
}
|
||||
if req.Message == "" {
|
||||
return util.NewErrBadRequest(errors.Errorf("empty message"))
|
||||
}
|
||||
|
||||
var baseGroupType common.GroupType
|
||||
var baseGroupID string
|
||||
var groupType common.GroupType
|
||||
var group string
|
||||
|
||||
if req.RunType == types.RunTypeProject {
|
||||
baseGroupType = common.GroupTypeProject
|
||||
baseGroupID = req.Project.ID
|
||||
} else {
|
||||
baseGroupType = common.GroupTypeUser
|
||||
baseGroupID = req.User.ID
|
||||
}
|
||||
|
||||
switch req.RefType {
|
||||
case types.RunRefTypeBranch:
|
||||
groupType = common.GroupTypeBranch
|
||||
group = req.Branch
|
||||
case types.RunRefTypeTag:
|
||||
groupType = common.GroupTypeTag
|
||||
group = req.Tag
|
||||
case types.RunRefTypePullRequest:
|
||||
groupType = common.GroupTypePullRequest
|
||||
group = req.PullRequestID
|
||||
}
|
||||
|
||||
runGroup := common.GenRunGroup(baseGroupType, baseGroupID, groupType, group)
|
||||
|
||||
gitURL, err := util.ParseGitURL(req.CloneURL)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to parse clone url: %w", err)
|
||||
}
|
||||
gitHost := gitURL.Hostname()
|
||||
gitPort := gitURL.Port()
|
||||
if gitPort == "" {
|
||||
gitPort = defaultSSHPort
|
||||
}
|
||||
|
||||
// this env vars overrides other env vars
|
||||
env := map[string]string{
|
||||
"CI": "true",
|
||||
"AGOLA_SSHPRIVKEY": req.SSHPrivKey,
|
||||
"AGOLA_REPOSITORY_URL": req.CloneURL,
|
||||
"AGOLA_GIT_HOST": gitHost,
|
||||
"AGOLA_GIT_PORT": gitPort,
|
||||
"AGOLA_GIT_BRANCH": req.Branch,
|
||||
"AGOLA_GIT_TAG": req.Tag,
|
||||
"AGOLA_GIT_REF": req.Ref,
|
||||
"AGOLA_GIT_COMMITSHA": req.CommitSHA,
|
||||
}
|
||||
|
||||
if req.SSHHostKey != "" {
|
||||
env["AGOLA_SSHHOSTKEY"] = req.SSHHostKey
|
||||
}
|
||||
if req.SkipSSHHostKeyCheck {
|
||||
env["AGOLA_SKIPSSHHOSTKEYCHECK"] = "1"
|
||||
}
|
||||
|
||||
variables := map[string]string{}
|
||||
if req.RunType == types.RunTypeProject {
|
||||
var err error
|
||||
variables, err = h.genRunVariables(ctx, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
annotations := map[string]string{
|
||||
AnnotationRunType: string(req.RunType),
|
||||
AnnotationRefType: string(req.RefType),
|
||||
AnnotationRunCreationTrigger: string(req.RunCreationTrigger),
|
||||
AnnotationWebhookEvent: req.WebhookEvent,
|
||||
AnnotationWebhookSender: req.WebhookSender,
|
||||
AnnotationCommitSHA: req.CommitSHA,
|
||||
AnnotationRef: req.Ref,
|
||||
AnnotationMessage: req.Message,
|
||||
AnnotationCommitLink: req.CommitLink,
|
||||
AnnotationCompareLink: req.CompareLink,
|
||||
}
|
||||
|
||||
if req.RunType == types.RunTypeProject {
|
||||
annotations[AnnotationProjectID] = req.Project.ID
|
||||
} else {
|
||||
annotations[AnnotationUserID] = req.User.ID
|
||||
}
|
||||
|
||||
if req.Branch != "" {
|
||||
annotations[AnnotationBranch] = req.Branch
|
||||
annotations[AnnotationBranchLink] = req.BranchLink
|
||||
}
|
||||
if req.Tag != "" {
|
||||
annotations[AnnotationTag] = req.Tag
|
||||
annotations[AnnotationTagLink] = req.TagLink
|
||||
}
|
||||
if req.PullRequestID != "" {
|
||||
annotations[AnnotationPullRequestID] = req.PullRequestID
|
||||
annotations[AnnotationPullRequestLink] = req.PullRequestLink
|
||||
}
|
||||
|
||||
data, filename, err := h.fetchConfigFiles(req.GitSource, req.RepoPath, req.CommitSHA)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to fetch config file: %w", err)
|
||||
}
|
||||
h.log.Debug("data: %s", data)
|
||||
|
||||
var configFormat config.ConfigFormat
|
||||
switch path.Ext(filename) {
|
||||
case ".jsonnet":
|
||||
configFormat = config.ConfigFormatJsonnet
|
||||
case ".json":
|
||||
fallthrough
|
||||
case ".yml":
|
||||
configFormat = config.ConfigFormatJSON
|
||||
|
||||
}
|
||||
config, err := config.ParseConfig([]byte(data), configFormat)
|
||||
if err != nil {
|
||||
h.log.Errorf("failed to parse config: %+v", err)
|
||||
|
||||
// create a run (per config file) with a generic error since we cannot parse
|
||||
// it and know how many runs are defined
|
||||
setupErrors = append(setupErrors, err.Error())
|
||||
createRunReq := &rsapi.RunCreateRequest{
|
||||
RunConfigTasks: nil,
|
||||
Group: runGroup,
|
||||
SetupErrors: setupErrors,
|
||||
Name: rstypes.RunGenericSetupErrorName,
|
||||
StaticEnvironment: env,
|
||||
Annotations: annotations,
|
||||
}
|
||||
|
||||
if _, _, err := h.runserviceClient.CreateRun(ctx, createRunReq); err != nil {
|
||||
h.log.Errorf("failed to create run: %+v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, run := range config.Runs {
|
||||
rcts := runconfig.GenRunConfigTasks(util.DefaultUUIDGenerator{}, config, run.Name, variables, req.Branch, req.Tag, req.Ref)
|
||||
|
||||
createRunReq := &rsapi.RunCreateRequest{
|
||||
RunConfigTasks: rcts,
|
||||
Group: runGroup,
|
||||
SetupErrors: setupErrors,
|
||||
Name: run.Name,
|
||||
StaticEnvironment: env,
|
||||
Annotations: annotations,
|
||||
}
|
||||
|
||||
if _, _, err := h.runserviceClient.CreateRun(ctx, createRunReq); err != nil {
|
||||
h.log.Errorf("failed to create run: %+v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *ActionHandler) fetchConfigFiles(gitSource gitsource.GitSource, repopath, commitSHA string) ([]byte, string, error) {
|
||||
var data []byte
|
||||
var filename string
|
||||
err := util.ExponentialBackoff(util.FetchFileBackoff, func() (bool, error) {
|
||||
for _, filename = range []string{agolaDefaultJsonnetConfigFile, agolaDefaultJsonConfigFile, agolaDefaultYamlConfigFile} {
|
||||
var err error
|
||||
data, err = gitSource.GetFile(repopath, commitSHA, path.Join(agolaDefaultConfigDir, filename))
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
h.log.Errorf("get file err: %v", err)
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return data, filename, nil
|
||||
}
|
||||
|
||||
func (h *ActionHandler) genRunVariables(ctx context.Context, req *CreateRunRequest) (map[string]string, error) {
|
||||
variables := map[string]string{}
|
||||
|
||||
// get project variables
|
||||
pvars, _, err := h.configstoreClient.GetProjectVariables(ctx, req.Project.ID, true)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("failed to get project variables: %w", err)
|
||||
}
|
||||
h.log.Infof("pvars: %v", util.Dump(pvars))
|
||||
|
||||
// remove overriden variables
|
||||
pvars = common.FilterOverriddenVariables(pvars)
|
||||
h.log.Infof("pvars: %v", util.Dump(pvars))
|
||||
|
||||
// get project secrets
|
||||
secrets, _, err := h.configstoreClient.GetProjectSecrets(ctx, req.Project.ID, true)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("failed to get project secrets: %w", err)
|
||||
}
|
||||
h.log.Infof("secrets: %v", util.Dump(secrets))
|
||||
for _, pvar := range pvars {
|
||||
// find the value match
|
||||
var varval types.VariableValue
|
||||
for _, varval = range pvar.Values {
|
||||
h.log.Infof("varval: %v", util.Dump(varval))
|
||||
match := types.MatchWhen(varval.When, req.Branch, req.Tag, req.Ref)
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
// get the secret value referenced by the variable, it must be a secret at the same level or a lower level
|
||||
secret := common.GetVarValueMatchingSecret(varval, pvar.ParentPath, secrets)
|
||||
h.log.Infof("secret: %v", util.Dump(secret))
|
||||
if secret != nil {
|
||||
varValue, ok := secret.Data[varval.SecretVar]
|
||||
if ok {
|
||||
variables[pvar.Name] = varValue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
h.log.Infof("variables: %v", util.Dump(variables))
|
||||
|
||||
return variables, nil
|
||||
}
|
||||
|
|
|
@ -225,6 +225,15 @@ func (c *Client) DeleteProject(ctx context.Context, projectRef string) (*http.Re
|
|||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/projects/%s", url.PathEscape(projectRef)), nil, jsonContent, nil)
|
||||
}
|
||||
|
||||
func (c *Client) ProjectCreateRun(ctx context.Context, projectRef string, req *ProjectCreateRunRequest) (*http.Response, error) {
|
||||
reqj, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.getResponse(ctx, "POST", fmt.Sprintf("/projects/%s/createrun", url.PathEscape(projectRef)), nil, jsonContent, bytes.NewReader(reqj))
|
||||
}
|
||||
|
||||
func (c *Client) ReconfigProject(ctx context.Context, projectRef string) (*http.Response, error) {
|
||||
return c.getResponse(ctx, "PUT", fmt.Sprintf("/projects/%s/reconfig", url.PathEscape(projectRef)), nil, jsonContent, nil)
|
||||
}
|
||||
|
@ -342,7 +351,7 @@ func (c *Client) GetRuns(ctx context.Context, phaseFilter, groups, runGroups []s
|
|||
}
|
||||
|
||||
getRunsResponse := []*RunsResponse{}
|
||||
resp, err := c.getParsedResponse(ctx, "GET", "/runs", q, jsonContent, nil, getRunsResponse)
|
||||
resp, err := c.getParsedResponse(ctx, "GET", "/runs", q, jsonContent, nil, &getRunsResponse)
|
||||
return getRunsResponse, resp, err
|
||||
}
|
||||
|
||||
|
|
|
@ -15,20 +15,15 @@
|
|||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"github.com/sorintlab/agola/internal/config"
|
||||
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
||||
"github.com/sorintlab/agola/internal/gitsources/agolagit"
|
||||
"github.com/sorintlab/agola/internal/runconfig"
|
||||
"github.com/sorintlab/agola/internal/services/common"
|
||||
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
|
||||
"github.com/sorintlab/agola/internal/services/gateway/action"
|
||||
rsapi "github.com/sorintlab/agola/internal/services/runservice/api"
|
||||
rstypes "github.com/sorintlab/agola/internal/services/runservice/types"
|
||||
"github.com/sorintlab/agola/internal/services/types"
|
||||
"github.com/sorintlab/agola/internal/util"
|
||||
|
||||
|
@ -36,37 +31,6 @@ import (
|
|||
errors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultSSHPort = "22"
|
||||
|
||||
agolaDefaultConfigDir = ".agola"
|
||||
agolaDefaultJsonnetConfigFile = "config.jsonnet"
|
||||
agolaDefaultJsonConfigFile = "config.json"
|
||||
agolaDefaultYamlConfigFile = "config.yml"
|
||||
|
||||
// List of runs annotations
|
||||
AnnotationRunType = "run_type"
|
||||
AnnotationRefType = "ref_type"
|
||||
AnnotationProjectID = "projectid"
|
||||
AnnotationUserID = "userid"
|
||||
|
||||
AnnotationRunCreationTrigger = "run_creation_trigger"
|
||||
|
||||
AnnotationCommitSHA = "commit_sha"
|
||||
AnnotationRef = "ref"
|
||||
AnnotationSender = "sender"
|
||||
AnnotationMessage = "message"
|
||||
AnnotationCommitLink = "commit_link"
|
||||
AnnotationCompareLink = "compare_link"
|
||||
|
||||
AnnotationBranch = "branch"
|
||||
AnnotationBranchLink = "branch_link"
|
||||
AnnotationTag = "tag"
|
||||
AnnotationTagLink = "tag_link"
|
||||
AnnotationPullRequestID = "pull_request_id"
|
||||
AnnotationPullRequestLink = "pull_request_link"
|
||||
)
|
||||
|
||||
type webhooksHandler struct {
|
||||
log *zap.SugaredLogger
|
||||
ah *action.ActionHandler
|
||||
|
@ -106,7 +70,6 @@ func (h *webhooksHandler) handleWebhook(r *http.Request) (int, string, error) {
|
|||
var cloneURL string
|
||||
var sshHostKey string
|
||||
var skipSSHHostKeyCheck bool
|
||||
variables := map[string]string{}
|
||||
|
||||
var gitSource gitsource.GitSource
|
||||
if runType == types.RunTypeProject {
|
||||
|
@ -114,7 +77,6 @@ func (h *webhooksHandler) handleWebhook(r *http.Request) (int, string, error) {
|
|||
if err != nil {
|
||||
return http.StatusBadRequest, "", errors.Errorf("failed to get project %s: %w", projectID, err)
|
||||
}
|
||||
h.log.Infof("project: %s", util.Dump(project))
|
||||
project = csProject.Project
|
||||
|
||||
user, _, err := h.configstoreClient.GetUserByLinkedAccount(ctx, project.LinkedAccountID)
|
||||
|
@ -159,46 +121,6 @@ func (h *webhooksHandler) handleWebhook(r *http.Request) (int, string, error) {
|
|||
|
||||
cloneURL = webhookData.SSHURL
|
||||
|
||||
// get project variables
|
||||
pvars, _, err := h.configstoreClient.GetProjectVariables(ctx, project.ID, true)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "", errors.Errorf("failed to get project variables: %w", err)
|
||||
}
|
||||
h.log.Infof("pvars: %v", util.Dump(pvars))
|
||||
|
||||
// remove overriden variables
|
||||
pvars = common.FilterOverriddenVariables(pvars)
|
||||
h.log.Infof("pvars: %v", util.Dump(pvars))
|
||||
|
||||
// get project secrets
|
||||
secrets, _, err := h.configstoreClient.GetProjectSecrets(ctx, project.ID, true)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "", errors.Errorf("failed to get project secrets: %w", err)
|
||||
}
|
||||
h.log.Infof("secrets: %v", util.Dump(secrets))
|
||||
for _, pvar := range pvars {
|
||||
// find the value match
|
||||
var varval types.VariableValue
|
||||
for _, varval = range pvar.Values {
|
||||
h.log.Infof("varval: %v", util.Dump(varval))
|
||||
match := types.MatchWhen(varval.When, webhookData.Branch, webhookData.Tag, webhookData.Ref)
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
// get the secret value referenced by the variable, it must be a secret at the same level or a lower level
|
||||
secret := common.GetVarValueMatchingSecret(varval, pvar.ParentPath, secrets)
|
||||
h.log.Infof("secret: %v", util.Dump(secret))
|
||||
if secret != nil {
|
||||
varValue, ok := secret.Data[varval.SecretVar]
|
||||
if ok {
|
||||
variables[pvar.Name] = varValue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
h.log.Infof("variables: %v", util.Dump(variables))
|
||||
|
||||
} else {
|
||||
gitSource = agolagit.New(h.apiExposedURL + "/repos")
|
||||
var err error
|
||||
|
@ -225,189 +147,35 @@ func (h *webhooksHandler) handleWebhook(r *http.Request) (int, string, error) {
|
|||
|
||||
h.log.Infof("webhookData: %s", util.Dump(webhookData))
|
||||
|
||||
data, filename, err := h.fetchConfigFiles(gitSource, webhookData)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "", errors.Errorf("failed to fetch config file: %w", err)
|
||||
}
|
||||
h.log.Debug("data: %s", data)
|
||||
req := &action.CreateRunRequest{
|
||||
RunType: runType,
|
||||
RefType: common.WebHookEventToRunRefType(webhookData.Event),
|
||||
RunCreationTrigger: types.RunCreationTriggerTypeWebhook,
|
||||
|
||||
gitURL, err := util.ParseGitURL(cloneURL)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "", errors.Errorf("failed to parse clone url: %w", err)
|
||||
}
|
||||
gitHost := gitURL.Hostname()
|
||||
gitPort := gitURL.Port()
|
||||
if gitPort == "" {
|
||||
gitPort = defaultSSHPort
|
||||
}
|
||||
Project: project,
|
||||
User: user,
|
||||
RepoPath: webhookData.Repo.Path,
|
||||
GitSource: gitSource,
|
||||
CommitSHA: webhookData.CommitSHA,
|
||||
Message: webhookData.Message,
|
||||
Branch: webhookData.Branch,
|
||||
Tag: webhookData.Tag,
|
||||
PullRequestID: webhookData.PullRequestID,
|
||||
Ref: webhookData.Ref,
|
||||
SSHPrivKey: sshPrivKey,
|
||||
SSHHostKey: sshHostKey,
|
||||
SkipSSHHostKeyCheck: skipSSHHostKeyCheck,
|
||||
CloneURL: cloneURL,
|
||||
|
||||
// this env vars ovverrides other env vars
|
||||
env := map[string]string{
|
||||
"CI": "true",
|
||||
"AGOLA_SSHPRIVKEY": sshPrivKey,
|
||||
"AGOLA_REPOSITORY_URL": cloneURL,
|
||||
"AGOLA_GIT_HOST": gitHost,
|
||||
"AGOLA_GIT_PORT": gitPort,
|
||||
"AGOLA_GIT_BRANCH": webhookData.Branch,
|
||||
"AGOLA_GIT_TAG": webhookData.Tag,
|
||||
"AGOLA_GIT_REF": webhookData.Ref,
|
||||
"AGOLA_GIT_COMMITSHA": webhookData.CommitSHA,
|
||||
CommitLink: webhookData.CommitLink,
|
||||
BranchLink: webhookData.BranchLink,
|
||||
TagLink: webhookData.TagLink,
|
||||
PullRequestLink: webhookData.PullRequestLink,
|
||||
CompareLink: webhookData.CompareLink,
|
||||
}
|
||||
|
||||
if sshHostKey != "" {
|
||||
env["AGOLA_SSHHOSTKEY"] = sshHostKey
|
||||
}
|
||||
if skipSSHHostKeyCheck {
|
||||
env["AGOLA_SKIPSSHHOSTKEYCHECK"] = "1"
|
||||
}
|
||||
|
||||
refType := common.WebHookEventToRunRefType(webhookData.Event)
|
||||
|
||||
annotations := map[string]string{
|
||||
AnnotationRunType: string(runType),
|
||||
AnnotationRefType: string(refType),
|
||||
AnnotationRunCreationTrigger: string(types.RunCreationTriggerTypeWebhook),
|
||||
AnnotationCommitSHA: webhookData.CommitSHA,
|
||||
AnnotationRef: webhookData.Ref,
|
||||
AnnotationSender: webhookData.Sender,
|
||||
AnnotationMessage: webhookData.Message,
|
||||
AnnotationCommitLink: webhookData.CommitLink,
|
||||
AnnotationCompareLink: webhookData.CompareLink,
|
||||
}
|
||||
|
||||
if runType == types.RunTypeProject {
|
||||
annotations[AnnotationProjectID] = webhookData.ProjectID
|
||||
} else {
|
||||
annotations[AnnotationUserID] = userID
|
||||
}
|
||||
|
||||
if webhookData.Event == types.WebhookEventPush {
|
||||
annotations[AnnotationBranch] = webhookData.Branch
|
||||
annotations[AnnotationBranchLink] = webhookData.BranchLink
|
||||
}
|
||||
if webhookData.Event == types.WebhookEventTag {
|
||||
annotations[AnnotationTag] = webhookData.Tag
|
||||
annotations[AnnotationTagLink] = webhookData.TagLink
|
||||
}
|
||||
if webhookData.Event == types.WebhookEventPullRequest {
|
||||
annotations[AnnotationPullRequestID] = webhookData.PullRequestID
|
||||
annotations[AnnotationPullRequestLink] = webhookData.PullRequestLink
|
||||
}
|
||||
|
||||
var baseGroupType common.GroupType
|
||||
var baseGroupID string
|
||||
var groupType common.GroupType
|
||||
var group string
|
||||
|
||||
if runType == types.RunTypeProject {
|
||||
baseGroupType = common.GroupTypeProject
|
||||
baseGroupID = project.ID
|
||||
} else {
|
||||
baseGroupType = common.GroupTypeUser
|
||||
baseGroupID = user.ID
|
||||
}
|
||||
|
||||
switch refType {
|
||||
case types.RunRefTypeBranch:
|
||||
groupType = common.GroupTypeBranch
|
||||
group = webhookData.Branch
|
||||
case types.RunRefTypeTag:
|
||||
groupType = common.GroupTypeTag
|
||||
group = webhookData.Tag
|
||||
case types.RunRefTypePullRequest:
|
||||
groupType = common.GroupTypePullRequest
|
||||
group = webhookData.PullRequestID
|
||||
}
|
||||
|
||||
runGroup := common.GenRunGroup(baseGroupType, baseGroupID, groupType, group)
|
||||
|
||||
if err := h.createRuns(ctx, filename, data, runGroup, annotations, env, variables, webhookData); err != nil {
|
||||
if err := h.ah.CreateRuns(ctx, req); err != nil {
|
||||
return http.StatusInternalServerError, "", errors.Errorf("failed to create run: %w", err)
|
||||
}
|
||||
//if err := gitSource.CreateStatus(webhookData.Repo.Owner, webhookData.Repo.Name, webhookData.CommitSHA, gitsource.CommitStatusPending, "localhost:8080", "build %s", "agola"); err != nil {
|
||||
// h.log.Errorf("failed to update commit status: %v", err)
|
||||
//}
|
||||
|
||||
return 0, "", nil
|
||||
}
|
||||
|
||||
// fetchConfigFiles tries to fetch a config file in one of the supported formats. The precedence is for jsonnet, then json and then yml
|
||||
// TODO(sgotti) For jsonnet, if we'll support custom import files inside the configdir, also fetch them.
|
||||
func (h *webhooksHandler) fetchConfigFiles(gitSource gitsource.GitSource, webhookData *types.WebhookData) ([]byte, string, error) {
|
||||
var data []byte
|
||||
var filename string
|
||||
err := util.ExponentialBackoff(util.FetchFileBackoff, func() (bool, error) {
|
||||
for _, filename = range []string{agolaDefaultJsonnetConfigFile, agolaDefaultJsonConfigFile, agolaDefaultYamlConfigFile} {
|
||||
var err error
|
||||
data, err = gitSource.GetFile(webhookData.Repo.Path, webhookData.CommitSHA, path.Join(agolaDefaultConfigDir, filename))
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
h.log.Errorf("get file err: %v", err)
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return data, filename, nil
|
||||
}
|
||||
|
||||
func (h *webhooksHandler) createRuns(ctx context.Context, filename string, configData []byte, runGroup string, annotations, staticEnv, variables map[string]string, webhookData *types.WebhookData) error {
|
||||
setupErrors := []string{}
|
||||
|
||||
var configFormat config.ConfigFormat
|
||||
switch path.Ext(filename) {
|
||||
case ".jsonnet":
|
||||
configFormat = config.ConfigFormatJsonnet
|
||||
case ".json":
|
||||
fallthrough
|
||||
case ".yml":
|
||||
configFormat = config.ConfigFormatJSON
|
||||
|
||||
}
|
||||
config, err := config.ParseConfig([]byte(configData), configFormat)
|
||||
if err != nil {
|
||||
log.Errorf("failed to parse config: %+v", err)
|
||||
|
||||
// create a run (per config file) with a generic error since we cannot parse
|
||||
// it and know how many runs are defined
|
||||
setupErrors = append(setupErrors, err.Error())
|
||||
createRunReq := &rsapi.RunCreateRequest{
|
||||
RunConfigTasks: nil,
|
||||
Group: runGroup,
|
||||
SetupErrors: setupErrors,
|
||||
Name: rstypes.RunGenericSetupErrorName,
|
||||
StaticEnvironment: staticEnv,
|
||||
Annotations: annotations,
|
||||
}
|
||||
|
||||
if _, _, err := h.runserviceClient.CreateRun(ctx, createRunReq); err != nil {
|
||||
log.Errorf("failed to create run: %+v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, run := range config.Runs {
|
||||
rcts := runconfig.GenRunConfigTasks(util.DefaultUUIDGenerator{}, config, run.Name, variables, webhookData.Branch, webhookData.Tag, webhookData.Ref)
|
||||
|
||||
h.log.Debugf("rcts: %s", util.Dump(rcts))
|
||||
h.log.Infof("group: %s", runGroup)
|
||||
createRunReq := &rsapi.RunCreateRequest{
|
||||
RunConfigTasks: rcts,
|
||||
Group: runGroup,
|
||||
SetupErrors: setupErrors,
|
||||
Name: run.Name,
|
||||
StaticEnvironment: staticEnv,
|
||||
Annotations: annotations,
|
||||
}
|
||||
|
||||
if _, _, err := h.runserviceClient.CreateRun(ctx, createRunReq); err != nil {
|
||||
log.Errorf("failed to create run: %+v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
||||
"github.com/sorintlab/agola/internal/services/common"
|
||||
"github.com/sorintlab/agola/internal/services/gateway"
|
||||
"github.com/sorintlab/agola/internal/services/gateway/action"
|
||||
rstypes "github.com/sorintlab/agola/internal/services/runservice/types"
|
||||
|
||||
errors "golang.org/x/xerrors"
|
||||
|
@ -98,7 +98,7 @@ func (n *NotificationService) updateCommitStatus(ctx context.Context, ev *rstype
|
|||
description := statusDescription(commitStatus)
|
||||
context := fmt.Sprintf("%s/%s/%s", n.gc.ID, project.Name, run.RunConfig.Name)
|
||||
|
||||
if err := gitSource.CreateCommitStatus(project.RepositoryPath, run.Run.Annotations[gateway.AnnotationCommitSHA], commitStatus, targetURL, description, context); err != nil {
|
||||
if err := gitSource.CreateCommitStatus(project.RepositoryPath, run.Run.Annotations[action.AnnotationCommitSHA], commitStatus, targetURL, description, context); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue