diff --git a/.github/workflows/python-ci.yaml b/.github/workflows/python-ci.yaml index fef05fb..347c506 100644 --- a/.github/workflows/python-ci.yaml +++ b/.github/workflows/python-ci.yaml @@ -2,7 +2,9 @@ name: CI/CD for simple-http-checker on: push: - branches: ['main'] + branches: ['main', 'dev'] + pull_request: + branches: ['main', 'dev'] workflow_dispatch: jobs: @@ -56,6 +58,7 @@ jobs: run: | pytest release: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest needs: - tests @@ -83,4 +86,3 @@ jobs: run: | semantic-release version semantic-release publish - diff --git a/src/media/workflow-overview.excalidraw b/public/media/workflow-overview.excalidraw similarity index 100% rename from src/media/workflow-overview.excalidraw rename to public/media/workflow-overview.excalidraw diff --git a/src/media/workflow-overview.png b/public/media/workflow-overview.png similarity index 100% rename from src/media/workflow-overview.png rename to public/media/workflow-overview.png diff --git a/pyproject.toml b/pyproject.toml index 0a47c32..9135544 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,6 @@ +# Writing Guide +# https://packaging.python.org/en/latest/guides/writing-pyproject-toml/ + [build-system] requires = ["setuptools>=77.0"] build-backend = "setuptools.build_meta" @@ -9,6 +12,27 @@ description = "A simple CLI tool to check the status of URLs." readme = "README.md" requires-python = ">=3.9" dependencies = ["click>=8.0,<9.0", "requests>=2.28,<3.0"] +authors = [{ name = "Pedro Lima" }, { email = "bizak.dev@outlook.com" }] +license = { text = "MIT" } +classifiers = [ + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Natural Language :: Portuguese (Brazilian)", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Libraries :: Python Modules", +] + +[project.urls] +Homepage = "https://github.com/PedroBizachi/python-devops-cicd-project" +Documentation = "https://github.com/lm-academy/python-devops-cicd-project/blob/main/README.md" +Repository = "https://github.com/PedroBizachi/python-devops-cicd-project" +Issues = "https://github.com/PedroBizachi/python-devops-cicd-project/issues" +Changelog = "https://github.com/PedroBizachi/python-devops-cicd-project/blob/main/CHANGELOG.md" [project.optional-dependencies] # Run `pip install .[dev]` to install newer dev dependencies diff --git a/src/simple_http_checker/checker.py b/src/simple_http_checker/checker.py index e8e515f..f8a256b 100644 --- a/src/simple_http_checker/checker.py +++ b/src/simple_http_checker/checker.py @@ -10,20 +10,21 @@ def check_urls(urls: Collection[str], timeout: int = 5) -> dict[str, str]: """Checks a list of urls and returns their status. Args: - urls (list[str]): A list of URLs to check. + urls (Collection[str]): A collection of URLs to check. timeout (int, optional): The timeout in seconds for each URL check. Defaults to 5. Returns: dict[str, str]: A dictionary mapping URLs to their status. """ + url_count = len(urls) + url_context = "URL" if url_count == 1 else "URLs" logger.info( - f"Starting check for {len(urls)} URLs with a timeout of {timeout} seconds." + f"Starting check for {url_count} {url_context} with a timeout of {timeout} seconds." ) results: dict[str, str] = {} for url in urls: - status = "UNKNOWN" try: logger.debug(f"Checking URL: {url}") response = requests.get(url, timeout=timeout) @@ -39,7 +40,7 @@ def check_urls(urls: Collection[str], timeout: int = 5) -> dict[str, str]: logger.warning(f"Connection error for URL: {url}") except requests.exceptions.RequestException as e: status = f"REQUEST_ERROR: {type(e).__name__}" - logger.exception( + logger.error( f"An unexpected error occurred for {url}:", ) diff --git a/src/simple_http_checker/cli.py b/src/simple_http_checker/cli.py index fc80785..c82fe3b 100644 --- a/src/simple_http_checker/cli.py +++ b/src/simple_http_checker/cli.py @@ -1,16 +1,43 @@ import logging from collections.abc import Collection +from typing import ClassVar import click from simple_http_checker.checker import check_urls -logging.basicConfig( - level=logging.INFO, - format="[%(asctime)s] %(levelname)s: %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", + +class ColoredLevelFormatter(logging.Formatter): + LEVEL_COLORS: ClassVar[dict[int, str]] = { + logging.DEBUG: "cyan", + logging.INFO: "green", + logging.WARNING: "yellow", + logging.ERROR: "red", + logging.CRITICAL: "magenta", + } + + def format(self, record: logging.LogRecord) -> str: + original_levelname = record.levelname + color = self.LEVEL_COLORS.get(record.levelno) + if color: + record.levelname = click.style(record.levelname, fg=color) + + try: + return super().format(record) + finally: + record.levelname = original_levelname + + +handler = logging.StreamHandler() +handler.setFormatter( + ColoredLevelFormatter( + fmt="[%(asctime)s] %(levelname)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) ) +logging.basicConfig(level=logging.INFO, handlers=[handler]) + logger = logging.getLogger(__name__) @@ -32,13 +59,11 @@ def main(urls: Collection[str], timeout: int, verbose: bool): click.echo("Usage: check-urls ...") return - logger.info(f"Starting check for {len(urls)} URLs...") - results = check_urls(urls, timeout) click.echo("\n --- Results ---") for url, status in results.items(): - if "OK" in status: + if status.endswith("OK"): fg_color = "green" else: fg_color = "red"