From 2e7494d907383bcaf86c5253f201acf74ee20b4f Mon Sep 17 00:00:00 2001 From: Joe Kaufeld Date: Thu, 27 Feb 2025 13:54:22 -0500 Subject: [PATCH] :sparkles: add env file support --- src/__init__.py.jinja | 49 ++++++++++++++++++++++ src/utils.py.jinja | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 src/__init__.py.jinja create mode 100644 src/utils.py.jinja diff --git a/src/__init__.py.jinja b/src/__init__.py.jinja new file mode 100644 index 0000000..45d629f --- /dev/null +++ b/src/__init__.py.jinja @@ -0,0 +1,49 @@ +from pathlib import Path +try: + from shiv.bootstrap import current_zipfile + IN_SHIV = True +except ImportError: + IN_SHIV = False + +ENABLE_ENV_FILE = False + +__version__ = "?????" # will be replaced during build by CI + +GITEA_TOKEN = "??GITEA_TOKEN??" # will be replaced during build by CI + +SERVICE_FILE = r"""[Unit] +Description=[[ description ]] +After=network.target + +[Service] +User=root +Group=www-data +WorkingDirectory={working_directory} +ExecStart={python_command} {filepath} + +[Install] +WantedBy=multi-user.target""" + +ENV_FILE_BASE = r"""# Fill me out! +EXAMPLE_KEY=example_value +""" + +if not IN_SHIV: + # shiv is not installed + BASE_DIR = Path(__file__).parent.parent +else: + with current_zipfile() as archive: + if archive: + # shiv is installed and we are inside a zipapp + BASE_DIR = Path(archive.filename).resolve(strict=True).parent + else: + # shiv is installed and we are NOT in a zipapp + BASE_DIR = Path(__file__).resolve(strict=True).parent.parent + +if ENABLE_ENV_FILE: + if not Path(BASE_DIR / ".env").exists(): + with open(BASE_DIR / ".env", "w") as f: + f.write(ENV_FILE_BASE) + + import dotenv + dotenv.load_dotenv(BASE_DIR / ".env") \ No newline at end of file diff --git a/src/utils.py.jinja b/src/utils.py.jinja new file mode 100644 index 0000000..1bf254b --- /dev/null +++ b/src/utils.py.jinja @@ -0,0 +1,95 @@ +import sys +import os +import shlex +import subprocess +from pathlib import Path + +import click +import httpx +from rich.status import Status +from shiv.bootstrap import current_zipfile + +import src + +def _install(): + if sys.platform != "linux": + click.echo("Sorry, this command only works on Ubuntu Linux systems.") + sys.exit(1) + if os.geteuid() != 0: + click.echo("WARNING: Not running as root... install may fail.") + click.echo("Installing service...") + python_path = click.prompt("What is the path for the Python executable?", type=str) + with current_zipfile() as archive: + filepath = Path(archive.filename).resolve(strict=True) + working_directory = filepath.parent + + with open("/etc/systemd/system/[[ module_name ]].service", "w") as f: + f.write( + src.SERVICE_FILE.format( + working_directory=working_directory, + python_command=python_path, + filepath=filepath + ) + ) + subprocess.check_call( + shlex.split("sudo systemctl enable [[ module_name ]].service") + ) + subprocess.check_call( + shlex.split("sudo systemctl start [[ module_name ]].service") + ) + click.echo("All done! Run `sudo systemctl status [[ module_name ]]` to see if it worked!") + + +def _uninstall(): + if sys.platform != "linux": + click.echo("Sorry, this command only works on Ubuntu Linux systems.") + sys.exit(1) + if os.geteuid() != 0: + click.echo("WARNING: Not running as root... uninstall may fail.") + subprocess.check_call( + shlex.split("sudo systemctl stop [[ module_name ]].service") + ) + subprocess.check_call( + shlex.split("sudo systemctl disable [[ module_name ]].service") + ) + os.unlink("/etc/systemd/system/[[ module_name ]].service") + subprocess.check_call(shlex.split("systemctl daemon-reload")) + click.echo("All done!") + + +def update_from_gitea(): + """Get the newest release from Gitea and install it.""" + status = Status("Checking for new release...") + status.start() + + response = httpx.get( + "https://git.joekaufeld.com/api/v1/repos/jkaufeld/[[ repo_name ]]/releases/latest" + ) + if response.status_code != 200: + status.stop() + click.echo( + f"Something went wrong when talking to Gitea; got a" + f" {response.status_code} with the following content:\n" + f"{response.content}" + ) + return + status.update("Checking for new release...") + release_data = response.json() + if release_data["tag_name"] == src.__version__: + status.stop() + click.echo( + "Server version is the same as current version; nothing to update." + ) + return + status.update("Updating...") + + url = release_data["assets"][0]["browser_download_url"] + with current_zipfile() as archive: + with open(archive.filename, "wb") as f, httpx.stream( + "GET", url, follow_redirects=True + ) as r: + for line in r.iter_bytes(): + f.write(line) + + status.stop() + click.echo(f"Updated to {release_data['tag_name']}! 🎉") \ No newline at end of file