Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Slack Service Refactor #4936

Merged
merged 21 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
19727b9
:recycle: Moved `GANDI_FUND_THRESHOLD` variables to `config.constants`
PepperMoJ Oct 22, 2024
bc0c22e
:fire: Removed message construction from bin scripts where relevant.
PepperMoJ Oct 22, 2024
bccfdac
:sparkles: `GANDI_FUND_THRESHOLD` and `GITHUB_LICENSE_THRESHOLD` adde…
PepperMoJ Oct 22, 2024
e06ef3b
:recycle: Refactored bin script tests to work with new Slack message …
PepperMoJ Oct 22, 2024
1f17234
:fire: Removed old messaging technique
PepperMoJ Oct 22, 2024
e765ae7
:sparkles: Added error handling to message posting function.
PepperMoJ Oct 22, 2024
c85efe2
:recycle: Added configurable block type for message formatting.
PepperMoJ Oct 22, 2024
618e4b9
:recycle: Added new messaging functions and corrected formatting of o…
PepperMoJ Oct 22, 2024
186cec6
:sparkles: Added repository URL as class variable
PepperMoJ Oct 22, 2024
a36a507
:sparkles: Added test coverage for all new functionality in slack ser…
PepperMoJ Oct 22, 2024
64ad117
:wrench: Corrected import for SlackApiError.
PepperMoJ Oct 22, 2024
db5c7eb
:fire: removed channel lookup tests.
PepperMoJ Oct 22, 2024
a81f525
:fire: Removed support stat reporting
PepperMoJ Oct 22, 2024
db2d896
:recycle: Formatting and unused import.
PepperMoJ Oct 22, 2024
387d7e0
:wrench: Fix formatting for dedent string.
PepperMoJ Oct 23, 2024
f61c5a4
:wrench: Corrected formatting for slack message
PepperMoJ Oct 23, 2024
4bf5314
:wrench: Moved to old formatting method for multiline strings.
PepperMoJ Oct 28, 2024
1f57c22
:wrench: Using exact message from last know working format
PepperMoJ Oct 28, 2024
2e4f24c
:wrench: Corrected formatting for all slack messages and tests.
PepperMoJ Oct 28, 2024
5cc6413
Merge branch 'main' into refactor-slack-service
PepperMoJ Oct 28, 2024
372fdd0
:recycle: Refactored POC alert script and tests to fit new Slack serv…
PepperMoJ Oct 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions bin/alarm_for_old_poc_repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@

from services.github_service import GithubService
from services.slack_service import SlackService
from config.constants import ENTERPRISE, MINISTRY_OF_JUSTICE, SLACK_CHANNEL

def construct_message(repositories):
intro = "The following POC GitHub Repositories persist:\n\n"

core_content = "\n".join([f"https://github.com/ministryofjustice/{repo} - {age} days old" for repo, age in repositories.items()])

action = "\n\nConsider if they are still required. If not, please archive them by removing them from the Terraform configuration: https://github.com/ministryofjustice/operations-engineering/tree/main/terraform/github/repositories/ministryofjustice"

return intro + core_content + action
from config.constants import ENTERPRISE, MINISTRY_OF_JUSTICE


def alert_for_old_poc_repositories():
Expand All @@ -33,7 +24,7 @@ def alert_for_old_poc_repositories():
old_poc_repositories = github_service.get_old_poc_repositories()

if old_poc_repositories:
slack_service.send_message_to_plaintext_channel_name(construct_message(old_poc_repositories), SLACK_CHANNEL)
slack_service.send_alert_for_poc_repositories(old_poc_repositories)


if __name__ == "__main__":
Expand Down
21 changes: 2 additions & 19 deletions bin/alert_on_low_gandi_funds.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,7 @@
import sys
from services.gandi_service import GandiService
from services.slack_service import SlackService
from config.constants import SLACK_CHANNEL

GANDI_FUND_THRESHOLD = 500


def low_gandi_funds_message(remaining_gandi_funds):
msg = (
f"Hi all, \n\n"
f"This is an alert do inform you that Gandi funds are low. \n\n"
f"*:warning: We currently have £{remaining_gandi_funds} left out of £{GANDI_FUND_THRESHOLD}*\n\n"
f"Please read the following runbook for next steps:\n"
f"https://runbooks.operations-engineering.service.justice.gov.uk/documentation/certificates/manual-ssl-certificate-processes.html#regenerating-certificates\n\n"
f"Have a swell day, \n\n"
"The GitHub Organisation Monitoring Bot"
)

return msg
from config.constants import GANDI_FUND_THRESHOLD


def alert_on_low_gandi_funds():
Expand All @@ -39,8 +23,7 @@ def alert_on_low_gandi_funds():
remaining_gandi_funds = gandi_service.get_current_account_balance_from_org(organisation_id)

if remaining_gandi_funds < GANDI_FUND_THRESHOLD:
SlackService(slack_token).send_message_to_plaintext_channel_name(
low_gandi_funds_message(remaining_gandi_funds), SLACK_CHANNEL)
SlackService(slack_token).send_low_gandi_funds_alert(remaining_gandi_funds, GANDI_FUND_THRESHOLD)


if __name__ == "__main__":
Expand Down
8 changes: 2 additions & 6 deletions bin/alert_on_low_github_actions_quota.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
import sys
from services.github_service import GithubService
from services.slack_service import SlackService
from config.constants import ENTERPRISE, MINISTRY_OF_JUSTICE, SLACK_CHANNEL


def low_threshold_triggered_message(percentage_used):
return f"Warning:\n\n {round(100 - percentage_used, 1)}% of the Github Actions minutes quota remains.\n\n What to do next: https://runbooks.operations-engineering.service.justice.gov.uk/documentation/internal/low-github-actions-minutes-procedure.html#low-github-actions-minutes-procedure"
from config.constants import ENTERPRISE, MINISTRY_OF_JUSTICE


def alert_on_low_quota():
Expand All @@ -25,7 +21,7 @@ def alert_on_low_quota():
check_result = github_service.check_if_gha_minutes_quota_is_low()

if check_result is not False:
slack_service.send_message_to_plaintext_channel_name(low_threshold_triggered_message(check_result['percentage_used']), SLACK_CHANNEL)
slack_service.send_low_github_actions_quota_alert(check_result['percentage_used'])
github_service.modify_gha_minutes_quota_threshold(check_result['threshold'] + 10)


Expand Down
42 changes: 7 additions & 35 deletions bin/alert_on_low_github_licences.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,11 @@
"""
GitHub License Monitoring Script

Purpose:
--------
This script monitors the number of available licenses in a GitHub Enterprise account.
It is designed to provide alerts when the license count falls below a
specified threshold.
"""

import os
import sys
from config.constants import ENTERPRISE, MINISTRY_OF_JUSTICE, SLACK_CHANNEL
from config.constants import ENTERPRISE, MINISTRY_OF_JUSTICE, GITHUB_LICENSE_THRESHOLD
from services.github_service import GithubService
from services.slack_service import SlackService


def low_threshold_triggered_message(remaining_licences):
msg = (
f"Hi team 👋, \n\n"
f"There are only {remaining_licences} \
GitHub licences remaining in the enterprise account. \n\n"
f"Please add more licences using the instructions outlined here: \n"
f"https://runbooks.operations-engineering.service.justice.gov.uk/documentation/internal/low-github-seats-procedure.html \n\n"

f"Thanks, \n\n"

"The GitHub Licence Alerting Bot"
)

return msg


def alert_on_low_github_licences(threshold):
def alert_on_low_github_licenses():
github_token = os.environ.get("ADMIN_GITHUB_TOKEN")
if github_token is None:
print("No GITHUB_TOKEN environment variable set")
Expand All @@ -41,18 +15,16 @@ def alert_on_low_github_licences(threshold):
print("No SLACK_TOKEN environment variable set")
sys.exit(1)

remaining_licences = GithubService(
remaining_licenses = GithubService(
github_token, MINISTRY_OF_JUSTICE, ENTERPRISE).get_remaining_licences()
trigger_alert = remaining_licences < threshold
trigger_alert = remaining_licenses < GITHUB_LICENSE_THRESHOLD

if trigger_alert:
print(
f"Low number of GitHub licences remaining, only {remaining_licences} remaining")
f"Low number of GitHub licenses remaining, only {remaining_licenses} remaining")

SlackService(slack_token). \
send_message_to_plaintext_channel_name(
low_threshold_triggered_message(remaining_licences), SLACK_CHANNEL)
SlackService(slack_token).send_low_github_licenses_alert(remaining_licenses)


if __name__ == "__main__":
alert_on_low_github_licences(20)
alert_on_low_github_licenses()
26 changes: 2 additions & 24 deletions bin/check_for_new_github_owners.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from datetime import datetime, timedelta
from config.constants import MINISTRY_OF_JUSTICE, SLACK_CHANNEL
from config.constants import MINISTRY_OF_JUSTICE

from services.github_service import GithubService
from services.slack_service import SlackService
Expand All @@ -13,25 +13,6 @@ def _calculate_date(in_last_days: int) -> str:
return date.strftime(timestamp_format)


def new_owner_detected_message(new_owner, date_added, added_by, org, audit_log_url):
msg = (
f"Hi all, \n\n"
f"A new owner has been detected in the `{org}` GitHub org. \n\n"
f"*New owner:* {new_owner}\n"
f"*Date added:* {date_added}\n"
f"*By who:* {added_by}\n\n"

f"Please review the audit log for more details: {audit_log_url}\n\n"


f"Thanks, \n\n"

"The GitHub Organisation Monitoring Bot"
)

return msg


def check_for_new_organisation_owners(in_last_days: int):
audit_log_url = f"https://github.com/organizations/{MINISTRY_OF_JUSTICE}/settings/audit-log?q=action%3Aorg.add_member++action%3Aorg.update_member"

Expand All @@ -46,10 +27,7 @@ def check_for_new_organisation_owners(in_last_days: int):

if changes:
for change in changes:
message = new_owner_detected_message(
change["userLogin"], change["createdAt"], change["actorLogin"], MINISTRY_OF_JUSTICE, audit_log_url)
slack.send_message_to_plaintext_channel_name(
message, SLACK_CHANNEL)
slack.send_new_github_owners_alert(change["userLogin"], change["createdAt"], change["actorLogin"], MINISTRY_OF_JUSTICE, audit_log_url)


if __name__ == "__main__":
Expand Down
23 changes: 3 additions & 20 deletions bin/fetch_github_joiner_metrics.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from datetime import datetime, timedelta
from config.constants import MINISTRY_OF_JUSTICE, SLACK_CHANNEL, OPERATIONS_ENGINEERING_GITHUB_USERNAMES
from config.constants import MINISTRY_OF_JUSTICE, OPERATIONS_ENGINEERING_GITHUB_USERNAMES

from services.github_service import GithubService
from services.slack_service import SlackService
Expand All @@ -26,23 +26,6 @@ def _calculate_date(in_last_days: int) -> str:
return date.strftime(timestamp_format)


def new_members_detected_message(new_members_added_by_oe, new_members_added_externally, percentage, total_new_members, org, audit_log_url, time_delta_in_days):
msg = (
f"Hi all, \n\n"
f"Here are the {total_new_members} new joiners added in the last {time_delta_in_days} days within the '{org}' GitHub org. \n\n"
f"*Added by Operations Engineering:*\n"
f"{new_members_added_by_oe}\n\n"
f"*Added externally:*\n"
f"{new_members_added_externally}\n\n"
f"{percentage}% of the new joiners were added by operations engineering.\n\n"
f"Please review the audit log for more details: {audit_log_url}\n\n"
f"Have a swell day, \n\n"
"The GitHub Organisation Monitoring Bot"
)

return msg


def main():
audit_log_url = f"https://github.com/organizations/{MINISTRY_OF_JUSTICE}/settings/audit-log?q=action%3Aorg.add_member"

Expand All @@ -67,8 +50,8 @@ def main():
new_members_added_externally += individual_message
percentage = round((total_members_added_by_oe / len(new_members)) * 100)

slack_service.send_message_to_plaintext_channel_name(
new_members_detected_message(new_members_added_by_oe, new_members_added_externally, percentage, total_new_members, MINISTRY_OF_JUSTICE, audit_log_url, time_delta_in_days), SLACK_CHANNEL)
slack_service.send_new_github_joiner_metrics_alert(
new_members_added_by_oe, new_members_added_externally, percentage, total_new_members, MINISTRY_OF_JUSTICE, audit_log_url, time_delta_in_days)


if __name__ == "__main__":
Expand Down
19 changes: 2 additions & 17 deletions bin/generate_pat_token_report.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
from config.constants import MINISTRY_OF_JUSTICE, SLACK_CHANNEL
from config.constants import MINISTRY_OF_JUSTICE

from services.github_service import GithubService
from services.slack_service import SlackService
Expand All @@ -18,21 +18,6 @@ def get_environment_variables() -> tuple:
return slack_token, github_token


def expired_tokens_message():
msg = (
"Hi team 👋, \n\n"
"Some expired PAT(s) have been detected. \n\n"
"Please review the current list here: \n"
"https://github.com/organizations/ministryofjustice/settings/personal-access-tokens/active \n\n"

"Have a swell day, \n\n"

"The GitHub PAT Bot"
)

return msg


def count_expired_tokens(pat_tokens):
expired_count = 0
for token in pat_tokens:
Expand All @@ -50,7 +35,7 @@ def generate_pat_token_report():
pat_tokens = github_service.get_new_pat_creation_events_for_organization()

if count_expired_tokens(pat_tokens) > 0:
slack_service.send_message_to_plaintext_channel_name(expired_tokens_message(), SLACK_CHANNEL)
slack_service.send_pat_report_alert()


if __name__ == "__main__":
Expand Down
17 changes: 5 additions & 12 deletions bin/identify_dormant_github_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
CSV_FILE_NAME = "dormant.csv"
MOJ_ORGANISATION = "ministryofjustice"
AP_ORGANISATION = "moj-analytical-services"
SLACK_CHANNEL = "operations-engineering-alerts"
# These are the users that are deemed acceptable to be dormant.
# They are either bots or service accounts and will be revisited regularly.
ALLOWED_BOT_USERS = [
Expand Down Expand Up @@ -143,12 +142,8 @@ def filter_out_active_auth0_users(dormant_users_according_to_github: list) -> li
return dormant_users_not_in_auth0


def message_to_slack_channel(dormant_users: list) -> str:
msg = (
"Hello 🤖, \n\n"
"Here is a list of dormant GitHub users that have not been seen in Auth0 logs:\n\n"
)

def _create_dormant_user_list(dormant_users: list) -> str:
msg = ""
for user in dormant_users:
msg += f"{user.name} | {user.email}\n"

Expand Down Expand Up @@ -187,14 +182,12 @@ def identify_dormant_github_users():
githubs_list_of_dormant_users = get_dormant_users_from_github_csv(
moj_github_org, ap_github_org)

dormant_users_accoding_to_github_and_auth0 = filter_out_active_auth0_users(
dormant_users_according_to_github_and_auth0 = filter_out_active_auth0_users(
githubs_list_of_dormant_users
)

SlackService(env.get("ADMIN_SLACK_TOKEN")).send_message_to_plaintext_channel_name(
message_to_slack_channel(dormant_users_accoding_to_github_and_auth0),
SLACK_CHANNEL,
)
SlackService(env.get("ADMIN_SLACK_TOKEN")).send_dormant_user_list(
_create_dormant_user_list(dormant_users_according_to_github_and_auth0))


if __name__ == "__main__":
Expand Down
2 changes: 2 additions & 0 deletions config/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# class Constants:
GANDI_FUND_THRESHOLD = 500
GITHUB_LICENSE_THRESHOLD = 20
MINISTRY_OF_JUSTICE = "ministryofjustice"
MOJ_ANALYTICAL_SERVICES = "moj-analytical-services"
MISSING_EMAIL_ADDRESS = "-"
Expand Down
Loading
Loading