Skip to content

Commit d93d5b9

Browse files
Merge pull request #72 from devtron-labs/oss-release-automations
feat: Added image-updater script
2 parents 82d9883 + 2ae3b6b commit d93d5b9

File tree

1 file changed

+224
-0
lines changed

1 file changed

+224
-0
lines changed

release/tag-update.sh

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#!/bin/bash
2+
3+
apk add yq || { echo "ERROR: Failed to install yq. Aborting." >&2; exit 1; }
4+
5+
log() {
6+
7+
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
8+
}
9+
10+
error_exit() {
11+
log "ERROR: $1"
12+
}
13+
14+
command -v yq >/dev/null 2>&1 || error_exit "yq is required but not installed or not in PATH. Aborting."
15+
command -v git >/dev/null 2>&2 || error_exit "git is required but not installed or not in PATH. Aborting."
16+
command -v jq >/dev/null 2>&1 || error_exit "jq is required but not installed or not in PATH. Aborting."
17+
command -v curl >/dev/null 2>&1 || error_exit "curl is required but not installed or not in PATH. Aborting."
18+
19+
: "${GITHUB_API_TOKEN:?GITHUB_API_TOKEN is not set or empty}"
20+
: "${GIT_USER_EMAIL:?GIT_USER_EMAIL is not set or empty}"
21+
: "${GIT_USER_NAME:?GIT_USER_NAME is not set or empty}"
22+
: "${CI_CD_EVENT:?CI_CD_EVENT is not set or empty}"
23+
24+
log "Setting Git user config"
25+
git config --global user.email "${GIT_USER_EMAIL}"
26+
git config --global user.name "${GIT_USER_NAME}"
27+
28+
REPO_OWNER=$(echo "$REPO_URL" | sed -E 's|https://github.com/([^/]+)/.*|\1|')
29+
REPO_NAME=$(echo "$REPO_URL" | sed -E 's|https://github.com/[^/]+/([^/]+)\.git|\1|')
30+
FULL_IMAGE_PATH=$(echo "$CI_CD_EVENT" | jq -r '.commonWorkflowRequest.dockerRepository')
31+
IMAGE_TAG=$(echo "$CI_CD_EVENT" | jq -r '.commonWorkflowRequest.dockerImageTag')
32+
33+
34+
IMAGE_NAME=$(echo "$FULL_IMAGE_PATH" | sed -E 's|.*/([^/]+)|\1|')
35+
36+
log "Full Image path from event: $FULL_IMAGE_PATH"
37+
log "Image Name to search for in YAML: $IMAGE_NAME"
38+
log "New Image Tag: $IMAGE_TAG"
39+
40+
PREVIOUS_TAG=""
41+
CHANGES_MADE=false
42+
43+
update_image() {
44+
local image_name="$1"
45+
local new_tag="$2"
46+
local file_to_change="$3"
47+
local found_image_string=false
48+
local update_required=false
49+
50+
log "Searching for image matching pattern '${image_name}:*' in file: $file_to_change"
51+
52+
while IFS='=' read -r current_path current_value; do
53+
54+
current_value=$(echo "$current_value" | xargs)
55+
current_value="${current_value%\"}"
56+
current_value="${current_value#\"}"
57+
58+
if [[ "$current_value" == "${image_name}":* ]]; then
59+
found_image_string=true
60+
61+
local current_tag="${current_value##*:}"
62+
63+
log "Found image : '$current_value' at path '.$current_path'"
64+
log "Extracted current tag: '$current_tag'"
65+
66+
if [ "$current_tag" != "$new_tag" ]; then
67+
log "New tag '$new_tag'."
68+
update_required=true
69+
PREVIOUS_TAG="$current_tag"
70+
71+
local new_image_string="${image_name}:${new_tag}"
72+
73+
log "Attempting to update path .$current_path in $file_to_change"
74+
if yq e ".${current_path} = \"${new_image_string}\"" -i "$file_to_change"; then
75+
log "Successfully updated path .$current_path"
76+
CHANGES_MADE=true
77+
break
78+
else
79+
log "ERROR: Failed to update path .$current_path in file $file_to_change."
80+
81+
fi
82+
else
83+
log "Image '$image_name' at path '.$current_path' already at desired version '$new_tag'."
84+
update_required=true
85+
break
86+
fi
87+
fi
88+
89+
done < <(yq e '.. | select(tag == "!!str") | {(path | join(".")): .} | to_props' "$file_to_change" 2>/dev/null)
90+
91+
if ! $found_image_string; then
92+
log "Image matching pattern '${image_name}:*' was NOT found in $file_to_change. No changes made for this file."
93+
elif ! $update_required; then
94+
log "Image matching pattern '${image_name}:*' found, but update logic didn't flag update required. This is unexpected."
95+
fi
96+
97+
}
98+
99+
log "Cloning repository: ${REPO_URL}"
100+
101+
if ! git clone "https://${GITHUB_API_TOKEN}@github.com/${REPO_OWNER}/${REPO_NAME}.git"; then
102+
error_exit "Failed to clone repository ${REPO_URL}"
103+
fi
104+
cd "${REPO_NAME}" || error_exit "Failed to change directory to ${REPO_NAME}"
105+
log "Changed directory to $(pwd)"
106+
107+
log "Fetching latest changes from origin"
108+
if ! git fetch origin; then
109+
error_exit "Failed to fetch latest changes from origin"
110+
fi
111+
112+
log "Checking out branch: ${BRANCH_NAME}"
113+
114+
if git ls-remote --exit-code --heads origin "$BRANCH_NAME" >/dev/null 2>&1; then
115+
log "Branch $BRANCH_NAME already exists remotely. Checking it out and pulling latest changes."
116+
if ! git checkout "$BRANCH_NAME"; then
117+
error_exit "Failed to checkout existing branch $BRANCH_NAME"
118+
fi
119+
log "Pulling latest changes for branch $BRANCH_NAME"
120+
if ! git pull origin "$BRANCH_NAME"; then
121+
error_exit "Failed to pull latest changes for branch $BRANCH_NAME"
122+
fi
123+
else
124+
log "Branch $BRANCH_NAME does not exist remotely. Creating a new branch based on origin/main."
125+
126+
if ! git rev-parse origin/main >/dev/null 2>&1; then
127+
error_exit "origin/main branch not found. Cannot create new branch $BRANCH_NAME."
128+
fi
129+
if ! git checkout -b "$BRANCH_NAME" origin/main; then
130+
error_exit "Failed to create new branch $BRANCH_NAME based on origin/main"
131+
fi
132+
log "Created new branch $BRANCH_NAME"
133+
fi
134+
135+
log "Updating Image Tag in $IMAGE_LIST_FILE"
136+
137+
sed -i "s|^quay.io/devtron/${FULL_IMAGE_PATH}:.*|quay.io/devtron/${FULL_IMAGE_PATH}:${IMAGE_TAG}|" "$IMAGE_LIST_FILE"
138+
139+
update_image "$IMAGE_NAME" "$IMAGE_TAG" "$FILE_TO_CHANGE_1"
140+
141+
update_image "$IMAGE_NAME" "$IMAGE_TAG" "$FILE_TO_CHANGE_2"
142+
log "Finished image updates."
143+
144+
if ! $CHANGES_MADE; then
145+
log "No changes to commit. Image $IMAGE_NAME:$IMAGE_TAG already present in all locations. Exiting."
146+
fi
147+
148+
COMMIT_MESSAGE="Updated $IMAGE_NAME to $IMAGE_TAG tag in values file"
149+
150+
log "Committing changes"
151+
if ! git add "$FILE_TO_CHANGE_1" "$FILE_TO_CHANGE_2" "$IMAGE_LIST_FILE"; then
152+
error_exit "Failed to stage changes"
153+
fi
154+
if ! git commit -m "$COMMIT_MESSAGE"; then
155+
error_exit "Failed to commit changes"
156+
fi
157+
158+
push_changes() {
159+
if ! git push origin "$BRANCH_NAME"; then
160+
log "Push failed. Pulling latest changes, rebasing, and trying again."
161+
if ! git pull --rebase origin "$BRANCH_NAME"; then
162+
error_exit "Failed to pull and rebase latest changes"
163+
fi
164+
if ! git push origin "$BRANCH_NAME"; then
165+
error_exit "Failed to push changes after rebase"
166+
fi
167+
fi
168+
}
169+
170+
log "Pushing changes"
171+
push_changes
172+
173+
if [ "$RAISE_PR" == "TRUE" ]; then
174+
PR_TITLE="Chore: Update $IMAGE_NAME"
175+
PR_BODY="This PR updates the image version for $IMAGE_NAME from $PREVIOUS_TAG to $IMAGE_TAG"
176+
177+
log "Checking for existing Pull Request"
178+
EXISTING_PR=$(curl -s -H "Authorization: token $GITHUB_API_TOKEN" \
179+
-H "Accept: application/vnd.github.v3+json" \
180+
"https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/pulls?head=$REPO_OWNER:$BRANCH_NAME&state=open")
181+
182+
183+
if [ "$(echo "$EXISTING_PR" | jq '. | length')" -gt 0 ]; then
184+
PR_NUMBER=$(echo "$EXISTING_PR" | jq -r '.[0].number')
185+
log "Existing Pull Request found. Updating PR #$PR_NUMBER"
186+
187+
UPDATE_PR_RESPONSE=$(curl -s -X PATCH \
188+
-H "Authorization: token $GITHUB_API_TOKEN" \
189+
-H "Accept: application/vnd.github.v3+json" \
190+
"https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/pulls/$PR_NUMBER" \
191+
-d '{
192+
"title": "'"$PR_TITLE"'",
193+
"body": "'"$PR_BODY"'"
194+
}')
195+
196+
PR_URL=$(echo "$UPDATE_PR_RESPONSE" | jq -r '.html_url')
197+
if [ "$PR_URL" != "null" ]; then
198+
log "Pull Request updated successfully: $PR_URL"
199+
else
200+
error_exit "Failed to update Pull Request. Response: $UPDATE_PR_RESPONSE"
201+
fi
202+
else
203+
log "Creating new Pull Request"
204+
PR_RESPONSE=$(curl -s -X POST \
205+
-H "Authorization: token $GITHUB_API_TOKEN" \
206+
-H "Accept: application/vnd.github.v3+json" \
207+
"https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/pulls" \
208+
-d '{
209+
"title": "'"$PR_TITLE"'",
210+
"body": "'"$PR_BODY"'",
211+
"head": "'"$BRANCH_NAME"'",
212+
"base": "main"
213+
}')
214+
215+
PR_URL=$(echo "$PR_RESPONSE" | jq -r '.html_url')
216+
if [ "$PR_URL" != "null" ]; then
217+
log "Pull Request created successfully: $PR_URL"
218+
else
219+
error_exit "Failed to create Pull Request. Response: $PR_RESPONSE"
220+
fi
221+
fi
222+
else
223+
log "Done and Dusted"
224+
fi

0 commit comments

Comments
 (0)