microblog.pub/tasks.py

194 lines
4.4 KiB
Python

import asyncio
import io
import subprocess
import tarfile
from contextlib import contextmanager
from pathlib import Path
from typing import Generator
from typing import Optional
import httpx
from invoke import Context # type: ignore
from invoke import run # type: ignore
from invoke import task # type: ignore
@task
def generate_db_migration(ctx, message):
# type: (Context, str) -> None
run(f'alembic revision --autogenerate -m "{message}"', echo=True)
@task
def migrate_db(ctx):
# type: (Context) -> None
run("alembic upgrade head", echo=True)
@task
def autoformat(ctx):
# type: (Context) -> None
run("black .", echo=True)
run("isort -sl .", echo=True)
@task
def lint(ctx):
# type: (Context) -> None
run("black --check .", echo=True)
run("isort -sl --check-only .", echo=True)
run("flake8 .", echo=True)
run("mypy .", echo=True)
@task
def compile_scss(ctx, watch=False):
# type: (Context, bool) -> None
from app.utils.favicon import build_favicon
build_favicon()
theme_file = Path("data/_theme.scss")
if not theme_file.exists():
theme_file.write_text("// override vars for theming here")
if watch:
run("boussole watch", echo=True)
else:
run("boussole compile", echo=True)
@task
def uvicorn(ctx):
# type: (Context) -> None
run("uvicorn app.main:app --no-server-header", pty=True, echo=True)
@task
def process_outgoing_activities(ctx):
# type: (Context) -> None
from app.outgoing_activities import loop
asyncio.run(loop())
@task
def process_incoming_activities(ctx):
# type: (Context) -> None
from app.incoming_activities import loop
asyncio.run(loop())
@task
def tests(ctx, k=None):
# type: (Context, Optional[str]) -> None
pytest_args = " -vvv"
if k:
pytest_args += f" -k {k}"
run(
f"MICROBLOGPUB_CONFIG_FILE=tests.toml pytest tests{pytest_args}",
pty=True,
echo=True,
)
@task
def generate_requirements_txt(ctx, where="requirements.txt"):
# type: (Context, str) -> None
run(
f"poetry export -f requirements.txt --without-hashes > {where}",
pty=True,
echo=True,
)
@task
def build_docs(ctx):
# type: (Context) -> None
with embed_version():
run("PYTHONPATH=. python scripts/build_docs.py", pty=True, echo=True)
@task
def download_twemoji(ctx):
# type: (Context) -> None
resp = httpx.get(
"https://github.com/twitter/twemoji/archive/refs/tags/v14.0.2.tar.gz",
follow_redirects=True,
)
resp.raise_for_status()
tf = tarfile.open(fileobj=io.BytesIO(resp.content))
members = [
member
for member in tf.getmembers()
if member.name.startswith("twemoji-14.0.2/assets/svg/")
]
for member in members:
emoji_name = Path(member.name).name
with open(f"app/static/twemoji/{emoji_name}", "wb") as f:
f.write(tf.extractfile(member).read()) # type: ignore
@task(download_twemoji, compile_scss)
def configuration_wizard(ctx):
# type: (Context) -> None
run("MICROBLOGPUB_CONFIG_FILE=tests.toml alembic upgrade head", echo=True)
run(
"MICROBLOGPUB_CONFIG_FILE=tests.toml PYTHONPATH=. python scripts/config_wizard.py", # noqa: E501
pty=True,
echo=True,
)
@task
def install_deps(ctx):
# type: (Context) -> None
run("poetry install", pty=True, echo=True)
@task(pre=[compile_scss], post=[migrate_db])
def update(ctx, update_deps=True):
# type: (Context, bool) -> None
if update_deps:
run("poetry install", pty=True, echo=True)
print("Done")
@task
def stats(ctx):
# type: (Context) -> None
from app.utils.stats import print_stats
print_stats()
@contextmanager
def embed_version() -> Generator[None, None, None]:
version_file = Path("app/_version.py")
version_file.unlink(missing_ok=True)
version = (
subprocess.check_output(["git", "rev-parse", "--short=8", "v2"])
.split()[0]
.decode()
)
version_file.write_text(f'VERSION_COMMIT = "{version}"')
try:
yield
finally:
version_file.unlink()
@task
def build_docker_image(ctx):
# type: (Context) -> None
with embed_version():
run("docker build -t microblogpub/microblogpub .")
@task
def prune_old_data(ctx):
# type: (Context) -> None
from app.prune import run_prune_old_data
asyncio.run(run_prune_old_data())