From 339e119cc5a153b6924e68137e37f58c19b509df Mon Sep 17 00:00:00 2001 From: Julian B Date: Fri, 23 Feb 2024 17:11:15 +0100 Subject: [PATCH 1/3] use django management commands for tools --- README.md | 6 +- .../management/commands}/create_test_data.py | 44 ++++------ .../management/commands}/install_bootstrap.py | 85 ++++++++----------- 3 files changed, 58 insertions(+), 77 deletions(-) rename {tools => myhpi/core/management/commands}/create_test_data.py (92%) rename {tools => myhpi/core/management/commands}/install_bootstrap.py (68%) diff --git a/README.md b/README.md index 8639ec9d..9cb02e56 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,13 @@ To set up a development version on your local machine, you need to execute the f 1. Set up a virtualenv for the project with Python >=3.11 and activate it (e.g., `python3 -m venv venv` and `source venv/bin/activate`) 1. Install poetry (if not already installed): `curl -sSL https://install.python-poetry.org/ | python -` 1. Install dependencies with `poetry install` -1. Install bootstrap with `python tools/install_bootstrap.py` 1. Create env file by copying the `.env.example` file to `.env`, e.g. `cp .env.example .env` (Notice that for some functionality like OIDC some settings must be changed) 1. Migrate the database with `python manage.py migrate` -1. Compile translations with `python manage.py compilemessages` (does not work on Windows, recommended to skip this step or see [docs](https://docs.djangoproject.com/en/4.0/topics/i18n/translation/#gettext-on-windows)) +1. Install bootstrap with `python manage.py install_bootstrap` +1. Optionally: Compile translations with `python manage.py compilemessages` (does not work on Windows, recommended to skip this step or see [docs](https://docs.djangoproject.com/en/4.0/topics/i18n/translation/#gettext-on-windows)) +1. Optionally: Create test data with `python manage.py create_test_data` 1. Create a local superuser with `python manage.py createsuperuser` 1. Start the development server with `python manage.py runserver` -1. Optionally: Create test data with `python tools/create_test_data.py` 1. Open your web browser, visit `http://localhost:8000/admin` and log in with the user you just created ### Tests diff --git a/tools/create_test_data.py b/myhpi/core/management/commands/create_test_data.py similarity index 92% rename from tools/create_test_data.py rename to myhpi/core/management/commands/create_test_data.py index 4e5286fc..e9bef6bf 100644 --- a/tools/create_test_data.py +++ b/myhpi/core/management/commands/create_test_data.py @@ -1,24 +1,11 @@ -import os -from datetime import date - -import django - -from myhpi.polls.models import PollList, RankedChoiceOption, RankedChoicePoll - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myhpi.settings") -django.setup() import random +from datetime import date -from django.contrib.auth.models import Group, Permission, User -from django.core.files import File -from django.db import IntegrityError -from wagtail.contrib.redirects.models import Redirect -from wagtail.documents.models import Document -from wagtail.models import Collection, GroupCollectionPermission +from django.contrib.auth.models import Group, User +from django.core.management import BaseCommand from myhpi.core.models import ( AbbreviationExplanation, - BasePage, FirstLevelMenuItem, InformationPage, Minutes, @@ -27,6 +14,7 @@ RootPage, SecondLevelMenuItem, ) +from myhpi.polls.models import PollList, RankedChoiceOption, RankedChoicePoll from myhpi.tests.core.setup import create_collections, create_documents @@ -354,14 +342,18 @@ def create_some_pages(users, groups, documents): slash_1999_poll.options.add(option_charlie) -def main(): - # Superuser is created manually via createsuperuser command - users, groups = create_users_and_groups() - collections = list(create_collections(groups)) - documents = create_documents([collections[1], collections[2]]) - create_abbreviation_explanations() - create_some_pages(users, groups, documents) - +class Command(BaseCommand): + help = "Creates test data (user, pages, etc.) for myHPI." -if __name__ == "__main__": - main() + def handle(self, *args, **options): + # Superuser is created manually via createsuperuser command + users, groups = create_users_and_groups() + collections = list(create_collections(groups)) + documents = create_documents([collections[1], collections[2]]) + create_abbreviation_explanations() + create_some_pages(users, groups, documents) + self.stdout.write( + self.style.SUCCESS( + 'Test data created succesfully. Remember that you need to create a superuser manually with "python manage.py createsuperuser".' + ) + ) diff --git a/tools/install_bootstrap.py b/myhpi/core/management/commands/install_bootstrap.py similarity index 68% rename from tools/install_bootstrap.py rename to myhpi/core/management/commands/install_bootstrap.py index b4b62100..fa662ed0 100644 --- a/tools/install_bootstrap.py +++ b/myhpi/core/management/commands/install_bootstrap.py @@ -5,6 +5,7 @@ import zipfile import requests +from django.core.management import BaseCommand TEMP_DIRECTORY = "tmp" ZIP_FILENAME = "bootstrap.zip" @@ -13,8 +14,6 @@ def ensure_correct_directory(): - if os.getcwd().endswith("tools"): - os.chdir("..") try: with open("pyproject.toml") as toml_file: return "myHPI" in toml_file.readlines()[1] @@ -95,50 +94,40 @@ def is_bootstrap_installed(): ) -def init_argparse() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser( - usage="%(prog)s [-u]", description="Install bootstrap for myHPI." - ) - parser.add_argument( - "-u", - "--update", - action="store_true", - help="Update (Remove and reinstall) current bootstrap installation.", - ) - parser.add_argument( - "-r", "--remove", action="store_true", help="Remove current bootstrap installation." - ) - parser.add_argument( - "--is-installed", action="store_true", help="Check if bootstrap is installed." - ) - return parser - - -def install_bootstrap(): - logger.setLevel(level=logging.INFO) - logger.addHandler(logging.StreamHandler()) - parser = init_argparse() - args = parser.parse_args() - correct_dir = ensure_correct_directory() - if not correct_dir: - logger.error( - "The program was not executed in the correct directory!\n\ - Ensure that it is run in the top directory of the repository." +class Command(BaseCommand): + help = "Install bootstrap for myHPI." + + def add_arguments(self, parser): + parser.add_argument( + "-u", + "--update", + action="store_true", + help="Update (Remove and reinstall) current bootstrap installation.", ) - exit(1) - if args.is_installed: - is_installed = is_bootstrap_installed() - exit(0 if is_installed else 1) - if args.update or args.remove: - remove_current_bootstrap() - if args.remove: - exit(0) - file_path = download_zip() - extract_zip(file_path) - move_files() - remove_temporary_directory() - print("Installed bootstrap") - - -if __name__ == "__main__": - install_bootstrap() + parser.add_argument( + "-r", "--remove", action="store_true", help="Remove current bootstrap installation." + ) + parser.add_argument( + "--is-installed", action="store_true", help="Check if bootstrap is installed." + ) + + def handle(self, *args, **options): + correct_dir = ensure_correct_directory() + if not correct_dir: + logger.error( + "The program was not executed in the correct directory!\n\ + Ensure that it is run in the top directory of the repository." + ) + exit(1) + if options["is_installed"]: + is_installed = is_bootstrap_installed() + exit(0 if is_installed else 1) + if options["update"] or options["remove"]: + remove_current_bootstrap() + if options["remove"]: + exit(0) + file_path = download_zip() + extract_zip(file_path) + move_files() + remove_temporary_directory() + self.stdout.write(self.style.SUCCESS("Installed bootstrap")) From 02dbb8805222cc8d1a63320cf51beba355d493ee Mon Sep 17 00:00:00 2001 From: Julian B Date: Fri, 23 Feb 2024 17:20:27 +0100 Subject: [PATCH 2/3] fix workflow --- .github/workflows/tests.yml | 9 ++------- Dockerfile | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5ec1fa0b..f5aff448 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -73,22 +73,17 @@ jobs: python -m venv env source env/bin/activate curl -sSL https://install.python-poetry.org | python3 - --version 1.3.2 - - name: Install dependencies + - name: Install dependencies and prepare files # always install all -E extras to use a single cache run: | sudo apt-get install gettext source env/bin/activate poetry run python -m pip install setuptools -U poetry install -E mysql -E pgsql - python tools/install_bootstrap.py - - name: Prepare files for test run - continue-on-error: true - run: | cp .env.example .env - source env/bin/activate + poetry run python manage.py install_bootstrap poetry run python manage.py compilemessages --settings myhpi.settings poetry run python manage.py collectstatic --settings myhpi.settings - - name: Setup postgres uses: harmon758/postgresql-action@v1 with: diff --git a/Dockerfile b/Dockerfile index 3b2129d5..e8520b64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,6 @@ RUN pip install "poetry==$POETRY_VERSION" "uwsgi==$UWSGI_PIP_VERSION" "psycopg2= RUN poetry self add "poetry-dynamic-versioning[plugin]" ADD . /app RUN poetry install --no-dev -RUN python tools/install_bootstrap.py -u +RUN python tools/install_bootstrap.py -u # FIXME RUN chmod +x /app/entrypoint.sh ENTRYPOINT ["/app/entrypoint.sh"] From b21aa47c68ee54c43dda0678e42f8fd43fbba9bd Mon Sep 17 00:00:00 2001 From: Julian B Date: Fri, 23 Feb 2024 17:40:43 +0100 Subject: [PATCH 3/3] revert bootstrap installation to standalone tool --- .github/workflows/tests.yml | 9 +- Dockerfile | 2 +- README.md | 2 +- .../commands => tools}/install_bootstrap.py | 85 +++++++++++-------- 4 files changed, 57 insertions(+), 41 deletions(-) rename {myhpi/core/management/commands => tools}/install_bootstrap.py (68%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f5aff448..5ec1fa0b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -73,17 +73,22 @@ jobs: python -m venv env source env/bin/activate curl -sSL https://install.python-poetry.org | python3 - --version 1.3.2 - - name: Install dependencies and prepare files + - name: Install dependencies # always install all -E extras to use a single cache run: | sudo apt-get install gettext source env/bin/activate poetry run python -m pip install setuptools -U poetry install -E mysql -E pgsql + python tools/install_bootstrap.py + - name: Prepare files for test run + continue-on-error: true + run: | cp .env.example .env - poetry run python manage.py install_bootstrap + source env/bin/activate poetry run python manage.py compilemessages --settings myhpi.settings poetry run python manage.py collectstatic --settings myhpi.settings + - name: Setup postgres uses: harmon758/postgresql-action@v1 with: diff --git a/Dockerfile b/Dockerfile index e8520b64..3b2129d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,6 @@ RUN pip install "poetry==$POETRY_VERSION" "uwsgi==$UWSGI_PIP_VERSION" "psycopg2= RUN poetry self add "poetry-dynamic-versioning[plugin]" ADD . /app RUN poetry install --no-dev -RUN python tools/install_bootstrap.py -u # FIXME +RUN python tools/install_bootstrap.py -u RUN chmod +x /app/entrypoint.sh ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/README.md b/README.md index 9cb02e56..a23922bd 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ To set up a development version on your local machine, you need to execute the f 1. Install dependencies with `poetry install` 1. Create env file by copying the `.env.example` file to `.env`, e.g. `cp .env.example .env` (Notice that for some functionality like OIDC some settings must be changed) 1. Migrate the database with `python manage.py migrate` -1. Install bootstrap with `python manage.py install_bootstrap` +1. Install bootstrap with `python tools/install_bootstrap.py` 1. Optionally: Compile translations with `python manage.py compilemessages` (does not work on Windows, recommended to skip this step or see [docs](https://docs.djangoproject.com/en/4.0/topics/i18n/translation/#gettext-on-windows)) 1. Optionally: Create test data with `python manage.py create_test_data` 1. Create a local superuser with `python manage.py createsuperuser` diff --git a/myhpi/core/management/commands/install_bootstrap.py b/tools/install_bootstrap.py similarity index 68% rename from myhpi/core/management/commands/install_bootstrap.py rename to tools/install_bootstrap.py index fa662ed0..b4b62100 100644 --- a/myhpi/core/management/commands/install_bootstrap.py +++ b/tools/install_bootstrap.py @@ -5,7 +5,6 @@ import zipfile import requests -from django.core.management import BaseCommand TEMP_DIRECTORY = "tmp" ZIP_FILENAME = "bootstrap.zip" @@ -14,6 +13,8 @@ def ensure_correct_directory(): + if os.getcwd().endswith("tools"): + os.chdir("..") try: with open("pyproject.toml") as toml_file: return "myHPI" in toml_file.readlines()[1] @@ -94,40 +95,50 @@ def is_bootstrap_installed(): ) -class Command(BaseCommand): - help = "Install bootstrap for myHPI." - - def add_arguments(self, parser): - parser.add_argument( - "-u", - "--update", - action="store_true", - help="Update (Remove and reinstall) current bootstrap installation.", - ) - parser.add_argument( - "-r", "--remove", action="store_true", help="Remove current bootstrap installation." - ) - parser.add_argument( - "--is-installed", action="store_true", help="Check if bootstrap is installed." +def init_argparse() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + usage="%(prog)s [-u]", description="Install bootstrap for myHPI." + ) + parser.add_argument( + "-u", + "--update", + action="store_true", + help="Update (Remove and reinstall) current bootstrap installation.", + ) + parser.add_argument( + "-r", "--remove", action="store_true", help="Remove current bootstrap installation." + ) + parser.add_argument( + "--is-installed", action="store_true", help="Check if bootstrap is installed." + ) + return parser + + +def install_bootstrap(): + logger.setLevel(level=logging.INFO) + logger.addHandler(logging.StreamHandler()) + parser = init_argparse() + args = parser.parse_args() + correct_dir = ensure_correct_directory() + if not correct_dir: + logger.error( + "The program was not executed in the correct directory!\n\ + Ensure that it is run in the top directory of the repository." ) - - def handle(self, *args, **options): - correct_dir = ensure_correct_directory() - if not correct_dir: - logger.error( - "The program was not executed in the correct directory!\n\ - Ensure that it is run in the top directory of the repository." - ) - exit(1) - if options["is_installed"]: - is_installed = is_bootstrap_installed() - exit(0 if is_installed else 1) - if options["update"] or options["remove"]: - remove_current_bootstrap() - if options["remove"]: - exit(0) - file_path = download_zip() - extract_zip(file_path) - move_files() - remove_temporary_directory() - self.stdout.write(self.style.SUCCESS("Installed bootstrap")) + exit(1) + if args.is_installed: + is_installed = is_bootstrap_installed() + exit(0 if is_installed else 1) + if args.update or args.remove: + remove_current_bootstrap() + if args.remove: + exit(0) + file_path = download_zip() + extract_zip(file_path) + move_files() + remove_temporary_directory() + print("Installed bootstrap") + + +if __name__ == "__main__": + install_bootstrap()