Skip to content

Commit 624dd79

Browse files
committed
[patch] move broadcast to slack utils
1 parent 76a682d commit 624dd79

4 files changed

Lines changed: 125 additions & 97 deletions

File tree

.secrets.baseline

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"files": "^.secrets.baseline$",
44
"lines": null
55
},
6-
"generated_at": "2025-12-11T13:22:20Z",
6+
"generated_at": "2025-12-12T20:28:52Z",
77
"plugins_used": [
88
{
99
"name": "AWSKeyDetector"
@@ -82,15 +82,15 @@
8282
"hashed_secret": "053f5ed451647be0bbb6f67b80d6726808cad97e",
8383
"is_secret": false,
8484
"is_verified": false,
85-
"line_number": 55,
85+
"line_number": 42,
8686
"type": "Secret Keyword",
8787
"verified_result": null
8888
},
8989
{
9090
"hashed_secret": "4f75456d6c1887d41ed176f7ad3e2cfff3fdfd91",
9191
"is_secret": false,
9292
"is_verified": false,
93-
"line_number": 64,
93+
"line_number": 51,
9494
"type": "Secret Keyword",
9595
"verified_result": null
9696
}

bin/mas-devops-notify-slack

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,8 @@ def _getToolchainLink() -> str:
3030
return toolchainLink
3131
return ""
3232

33-
def _broadcast(channels: str, message: list):
34-
channelList = [ch.strip() for ch in channels.split(",")]
35-
responses = []
36-
for channel in channelList:
37-
try:
38-
if channel:
39-
response = SlackUtil.postMessageBlocks(channel, message)
40-
responses.append(response.data.get("ok", False))
41-
except Exception as e:
42-
print(f"Failed to send message to channel {channel}: {e}")
43-
responses.append(False)
44-
return all(responses) if responses else True
45-
4633

47-
def notifyProvisionFyre(channels: str, rc: int) -> bool:
34+
def notifyProvisionFyre(channels: list[str], rc: int, additionalMsg: str = "") -> bool:
4835
"""Send Slack notification about Fyre OCP cluster provisioning status."""
4936
name = _getClusterName()
5037
toolchainLink = _getToolchainLink()
@@ -64,16 +51,21 @@ def notifyProvisionFyre(channels: str, rc: int) -> bool:
6451
SlackUtil.buildSection(f"- Username: `{username}`\n- Password: `{password}`"),
6552
SlackUtil.buildSection(f"<https://beta.fyre.ibm.com/development/vms|Fyre Dashboard>{toolchainLink}")
6653
]
54+
if additionalMsg:
55+
message.append(SlackUtil.buildSection(additionalMsg))
6756
else:
6857
message = [
6958
SlackUtil.buildHeader(f":glyph-fail: Your IBM DevIT Fyre OCP cluster ({name}) failed to deploy"),
7059
SlackUtil.buildSection(f"<https://beta.fyre.ibm.com/development/vms|Fyre Dashboard>{toolchainLink}")
7160
]
72-
73-
return _broadcast(channels, message)
61+
62+
response = SlackUtil.postMessageBlocks(channels, message)
63+
if isinstance(response, list):
64+
return all([res.data.get("ok", False) for res in response])
65+
return response.data.get("ok", False)
7466

7567

76-
def notifyProvisionRoks(channels: str, rc: int, additionalDetails: str = "") -> bool:
68+
def notifyProvisionRoks(channels: list[str], rc: int, additionalMsg: str = "") -> bool:
7769
"""Send Slack notification about ROKS cluster provisioning status."""
7870
name = _getClusterName()
7971
toolchainLink = _getToolchainLink()
@@ -89,15 +81,18 @@ def notifyProvisionRoks(channels: str, rc: int, additionalDetails: str = "") ->
8981
SlackUtil.buildSection(f"{url}"),
9082
SlackUtil.buildSection(f"<https://cloud.ibm.com/kubernetes/clusters|IBM Cloud Dashboard>{toolchainLink}")
9183
]
92-
if additionalDetails != "":
93-
message.append(SlackUtil.buildSection(additionalDetails))
84+
if additionalMsg:
85+
message.append(SlackUtil.buildSection(additionalMsg))
9486
else:
9587
message = [
9688
SlackUtil.buildHeader(f":glyph-fail: Your IBM Cloud ROKS cluster ({name}) failed to deploy"),
9789
SlackUtil.buildSection(f"<https://cloud.ibm.com/kubernetes/clusters|IBM Cloud Dashboard>{toolchainLink}")
9890
]
9991

100-
return _broadcast(channels, message)
92+
response = SlackUtil.postMessageBlocks(channels, message)
93+
if isinstance(response, list):
94+
return all([res.data.get("ok", False) for res in response])
95+
return response.data.get("ok", False)
10196

10297

10398
if __name__ == "__main__":
@@ -106,21 +101,21 @@ if __name__ == "__main__":
106101
SLACK_CHANNEL = os.getenv("SLACK_CHANNEL", "")
107102
if SLACK_TOKEN == "" or SLACK_CHANNEL == "":
108103
sys.exit(0)
109-
104+
105+
# Parse comma-separated channel list
106+
channelList = [ch.strip() for ch in SLACK_CHANNEL.split(",")]
107+
110108
# Initialize the properties we need
111109
parser = argparse.ArgumentParser()
112110

113111
# Primary Options
114112
parser.add_argument("--action", required=True)
115113
parser.add_argument("--rc", required=True, type=int)
116-
parser.add_argument("--add-details")
114+
parser.add_argument("--msg", required=False, default="")
117115

118116
args, unknown = parser.parse_known_args()
119117

120118
if args.action == "ocp-provision-fyre":
121-
notifyProvisionFyre(SLACK_CHANNEL, args.rc)
119+
notifyProvisionFyre(channelList, args.rc, args.msg)
122120
elif args.action == "ocp-provision-roks":
123-
if args.add_details:
124-
notifyProvisionRoks(SLACK_CHANNEL, args.rc, args.add_details)
125-
else:
126-
notifyProvisionRoks(SLACK_CHANNEL, args.rc)
121+
notifyProvisionRoks(channelList, args.rc, args.msg)

src/mas/devops/slack.py

Lines changed: 87 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -39,73 +39,93 @@ def client(cls) -> WebClient:
3939

4040
# Post message to Slack
4141
# -----------------------------------------------------------------------------
42-
def postMessageBlocks(cls, channelName: str, messageBlocks: list, threadId: str = "") -> SlackResponse:
43-
if threadId == "":
44-
logger.debug(f"Posting {len(messageBlocks)} block message to {channelName} in Slack")
45-
response = cls.client.chat_postMessage(
46-
channel=channelName,
47-
blocks=messageBlocks,
48-
text="Summary text unavailable",
49-
mrkdwn=True,
50-
parse="none",
51-
unfurl_links=False,
52-
unfurl_media=False,
53-
link_names=True,
54-
as_user=True,
55-
)
56-
else:
57-
logger.debug(f"Posting {len(messageBlocks)} block message to {channelName} on thread {threadId} in Slack")
58-
response = cls.client.chat_postMessage(
59-
channel=channelName,
60-
thread_ts=threadId,
61-
blocks=messageBlocks,
62-
text="Summary text unavailable",
63-
mrkdwn=True,
64-
parse="none",
65-
unfurl_links=False,
66-
unfurl_media=False,
67-
link_names=True,
68-
as_user=True,
69-
)
70-
71-
if not response["ok"]:
72-
logger.warning(response.data)
73-
logger.warning("Failed to call Slack API")
74-
return response
75-
76-
def postMessageText(cls, channelName, message, attachments=None, threadId=None):
77-
if threadId is None:
78-
logger.debug(f"Posting message to {channelName} in Slack")
79-
response = cls.client.chat_postMessage(
80-
channel=channelName,
81-
text=message,
82-
attachments=attachments,
83-
mrkdwn=True,
84-
parse="none",
85-
unfurl_links=False,
86-
unfurl_media=False,
87-
link_names=True,
88-
as_user=True,
89-
)
90-
else:
91-
logger.debug(f"Posting message to {channelName} on thread {threadId} in Slack")
92-
response = cls.client.chat_postMessage(
93-
channel=channelName,
94-
thread_ts=threadId,
95-
text=message,
96-
attachments=attachments,
97-
mrkdwn=True,
98-
parse="none",
99-
unfurl_links=False,
100-
unfurl_media=False,
101-
link_names=True,
102-
as_user=True,
103-
)
104-
105-
if not response["ok"]:
106-
logger.warning(response.data)
107-
logger.warning("Failed to call Slack API")
108-
return response
42+
def postMessageBlocks(cls, channelList: str | list[str], messageBlocks: list, threadId: str = "") -> SlackResponse | list[SlackResponse]:
43+
responses = []
44+
45+
if isinstance(channelList, str):
46+
channelList = [channelList]
47+
for channel in channelList:
48+
logger.info(f"{channel}")
49+
try:
50+
if threadId == "":
51+
logger.debug(f"Posting {len(messageBlocks)} block message to {channel} in Slack")
52+
response = cls.client.chat_postMessage(
53+
channel=channel,
54+
blocks=messageBlocks,
55+
text="Summary text unavailable",
56+
mrkdwn=True,
57+
parse="none",
58+
unfurl_links=False,
59+
unfurl_media=False,
60+
link_names=True,
61+
as_user=True,
62+
)
63+
else:
64+
logger.debug(f"Posting {len(messageBlocks)} block message to {channel} on thread {threadId} in Slack")
65+
response = cls.client.chat_postMessage(
66+
channel=channel,
67+
thread_ts=threadId,
68+
blocks=messageBlocks,
69+
text="Summary text unavailable",
70+
mrkdwn=True,
71+
parse="none",
72+
unfurl_links=False,
73+
unfurl_media=False,
74+
link_names=True,
75+
as_user=True,
76+
)
77+
78+
if not response["ok"]:
79+
logger.warning(response.data)
80+
logger.warning("Failed to call Slack API")
81+
responses.append(response)
82+
except Exception as e:
83+
logger.error(f"Fail to send a message to {channel}: {e}")
84+
raise
85+
86+
return responses if len(responses) > 1 else responses[0]
87+
88+
def postMessageText(cls, channelList: str | list[str], message: str, attachments=None, threadId: str = "") -> SlackResponse | list[SlackResponse]:
89+
responses: list[str] = []
90+
91+
if isinstance(channelList, str):
92+
channelList = [channelList]
93+
94+
for channel in channelList:
95+
if threadId == "":
96+
logger.debug(f"Posting message to {channel} in Slack")
97+
response = cls.client.chat_postMessage(
98+
channel=channel,
99+
text=message,
100+
attachments=attachments,
101+
mrkdwn=True,
102+
parse="none",
103+
unfurl_links=False,
104+
unfurl_media=False,
105+
link_names=True,
106+
as_user=True,
107+
)
108+
else:
109+
logger.debug(f"Posting message to {channel} on thread {threadId} in Slack")
110+
response = cls.client.chat_postMessage(
111+
channel=channel,
112+
thread_ts=threadId,
113+
text=message,
114+
attachments=attachments,
115+
mrkdwn=True,
116+
parse="none",
117+
unfurl_links=False,
118+
unfurl_media=False,
119+
link_names=True,
120+
as_user=True,
121+
)
122+
123+
if not response["ok"]:
124+
logger.warning(response.data)
125+
logger.warning("Failed to call Slack API")
126+
responses.append(response)
127+
128+
return responses if len(responses) > 1 else responses[0]
109129

110130
def createMessagePermalink(
111131
cls, slackResponse: SlackResponse = None, channelId: str = "", messageTimestamp: str = "", domain: str = "ibm-mas"

test/src/test_slack.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,16 @@ def testSendMessage():
2121
assert response.data["ok"] is True
2222

2323
assert "ts" in response.data
24+
25+
26+
def testBroadcast():
27+
responses = SlackUtil.postMessageText(["#bot-test", "#bot-test"], "mas-devops unittest")
28+
29+
for response in responses:
30+
assert "channel" in response.data
31+
assert response.data["channel"] == "C06453F9KFC"
32+
33+
assert "ok" in response.data
34+
assert response.data["ok"] is True
35+
36+
assert "ts" in response.data

0 commit comments

Comments
 (0)