Skip to content

Commit

Permalink
Add linters
Browse files Browse the repository at this point in the history
  • Loading branch information
RealOrangeOne committed Aug 17, 2023
1 parent 448b0d7 commit 1e18731
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 118 deletions.
26 changes: 9 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ jobs:
with:
python-version: "3.8"
- name: Install dependencies
run: python -m pip install .
run: |
python -m pip install --upgrade flit
flit install --deps=all
- name: Type check
run: mypy heroku_audit stubs
- name: Format
run: black --check heroku_audit stubs
- name: lint
run: ruff check heroku_audit stubs

build:
permissions:
Expand All @@ -23,22 +31,6 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: "3.8"
- name: Install dependencies
run: |
python -m pip install .
- name: Build package
run: |
flit build
- name: Save built package
uses: actions/upload-artifact@v3
with:
name: package
path: |
dist
- name: Publish to PyPi
if: ${{ github.ref_type == 'tag' }}
uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
23 changes: 12 additions & 11 deletions heroku_audit/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import typer
from typing import Annotated, Optional, cast

from . import apps, env, postgres, redis
from typing import Annotated, Optional
from heroku_audit import __version__
from rich.table import Table
import typer
from rich.console import Console
from typer.rich_utils import _print_commands_panel

from heroku_audit import __version__

from . import apps, env, postgres, redis

app = typer.Typer(help="Heroku audit tool")

Expand All @@ -17,19 +17,20 @@
app.add_typer(redis.app)


def version_callback(version: bool):
def version_callback(version: bool) -> None:
if version:
print("Version", __version__)
raise typer.Exit()


def list_callback(should_list: bool):
def list_callback(should_list: bool) -> None:
if should_list:
click_command = typer.main.get_command(app)
typer_group = typer.main.get_group(app)

commands = []
for group_name, group in sorted(click_command.commands.items()):
for _command_name, command in sorted(group.commands.items()):
for group_name, group in sorted(typer_group.commands.items()):
command_group = cast(typer.core.TyperGroup, group)
for _command_name, command in sorted(command_group.commands.items()):
# Prefix command name
command.name = f"{group_name} {command.name}"
commands.append(command)
Expand Down Expand Up @@ -63,5 +64,5 @@ def main(
callback=list_callback,
),
] = False,
):
) -> None:
pass
18 changes: 10 additions & 8 deletions heroku_audit/cli/apps.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import typer
from heroku_audit.client import heroku
from concurrent.futures import ThreadPoolExecutor
from typing import Annotated

import typer
from rich.progress import track
from concurrent.futures import ThreadPoolExecutor
from heroku_audit.format import display_data, FormatOption, Format
from heroku_audit.utils import get_apps_for_teams, SHOW_PROGRESS
from rich.text import Text

from heroku_audit.client import heroku
from heroku_audit.format import Format, FormatOption, display_data
from heroku_audit.options import TeamOption
from heroku_audit.utils import SHOW_PROGRESS, get_apps_for_teams

app = typer.Typer(name="apps", help="Report on Heroku apps.")

Expand All @@ -15,8 +17,8 @@
def formation(
process: Annotated[str, typer.Option()] = "web",
team: TeamOption = None,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Review formation for a given process.
"""
Expand Down Expand Up @@ -56,5 +58,5 @@ def formation(
),
key=lambda r: r["App"],
),
format,
display_format,
)
30 changes: 16 additions & 14 deletions heroku_audit/cli/env.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import fnmatch
import re
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor
from typing import Annotated, Optional

import typer
from heroku_audit.client import heroku
from typing import Optional, Annotated
from rich.progress import track
from concurrent.futures import ThreadPoolExecutor
from heroku_audit.format import display_data, FormatOption, Format
from heroku_audit.utils import get_apps_for_teams, SHOW_PROGRESS
from rich.text import Text
from collections import defaultdict
import fnmatch
import re

from heroku_audit.client import heroku
from heroku_audit.format import Format, FormatOption, display_data
from heroku_audit.options import TeamOption
from heroku_audit.utils import SHOW_PROGRESS, get_apps_for_teams

app = typer.Typer(name="env", help="Report on Environment variables.")

Expand All @@ -22,8 +24,8 @@ def value_of(
typer.Option(help="Only show apps with the variable missing"),
] = None,
team: TeamOption = None,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Find the value of a given environment variable
"""
Expand Down Expand Up @@ -52,7 +54,7 @@ def value_of(
({"App": app.name, "Value": value} for app, value in app_values.items()),
key=lambda r: r["App"],
),
format,
display_format,
)


Expand All @@ -62,8 +64,8 @@ def contains(
str, typer.Argument(help="Value to search for. Glob syntax is supported.")
],
team: TeamOption = None,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Find applications with a given environment variable value set.
"""
Expand Down Expand Up @@ -96,5 +98,5 @@ def contains(
),
key=lambda r: (r["Match Count"], r["App"]),
),
format,
display_format,
)
56 changes: 29 additions & 27 deletions heroku_audit/cli/postgres.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import typer
from heroku_audit.client import heroku
from typing import Optional, Annotated, TypedDict
from rich.progress import track
from concurrent.futures import ThreadPoolExecutor
from heroku_audit.format import display_data, FormatOption, Format
from typing import Annotated, Optional, TypedDict

import typer
from heroku3.models.addon import Addon
from heroku_audit.utils import get_apps_for_teams, SHOW_PROGRESS, get_addon_plan
from heroku_audit.options import TeamOption
from rich.progress import track
from rich.text import Text

from heroku_audit.client import heroku
from heroku_audit.format import Format, FormatOption, display_data
from heroku_audit.options import TeamOption
from heroku_audit.utils import SHOW_PROGRESS, get_addon_plan, get_apps_for_teams

app = typer.Typer(name="postgres", help="Report on Heroku Postgres databases.")

HEROKU_POSTGRES = "heroku-postgresql:"
Expand Down Expand Up @@ -36,7 +38,7 @@ def get_heroku_postgres_details(addon: Addon) -> HerokuPostgresDetails:
return {"postgres_version": data["info"]["PG Version"][0]}


def get_heroku_postgres_backup_schedules(addon: Addon) -> HerokuPostgresDetails:
def get_heroku_postgres_backup_schedules(addon: Addon) -> list[str]:
host = get_postgres_api_hostname(addon)
response = heroku._session.get(
f"https://{host}/client/v11/databases/{addon.id}/transfer-schedules"
Expand All @@ -47,7 +49,7 @@ def get_heroku_postgres_backup_schedules(addon: Addon) -> HerokuPostgresDetails:
return [f"Daily at {s['hour']}:00 {s['timezone']}" for s in data]


def get_version_column(addon: Addon):
def get_version_column(addon: Addon) -> dict:
return {
"App": addon.app.name,
"Addon": addon.name,
Expand All @@ -56,7 +58,7 @@ def get_version_column(addon: Addon):
}


def get_backup_column(addon: Addon):
def get_backup_column(addon: Addon) -> dict:
backup_schedules = get_heroku_postgres_backup_schedules(addon)

return {
Expand All @@ -76,15 +78,15 @@ def major_version(
typer.Option(help="Version to look for"),
] = None,
team: TeamOption = None,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Audit the available postgres database versions
"""
with ThreadPoolExecutor() as executor:
apps = heroku.apps() if team is None else get_apps_for_teams(team)

collected_addons = []
collected_addons: list[Addon] = []
for addons in track(
executor.map(lambda a: a.addons(), apps),
description="Loading addons...",
Expand All @@ -106,7 +108,7 @@ def major_version(
continue
results.append(result)

display_data(sorted(results, key=lambda r: r["Version"]), format)
display_data(sorted(results, key=lambda r: r["Version"]), display_format)


@app.command()
Expand All @@ -116,18 +118,18 @@ def plan(
typer.Argument(help="Plan to look for"),
] = None,
team: TeamOption = None,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Find Heroku Postgres instances with a given plan
"""
# HACK: https://github.com/martyzz1/heroku3.py/pull/132
Addon._strs.append("config_vars")
Addon._strs.append("config_vars") # type:ignore

with ThreadPoolExecutor() as executor:
apps = heroku.apps() if team is None else get_apps_for_teams(team)

collected_addons = []
collected_addons: list[Addon] = []
for addons in track(
executor.map(lambda a: a.addons(), apps),
description="Loading addons...",
Expand Down Expand Up @@ -156,7 +158,7 @@ def plan(
),
key=lambda r: r["App"],
),
format,
display_format,
)


Expand All @@ -170,13 +172,13 @@ def count(
),
] = 1,
team: TeamOption = None,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Find apps with a given number of databases
"""
# HACK: https://github.com/martyzz1/heroku3.py/pull/132
Addon._strs.append("config_vars")
Addon._strs.append("config_vars") # type:ignore

with ThreadPoolExecutor() as executor:
apps = heroku.apps() if team is None else get_apps_for_teams(team)
Expand Down Expand Up @@ -207,7 +209,7 @@ def count(
key=lambda r: r["Databases"],
reverse=True,
),
format,
display_format,
)


Expand All @@ -218,16 +220,16 @@ def backup_schedule(
Optional[bool],
typer.Option(help="Only show databases without backup schedules"),
] = False,
format: FormatOption = Format.TABLE,
):
display_format: FormatOption = Format.TABLE,
) -> None:
"""
Find backup schedules for databases
"""

with ThreadPoolExecutor() as executor:
apps = heroku.apps() if team is None else get_apps_for_teams(team)

collected_addons = []
collected_addons: list[Addon] = []
for addons in track(
executor.map(lambda a: a.addons(), apps),
description="Loading addons...",
Expand All @@ -249,4 +251,4 @@ def backup_schedule(
continue
results.append(result)

display_data(sorted(results, key=lambda r: r["App"]), format)
display_data(sorted(results, key=lambda r: r["App"]), display_format)
Loading

0 comments on commit 1e18731

Please sign in to comment.