#!/usr/bin/env python3
# (c) Copyright IBM Corp. 2023
import json
import logging
import os
import re
import requests
import sys
from github import Github
def ensure_environment_variables_are_present():
required_env_vars = ('GITHUB_RELEASE_TAG', 'GITHUB_TOKEN',
'SLACK_BOT_TOKEN', 'SLACK_CHANNEL_ID_RELEASES')
for v in required_env_vars:
if not os.environ.get(v):
logging.fatal("A required environment variable is missing: %s", v)
sys.exit(1)
def get_gh_release_info_text_with_token(release_tag, access_token):
g = Github(access_token)
repo_name = "instana/ruby-sensor"
repo = g.get_repo(repo_name)
release = repo.get_release(release_tag)
logging.info("GH Release fetched successfully %s", release)
msg = (
f":mega: :package: A new version is released in {repo_name}\n"
f"Name: {release.title}\n"
f"Tag: {release.tag_name}\n"
f"Created at: {release.created_at}\n"
f"Published at: {release.published_at}\n"
f"{release.body}\n")
logging.info(msg)
return msg
def reformat_github_md_to_slack_markup(msg):
# Based on:
# https://github.com/atomist/slack-messages/blob
# /c938c67e957345ba6a0015ca3ace1fd779d0979c/lib/Markdown.ts#LL111C1-L116C44
msg = re.sub(r'^(\s*)[-*](\s+)', r'\1•\2', msg, flags=re.MULTILINE)
msg = re.sub(r'(\*|_)\1(\S|\S.*?\S)\1\1(?!\1)', r'\2', msg)
msg = re.sub(r'(\*|_)(?!\1)(\S|\S.*?\S)\1(?!\1)', r'\2', msg)
msg = msg.replace('', '*').replace('', '_')
msg = re.sub(r'^([#]+)\s+([\S ]+)$', r'*\2*', msg, flags=re.MULTILINE)
# TODO: The message text has to have a partial entity encoding
# https://api.slack.com/reference/surfaces/formatting#escaping
# Validate it if we can?
# A naive replace like this is not enough, because
# it might already be encoded and then we would encode again.
#s = s.replace('&', '&')
#s = s.replace('<', '<')
#s = s.replace('>', '>')
# Use the tester here:
# https://api.slack.com/methods/chat.postMessage/test
return msg
def post_on_slack_channel(slack_token, slack_channel_id, message_text):
api_url = "https://slack.com/api/chat.postMessage"
headers = {"Authorization": f"Bearer {slack_token}",
"Content-Type": "application/json"}
body = {"channel": slack_channel_id, "text": message_text}
response = requests.post(api_url, headers=headers, data=json.dumps(body))
response_data = json.loads(response.text)
if response_data["ok"]:
logging.info("Message sent successfully!")
else:
logging.fatal("Error sending message: %s", response_data['error'])
def main():
# Setting this globally to DEBUG will also debug PyGithub,
# which will produce even more log output
logging.basicConfig(level=logging.INFO)
ensure_environment_variables_are_present()
msg = get_gh_release_info_text_with_token(os.environ['GITHUB_RELEASE_TAG'],
os.environ['GITHUB_TOKEN'])
slack_formatted_msg = reformat_github_md_to_slack_markup(msg)
post_on_slack_channel(os.environ['SLACK_BOT_TOKEN'],
os.environ['SLACK_CHANNEL_ID_RELEASES'],
slack_formatted_msg)
if __name__ == "__main__":
main()