diff --git a/.gitignore b/.gitignore index 86b4cf9..6f40a53 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ db.sqlite3 .env venv/ .venv/ + + +# collectstatic +src/static/ diff --git a/Dockerfile b/Dockerfile index fe342b7..2e9448d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,9 +15,7 @@ WORKDIR /app RUN groupadd -g 1000 www && useradd -u 1000 -ms /bin/bash -g www www COPY --chown=www:www . . -RUN mkdir /app/src/static && \ - chown www:www /app/src/static && \ - apt-get update && \ +RUN apt-get update && \ apt-get install -y \ binutils \ libpq-dev \ @@ -29,9 +27,15 @@ RUN mkdir /app/src/static && \ libgdk-pixbuf2.0-0 \ libffi-dev \ shared-mime-info \ - gettext && \ - pip install --no-cache-dir -r $REQUIREMENTS_FILE && \ - django-admin compilemessages + gettext + +COPY --chown=www:www . . + +RUN mkdir /app/src/static && \ + chown www:www /app/src/static + +RUN pip install --no-cache-dir -r $REQUIREMENTS_FILE +RUN django-admin compilemessages ENTRYPOINT ["./entrypoint.sh"] diff --git a/Makefile b/Makefile index a577606..651ed32 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,17 @@ DOCKER_COMPOSE = COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose DOCKER_RUN = ${DOCKER_COMPOSE} run -u `id -u` -DOCKER_BUILD = DOCKER_BUILDKIT=1 docker build MANAGE_EXEC = python /app/src/manage.py MANAGE_COMMAND = ${DOCKER_RUN} app ${MANAGE_EXEC} run: ${DOCKER_COMPOSE} up +pre_commit_install: + venv/bin/pre-commit install + +pre_commit_run_all: + venv/bin/pre-commit run --all-files + makemigrations: ${MANAGE_COMMAND} makemigrations ${ARGS} @@ -21,3 +26,6 @@ shell: manage_command: ${MANAGE_COMMAND} ${ARGS} + +build: + ${DOCKER_COMPOSE} build diff --git a/README.md b/README.md index 2c8d5d3..41ef329 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ There are two ways to setup the development environment. - Using the Docker Compose setup provided in this repository. - Using [hatch](https://hatch.pypa.io/) in your host OS. - ### Using Docker Compose Working with the Docker Compose setup is made easy with the `Makefile` provided in the repository. @@ -21,24 +20,37 @@ Working with the Docker Compose setup is made easy with the `Makefile` provided 1. Setup .env file -An example .env file is provided in the repository. You can copy it to .env file using the following command: + An example .env file is provided in the repository. You can copy it to .env file using the following command: -```bash -cp .env.example .env -``` + ```bash + cp .env.example .env + ``` -The default values in the .env file are suitable for the docker-compose setup. + The default values in the .env file are suitable for the docker-compose setup. 2. Migrate -```bash -make migrate -``` + ```bash + make migrate + ``` 3. Run the development server + ```bash + make run + ``` + +#### Building and running other things + ```bash -make run +# Build the containers +make build + +# Create a superuser +make createsuperuser + +# Create Django migrations (after this, maybe you need to change file permissions in volume) +make makemigrations ``` ### Using hatch @@ -53,22 +65,22 @@ make run 1. Setup .env file -An example .env file is provided in the repository. You can copy it to .env file using the following command: + An example .env file is provided in the repository. You can copy it to .env file using the following command: -```bash -cp .env.example .env -``` + ```bash + cp .env.example .env + ``` -Edit the .env file and set the values for the environment variables, especially the database variables. + Edit the .env file and set the values for the environment variables, especially the database variables. 2. Run migrate -```bash -hatch run dev:migrate -``` + ```bash + hatch run dev:migrate + ``` 3. Run the development server -```bash -hatch run dev:server -``` + ```bash + hatch run dev:server + ``` diff --git a/docker-compose.yml b/docker-compose.yml index 9bd0957..c957cd0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ ---- services: app: build: @@ -12,7 +11,8 @@ services: volumes: - ./:/app/ depends_on: - - postgres + postgres: + condition: service_healthy env_file: - .env @@ -24,6 +24,13 @@ services: - 5432:5432 env_file: - .env + # This healthcheck has a large number of retries, this is currently based on the number of + # retries necessary to get the database running in GitHub Actions. + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U postgres -d postgres" ] + interval: 5s + timeout: 5s + retries: 30 volumes: postgres_data: diff --git a/entrypoint.sh b/entrypoint.sh index 9df57b6..008f7be 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,16 +1,5 @@ #!/bin/sh -echo "Waiting for postgres..." - -POSTGRES_PORT=${POSTGRES_PORT:-5432} -POSTGRES_HOST=${POSTGRES_HOST:-localhost} - -while ! nc -z "$POSTGRES_HOST" "$POSTGRES_PORT"; do - sleep 0.1 -done - -echo "PostgreSQL started" - # Only migrate, collectstatic and compilemessages if we are NOT in development if [ -z "$DEBUG" ]; then python src/manage.py migrate; diff --git a/src/membership/admin.py b/src/membership/admin.py index 6fdb423..8224ff6 100644 --- a/src/membership/admin.py +++ b/src/membership/admin.py @@ -36,3 +36,8 @@ class MemberAdmin(UserAdmin): """Member admin is actually an admin for User objects.""" inlines = (MembershipInlineAdmin,) + + +@admin.register(models.WaitingListEntry) +class WaitingListEntryAdmin(admin.ModelAdmin): + """Admin for WaitingList model.""" diff --git a/src/membership/migrations/0006_waitinglistentry_alter_membership_options.py b/src/membership/migrations/0006_waitinglistentry_alter_membership_options.py new file mode 100644 index 0000000..9c2d923 --- /dev/null +++ b/src/membership/migrations/0006_waitinglistentry_alter_membership_options.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.7 on 2024-07-20 20:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('membership', '0005_member'), + ] + + operations = [ + migrations.CreateModel( + name='WaitingListEntry', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), + ('email', models.EmailField(max_length=254)), + ('geography', models.CharField(blank=True, default='', verbose_name='geography')), + ('comment', models.TextField(blank=True)), + ], + options={ + 'verbose_name': 'waiting list entry', + 'verbose_name_plural': 'waiting list entries', + }, + ), + migrations.AlterModelOptions( + name='membership', + options={'verbose_name': 'medlemskab', 'verbose_name_plural': 'medlemskaber'}, + ), + ] diff --git a/src/membership/models.py b/src/membership/models.py index 7e71393..2d5e69d 100644 --- a/src/membership/models.py +++ b/src/membership/models.py @@ -153,3 +153,18 @@ class MembershipType(CreatedModifiedAbstract): user=user, period=get_current_subscription_period(), ) + + +class WaitingListEntry(CreatedModifiedAbstract): + """People who for some reason could want to be added to a waiting list and invited to join later.""" + + email = models.EmailField() + geography = models.CharField(verbose_name=_("geography"), blank=True, default="") + comment = models.TextField(blank=True) + + def __str__(self) -> str: + return self.email + + class Meta: + verbose_name = _("waiting list entry") + verbose_name_plural = _("waiting list entries") diff --git a/src/pytest.ini b/src/pytest.ini deleted file mode 100644 index 9929fa7..0000000 --- a/src/pytest.ini +++ /dev/null @@ -1,5 +0,0 @@ -[pytest] -testpaths = . -python_files = tests.py test_*.py *_tests.py -DJANGO_SETTINGS_MODULE = project.settings -#norecursedirs = dist tmp* .svn .*