mirror of https://gitlab.com/tildes/tildes.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.3 KiB
145 lines
4.3 KiB
# Copyright (c) 2020 Tildes contributors <code@tildes.net>
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
"""Contains tasks that can be run through the invoke tool."""
|
|
|
|
from pathlib import Path
|
|
|
|
from invoke import task
|
|
from invoke.exceptions import Exit
|
|
|
|
|
|
def output(string):
|
|
"""Output a string without a line ending and flush immediately."""
|
|
print(string, end="", flush=True)
|
|
|
|
|
|
@task
|
|
def web_server_reload(context):
|
|
"""Reload the web server, in order to apply config updates."""
|
|
context.run("sudo systemctl reload nginx.service")
|
|
|
|
|
|
@task(help={"full": "Include all checks (very slow)"})
|
|
def code_style_check(context, full=False):
|
|
"""Run the various utilities to check code style.
|
|
|
|
By default, runs checks that return relatively quickly. To run the full set of
|
|
checks (which will be quite slow), add the --full flag.
|
|
"""
|
|
output("Checking if Black would reformat any Python code... ")
|
|
context.run("black --check .")
|
|
|
|
print("Checking SCSS style...", flush=True)
|
|
context.run("npm run --silent lint:scss")
|
|
|
|
print("Checking JS style...", flush=True)
|
|
context.run("npm run --silent lint:js")
|
|
|
|
if full:
|
|
output("Checking Python style fully (takes a couple minutes)... ")
|
|
|
|
# -M flag hides the "summary information"
|
|
context.run("prospector -M")
|
|
|
|
|
|
@task
|
|
def pip_requirements_update(context):
|
|
"""Use pip-tools to update package versions in the requirements files."""
|
|
|
|
for filename in ("requirements.in", "requirements-dev.in"):
|
|
print(f"Updating package versions from {filename}")
|
|
context.run(
|
|
f"pip-compile --no-header --no-annotate --quiet --upgrade {filename}"
|
|
)
|
|
|
|
|
|
@task
|
|
def shell(context):
|
|
"""Start an IPython shell inside the app environment.
|
|
|
|
Will use the settings in production.ini if that file exists, otherwise will fall
|
|
back to using development.ini.
|
|
"""
|
|
if Path("production.ini").exists():
|
|
context.run("pshell production.ini", pty=True)
|
|
else:
|
|
context.run("pshell development.ini", pty=True)
|
|
|
|
|
|
@task(
|
|
help={
|
|
"full": "Include all tests",
|
|
"html-validation": "Include HTML validation (very slow, includes webtests)",
|
|
"quiet": "Reduce verbosity",
|
|
"webtests": "Include webtests (a little slow)",
|
|
}
|
|
)
|
|
def test(context, full=False, quiet=False, webtests=False, html_validation=False):
|
|
"""Run the tests.
|
|
|
|
By default, webtests (ones that make actual HTTP requests to the app) and HTML
|
|
validation tests (checking the validity of the HTML on some of the site's pages) are
|
|
not run because they are slow, but you can include them with the appropriate flag.
|
|
"""
|
|
# webtests are required as part of HTML validation
|
|
if html_validation:
|
|
webtests = True
|
|
|
|
pytest_args = []
|
|
excluded_markers = []
|
|
|
|
if not full:
|
|
if not webtests:
|
|
excluded_markers.append("webtest")
|
|
if not html_validation:
|
|
excluded_markers.append("html_validation")
|
|
|
|
if excluded_markers:
|
|
excluded_marker_str = " or ".join(excluded_markers)
|
|
pytest_args.append(f'-m "not ({excluded_marker_str})"')
|
|
|
|
if quiet:
|
|
output("Running tests... ")
|
|
|
|
pytest_args.append("-q")
|
|
result = context.run("pytest " + " ".join(pytest_args), hide=True)
|
|
|
|
# only output the final line of pytest's stdout (test count + runtime)
|
|
print(result.stdout.splitlines()[-1])
|
|
else:
|
|
context.run("pytest " + " ".join(pytest_args), pty=True)
|
|
|
|
|
|
@task(
|
|
help={
|
|
"domain": "Domain to obtain a cert for (can be specified multiple times)",
|
|
},
|
|
iterable=["domain"],
|
|
post=[web_server_reload],
|
|
)
|
|
def tls_certificate_renew(context, domain, wildcard=True):
|
|
"""Renew the TLS certificate for the specified domain(s)."""
|
|
if not domain:
|
|
raise Exit("No domains specified")
|
|
|
|
domains = []
|
|
for dom in domain:
|
|
domains.append(dom)
|
|
if wildcard:
|
|
domains.append(f"*.{dom}")
|
|
|
|
domain_args = " ".join([f"-d {dom}" for dom in domains])
|
|
|
|
context.run(
|
|
f"sudo certbot certonly --manual {domain_args} "
|
|
"--preferred-challenges dns-01 "
|
|
"--server https://acme-v02.api.letsencrypt.org/directory"
|
|
)
|
|
|
|
|
|
@task
|
|
def type_check(context):
|
|
"""Run static type checking on the Python code."""
|
|
output("Running static type checking... ")
|
|
context.run("mypy .")
|