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

Change dir #143

Merged
merged 23 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
fbd76b4
BUG: Removing parent from imports as source files are siblings.
khalford Jun 11, 2024
56719c3
ENH: Changed exceptions to inherit from specific errors.
khalford Jun 11, 2024
9f1f035
ENH: Modularised classes as they were doing multiple thins
khalford Jun 12, 2024
fe702be
LINT; Pylint and black
khalford Jun 12, 2024
b1d172c
BUG: Changed directory structure
khalford Jun 12, 2024
f53ee7c
BUG: Changed the workflow linting path
khalford Jun 12, 2024
dd761aa
BUG: Changed test import path
khalford Jun 12, 2024
0695c5c
LINT: Removing a legacy ignore statement
khalford Jun 12, 2024
1139e9e
BUG: Ignoring this lint error as test are not crucial to be perfect
khalford Jun 12, 2024
bb6601f
BUG: Changing directories again to fix import errors
khalford Jun 12, 2024
f2ac54d
ENH: Added a pytest config file
khalford Jun 12, 2024
f927eaf
BUG: Tests not being patched properly
khalford Jun 12, 2024
8521877
DOC: Response to PR comments
khalford Jun 24, 2024
58f2eea
BUG: Changed directory structure
khalford Jun 12, 2024
ebabf6a
BUG: Changed the workflow linting path
khalford Jun 12, 2024
0ab1104
BUG: Changed test import path
khalford Jun 12, 2024
df274d7
LINT: Removing a legacy ignore statement
khalford Jun 12, 2024
aef42e2
BUG: Ignoring this lint error as test are not crucial to be perfect
khalford Jun 12, 2024
1e542b5
BUG: Changing directories again to fix import errors
khalford Jun 12, 2024
b82e322
ENH: Added a pytest config file
khalford Jun 12, 2024
b035084
BUG: Tests not being patched properly
khalford Jun 12, 2024
ce43ddf
Merge branch 'change_dir' of github.com:stfc/SCD-OpenStack-Utils into…
khalford Sep 2, 2024
28417e5
ENH: PR comment changes
khalford Sep 5, 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
7 changes: 2 additions & 5 deletions .github/workflows/cloud_chatops.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ jobs:
cd cloud_chatops && pip install -r requirements.txt

- name: Analyse with pylint
run: pylint cloud_chatops/src --rcfile=cloud_chatops/.pylintrc

- name: Run tests
run: cd cloud_chatops && python3 -m pytest
run: pylint cloud_chatops --rcfile=cloud_chatops/.pylintrc

- name: Run tests and collect coverage
run: cd cloud_chatops && python3 -m pytest . --cov-report xml:coverage.xml --cov
run: cd cloud_chatops && python3 -m pytest tests --cov-report xml:coverage.xml --cov

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
Expand Down
3 changes: 1 addition & 2 deletions cloud_chatops/.pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
max-line-length=120

# Disable various warnings:
# R0913: too-many-arguments, disabling this as the PR functions require a large amount of information.

disable=R0913
disable=
4 changes: 2 additions & 2 deletions cloud_chatops/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Using Slack's Bolt for Python library here I have developed a Slack Application
This application is designed to help promote the closing of GitHub pull requests either by getting them approved and merged or closed when they go stale.<br>
In principle, the app will notify authors about their pull requests until they are closed.<br>
### Deployment
The entry point for is in [main.py](/cloud_chatops/src/main.py) which will run the application.<br>
The required files (below) need to be in the [cloud_chatops](/cloud_chatops) directory.<br>
The entry point for is in [main.py](main.py) which will run the application.<br>
The required files (below) need to be in the [cloud_chatops](.) directory.<br>
### Functionality
As of current, the application gets all open pull requests from any Cloud owned repository and will send a message to our pull-request channel about each pull request notifying the author.<br>
The app runs on an asynchronous loop scheduling each reminder to be sent out on days of our catch-ups (Monday, Wednesday and Friday).<br>
Expand Down
File renamed without changes.
khalford marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

from typing import List, Dict
import requests
from read_data import get_token
from pr_dataclass import PrData
from custom_exceptions import RepoNotFound, UnknownHTTPError, BadGitHubToken
from lib.read_data import get_token
from lib.pr_dataclass import PrData
from lib.custom_exceptions import RepoNotFound, UnknownHTTPError, BadGitHubToken


class GetGitHubPRs:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This module handles the Slack Application status notifications."""

from slack_sdk import WebClient
from read_data import get_token, get_maintainer
from lib.read_data import get_token, get_maintainer


def online_notif() -> None:
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from datetime import datetime, timedelta
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from read_data import get_token, get_user_map, get_repos
from get_github_prs import GetGitHubPRs
from pr_dataclass import PrData
from custom_exceptions import ChannelNotFound
from lib.read_data import get_token, get_user_map, get_repos
from lib.get_github_prs import GetGitHubPRs
from lib.pr_dataclass import PrData
from lib.custom_exceptions import ChannelNotFound


class PostPRsToSlack:
Expand All @@ -16,20 +16,24 @@ class PostPRsToSlack:
"""
This class handles the Slack posting.
"""
# The default channel is dev-chatops
def __init__(self, mention=False, channel="C06U37Y02R4"):
self.channel = channel

def __init__(self, mention=False):
self.channel = "C06U37Y02R4" # STFC-cloud: dev-chatops
khalford marked this conversation as resolved.
Show resolved Hide resolved
self.thread_ts = ""
self.mention = mention
self.slack_ids = get_user_map()
self.message_builder = PRMessageBuilder(self.mention)
self.client = WebClient(token=get_token("SLACK_BOT_TOKEN"))
self.prs = GetGitHubPRs(get_repos(), "stfc").run()

def run(self) -> None:
def run(self, channel=None) -> None:
"""
This method sets class attributes then cals the reminder and thread post methods.
:param channel: Changes the channel to post the messages to.
"""
if channel:
self._set_channel_id(channel)

self._post_reminder_message()
self._post_thread_messages(self.prs)

Expand Down Expand Up @@ -127,12 +131,10 @@ class PRMessageBuilder:

# pylint: disable=R0903
# Disabling this as there only needs to be one entry point.
# The default user here is David Fairbrother
def __init__(self, mention, default_user_id="U01JG0LKU3W"):
def __init__(self, mention):
self.client = WebClient(token=get_token("SLACK_BOT_TOKEN"))
self.slack_ids = get_user_map()
self.mention = mention
self.default_user_id = default_user_id

def make_message(self, pr_data: PrData) -> str:
"""
Expand Down Expand Up @@ -179,7 +181,10 @@ def _github_to_slack_username(self, user: str) -> str:
:return: Slack ID or GitHub username
"""
if user not in self.slack_ids:
user = self.default_user_id
# If the PR author is not in the Slack ID mapping
# then we set the user to mention as David Fairbrother
# as the team lead to deal with this PR.
user = "U01JG0LKU3W"
khalford marked this conversation as resolved.
Show resolved Hide resolved
else:
user = self.slack_ids[user]
return user
Expand All @@ -194,7 +199,9 @@ def _check_pr_age(time_created: str) -> bool:
opened_date = datetime.fromisoformat(time_created).replace(tzinfo=None)
datetime_now = datetime.now().replace(tzinfo=None)
time_cutoff = datetime_now - timedelta(days=30 * 6)
return opened_date < time_cutoff
if opened_date < time_cutoff:
return True
return False
khalford marked this conversation as resolved.
Show resolved Hide resolved

def _check_pr_info(self, info: PrData) -> PrData:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import List, Dict
import json
from custom_exceptions import RepositoriesNotGiven, UserMapNotGiven, TokensNotGiven
from lib.custom_exceptions import RepositoriesNotGiven, UserMapNotGiven, TokensNotGiven


def validate_required_files() -> None:
Expand Down Expand Up @@ -34,7 +34,7 @@ def get_token(secret: str) -> str:
:param secret: The secret to find
:return: A secret as string
"""
with open("../secrets.json", "r", encoding="utf-8") as file:
with open("secrets.json", "r", encoding="utf-8") as file:
data = file.read()
secrets = json.loads(data)
return secrets[secret]
Expand All @@ -45,7 +45,7 @@ def get_repos() -> List[str]:
This function reads the repo csv file and returns a list of repositories
:return: List of repositories as strings
"""
with open("../repos.csv", "r", encoding="utf-8") as file:
with open("repos.csv", "r", encoding="utf-8") as file:
data = file.read()
repos = data.split(",")
if not repos[-1]:
Expand All @@ -58,7 +58,7 @@ def get_user_map() -> Dict:
This function gets the GitHub to Slack username mapping from the map file.
:return: Dictionary of username mapping
"""
with open("../user_map.json", "r", encoding="utf-8") as file:
with open("user_map.json", "r", encoding="utf-8") as file:
data = file.read()
user_map = json.loads(data)
return user_map
Expand All @@ -69,7 +69,7 @@ def get_maintainer() -> str:
This function will get the maintainer user's Slack ID from the text file.
:return: Slack Member ID
"""
with open("../maintainer.txt", "r", encoding="utf-8") as file:
with open("maintainer.txt", "r", encoding="utf-8") as file:
data = file.read()
if not data:
return "U05RBU0RF4J" # Default Maintainer: Kalibh Halford
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
This module starts the Slack Bolt application Asynchronously running the event loop.
Using Socket Mode the application listens for events from the Slack API client.
Using Socket mode, the application listens for events from the Slack API client.
Slash commands are also defined here.
"""

Expand All @@ -9,9 +9,9 @@
from slack_bolt.app.async_app import AsyncApp
from slack_bolt.adapter.socket_mode.async_handler import AsyncSocketModeHandler
import schedule
from pr_reminder import PostPRsToSlack
from read_data import get_token, validate_required_files
from online_notif import online_notif
from lib.pr_reminder import PostPRsToSlack
from lib.read_data import get_token, validate_required_files
from lib.online_notif import online_notif


logging.basicConfig(level=logging.DEBUG)
Expand All @@ -27,7 +27,7 @@ def run_pr(channel, mention=False) -> None:
"""
This is a placeholder function for the schedule to accept.
"""
PostPRsToSlack(mention=mention, channel=channel).run()
PostPRsToSlack(mention=mention).run(channel=channel)

schedule.every().monday.at("09:00").do(
run_pr, mention=True, channel="pull-requests"
Expand Down
2 changes: 1 addition & 1 deletion cloud_chatops/src/main.py → cloud_chatops/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""

import asyncio
from slack_app import run_app
from lib.slack_app import run_app


def main():
Expand Down
5 changes: 5 additions & 0 deletions cloud_chatops/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[pytest]
pythonpath = lib
testpaths = tests
python_files = *.py
python_functions = test_*
3 changes: 1 addition & 2 deletions cloud_chatops/tests/test_read_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""This test file covers all tests for the read_data module."""

from unittest.mock import patch, mock_open
from src.read_data import get_token, get_repos, get_user_map, get_maintainer
from lib.read_data import get_token, get_repos, get_user_map, get_maintainer


def test_get_token():
Expand Down
Loading