Skip to content

Commit

Permalink
Merge pull request #14 from wagtail-examples/use-rich
Browse files Browse the repository at this point in the history
Improve output layout
  • Loading branch information
nickmoreton authored Mar 3, 2024
2 parents 6baed34 + bd1f66a commit 0392de7
Show file tree
Hide file tree
Showing 19 changed files with 833 additions and 678 deletions.
78 changes: 57 additions & 21 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,64 @@
name: Python Tests
name: dependency-check

on: [pull_request]
on:
pull_request:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read # to fetch code (actions/checkout)

jobs:
test:
name: Run Tests
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.x

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-test.txt
- name: Run pytest
run: |
# Run all tests except the ones that are marked as --deselect
# This is because they can only be run locally till I find a way around that
pytest --deselect tests/test_main --deselect tests/test_repository
#----------------------------------------------
# check-out repo and set-up python
#----------------------------------------------
- name: Check out repository
uses: actions/checkout@v4
- name: Set up python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: 3.9
#----------------------------------------------
# ----- install & configure poetry -----
#----------------------------------------------
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
virtualenvs-in-project: true
#----------------------------------------------
# load cached venv if cache exists
#----------------------------------------------
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
#----------------------------------------------
# install dependencies if cache does not exist
#----------------------------------------------
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root
#----------------------------------------------
# install your root project, if required
#----------------------------------------------
- name: Install library
run: poetry install --no-interaction
#----------------------------------------------
# run test suite
#----------------------------------------------
- name: Run tests
run: |
source .venv/bin/activate
pytest tests/ --cov=./
24 changes: 18 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
default_language_version:
python: python3

repos:
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 23.7.0
rev: 24.2.0
hooks:
- id: black
language_version: python3
args: ["--target-version", "py38"]
- repo: https://github.com/adamchainz/blacken-docs
rev: 1.16.0
hooks:
- id: blacken-docs
additional_dependencies: [black==23.9.1]
- repo: https://github.com/pycqa/isort
# isort config is in setup.cfg
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
# flake8 config is in setup.cfg
rev: 7.0.0
hooks:
- id: flake8
2 changes: 0 additions & 2 deletions Makefile

This file was deleted.

731 changes: 389 additions & 342 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ python = "^3.9"
requests = "^2.31.0"
click = "^8.1.3"
tomli = "^2.0.1"
rich = "^13.7.1"


[tool.poetry.group.dev.dependencies]
Expand Down
34 changes: 0 additions & 34 deletions requirements-test.txt

This file was deleted.

149 changes: 86 additions & 63 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import click
from rich import box
from rich.console import Console
from rich.table import Table
from src.managers.package import Client, Package
from src.managers.repository import RepositoryManager
from src.managers.runner import DockerManager
from src.parsers.frozen import FrozenParser
from src.parsers.toml import TomlParser

console = Console()


@click.command()
@click.option(
Expand All @@ -31,99 +36,117 @@
default="./",
)
def start(repo_url, branch_name, docker_file_name, docker_file_location=None):
console.print("\n")
table = Table(title="Repository Information", box=box.MARKDOWN, show_lines=True)
table.add_column("Repository URL", style="bright_white")
table.add_column("Branch Name", style="bright_white")
table.add_column("Dockerfile", style="bright_white")
table.add_column("Dockerfile Location", style="bright_white")
table.add_row(repo_url, branch_name, docker_file_name, docker_file_location)
console.print(table)

# clone the repository
if not docker_file_location == "./":
df = f"{docker_file_location}/{docker_file_name}"
repo_manager = RepositoryManager(repo_url, df)
else:
repo_manager = RepositoryManager(repo_url, docker_file_name)

click.echo(f"Cloning repository {repo_url} ...")
repo_manager.clone()
click.secho(f"Cloned repository to {repo_manager.repo_dir}")
client = Client("https://pypi.org/pypi")

repo_manager.clone()
# switch to an alternative branch if specified
# if branch_name != 'main':
repo_manager.branch(branch_name)
click.secho(f"Checked out branch {branch_name}")

# get the docker image from the Dockerfile
docker_image = repo_manager.docker_image
click.secho(f"Found Docker image {docker_image}")

# get the poetry version from the Dockerfile
poetry_version = repo_manager.poetry_version
click.secho(f"Found Poetry version {poetry_version}")
poetry_latest_version = client.get("poetry").json()["info"]["version"]

console.print("\n")
table = Table(title="Docker Information", box=box.MARKDOWN, show_lines=True)
table.add_column("Docker Image", style="bright_white")
table.add_column("Poetry Version", style="bright_white")
table.add_column("Latest Poetry Version", style="bright_white")
table.add_row(docker_image, poetry_version, poetry_latest_version)
console.print(table)

# run the docker image
docker = DockerManager(docker_image, poetry_version, repo_manager.repo_dir)
click.echo("Running the docker image. This may take some time ...")
console.print("Running the docker image. This may take some time ...", style="yellow1")
docker.run(docker.run_cmd, docker.run_args)
click.secho("Generated requirements-frozen.txt")

# process the requirements-frozen.txt file as a FrozenParser object
# it's used to lookup the package name and version installed in the docker image
frozen = FrozenParser()
click.echo("Processing frozen requirements ...")
frozen.parse_requirements()
frozen_dependencies = frozen.requirements

# process the pyproject.toml file as a TomlParser object
# it's used to lookup the package name and version specified in the pyproject.toml file
toml = TomlParser(repo_manager.toml)
click.echo("Processing pyproject.toml ...")
dependencies = sorted(toml.dependencies().keys())
dev_dependencies = sorted(toml.dev_dependencies().keys())

report_production_dependencies = []
report_dev_dependencies = []
messages = []

client = Client("https://pypi.org/pypi")

click.echo("\n")
click.secho("RED: Manual check should be carried out", fg="bright_red")
click.secho("YELLOW: The latest available version is not installed", fg="bright_yellow")
click.secho("GREEN: Using the latest version available is installed", fg="bright_green")
production_packages = []
development_packages = []

# production dependencies
click.echo("\n")
click.secho("Production dependencies ...", **{"underline": True, "fg": "bright_white"})
console.print("\n")
table = Table(title="Production Dependencies", box=box.MARKDOWN, show_lines=True)
table.add_column("Package", style="bright_white")
table.add_column("Installed Version", style="bright_white")
table.add_column("Latest Version", style="bright_white")
table.add_column("Status", style="bright_white")

for dependency in dependencies:
c = client.get(dependency)
if isinstance(c, int):
# deals with cases such as package names with [extras] in them
messages.append(f"{dependency}")
continue

package = Package(c.json())
latest_version = package.latest_version
frozen_version = frozen_dependencies.get(dependency.lower())

if frozen_version is None:
# deals with cases such as package names that don't exist such as "python"
messages.append(f"{dependency}")
continue
production_packages.append(package)

if frozen_version != latest_version:
if "git+https://" not in frozen_version:
report_production_dependencies.append(
(f"{dependency} {frozen_version} -> {latest_version}", "bright_yellow")
)
for package in production_packages:
name = package.name
latest_version = package.latest_version
frozen_version = frozen_dependencies.get(name.lower())
if frozen_version and frozen_version != latest_version:
if "git+https://" in frozen_version:
status = "Check"
style = "red1"
else:
report_production_dependencies.append(
(f"{dependency} {frozen_version} -> {latest_version}", "bright_red")
)
status = "Outdated"
style = "yellow1"
elif not frozen_version:
status = "Check"
style = "cyan1"
frozen_version = "Unable to determine version"
else:
report_production_dependencies.append((f"{dependency} == {frozen_version}", "bright_green"))
status = "OK"
style = "green3"

if "git+https://" in frozen_version:
frozen_version = frozen_version.replace("git+https://", "")
frozen_version = f"{frozen_version.split('@')[0]} TAG {frozen_version.split('@')[1]}"

table.add_row(name, frozen_version, latest_version, status, style=style)

if report_production_dependencies:
for item in report_production_dependencies:
click.secho(item[0], fg=item[1])
console.print(table)

# development dependencies
console.print("\n")
table = Table(title="Development Dependencies", box=box.MARKDOWN, show_lines=True)
table.add_column("Package", style="bright_white")
table.add_column("Installed Version", style="bright_white")
table.add_column("Latest Version", style="bright_white")
table.add_column("Status", style="bright_white")

# development dependencies
click.echo("\n")
click.secho("Development dependencies ...", **{"underline": True, "fg": "bright_white"})
for dependency in dev_dependencies:
c = client.get(dependency)
if isinstance(c, int):
Expand All @@ -132,31 +155,31 @@ def start(repo_url, branch_name, docker_file_name, docker_file_location=None):
continue

package = Package(c.json())
latest_version = package.latest_version
frozen_version = frozen_dependencies.get(dependency.lower())

if frozen_version is None:
# deals with cases such as package names that don't exist such as "python"
messages.append(f"{dependency}")
continue
development_packages.append(package)

if frozen_version != latest_version:
if "git+https://" not in frozen_version:
report_dev_dependencies.append((f"{dependency} {frozen_version} -> {latest_version}", "bright_yellow"))
for package in development_packages:
name = package.name
latest_version = package.latest_version
frozen_version = frozen_dependencies.get(name.lower())
if frozen_version and frozen_version != latest_version:
if "git+https://" in frozen_version:
status = "Check"
style = "bright_red"
else:
report_dev_dependencies.append((f"{dependency} {frozen_version} -> {latest_version}", "bright_red"))
status = "Outdated"
style = "bright_yellow"
elif not frozen_version:
status = "Check"
style = "magenta"
frozen_version = "Unable to determine version"
else:
report_dev_dependencies.append((f"{dependency} == {frozen_version}", "bright_green"))
status = "OK"
style = "bright_green"

if report_dev_dependencies:
for item in report_dev_dependencies:
click.secho(item[0], fg=item[1])
table.add_row(name, frozen_version, latest_version, status, style=style)

if len(messages) > 0:
click.secho("\n")
click.secho("Manual check required", **{"underline": True, "fg": "bright_white"})
for message in messages:
click.secho(f"{message}", fg="bright_red")
console.print(table)

# cleanup
frozen.clean_up_frozen()
Expand Down
Loading

0 comments on commit 0392de7

Please sign in to comment.