From 452aebd66894f861cee92fcb4148ec87f49cbe82 Mon Sep 17 00:00:00 2001 From: Mark Clapa <162181227+mark-novi@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:10:38 -0400 Subject: [PATCH] ENG-5982 fix: increase timeout for httpx client to 30s + added logging (#26) * fix: increase timeout for httpx client to 30s + added logging * wip: added README.md extension for local environment * chore: fix ruff format issues * wip: update to README.md for linting checklist * wip: moved changes from auto-gen file to __init__ file + more error logging * wip: remove unnecessary graphql_client abstraction, build httpx directly inside init * chore: more ruff formatting --- README.md | 79 +++++++++++++++++++ entrypoint.sh | 4 +- main.py | 1 + .../issue_management/linear/__init__.py | 8 +- release_helper/messaging/slack.py | 10 +++ taskfile.sh | 4 + 6 files changed, 103 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f30f4a4..9b5c490 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,82 @@ A tool to check related tickets are in a ready state for deployment. HELPER_SLACK_BOT_TOKEN: '${{ secrets.SLACK_BOT_TOKEN }}' HELPER_SLACK_CHANNEL_NAME: '#production-deploys' ``` + +## Development Guide + +This section provides a comprehensive guide on how to set up and develop the release_helper project. + +### Prerequisites + +- Docker +- Docker Compose +- Poetry (for local development without Docker) + +### Getting Started + +1. Clone the repository: + ``` + git clone https://github.com/Noviconnect/release_helper.git + cd release_helper + ``` + +2. Set up environment variables: + This is WIP as a practice hasn't been introduced to this repository just yet. + +### Building the Project + +To build the Docker image for the project, run: + +``` +./taskfile.sh build +``` + +This command uses Docker Compose to build the image defined in the `Dockerfile`. It will install all the necessary dependencies and set up the environment for the release_helper. + +### Running the Project + +To run the release_helper, use the following command: + +``` +./taskfile.sh run +``` + +This command starts the Docker container and runs the main.py script. It will process any potential releases, check the status of related tickets, and send notifications as configured. + +### Additional Development Tasks + +The `taskfile.sh` script provides several other useful commands for development: + +- `./taskfile.sh clean`: Removes the `.cache` directory. +- `./taskfile.sh install`: Installs project dependencies using Poetry (for local development). +- `./taskfile.sh generate-linear-client`: Generates the Linear API client using ariadne-codegen. + +### Local Development + +If you prefer to develop without Docker: + +1. Install Poetry: https://python-poetry.org/docs/#installation +2. Install dependencies: `poetry install` +3. Activate the virtual environment: `poetry shell` +4. Run the script: `python main.py` + +### Updating the Linear API Client + +If you need to update the Linear API client: + +1. Modify the GraphQL schema or queries in `release_helper/issue_management/linear/queries.graphql` +2. Run `./taskfile.sh generate-linear-client` +3. The updated client will be generated in `release_helper/issue_management/linear/graphql_client/` + +### Testing + +Currently, there are no specific test commands defined in the taskfile. It's recommended to add unit tests and integration tests to ensure the reliability of the release_helper. + +### Linting and Formatting + +The project uses Ruff for linting and formatting. The configuration can be found in `ruff.toml`. To run linting and formatting: + +1. Activate the virtual environment: `poetry shell` +2. Install Ruff: `pip install ruff` +3. Run linter: `ruff check .` +4. Run formatter: `ruff format .` diff --git a/entrypoint.sh b/entrypoint.sh index 4bd6525..a85565d 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -9,9 +9,9 @@ set -o nounset # Consider a pipeline to fail if any of the commands fail set -o pipefail # Print shell input lines as they are read -#set -o verbose +# set -o verbose # Print commands and their arguments as they are executed -#set -o xtrace +# set -o xtrace export PYTHONPATH=/app diff --git a/main.py b/main.py index 91eaaf7..6759ac0 100644 --- a/main.py +++ b/main.py @@ -10,6 +10,7 @@ if TYPE_CHECKING: from github import GitRelease +logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) diff --git a/release_helper/issue_management/linear/__init__.py b/release_helper/issue_management/linear/__init__.py index a9daeda..1e1b2a3 100644 --- a/release_helper/issue_management/linear/__init__.py +++ b/release_helper/issue_management/linear/__init__.py @@ -2,6 +2,8 @@ import os +import httpx + from release_helper.exceptions import IssueError, ReleaseHelperError from release_helper.issue_management.linear.graphql_client import ( Client, @@ -24,7 +26,11 @@ def get_client() -> Client: "Content-Type": "application/json", "Authorization": f"{token}", } - linear_client = Client(url="https://api.linear.app/graphql", headers=headers) + linear_client = Client( + url="https://api.linear.app/graphql", + headers=headers, + http_client=httpx.Client(headers=headers, timeout=httpx.Timeout(30)), + ) return linear_client def get_issues( diff --git a/release_helper/messaging/slack.py b/release_helper/messaging/slack.py index 879bffb..85eeb46 100644 --- a/release_helper/messaging/slack.py +++ b/release_helper/messaging/slack.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging import os from typing import TYPE_CHECKING @@ -14,6 +15,9 @@ from slack_sdk import WebClient +logger = logging.getLogger(__name__) + + class MessagingSlack: def __init__(self): self.client = self.get_client() @@ -23,6 +27,8 @@ def get_client() -> WebClient: return WebClient(token=os.environ["HELPER_SLACK_BOT_TOKEN"]) def send_blocks(self, blocks: list[dict]) -> None: + logger.info("Sending Slack message with #%d blocks", len(blocks)) + self.client.chat_postMessage( channel=os.environ.get("HELPER_SLACK_CHANNEL_NAME"), blocks=blocks, @@ -34,6 +40,10 @@ def generate_user_message(self, issue: graphql_client.IssueIssue) -> dict[str, s issue_state = issue.state.name issue_url = issue.url issue_assignee = issue.assignee + + if issue_assignee is None: + logger.error("Issue %s has no assignee", issue_id) + issue_assignee_email = issue_assignee.email user_notification = "" diff --git a/taskfile.sh b/taskfile.sh index 677302a..11a7df1 100755 --- a/taskfile.sh +++ b/taskfile.sh @@ -61,6 +61,10 @@ function build() { docker compose build } +function run() { + docker compose up +} + function install() { poetry install --with development }