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

misc: cd trigger plugin fix #6050

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions scripts/sql/30902500_devtron_cd_trigger_v1_1.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DELETE FROM plugin_step_variable WHERE plugin_step_id=(SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger');
DELETE FROM plugin_step where plugin_id=(SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger');
DELETE FROM plugin_pipeline_script where id=(SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger');
DELETE FROM plugin_stage_mapping where plugin_id=(SELECT id from plugin_metadata where name='Devtron CD Trigger');
DELETE FROM plugin_metadata where name='Devtron CD Trigger';
UPDATE plugin_metadata SET is_latest = true WHERE id = (SELECT id FROM plugin_metadata WHERE name= 'Devtron CD Trigger v1.0.0' and is_latest= false);
266 changes: 266 additions & 0 deletions scripts/sql/30902500_devtron_cd_trigger_v1_1.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
UPDATE plugin_metadata SET is_latest = false WHERE id = (SELECT id FROM plugin_metadata WHERE name= 'Devtron CD Trigger v1.0.0' and is_latest= true);

INSERT INTO "plugin_metadata" ("id", "name", "description","deleted", "created_on", "created_by", "updated_on", "updated_by","plugin_parent_metadata_id","plugin_version","is_deprecated","is_latest")
VALUES (nextval('id_seq_plugin_metadata'), 'Devtron CD Trigger','Triggers the CD pipeline of Devtron Application','f', 'now()', 1, 'now()', 1, (SELECT id FROM plugin_parent_metadata WHERE identifier='devtron-cd-trigger-v1-0-0'),'1.1.0', false, true);

INSERT INTO "plugin_stage_mapping" ("plugin_id","stage_type","created_on", "created_by", "updated_on", "updated_by")
VALUES ((SELECT id FROM plugin_metadata WHERE plugin_version='1.1.0' and name='Devtron CD Trigger' and deleted= false),0,'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'),
E'#!/bin/bash
pipeline_type=$(echo $CI_CD_EVENT | jq -r \'.type\')
if [[ "$pipeline_type" == "CI" ]]; then
triggeredFromAppName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.appName\')
triggeredFromPipelineName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.pipelineName\')
elif [[ "$pipeline_type" == "CD" ]]; then
triggeredFromAppName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.extraEnvironmentVariables.APP_NAME\')
triggeredFromPipelineName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.Pipeline.Name\')
fi
# Convert CD Workflow Type to uppercase to make it case-insensitive
TargetTriggerStage=$(echo "$TargetTriggerStage" | tr \'[:lower:]\' \'[:upper:]\')

# Set default value for TargetTriggerStage to DEPLOY if not provided or invalid
case $TargetTriggerStage in
"PRE")
;;
"POST")
;;
"DEPLOY")
;;
"")
TargetTriggerStage="DEPLOY" # Set to DEPLOY if no input provided
;;
*)
echo "Error: Invalid CD Workflow Type. Please enter PRE/DEPLOY/POST. Exiting..."
exit 1
;;
esac

# Set default value for StatusTimeOutSeconds to 0 if not provided or not an integer
if ! [[ "$StatusTimeOutSeconds" =~ ^[0-9]+$ ]]; then
StatusTimeOutSeconds=0
fi

DevtronEndpoint=$(echo "$DevtronEndpoint" | sed \'s:/*$::\')

# Determine sleep interval based on StatusTimeOutSeconds
if [ "$StatusTimeOutSeconds" -lt "60" ]; then
sleepInterval=$(($StatusTimeOutSeconds / 2))
else
sleepInterval=30
fi

verify(){
local response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/devtron/auth/verify")
echo $response
exit 1
}
verify_response=$(verify)
verify_status=$( echo "$verify_response" | jq \'.code\')
# echo $verify_status
if [[ "$verify_status" == "401" ]]; then
echo "Enter the valid DevtronApiToken. Exiting..."
exit 1
elif [[ -z "$verify_status" ]]; then
echo "Enter the valid DevtronEndpoint. Exiting..."
exit 1
fi

fetch_app_id() {
# Check if DevtronApp is numeric, if yes, use it directly as App ID
if [[ "$DevtronApp" =~ ^[0-9]+$ ]]; then
echo "$DevtronApp"
else
local api_response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/app/autocomplete")
local app_id=$(echo "$api_response" | jq -r --arg app_name "$DevtronApp" \'.result[] | select(.name == $app_name) | .id\')

if [[ -z "$app_id" || "$app_id" == "null" ]]; then
echo "Error: Application \'$DevtronApp\' not found. Please verify the DevtronApp."
exit 1
fi
echo "$app_id"
fi
}

fetch_env_id() {
# Check if DevtronEnv is numeric, if yes, use it directly as Env ID
if [[ "$DevtronEnv" =~ ^[0-9]+$ ]]; then
echo "$DevtronEnv"
else
local api_response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/env/autocomplete")
local env_id=$(echo "$api_response" | jq -r --arg env_name "$DevtronEnv" \'.result[] | select(.environment_name == $env_name) | .id\')

if [[ -z "$env_id" || "$env_id" == "null" ]]; then
echo "Error: Environment \'$DevtronEnv\' not found. Please verify the DevtronEnv."
exit 1
fi
echo "$env_id"
fi
}

fetch_pipeline_id() {
local app_id=$1
local env_id=$2
local api_response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/app/app-wf/view/$app_id")
local pipeline_id=$(echo "$api_response" | jq -r --arg env_id "$env_id" \'.result.cdConfig.pipelines[] | select(.environmentId == ($env_id | tonumber)) | .id\')

if [[ -z "$pipeline_id" || "$pipeline_id" == "null" ]]; then
echo "Error: Pipeline not found for the provided Environment. Please verify the Environment ID."
echo "Environment ID: $env_id"
echo "API Response: $api_response"
exit 1
fi
echo "$pipeline_id"
}

fetch_ci_artifact_id() {
local pipeline_id=$1
local apiUrl="$DevtronEndpoint/orchestrator/app/cd-pipeline/$pipeline_id/material?offset=0&size=20&stage=$TargetTriggerStage"
local apiResponse=$(curl -s -H "token: $DevtronApiToken" "$apiUrl")

local ciArtifactId=""
if [[ -n "$GitCommitHash" ]]; then
ciArtifactId=$(echo "$apiResponse" | jq -r --arg hash "$GitCommitHash" \'.result.ci_artifacts[] | select(.material_info[].revision == $hash) | .id\' | head -n 1)
if [[ -z "$ciArtifactId" || "$ciArtifactId" == "null" || "$ciArtifactId" == "" ]]; then
echo "Error: CI Artifact ID for the provided commit hash \'$GitCommitHash\' not found. Please verify the commit hash."
exit 1
fi
else
ciArtifactId=$(echo "$apiResponse" | jq -r \'.result.ci_artifacts[0].id\')
if [[ -z "$ciArtifactId" || "$ciArtifactId" == "null" ]]; then
echo "Error: CI Artifact ID not found."
exit 1
fi
fi

echo "$ciArtifactId"
}

# Fetch the app ID. Exit the script if the app name is incorrect.
app_id=$(fetch_app_id)
if [ $? -ne 0 ]; then
echo "Error: Application \'$DevtronApp\' not found. Enter the correct App Name. Exiting...."
exit 1
fi

# Fetch the env ID. Exit the script if the environment name or ID is incorrect.
env_id=$(fetch_env_id)
if [ $? -ne 0 ]; then
echo "Error: Environment \'$DevtronEnv\' not found. Enter the correct Environment Name. Exiting..."
exit 1
fi

# Fetch the pipeline ID using the env ID. Exit the script if the environment is incorrect.
pipeline_id=$(fetch_pipeline_id "$app_id" "$env_id")
if [ $? -ne 0 ]; then
echo "Verify your App Name/ID and Env Name/ID. Exiting..."
exit 1
fi

# Fetch the CI Artifact ID based on the commit hash.
ciArtifactId=$(fetch_ci_artifact_id "$pipeline_id")
if [ $? -ne 0 ]; then
echo "Enter the correct GitCommitHash. Exiting..."
exit 1
fi

trigger_cd_pipeline() {
local pipeline_id=$1
local app_id=$2
local ciArtifactId=$3
local jsonPayload=$(jq -n \\
--arg pipelineId "$pipeline_id" \\
--arg appId "$app_id" \\
--arg ciArtifactId "$ciArtifactId" \\
--arg TargetTriggerStage "$TargetTriggerStage" \\
--arg deploymentWithConfig "LAST_SAVED_CONFIG" \\
--arg triggeredFromAppName "$triggeredFromAppName" \\
--arg triggeredFromPipelineName "$triggeredFromPipelineName" \\
\'{
pipelineId: ($pipelineId | tonumber),
appId: ($appId | tonumber),
ciArtifactId: ($ciArtifactId | tonumber),
cdWorkflowType: $TargetTriggerStage,
deploymentWithConfig: $deploymentWithConfig,
triggeredFromAppName: $triggeredFromAppName,
triggeredFromPipelineName: $triggeredFromPipelineName
}\')

curl -sS -X POST "$DevtronEndpoint/orchestrator/app/cd-pipeline/trigger" \\
-H "Content-Type: application/json" \\
-H "token: $DevtronApiToken" \\
--data "$jsonPayload" \\
--compressed
}

echo "Triggering CD Pipeline for App ID: $app_id, Pipeline ID: $pipeline_id, CI Artifact ID: $ciArtifactId, and CD Workflow Type: $TargetTriggerStage"
cd_pipeline=$(trigger_cd_pipeline "$pipeline_id" "$app_id" "$ciArtifactId")

check_deploy_status() {
if [ "$StatusTimeOutSeconds" -le "0" ]; then
echo "Skipping deployment status check. Taking StatusTimeOutSecond0 as a default input"
return
fi

local appId=$1
local pipelineId=$2
local max_wait=$StatusTimeOutSeconds
local statusKey="deploy_status" # Default status key

if [[ "$TargetTriggerStage" == "PRE" ]]; then
statusKey="pre_status"
elif [[ "$TargetTriggerStage" == "POST" ]]; then
statusKey="post_status"
fi

local start_time=$(date +%s)

while :; do
local current_time=$(date +%s)
local elapsed_time=$((current_time - start_time))

if [ "$elapsed_time" -ge "$max_wait" ]; then
echo "Timeout reached without success. Exiting..."
exit 1
fi

local statusUrl="$DevtronEndpoint/orchestrator/app/workflow/status/$appId/v2"
local response=$(curl -s -H "token: $DevtronApiToken" "$statusUrl")
local code=$(echo "$response" | jq -r \'.code\')

if [ "$code" != "200" ]; then
echo "Error: Received response - $response. Exiting..."
exit 1
fi
local status=$(echo "$response" | jq -r --arg pipelineId "$pipelineId" --arg statusKey "$statusKey" \'.result.cdWorkflowStatus[] | select(.pipeline_id == ($pipelineId | tonumber)) | .[$statusKey]\')

echo "Current $TargetTriggerStage status: $status"

if [[ "$status" == "Succeeded" ]]; then
echo "Deployment succeeded."
break
elif [[ "$status" == "Failed" ]]; then
echo "$TargetTriggerStage workflow failed."
exit 1
fi

sleep $sleepInterval
done
}

# Optionally check the deployment status based on the CD workflow type
check_deploy_status "$app_id" "$pipeline_id"','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='Devtron CD Trigger'),'Step 1','Runnig the plugin','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,default_value,value,variable_type,value_type,previous_step_index,variable_step_index,variable_step_index_in_plugin,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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'DevtronApiToken','STRING','Enter Devtron API Token','t','f',null,null,'INPUT','NEW',null,1,null,null,'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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'DevtronEndpoint','STRING','Enter URL of Devtron','t','f',null,null,'INPUT','NEW',null,1,null,null,'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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'DevtronApp','STRING','Enter the Devtron Application name/Id','t','f',null,null,'INPUT','NEW',null,1,null,null,'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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'DevtronEnv','STRING','Enter the Environment name/Id','t','f',null,null,'INPUT','NEW',null,1,null,null,'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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'StatusTimeOutSeconds','STRING','Enter the maximum time (in seconds) a user can wait for the application to deploy.Enter a postive integer value','t','t',0,null,'INPUT','NEW',null,1,null,null,'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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'GitCommitHash','STRING','Enter the git hash from which user wants to deploy its application. By deault it takes latest Artifact ID to deploy the application','t','t',null,null,'INPUT','NEW',null,1,null,null,'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='Devtron CD Trigger' and ps."index"=1 and ps.deleted=false),'TargetTriggerStage','STRING','Enter Trigger Stage PRE/DEPLOY/POST, Default DEPLOY','t','t','DEPLOY',null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1);
Loading