Skip to content

Commit 52b05df

Browse files
committed
Add a slack message to end of prd build process [infra]
1 parent fe1e12f commit 52b05df

File tree

4 files changed

+220
-0
lines changed

4 files changed

+220
-0
lines changed

infrastructure/cinco/config/prd/arclight/build.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ parameters:
1010
sceptre_user_data:
1111
BuildEnvironment:
1212
- SUBNET_IDS: {{ var.prd.SUBNET_IDS }}
13+
- SLACK_HOOK: {{ var.prd.SLACK_HOOK }}
1314
TriggerFilterGroups:
1415
# A build is triggered if any filter group evaluates to true, which
1516
# occurs when all the filters in the group evaluate to true.
@@ -20,6 +21,9 @@ sceptre_user_data:
2021
version: 0.2
2122
2223
phases:
24+
install:
25+
runtime-versions:
26+
python: 3.12
2327
build:
2428
commands:
2529
- TAG=`git describe --tags --abbrev=0`
@@ -36,4 +40,5 @@ sceptre_user_data:
3640
- NEW_TASK_DEFINITION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$NEW_IMAGE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)')
3741
- REGISTERED_DEFINITION=$(aws ecs register-task-definition --cli-input-json "$NEW_TASK_DEFINITION")
3842
- TD_REVISION=$(echo $REGISTERED_DEFINITION | jq -r '.taskDefinition.revision')
43+
- python $CODEBUILD_SRC_DIR/infrastructure/cinco/scripts/message_slack.py --application arclight --cinco_version $TAG --td_family_revisions "$TASK_FAMILY:$TD_REVISION"
3944
- aws ecs update-service --cluster cinco-prd --service cinco-arclight-prd-service --task-definition $TASK_FAMILY:$TD_REVISION --force-new-deployment

infrastructure/cinco/config/prd/cincoctrl/build.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ parameters:
1010
sceptre_user_data:
1111
BuildEnvironment:
1212
- SUBNET_IDS: {{ var.prd.SUBNET_IDS }}
13+
- SLACK_HOOK: {{ var.prd.SLACK_HOOK }}
1314
TriggerFilterGroups:
1415
# A build is triggered if any filter group evaluates to true, which
1516
# occurs when all the filters in the group evaluate to true.
@@ -46,4 +47,5 @@ sceptre_user_data:
4647
- python $CODEBUILD_SRC_DIR/infrastructure/cinco/scripts/ecs_manage.py --prd --task-definition $TD_REVISION collectstatic --no-input
4748
- python $CODEBUILD_SRC_DIR/infrastructure/cinco/scripts/ecs_manage.py --prd --task-definition $TD_REVISION migrate --no-input
4849
- echo "Forcing a new deployment of the service to apply changes"
50+
- python $CODEBUILD_SRC_DIR/infrastructure/cinco/scripts/message_slack.py --application cincoctrl --cinco_version $TAG --td_family_revisions "$TASK_FAMILY:$TD_REVISION"
4951
- aws ecs update-service --cluster cinco-prd --service cinco-ctrl-prd-service --task-definition $TASK_FAMILY:$TD_REVISION --force-new-deployment

infrastructure/cinco/config/prd/solr/build.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@ sceptre_user_data:
1313
# occurs when all the filters in the group evaluate to true.
1414
- - Type: EVENT
1515
Pattern: RELEASED
16+
BuildEnvironment:
17+
- SLACK_HOOK: {{ var.prd.SLACK_HOOK }}
1618
build_spec: |-
1719
!Sub >-
1820
version: 0.2
1921
2022
phases:
23+
install:
24+
runtime-versions:
25+
python: 3.12
2126
pre_build:
2227
commands:
2328
- cd $CODEBUILD_SRC_DIR/arclight
@@ -40,6 +45,7 @@ sceptre_user_data:
4045
- TD_REVISION=$(echo $REGISTERED_DEFINITION | jq -r '.taskDefinition.revision')
4146
- echo "Please update solr leader service, task definition revision:"
4247
- echo $TD_REVISION
48+
- LEADER="cinco-solr-prd:$TD_REVISION"
4349
# - aws ecs update-service --cluster cinco-prd --service cinco-solr-prd-service --task-definition $TASK_FAMILY:$TD_REVISION --force-new-deployment
4450
##### Update solr follower 1 task definition #####
4551
- echo "Updating solr follower 1 task definition"
@@ -50,6 +56,7 @@ sceptre_user_data:
5056
- TD_REVISION=$(echo $REGISTERED_DEFINITION | jq -r '.taskDefinition.revision')
5157
- echo "Please update solr follower 1 service, task definition revision:"
5258
- echo $TD_REVISION
59+
- FOLLOWER_1="cinco-solr-follower-1-prd:$TD_REVISION"
5360
# - aws ecs update-service --cluster cinco-prd --service cinco-solr-follower-1-prd-service --task-definition $TASK_FAMILY:$TD_REVISION --force-new-deployment
5461
##### Update solr follower 2 task definition #####
5562
- echo "Updating solr follower 2 task definition"
@@ -60,4 +67,7 @@ sceptre_user_data:
6067
- TD_REVISION=$(echo $REGISTERED_DEFINITION | jq -r '.taskDefinition.revision')
6168
- echo "Please update solr follower 2 service, task definition revision:"
6269
- echo $TD_REVISION
70+
- FOLLOWER_2="cinco-solr-follower-2-prd:$TD_REVISION"
6371
# - aws ecs update-service --cluster cinco-prd --service cinco-solr-follower-2-prd-service --task-definition $TASK_FAMILY:$TD_REVISION --force-new-deployment
72+
###### Message Slack #####
73+
- python $CODEBUILD_SRC_DIR/infrastructure/cinco/scripts/message_slack.py --application solr --cinco_version $TAG --td_family_revisions $LEADER $FOLLOWER_1 $FOLLOWER_2
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import json
2+
import urllib3
3+
import os
4+
import argparse
5+
6+
http = urllib3.PoolManager()
7+
8+
# set as part of the build environment
9+
AWS_ACCOUNT = os.environ.get("AWS_ACCOUNT_ID", "")
10+
AWS_REGION = os.environ.get("AWS_DEFAULT_REGION", "")
11+
SLACK_HOOK = os.environ.get("SLACK_HOOK", "")
12+
13+
td_url_template = "https://{aws_account}.{aws_region}.console.aws.amazon.com/ecs/v2/task-definitions/{td_family}/{td_revision}/containers"
14+
service_url_template = "https://{aws_account}.{aws_region}.console.aws.amazon.com/ecs/v2/clusters/cinco-prd/services/{service_name}"
15+
16+
17+
def craft_slack_message(application, cinco_version, family_revision):
18+
if application == "cincoctrl":
19+
image = "cinco-ctrl"
20+
name = "CincoCtrl prd"
21+
elif application == "arclight":
22+
image = "arclight"
23+
name = "Arclight prd"
24+
25+
td_family = family_revision.split(":")[0]
26+
td_revision = family_revision.split(":")[1]
27+
service_name = f"{td_family}-service"
28+
29+
task_definition_url = td_url_template.format(
30+
aws_account=AWS_ACCOUNT,
31+
aws_region=AWS_REGION,
32+
td_family=td_family,
33+
td_revision=td_revision,
34+
)
35+
service_url = service_url_template.format(
36+
aws_account=AWS_ACCOUNT, aws_region=AWS_REGION, service_name=service_name
37+
)
38+
39+
tasks = f"{service_url}/tasks?region={AWS_REGION}"
40+
logs = f"{service_url}/logs?region={AWS_REGION}"
41+
deployments = f"{service_url}/deployments?region={AWS_REGION}"
42+
43+
button_links = [("Tasks", tasks), ("Logs", logs), ("Deployments", deployments)]
44+
mrkdwn_message = f"*{name}* - deploying image `{image}:{cinco_version}` ; task definition: <{task_definition_url}|{td_family}:{td_revision}>"
45+
46+
message = {
47+
"blocks": [
48+
{"type": "section", "text": {"type": "mrkdwn", "text": mrkdwn_message}},
49+
{
50+
"type": "actions",
51+
"elements": [
52+
{
53+
"type": "button",
54+
"text": {
55+
"type": "plain_text",
56+
"text": link[0],
57+
},
58+
"url": link[1],
59+
}
60+
for link in button_links
61+
],
62+
},
63+
]
64+
}
65+
66+
return message
67+
68+
69+
def craft_solr_slack_message(cinco_version, family_revisions):
70+
"""
71+
Crafts a Slack message for Solr deployments.
72+
:param cinco_version: Version of Cinco being deployed.
73+
:param family_revisions: Dictionary with family names as keys and their revisions as values.
74+
:return: Formatted Slack message.
75+
"""
76+
rich_text_elements = []
77+
for family_revision in family_revisions:
78+
family, revision = family_revision.split(":")
79+
td_url = td_url_template.format(
80+
aws_account=AWS_ACCOUNT,
81+
aws_region=AWS_REGION,
82+
td_family=family,
83+
td_revision=revision,
84+
)
85+
service_name = f"{family}-service"
86+
service_url = (
87+
service_url_template.format(
88+
aws_account=AWS_ACCOUNT,
89+
aws_region=AWS_REGION,
90+
service_name=service_name,
91+
)
92+
+ "/health?region="
93+
+ AWS_REGION
94+
)
95+
rich_text_elements.append(
96+
{
97+
"type": "rich_text_section",
98+
"elements": [
99+
{"type": "link", "url": service_url, "text": service_name},
100+
{"type": "text", "text": " with task definition "},
101+
{"type": "link", "url": td_url, "text": f"{family}:{revision}"},
102+
],
103+
}
104+
)
105+
106+
return {
107+
"blocks": [
108+
{
109+
"type": "section",
110+
"text": {
111+
"type": "mrkdwn",
112+
"text": f"*CincoSolr prd* - built image `cinco-solr:{cinco_version}` and created task definition revisions.\nPlease update the following services (one at a time, in the following order):",
113+
},
114+
},
115+
{
116+
"type": "rich_text",
117+
"elements": [
118+
{
119+
"type": "rich_text_list",
120+
"style": "bullet",
121+
"indent": 0,
122+
"elements": rich_text_elements,
123+
}
124+
],
125+
},
126+
{
127+
"type": "section",
128+
"text": {
129+
"type": "mrkdwn",
130+
"text": "*Indexing will pause during update of cinco-solr-prd-service*",
131+
},
132+
},
133+
]
134+
}
135+
136+
137+
def main(application, cinco_version, td_family_revisions):
138+
try:
139+
if application == "solr":
140+
message = craft_solr_slack_message(cinco_version, td_family_revisions)
141+
icon_emoji = ":solr:"
142+
else:
143+
message = craft_slack_message(
144+
application, cinco_version, td_family_revisions[0]
145+
)
146+
icon_emoji = ":hammer_and_wrench:"
147+
148+
data = {
149+
"channel": "#dsc_looks_wrong",
150+
"username": "aws-codebuild",
151+
"icon_emoji": icon_emoji,
152+
"blocks": message["blocks"],
153+
"unfurl_links": False,
154+
"unfurl_media": False,
155+
}
156+
157+
resp = http.request("POST", SLACK_HOOK, body=json.dumps(data).encode("utf-8"))
158+
except Exception as e:
159+
print({"error": f"Slack notification failed: {e}"})
160+
return
161+
162+
print(
163+
{
164+
"message": message,
165+
"status_code": resp.status,
166+
"response": resp.data,
167+
}
168+
)
169+
170+
171+
if __name__ == "__main__":
172+
# add cinco_version, td_revision as required arguments to the script
173+
parser = argparse.ArgumentParser(
174+
description="Send a slack notification on deployment"
175+
)
176+
177+
parser.add_argument(
178+
"--application",
179+
type=str,
180+
required=True,
181+
help="Application that was deployed: cincoctrl, arclight, or solr",
182+
)
183+
parser.add_argument(
184+
"--cinco_version",
185+
type=str,
186+
required=True,
187+
help="Cinco version that was deployed",
188+
)
189+
parser.add_argument(
190+
"--td_family_revisions",
191+
nargs="+",
192+
required=True,
193+
help="Any task definition family revisions that were created",
194+
)
195+
196+
try:
197+
args = parser.parse_args()
198+
application = args.application
199+
cinco_version = args.cinco_version
200+
td_family_revisions = args.td_family_revisions
201+
main(application, cinco_version, td_family_revisions)
202+
except Exception as e:
203+
print({"error": f"Argument parsing failed: {e}"})

0 commit comments

Comments
 (0)