diff --git a/client/gitSensor/GitSensorClient.go b/client/gitSensor/GitSensorClient.go index 159c5e747b..58fee3ca41 100644 --- a/client/gitSensor/GitSensorClient.go +++ b/client/gitSensor/GitSensorClient.go @@ -60,12 +60,13 @@ type HeadRequest struct { type SourceType string type CiPipelineMaterial struct { - Id int - GitMaterialId int - Type SourceType - Value string - Active bool - GitCommit GitCommit + Id int + GitMaterialId int + Type SourceType + Value string + Active bool + GitCommit GitCommit + ExtraEnvironmentVariables map[string]string // extra env variables which will be used for CI } type GitMaterial struct { @@ -100,6 +101,11 @@ type GitCommit struct { WebhookData *WebhookData } +type WebhookAndCiData struct { + ExtraEnvironmentVariables map[string]string `json:"extraEnvironmentVariables"` // extra env variables which will be used for CI + WebhookData *WebhookData `json:"webhookData"` +} + type WebhookData struct { Id int `json:"id"` EventActionType string `json:"eventActionType"` @@ -133,7 +139,8 @@ type RefreshGitMaterialResponse struct { } type WebhookDataRequest struct { - Id int `json:"id"` + Id int `json:"id"` + CiPipelineMaterialId int `json:"ciPipelineMaterialId"` } type WebhookEventConfigRequest struct { @@ -219,7 +226,7 @@ type GitSensorClient interface { SavePipelineMaterial(material []*CiPipelineMaterial) (materialRes []*CiPipelineMaterial, err error) RefreshGitMaterial(req *RefreshGitMaterialRequest) (refreshRes *RefreshGitMaterialResponse, err error) - GetWebhookData(req *WebhookDataRequest) (*WebhookData, error) + GetWebhookData(req *WebhookDataRequest) (*WebhookAndCiData, error) GetAllWebhookEventConfigForHost(req *WebhookEventConfigRequest) (webhookEvents []*WebhookEventConfig, err error) GetWebhookEventConfig(req *WebhookEventConfigRequest) (webhookEvent *WebhookEventConfig, err error) @@ -376,8 +383,8 @@ func (session GitSensorClientImpl) RefreshGitMaterial(req *RefreshGitMaterialReq return refreshRes, err } -func (session GitSensorClientImpl) GetWebhookData(req *WebhookDataRequest) (*WebhookData, error) { - webhookData := new(WebhookData) +func (session GitSensorClientImpl) GetWebhookData(req *WebhookDataRequest) (*WebhookAndCiData, error) { + webhookData := new(WebhookAndCiData) request := &ClientRequest{ResponseBody: webhookData, Method: "GET", RequestBody: req, Path: "webhook/data"} _, _, err := session.doRequest(request) return webhookData, err diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 4c57637a83..a4bddafad6 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -1,8 +1,7 @@ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire -//go:build !wireinject -// +build !wireinject +//+build !wireinject package main diff --git a/pkg/bean/app.go b/pkg/bean/app.go index c5e3c5104b..e0a621170a 100644 --- a/pkg/bean/app.go +++ b/pkg/bean/app.go @@ -215,8 +215,9 @@ type CiRegexPatchRequest struct { } type GitCiTriggerRequest struct { - CiPipelineMaterial CiPipelineMaterial `json:"ciPipelineMaterial" validate:"required"` - TriggeredBy int32 `json:"triggeredBy"` + CiPipelineMaterial CiPipelineMaterial `json:"ciPipelineMaterial" validate:"required"` + TriggeredBy int32 `json:"triggeredBy"` + ExtraEnvironmentVariables map[string]string `json:"extraEnvironmentVariables"` // extra env variables which will be used for CI } type GitCommit struct { diff --git a/pkg/git/GitWebhookService.go b/pkg/git/GitWebhookService.go index 91cdb26ca5..a9bde07504 100644 --- a/pkg/git/GitWebhookService.go +++ b/pkg/git/GitWebhookService.go @@ -70,8 +70,9 @@ func (impl *GitWebhookServiceImpl) HandleGitWebhook(gitWebhookRequest gitSensor. } resp, err := impl.ciHandler.HandleCIWebhook(bean.GitCiTriggerRequest{ - CiPipelineMaterial: ciPipelineMaterial, - TriggeredBy: 1, // Automatic trigger, userId is 1 + CiPipelineMaterial: ciPipelineMaterial, + TriggeredBy: 1, // Automatic trigger, userId is 1 + ExtraEnvironmentVariables: gitWebhookRequest.ExtraEnvironmentVariables, }) if err != nil { impl.logger.Errorw("failed HandleCIWebhook", "err", err) diff --git a/pkg/pipeline/CiHandler.go b/pkg/pipeline/CiHandler.go index 3cb5f8ecf8..ed83bde595 100644 --- a/pkg/pipeline/CiHandler.go +++ b/pkg/pipeline/CiHandler.go @@ -170,11 +170,12 @@ type GitTriggerInfoResponse struct { } type Trigger struct { - PipelineId int - CommitHashes map[int]bean.GitCommit - CiMaterials []*pipelineConfig.CiPipelineMaterial - TriggeredBy int32 - InvalidateCache bool + PipelineId int + CommitHashes map[int]bean.GitCommit + CiMaterials []*pipelineConfig.CiPipelineMaterial + TriggeredBy int32 + InvalidateCache bool + ExtraEnvironmentVariables map[string]string // extra env variables which will be used for CI } const WorkflowCancel = "CANCELLED" @@ -184,16 +185,17 @@ const Starting = "Starting" func (impl *CiHandlerImpl) HandleCIManual(ciTriggerRequest bean.CiTriggerRequest) (int, error) { impl.Logger.Debugw("HandleCIManual for pipeline ", "PipelineId", ciTriggerRequest.PipelineId) - commitHashes, err := impl.buildManualTriggerCommitHashes(ciTriggerRequest) + commitHashes, extraEnvironmentVariables, err := impl.buildManualTriggerCommitHashes(ciTriggerRequest) if err != nil { return 0, err } trigger := Trigger{ - PipelineId: ciTriggerRequest.PipelineId, - CommitHashes: commitHashes, - CiMaterials: nil, - TriggeredBy: ciTriggerRequest.TriggeredBy, - InvalidateCache: ciTriggerRequest.InvalidateCache, + PipelineId: ciTriggerRequest.PipelineId, + CommitHashes: commitHashes, + CiMaterials: nil, + TriggeredBy: ciTriggerRequest.TriggeredBy, + InvalidateCache: ciTriggerRequest.InvalidateCache, + ExtraEnvironmentVariables: extraEnvironmentVariables, } id, err := impl.ciService.TriggerCiPipeline(trigger) if err != nil { @@ -230,10 +232,11 @@ func (impl *CiHandlerImpl) HandleCIWebhook(gitCiTriggerRequest bean.GitCiTrigger } trigger := Trigger{ - PipelineId: ciPipeline.Id, - CommitHashes: commitHashes, - CiMaterials: ciMaterials, - TriggeredBy: gitCiTriggerRequest.TriggeredBy, + PipelineId: ciPipeline.Id, + CommitHashes: commitHashes, + CiMaterials: ciMaterials, + TriggeredBy: gitCiTriggerRequest.TriggeredBy, + ExtraEnvironmentVariables: gitCiTriggerRequest.ExtraEnvironmentVariables, } id, err := impl.ciService.TriggerCiPipeline(trigger) if err != nil { @@ -868,14 +871,15 @@ func SetGitCommitValuesForBuildingCommitHash(ciMaterial *pipelineConfig.CiPipeli return newGitCommit } -func (impl *CiHandlerImpl) buildManualTriggerCommitHashes(ciTriggerRequest bean.CiTriggerRequest) (map[int]bean.GitCommit, error) { +func (impl *CiHandlerImpl) buildManualTriggerCommitHashes(ciTriggerRequest bean.CiTriggerRequest) (map[int]bean.GitCommit, map[string]string, error) { commitHashes := map[int]bean.GitCommit{} + extraEnvironmentVariables := make(map[string]string) for _, ciPipelineMaterial := range ciTriggerRequest.CiPipelineMaterial { pipeLineMaterialFromDb, err := impl.ciPipelineMaterialRepository.GetById(ciPipelineMaterial.Id) if err != nil { impl.Logger.Errorw("err in fetching pipeline material by id", "err", err) - return map[int]bean.GitCommit{}, err + return map[int]bean.GitCommit{}, nil, err } pipelineType := pipeLineMaterialFromDb.Type @@ -883,22 +887,22 @@ func (impl *CiHandlerImpl) buildManualTriggerCommitHashes(ciTriggerRequest bean. gitCommit, err := impl.BuildManualTriggerCommitHashesForSourceTypeBranchFix(ciPipelineMaterial, pipeLineMaterialFromDb) if err != nil { impl.Logger.Errorw("err", "err", err) - return map[int]bean.GitCommit{}, err + return map[int]bean.GitCommit{}, nil, err } commitHashes[ciPipelineMaterial.Id] = gitCommit } else if pipelineType == pipelineConfig.SOURCE_TYPE_WEBHOOK { - gitCommit, err := impl.BuildManualTriggerCommitHashesForSourceTypeWebhook(ciPipelineMaterial, pipeLineMaterialFromDb) + gitCommit, extraEnvVariables, err := impl.BuildManualTriggerCommitHashesForSourceTypeWebhook(ciPipelineMaterial, pipeLineMaterialFromDb) if err != nil { impl.Logger.Errorw("err", "err", err) - return map[int]bean.GitCommit{}, err + return map[int]bean.GitCommit{}, nil, err } commitHashes[ciPipelineMaterial.Id] = gitCommit - + extraEnvironmentVariables = extraEnvVariables } } - return commitHashes, nil + return commitHashes, extraEnvironmentVariables, nil } func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeBranchFix(ciPipelineMaterial bean.CiPipelineMaterial, pipeLineMaterialFromDb *pipelineConfig.CiPipelineMaterial) (bean.GitCommit, error) { @@ -931,19 +935,21 @@ func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeBranchFix( return gitCommit, nil } -func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeWebhook(ciPipelineMaterial bean.CiPipelineMaterial, pipeLineMaterialFromDb *pipelineConfig.CiPipelineMaterial) (bean.GitCommit, error) { +func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeWebhook(ciPipelineMaterial bean.CiPipelineMaterial, pipeLineMaterialFromDb *pipelineConfig.CiPipelineMaterial) (bean.GitCommit, map[string]string, error) { webhookDataInput := ciPipelineMaterial.GitCommit.WebhookData // fetch webhook data on the basis of Id webhookDataRequest := &gitSensor.WebhookDataRequest{ - Id: webhookDataInput.Id, + Id: webhookDataInput.Id, + CiPipelineMaterialId: ciPipelineMaterial.Id, } - webhookData, err := impl.gitSensorClient.GetWebhookData(webhookDataRequest) + webhookAndCiData, err := impl.gitSensorClient.GetWebhookData(webhookDataRequest) if err != nil { impl.Logger.Errorw("err", "err", err) - return bean.GitCommit{}, err + return bean.GitCommit{}, nil, err } + webhookData := webhookAndCiData.WebhookData // if webhook event is of merged type, then fetch latest commit for target branch if webhookData.EventActionType == bean.WEBHOOK_EVENT_MERGED_ACTION_TYPE { @@ -952,7 +958,7 @@ func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeWebhook(ci targetBranchName := webhookData.Data[bean.WEBHOOK_SELECTOR_TARGET_BRANCH_NAME_NAME] if targetBranchName == "" { impl.Logger.Error("target branch not found from webhook data") - return bean.GitCommit{}, err + return bean.GitCommit{}, nil, err } // get latest commit hash for target branch @@ -965,7 +971,7 @@ func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeWebhook(ci if err != nil { impl.Logger.Errorw("err", "err", err) - return bean.GitCommit{}, err + return bean.GitCommit{}, nil, err } // update webhookData (local) with target latest hash @@ -986,7 +992,7 @@ func (impl *CiHandlerImpl) BuildManualTriggerCommitHashesForSourceTypeWebhook(ci }, } - return gitCommit, nil + return gitCommit, webhookAndCiData.ExtraEnvironmentVariables, nil } func (impl *CiHandlerImpl) getLastSeenCommit(ciMaterialId int) (bean.GitCommit, error) { diff --git a/pkg/pipeline/CiService.go b/pkg/pipeline/CiService.go index 8e796ae39e..74b1891e75 100644 --- a/pkg/pipeline/CiService.go +++ b/pkg/pipeline/CiService.go @@ -482,6 +482,7 @@ func (impl *CiServiceImpl) buildWfRequestForCiPipeline(pipeline *pipelineConfig. IgnoreDockerCachePush: impl.ciConfig.IgnoreDockerCacheForCI, IgnoreDockerCachePull: impl.ciConfig.IgnoreDockerCacheForCI, CacheInvalidate: trigger.InvalidateCache, + ExtraEnvironmentVariables: trigger.ExtraEnvironmentVariables, } if ciWorkflowConfig.LogsBucket == "" { diff --git a/pkg/pipeline/WorkflowDagExecutor.go b/pkg/pipeline/WorkflowDagExecutor.go index 47d7fc537f..384b70a37b 100644 --- a/pkg/pipeline/WorkflowDagExecutor.go +++ b/pkg/pipeline/WorkflowDagExecutor.go @@ -23,6 +23,7 @@ import ( "fmt" "github.com/argoproj/gitops-engine/pkg/health" blob_storage "github.com/devtron-labs/common-lib/blob-storage" + "github.com/devtron-labs/devtron/client/gitSensor" "github.com/devtron-labs/devtron/util/argo" "go.opentelemetry.io/otel" "strconv" @@ -101,6 +102,7 @@ type WorkflowDagExecutorImpl struct { CiTemplateRepository pipelineConfig.CiTemplateRepository ciWorkflowRepository pipelineConfig.CiWorkflowRepository appLabelRepository pipelineConfig.AppLabelRepository + gitSensorClient gitSensor.GitSensorClient } const ( @@ -165,7 +167,7 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi pipelineStatusTimelineService app.PipelineStatusTimelineService, CiTemplateRepository pipelineConfig.CiTemplateRepository, ciWorkflowRepository pipelineConfig.CiWorkflowRepository, - appLabelRepository pipelineConfig.AppLabelRepository) *WorkflowDagExecutorImpl { + appLabelRepository pipelineConfig.AppLabelRepository, gitSensorClient gitSensor.GitSensorClient) *WorkflowDagExecutorImpl { wde := &WorkflowDagExecutorImpl{logger: Logger, pipelineRepository: pipelineRepository, cdWorkflowRepository: cdWorkflowRepository, @@ -196,6 +198,7 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi CiTemplateRepository: CiTemplateRepository, ciWorkflowRepository: ciWorkflowRepository, appLabelRepository: appLabelRepository, + gitSensorClient: gitSensorClient, } err := wde.Subscribe() if err != nil { @@ -738,10 +741,33 @@ func (impl *WorkflowDagExecutorImpl) buildWFRequest(runner *pipelineConfig.CdWor if ciWf != nil && ciWf.GitTriggers != nil { i := 1 - for _, gitTrigger := range ciWf.GitTriggers { + for ciPipelineMaterialId, gitTrigger := range ciWf.GitTriggers { extraEnvVariables[fmt.Sprintf("%s_%d", GIT_COMMIT_HASH_PREFIX, i)] = gitTrigger.Commit extraEnvVariables[fmt.Sprintf("%s_%d", GIT_SOURCE_TYPE_PREFIX, i)] = string(gitTrigger.CiConfigureSourceType) extraEnvVariables[fmt.Sprintf("%s_%d", GIT_SOURCE_VALUE_PREFIX, i)] = gitTrigger.CiConfigureSourceValue + + // CODE-BLOCK starts - store extra environment variables if webhook + if gitTrigger.CiConfigureSourceType == pipelineConfig.SOURCE_TYPE_WEBHOOK { + webhookDataId := gitTrigger.WebhookData.Id + if webhookDataId > 0 { + webhookDataRequest := &gitSensor.WebhookDataRequest{ + Id: webhookDataId, + CiPipelineMaterialId: ciPipelineMaterialId, + } + webhookAndCiData, err := impl.gitSensorClient.GetWebhookData(webhookDataRequest) + if err != nil { + impl.logger.Errorw("err while getting webhook data from git-sensor", "err", err, "webhookDataRequest", webhookDataRequest) + return nil, err + } + if webhookAndCiData != nil { + for extEnvVariableKey, extEnvVariableVal := range webhookAndCiData.ExtraEnvironmentVariables { + extraEnvVariables[extEnvVariableKey] = extEnvVariableVal + } + } + } + } + // CODE_BLOCK ends + i++ } extraEnvVariables[GIT_SOURCE_COUNT] = strconv.Itoa(len(ciWf.GitTriggers)) diff --git a/pkg/pipeline/WorkflowService.go b/pkg/pipeline/WorkflowService.go index 7c57253140..96b2230a36 100644 --- a/pkg/pipeline/WorkflowService.go +++ b/pkg/pipeline/WorkflowService.go @@ -116,6 +116,7 @@ type WorkflowRequest struct { IgnoreDockerCachePull bool `json:"ignoreDockerCachePull"` CacheInvalidate bool `json:"cacheInvalidate"` IsPvcMounted bool `json:"IsPvcMounted"` + ExtraEnvironmentVariables map[string]string `json:"extraEnvironmentVariables"` } const ( diff --git a/scripts/sql/115_jira_issue_validator_plugin.down.sql b/scripts/sql/115_jira_issue_validator_plugin.down.sql new file mode 100644 index 0000000000..993732ca44 --- /dev/null +++ b/scripts/sql/115_jira_issue_validator_plugin.down.sql @@ -0,0 +1,4 @@ +DELETE FROM plugin_step_variable WHERE name = 'JiraUsername'; +DELETE FROM plugin_step_variable WHERE name = 'JiraPassword'; +DELETE FROM plugin_step_variable WHERE name = 'JiraBaseUrl'; +DELETE FROM plugin_step_variable WHERE name = 'JiraId'; \ No newline at end of file diff --git a/scripts/sql/115_jira_issue_validator_plugin.up.sql b/scripts/sql/115_jira_issue_validator_plugin.up.sql new file mode 100644 index 0000000000..4f7b3c5d3f --- /dev/null +++ b/scripts/sql/115_jira_issue_validator_plugin.up.sql @@ -0,0 +1,71 @@ +INSERT INTO plugin_metadata (id,name,description,type,icon,deleted,created_on,created_by,updated_on,updated_by) +VALUES (nextval('id_seq_plugin_metadata'),'Jira Issue Validator','This plugin extends the filtering capabilities of the Devtron CI and lets the users perform validation based on JIRA Ticket ID status.','PRESET','https://raw.githubusercontent.com/devtron-labs/devtron/main/assets/plugin-jira.png',false,'now()',1,'now()',1); + +INSERT INTO "plugin_pipeline_script" ("id", "script","type","deleted","created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_pipeline_script'), + '#!/bin/sh +# step-1 -> find the jira issue +echo -e "\033[1m======== Finding the Jira issue ========" +curl -u $JiraUsername:$JiraPassword $JiraBaseUrl/rest/api/2/issue/$JiraId > jira_issue_search_result.txt + +if [ $? != 0 ]; then + echo -e "\033[1m======== Finding the jira issue failed ========" + exit 1 +fi + +# step-2 -> converting to JSON +echo "Converting to json result" +cat jira_issue_search_result.txt | jq > jira_issue_search_result_json.txt + +if [ $? != 0 ]; then + echo -e "\033[1m======== Converting to json result failed ========" + exit 1 +fi + +# step-3 -> Find the error message from JSON result +echo "Finding the error message from JSON result" +jq ".errorMessages" jira_issue_search_result_json.txt > error_message.txt +jq ".fields.status.statusCategory.name" jira_issue_search_result_json.txt > jira_issue_status_category_name.txt + +if [ $? != 0 ]; then + echo -e "\033[1m======== Finding the error message from JSON result failed ========" + exit 1 +fi + +# step-4 -> check if error message if null or not +echo "checking if error message is not null" + +if [ null == "$(cat error_message.txt)" ] ;then + echo -e "\033[1m======== Jira issue exists ========" + echo "validating jira issue status" + if [ "\"Done\"" == "$(cat jira_issue_status_category_name.txt)" ] ;then + echo -e "\033[1m======== Jira issue is in closed state ========" + exit 1 + else + echo -e "\033[1m======== Jira issue is not in closed state ========" + fi +else + echo -e "\033[1m======== Jira issue does not exist ========" + exit 1 +fi +' + , + 'SHELL', + 'f', + 'now()', + 1, + 'now()', + 1 +); + +INSERT INTO "plugin_step" ("id", "plugin_id","name","description","index","step_type","script_id","deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES (nextval('id_seq_plugin_step'), (SELECT id FROM plugin_metadata WHERE name='Jira Issue Validator'),'Step 1','Step 1 - Jira Issue Validator','1','INLINE',(SELECT last_value FROM id_seq_plugin_pipeline_script),'f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value", "variable_type", "value_type", "variable_step_index", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Validator' and ps."index"=1 and ps.deleted=false), 'JiraUsername','STRING','Username of Jira account',true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1), +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Validator' and ps."index"=1 and ps.deleted=false), 'JiraPassword','STRING','Password of Jira account',true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1), +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Validator' and ps."index"=1 and ps.deleted=false), 'JiraBaseUrl','STRING','Base Url of Jira account',true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value","value","variable_type", "value_type", "variable_step_index",reference_variable_name, "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Validator' and ps."index"=1 and ps.deleted=false), 'JiraId','STRING','Jira Id',false,true,3,'INPUT','GLOBAL',1 ,'JIRA_ID','f','now()', 1, 'now()', 1); \ No newline at end of file diff --git a/scripts/sql/116_jira_issue_updater_plugin.down.sql b/scripts/sql/116_jira_issue_updater_plugin.down.sql new file mode 100644 index 0000000000..d53c583691 --- /dev/null +++ b/scripts/sql/116_jira_issue_updater_plugin.down.sql @@ -0,0 +1,2 @@ +DELETE FROM plugin_step_variable +WHERE plugin_step_id = (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false); \ No newline at end of file diff --git a/scripts/sql/116_jira_issue_updater_plugin.up.sql b/scripts/sql/116_jira_issue_updater_plugin.up.sql new file mode 100644 index 0000000000..d17f02f772 --- /dev/null +++ b/scripts/sql/116_jira_issue_updater_plugin.up.sql @@ -0,0 +1,65 @@ +INSERT INTO plugin_metadata (id,name,description,type,icon,deleted,created_on,created_by,updated_on,updated_by) +VALUES (nextval('id_seq_plugin_metadata'),'Jira Issue Updater','This plugin extends the capabilities of Devtron CI and can update issues in JIRA by adding pipeline status and metadata as comment on the tickets.','PRESET','https://raw.githubusercontent.com/devtron-labs/devtron/main/assets/plugin-jira.png',false,'now()',1,'now()',1); + +INSERT INTO "plugin_pipeline_script" ("id", "script","type","deleted","created_on", "created_by", "updated_on", "updated_by") +VALUES ( + nextval('id_seq_plugin_pipeline_script'), + '#!/bin/sh +if [[ $UpdateWithBuildStatus == true ]] +then + # step-1 -> updating the jira issue with build status + echo -e "\033[1m======== Updating the Jira issue with build status ========" + buildStatusMessage="Failed" + if [[ $BuildSuccess == true ]] + then + buildStatusMessage="Succeeded" + fi + curl -u $JiraUsername:$JiraPassword -X PUT $JiraBaseUrl/rest/api/2/issue/$JiraId -H "Content-Type: application/json" -d ''{"update": {"comment": [{"add":{"body":"''"Build status : $buildStatusMessage"''"}}]}}'' + + if [ $? != 0 ]; then + echo -e "\033[1m======== Updating the jira Jira with build status failed ========" + exit 1 + fi +fi + +if [[ $UpdateWithDockerImageId == true && $BuildSuccess == true ]] +then + # step-2 -> updating the jira issue with docker image Id + echo -e "\033[1m======== Updating the Jira issue with docker image Id ========" + curl -u $JiraUsername:$JiraPassword -X PUT $JiraBaseUrl/rest/api/2/issue/$JiraId -H "Content-Type: application/json" -d ''{"update": {"comment": [{"add":{"body":"''"Image built : $DockerImage"''"}}]}}'' + + if [ $? != 0 ]; then + echo -e "\033[1m======== Updating the jira Jira with docker image Id failed ========" + exit 1 + fi +fi +' + , + 'SHELL', + 'f', + 'now()', + 1, + 'now()', + 1 +); + +INSERT INTO "plugin_step" ("id", "plugin_id","name","description","index","step_type","script_id","deleted", "created_on", "created_by", "updated_on", "updated_by") +VALUES (nextval('id_seq_plugin_step'), (SELECT id FROM plugin_metadata WHERE name='Jira Issue Updater'),'Step 1','Step 1 - Jira Issue Updater','1','INLINE',(SELECT last_value FROM id_seq_plugin_pipeline_script),'f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value", "variable_type", "value_type", "variable_step_index", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'JiraUsername','STRING','Username of Jira account',true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1), +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'JiraPassword','STRING','Password of Jira account',true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1), +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'JiraBaseUrl','STRING','Base Url of Jira account',true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value", "default_value", "variable_type", "value_type", "variable_step_index", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'UpdateWithDockerImageId','BOOL','If true - Jira Issue will be updated with docker image Id in comment. Default: true',true,true, true, 'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1), +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'UpdateWithBuildStatus','BOOL','If true - Jira Issue will be updated with build status in comment. Default: true',true,true,true,'INPUT','NEW',1 ,'f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value","value","variable_type", "value_type", "variable_step_index",reference_variable_name, "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'JiraId','STRING','Jira Id',false,true,3,'INPUT','GLOBAL',1 ,'JIRA_ID','f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value","value","variable_type", "value_type", "variable_step_index",reference_variable_name, "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'DockerImage','STRING','Docker Image',false,true,3,'INPUT','GLOBAL',1 ,'DOCKER_IMAGE','f','now()', 1, 'now()', 1); + +INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value","value","variable_type", "value_type", "variable_step_index",reference_variable_name, "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES +(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Jira Issue Updater' and ps."index"=1 and ps.deleted=false), 'BuildSuccess','BOOL','Build Success',false,true,3,'INPUT','GLOBAL',1 ,'BUILD_SUCCESS','f','now()', 1, 'now()', 1); \ No newline at end of file diff --git a/scripts/sql/54_create_dtrack_plugin.up.sql b/scripts/sql/54_create_dtrack_plugin.up.sql index ba36566137..0f356687a6 100644 --- a/scripts/sql/54_create_dtrack_plugin.up.sql +++ b/scripts/sql/54_create_dtrack_plugin.up.sql @@ -179,7 +179,7 @@ VALUES ((nextval('id_seq_plugin_step_variable')), (select currval('id_seq_plugin INSERT INTO "public"."plugin_metadata" ("id", "name", "description", "type", "icon", "deleted", "created_on", "created_by", "updated_on", "updated_by") -VALUES (nextval('id_seq_plugin_metadata'), 'Dependency track for Maven & Gradle)', +VALUES (nextval('id_seq_plugin_metadata'), 'Dependency track for Maven & Gradle', 'Creates a bill of materials from Maven/Gradle projects and environments and uploads it to D-track for Component Analysis, to identify and reduce risk in the software supply chain.', 'PRESET', 'https://raw.githubusercontent.com/devtron-labs/devtron/main/assets/dTrack-plugin-icon.png', 'f', 'now()', '1', @@ -233,7 +233,7 @@ fi', 'SHELL', 'f', 'now()', '1', 'now()', '1'); INSERT INTO "public"."plugin_step" ("id", "plugin_id", "name", "description", "index", "step_type", "script_id", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES ((nextval('id_seq_plugin_step')), (select currval('id_seq_plugin_metadata')), 'Step 1', - 'Step 1 for Dependency Track for Maven & Gradle)', '1', 'INLINE', + 'Step 1 for Dependency Track for Maven & Gradle', '1', 'INLINE', (select currval('id_seq_plugin_pipeline_script')), 'f', 'now()', '1', 'now()', '1'); diff --git a/wire_gen.go b/wire_gen.go index 3cd1df4427..39cc8779ff 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -1,8 +1,7 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate wire -//go:build !wireinject -// +build !wireinject +//go:generate go run github.com/google/wire/cmd/wire +//+build !wireinject package main @@ -354,13 +353,6 @@ func InitializeApp() (*App, error) { prePostCdScriptHistoryRepositoryImpl := repository6.NewPrePostCdScriptHistoryRepositoryImpl(sugaredLogger, db) prePostCdScriptHistoryServiceImpl := history.NewPrePostCdScriptHistoryServiceImpl(sugaredLogger, prePostCdScriptHistoryRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl) ciTemplateRepositoryImpl := pipelineConfig.NewCiTemplateRepositoryImpl(db, sugaredLogger) - workflowDagExecutorImpl := pipeline.NewWorkflowDagExecutorImpl(sugaredLogger, pipelineRepositoryImpl, cdWorkflowRepositoryImpl, pubSubClientServiceImpl, appServiceImpl, cdWorkflowServiceImpl, cdConfig, ciArtifactRepositoryImpl, ciPipelineRepositoryImpl, materialRepositoryImpl, pipelineOverrideRepositoryImpl, userServiceImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, enforcerImpl, enforcerUtilImpl, tokenCache, acdAuthConfig, eventSimpleFactoryImpl, eventRESTClientImpl, cvePolicyRepositoryImpl, imageScanResultRepositoryImpl, appWorkflowRepositoryImpl, prePostCdScriptHistoryServiceImpl, argoUserServiceImpl, pipelineStatusTimelineRepositoryImpl, pipelineStatusTimelineServiceImpl, ciTemplateRepositoryImpl, ciWorkflowRepositoryImpl, appLabelRepositoryImpl) - deploymentGroupAppRepositoryImpl := repository.NewDeploymentGroupAppRepositoryImpl(sugaredLogger, db) - deploymentGroupServiceImpl := deploymentGroup.NewDeploymentGroupServiceImpl(appRepositoryImpl, sugaredLogger, pipelineRepositoryImpl, ciPipelineRepositoryImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, deploymentGroupAppRepositoryImpl, ciArtifactRepositoryImpl, appWorkflowRepositoryImpl, workflowDagExecutorImpl) - deploymentConfigServiceImpl := pipeline.NewDeploymentConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, pipelineRepositoryImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl, chartRefRepositoryImpl) - pipelineTriggerRestHandlerImpl := restHandler.NewPipelineRestHandler(appServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, sugaredLogger, enforcerUtilImpl, workflowDagExecutorImpl, deploymentGroupServiceImpl, argoUserServiceImpl, deploymentConfigServiceImpl) - sseSSE := sse.NewSSE() - pipelineTriggerRouterImpl := router.NewPipelineTriggerRouter(pipelineTriggerRestHandlerImpl, sseSSE) gitSensorConfig, err := gitSensor.GetGitSensorConfig() if err != nil { return nil, err @@ -369,6 +361,13 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } + workflowDagExecutorImpl := pipeline.NewWorkflowDagExecutorImpl(sugaredLogger, pipelineRepositoryImpl, cdWorkflowRepositoryImpl, pubSubClientServiceImpl, appServiceImpl, cdWorkflowServiceImpl, cdConfig, ciArtifactRepositoryImpl, ciPipelineRepositoryImpl, materialRepositoryImpl, pipelineOverrideRepositoryImpl, userServiceImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, enforcerImpl, enforcerUtilImpl, tokenCache, acdAuthConfig, eventSimpleFactoryImpl, eventRESTClientImpl, cvePolicyRepositoryImpl, imageScanResultRepositoryImpl, appWorkflowRepositoryImpl, prePostCdScriptHistoryServiceImpl, argoUserServiceImpl, pipelineStatusTimelineRepositoryImpl, pipelineStatusTimelineServiceImpl, ciTemplateRepositoryImpl, ciWorkflowRepositoryImpl, appLabelRepositoryImpl, gitSensorClientImpl) + deploymentGroupAppRepositoryImpl := repository.NewDeploymentGroupAppRepositoryImpl(sugaredLogger, db) + deploymentGroupServiceImpl := deploymentGroup.NewDeploymentGroupServiceImpl(appRepositoryImpl, sugaredLogger, pipelineRepositoryImpl, ciPipelineRepositoryImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, deploymentGroupAppRepositoryImpl, ciArtifactRepositoryImpl, appWorkflowRepositoryImpl, workflowDagExecutorImpl) + deploymentConfigServiceImpl := pipeline.NewDeploymentConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, pipelineRepositoryImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl, chartRefRepositoryImpl) + pipelineTriggerRestHandlerImpl := restHandler.NewPipelineRestHandler(appServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, sugaredLogger, enforcerUtilImpl, workflowDagExecutorImpl, deploymentGroupServiceImpl, argoUserServiceImpl, deploymentConfigServiceImpl) + sseSSE := sse.NewSSE() + pipelineTriggerRouterImpl := router.NewPipelineTriggerRouter(pipelineTriggerRestHandlerImpl, sseSSE) ciConfig, err := pipeline.GetCiConfig() if err != nil { return nil, err