Skip to content

Commit 61beb25

Browse files
feat: Support to trigger with same hash in CD trigger plugin (#6205)
* cd trigger v2 * changes in down script --------- Co-authored-by: Pawan Mehta <[email protected]>
1 parent 0e2ba49 commit 61beb25

File tree

2 files changed

+309
-0
lines changed

2 files changed

+309
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
DELETE FROM plugin_step_variable WHERE plugin_step_id=(SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger' and plugin_version='1.2.0');
2+
DELETE FROM plugin_step where plugin_id=(SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger' and plugin_version='1.2.0');
3+
DELETE FROM plugin_pipeline_script where id=(SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger');
4+
DELETE FROM plugin_stage_mapping where plugin_id=(SELECT id from plugin_metadata where name='Devtron CD Trigger');
5+
DELETE FROM plugin_metadata where name='Devtron CD Trigger';
6+
UPDATE plugin_metadata SET is_latest = true WHERE id = (SELECT id FROM plugin_metadata WHERE name= 'Devtron CD Trigger' and is_latest= false and plugin_version='1.1.0');
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
-- update the is_latest flag to false, for the plugin version 1.0.0
2+
UPDATE plugin_metadata SET is_latest = false WHERE id = (SELECT id FROM plugin_metadata WHERE name= 'Devtron CD Trigger' and is_latest= true);
3+
4+
-- insert the new plugin version 1.2.0
5+
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")
6+
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.2.0', false, true);
7+
8+
INSERT INTO "plugin_stage_mapping" ("plugin_id","stage_type","created_on", "created_by", "updated_on", "updated_by")
9+
VALUES ((SELECT id FROM plugin_metadata WHERE plugin_version='1.2.0' and name='Devtron CD Trigger' and deleted= false),0,'now()', 1, 'now()', 1);
10+
11+
INSERT INTO "plugin_pipeline_script" ("id", "script","type","deleted","created_on", "created_by", "updated_on", "updated_by")VALUES (
12+
nextval('id_seq_plugin_pipeline_script'),
13+
E'#!/bin/bash
14+
set -ex
15+
pipeline_type=$(echo $CI_CD_EVENT | jq -r \'.type\')
16+
if [[ "$pipeline_type" == "CI" ]]; then
17+
triggeredFromAppName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.appName\')
18+
triggeredFromPipelineName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.pipelineName\')
19+
elif [[ "$pipeline_type" == "CD" ]]; then
20+
triggeredFromAppName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.extraEnvironmentVariables.APP_NAME\')
21+
triggeredFromPipelineName=$(echo $CI_CD_EVENT | jq \'.commonWorkflowRequest.Pipeline.Name\')
22+
fi
23+
# Convert CD Workflow Type to uppercase to make it case-insensitive
24+
TargetTriggerStage=$(echo "$TargetTriggerStage" | tr \'[:lower:]\' \'[:upper:]\')
25+
26+
# Set default value for TargetTriggerStage to DEPLOY if not provided or invalid
27+
case $TargetTriggerStage inwa
28+
"PRE")
29+
;;
30+
"POST")
31+
;;
32+
"DEPLOY")
33+
;;
34+
"")
35+
TargetTriggerStage="DEPLOY" # Set to DEPLOY if no input provided
36+
;;
37+
*)
38+
echo "Error: Invalid CD Workflow Type. Please enter PRE/DEPLOY/POST. Exiting..."
39+
exit 1
40+
;;
41+
esac
42+
43+
# Set default value for StatusTimeOutSeconds to 0 if not provided or not an integer
44+
if ! [[ "$StatusTimeOutSeconds" =~ ^[0-9]+$ ]]; then
45+
StatusTimeOutSeconds=0
46+
fi
47+
48+
DevtronEndpoint=$(echo "$DevtronEndpoint" | sed \'s:/*$::\')
49+
50+
# Determine sleep interval based on StatusTimeOutSeconds
51+
if [ "$StatusTimeOutSeconds" -lt "60" ]; then
52+
sleepInterval=$(($StatusTimeOutSeconds / 2))
53+
else
54+
sleepInterval=30
55+
fi
56+
57+
verify(){
58+
local response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/devtron/auth/verify")
59+
echo $response
60+
}
61+
verify_response=$(verify)
62+
verify_status=$( echo "$verify_response" | jq \'.code\')
63+
# echo $verify_status
64+
if [[ "$verify_status" == "401" ]]; then
65+
echo "Enter the valid DevtronApiToken. Exiting..."
66+
exit 1
67+
elif [[ -z "$verify_status" ]]; then
68+
echo "Enter the valid DevtronEndpoint. Exiting..."
69+
exit 1
70+
fi
71+
72+
fetch_app_id() {
73+
# Check if DevtronApp is numeric, if yes, use it directly as App ID
74+
if [[ "$DevtronApp" =~ ^[0-9]+$ ]]; then
75+
echo "$DevtronApp"
76+
else
77+
local api_response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/app/autocomplete")
78+
local app_id=$(echo "$api_response" | jq -r --arg app_name "$DevtronApp" \'.result[] | select(.name == $app_name) | .id\')
79+
80+
if [[ -z "$app_id" || "$app_id" == "null" ]]; then
81+
echo "Error: Application \'$DevtronApp\' not found. Please verify the DevtronApp."
82+
exit 1
83+
fi
84+
echo "$app_id"
85+
fi
86+
}
87+
88+
fetch_env_id() {
89+
# Check if DevtronEnv is numeric, if yes, use it directly as Env ID
90+
if [[ "$DevtronEnv" =~ ^[0-9]+$ ]]; then
91+
echo "$DevtronEnv"
92+
else
93+
local api_response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/env/autocomplete")
94+
local env_id=$(echo "$api_response" | jq -r --arg env_name "$DevtronEnv" \'.result[] | select(.environment_name == $env_name) | .id\')
95+
96+
if [[ -z "$env_id" || "$env_id" == "null" ]]; then
97+
echo "Error: Environment \'$DevtronEnv\' not found. Please verify the DevtronEnv."
98+
exit 1
99+
fi
100+
echo "$env_id"
101+
fi
102+
}
103+
104+
fetch_pipeline_id() {
105+
local app_id=$1
106+
local env_id=$2
107+
local api_response=$(curl -s -H "token: $DevtronApiToken" "$DevtronEndpoint/orchestrator/app/app-wf/view/$app_id")
108+
local pipeline_id=$(echo "$api_response" | jq -r --arg env_id "$env_id" \'.result.cdConfig.pipelines[] | select(.environmentId == ($env_id | tonumber)) | .id\')
109+
110+
if [[ -z "$pipeline_id" || "$pipeline_id" == "null" ]]; then
111+
echo "Error: Pipeline not found for the provided Environment. Please verify the Environment ID."
112+
echo "Environment ID: $env_id"
113+
echo "API Response: $api_response"
114+
exit 1
115+
fi
116+
echo "$pipeline_id"
117+
}
118+
119+
multigit_hash_id(){
120+
121+
local len=$1
122+
local artifact_id=""
123+
local apiResponse=$2
124+
i=0
125+
while [[ "$i" -lt "$len" ]]; do
126+
id2=$(echo "$apiResponse" | jq -r --argjson index "$i" \'.result.ci_artifacts[$index].material_info[].revision \')
127+
if [[ "$hash" == "$id2" ]];then
128+
id=$(echo "$apiResponse" | jq -r --argjson index "$i" \'.result.ci_artifacts[$index].id \')
129+
artifact_id=$id
130+
break
131+
fi
132+
i=$((i + 1))
133+
done
134+
echo "$artifact_id"
135+
}
136+
137+
fetch_ci_artifact_id() {
138+
local pipeline_id=$1
139+
local apiUrl="$DevtronEndpoint/orchestrator/app/cd-pipeline/$pipeline_id/material?offset=0&size=20&stage=$TargetTriggerStage"
140+
local apiResponse=$(curl -s -H "token: $DevtronApiToken" "$apiUrl")
141+
142+
local ciArtifactId=""
143+
if [[ -n "$GitCommitHash" ]]; then
144+
ciArtifactId=$(echo "$apiResponse" | jq -r --arg hash "$GitCommitHash" \'.result.ci_artifacts[] | select(.material_info[].revision == $hash) | .id\' | head -n 1)
145+
if [[ -z "$ciArtifactId" || "$ciArtifactId" == "null" || "$ciArtifactId" == "" ]]; then
146+
echo "Error: CI Artifact ID for the provided commit hash \'$GitCommitHash\' not found. Please verify the commit hash."
147+
exit 1
148+
fi
149+
elif [[ "$TriggerFromSameHash" == "true" ]]; then
150+
len=$(echo "$apiResponse" | jq -r \'.result.ci_artifacts\' | jq \'length\')
151+
image=$(echo $CI_CD_EVENT | jq -r \'.commonWorkflowRequest.ciArtifactDTO.image\')
152+
hash=$(echo $CI_CD_EVENT | jq -r \'.commonWorkflowRequest.ciProjectDetails[].commitHash\')
153+
id1=$(echo "$apiResponse" | jq -r --arg image "$image" \'.result.ci_artifacts[] | select(.image == $image) | .id\' | head -n 1)
154+
if [[ -z "$id" || "$id" == "null" || "id" == "" ]]; then
155+
id1=$(multigit_hash_id "$len" "$apiResponse")
156+
fi
157+
ciArtifactId=$id1
158+
if [[ -z "$ciArtifactId" || "$ciArtifactId" == "null" || "$ciArtifactId" == "" ]]; then
159+
echo "Error: CI Artifact ID for the provided commit hash \'$GitCommitHash\' not found. Please verify the commit hash."
160+
exit 1
161+
fi
162+
else
163+
ciArtifactId=$(echo "$apiResponse" | jq -r \'.result.ci_artifacts[0].id\')
164+
if [[ -z "$ciArtifactId" || "$ciArtifactId" == "null" ]]; then
165+
echo "Error: CI Artifact ID not found."
166+
exit 1
167+
fi
168+
fi
169+
170+
echo "$ciArtifactId"
171+
}
172+
173+
# Fetch the app ID. Exit the script if the app name is incorrect.
174+
app_id=$(fetch_app_id)
175+
if [ $? -ne 0 ]; then
176+
echo "Error: Application \'$DevtronApp\' not found. Enter the correct App Name. Exiting...."
177+
exit 1
178+
fi
179+
180+
# Fetch the env ID. Exit the script if the environment name or ID is incorrect.
181+
env_id=$(fetch_env_id)
182+
if [ $? -ne 0 ]; then
183+
echo "Error: Environment \'$DevtronEnv\' not found. Enter the correct Environment Name. Exiting..."
184+
exit 1
185+
fi
186+
187+
# Fetch the pipeline ID using the env ID. Exit the script if the environment is incorrect.
188+
pipeline_id=$(fetch_pipeline_id "$app_id" "$env_id")
189+
if [ $? -ne 0 ]; then
190+
echo "Verify your App Name/ID and Env Name/ID. Exiting..."
191+
exit 1
192+
fi
193+
194+
# Fetch the CI Artifact ID based on the commit hash.
195+
ciArtifactId=$(fetch_ci_artifact_id "$pipeline_id")
196+
if [ $? -ne 0 ]; then
197+
echo "Enter the correct GitCommitHash. Exiting..."
198+
exit 1
199+
fi
200+
201+
trigger_cd_pipeline() {
202+
local pipeline_id=$1
203+
local app_id=$2
204+
local ciArtifactId=$3
205+
local jsonPayload=$(jq -n \\
206+
--arg pipelineId "$pipeline_id" \\
207+
--arg appId "$app_id" \\
208+
--arg ciArtifactId "$ciArtifactId" \\
209+
--arg TargetTriggerStage "$TargetTriggerStage" \\
210+
--arg deploymentWithConfig "LAST_SAVED_CONFIG" \\
211+
--arg triggeredFromAppName "$triggeredFromAppName" \\
212+
--arg triggeredFromPipelineName "$triggeredFromPipelineName" \\
213+
\'{
214+
pipelineId: ($pipelineId | tonumber),
215+
appId: ($appId | tonumber),
216+
ciArtifactId: ($ciArtifactId | tonumber),
217+
cdWorkflowType: $TargetTriggerStage,
218+
deploymentWithConfig: $deploymentWithConfig,
219+
triggeredFromAppName: $triggeredFromAppName,
220+
triggeredFromPipelineName: $triggeredFromPipelineName
221+
}\')
222+
223+
curl -sS -X POST "$DevtronEndpoint/orchestrator/app/cd-pipeline/trigger" \\
224+
-H "Content-Type: application/json" \\
225+
-H "token: $DevtronApiToken" \\
226+
--data "$jsonPayload" \\
227+
--compressed
228+
}
229+
230+
echo "Triggering CD Pipeline for App ID: $app_id, Pipeline ID: $pipeline_id, CI Artifact ID: $ciArtifactId, and CD Workflow Type: $TargetTriggerStage"
231+
cd_pipeline=$(trigger_cd_pipeline "$pipeline_id" "$app_id" "$ciArtifactId")
232+
233+
check_deploy_status() {
234+
if [ "$StatusTimeOutSeconds" -le "0" ]; then
235+
echo "Skipping deployment status check. Taking StatusTimeOutSecond0 as a default input"
236+
return
237+
fi
238+
239+
local appId=$1
240+
local pipelineId=$2
241+
local max_wait=$StatusTimeOutSeconds
242+
local statusKey="deploy_status" # Default status key
243+
244+
if [[ "$TargetTriggerStage" == "PRE" ]]; then
245+
statusKey="pre_status"
246+
elif [[ "$TargetTriggerStage" == "POST" ]]; then
247+
statusKey="post_status"
248+
fi
249+
250+
local start_time=$(date +%s)
251+
252+
while :; do
253+
local current_time=$(date +%s)
254+
local elapsed_time=$((current_time - start_time))
255+
256+
if [ "$elapsed_time" -ge "$max_wait" ]; then
257+
echo "Timeout reached without success. Exiting..."
258+
exit 1
259+
fi
260+
261+
local statusUrl="$DevtronEndpoint/orchestrator/app/workflow/status/$appId/v2"
262+
local response=$(curl -s -H "token: $DevtronApiToken" "$statusUrl")
263+
local code=$(echo "$response" | jq -r \'.code\')
264+
265+
if [ "$code" != "200" ]; then
266+
echo "Error: Received response - $response. Exiting..."
267+
exit 1
268+
fi
269+
local status=$(echo "$response" | jq -r --arg pipelineId "$pipelineId" --arg statusKey "$statusKey" \'.result.cdWorkflowStatus[] | select(.pipeline_id == ($pipelineId | tonumber)) | .[$statusKey]\')
270+
271+
echo "Current $TargetTriggerStage status: $status"
272+
273+
if [[ "$status" == "Succeeded" ]]; then
274+
echo "Deployment succeeded."
275+
break
276+
elif [[ "$status" == "Failed" ]]; then
277+
echo "$TargetTriggerStage workflow failed."
278+
exit 1
279+
fi
280+
281+
sleep $sleepInterval
282+
done
283+
}
284+
285+
# Optionally check the deployment status based on the CD workflow type
286+
check_deploy_status "$app_id" "$pipeline_id"' ,'SHELL','f','now()',1,'now()',1);
287+
288+
289+
INSERT INTO "plugin_step" ("id", "plugin_id","name","description","index","step_type","script_id","deleted", "created_on", "created_by", "updated_on", "updated_by")
290+
VALUES (nextval('id_seq_plugin_step'), (SELECT id FROM plugin_metadata WHERE name='Devtron CD Trigger' AND plugin_version='1.2.0' AND deleted= false),'Step 1','Runnig the plugin','1','INLINE',(SELECT last_value FROM id_seq_plugin_pipeline_script),'f','now()', 1, 'now()', 1);
291+
292+
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)
293+
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 p.plugin_version='1.2.0' 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),
294+
(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 p.plugin_version='1.2.0' 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),
295+
(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 p.plugin_version='1.2.0' 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),
296+
(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 p.plugin_version='1.2.0' 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),
297+
(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 p.plugin_version='1.2.0' 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),
298+
(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 p.plugin_version='1.2.0' 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),
299+
(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 p.plugin_version='1.2.0' 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),
300+
(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 p.plugin_version='1.2.0' and ps."index"=1 and ps.deleted=false),'TriggerFromSameHash','STRING','Provide value true if want to trigger CD with same hash','t','t',null,null,'INPUT','NEW',null,1,null,null,'f','now()',1,'now()',1);
301+
302+
303+

0 commit comments

Comments
 (0)