From d6eafd053f528464f3c3517b6e44f18290d59b33 Mon Sep 17 00:00:00 2001 From: Joeri Bekker Date: Wed, 17 Jul 2024 15:56:34 +0200 Subject: [PATCH 1/4] :whale: Updated Dockerfile, separated Celery containers - Added os upgrade to be sure the libraries as up to date as possible everytime the image is built. - Replaced vim with nano - Used uv instead of pip (super fast drop in replacement) - Compile translatable messages during build - Added proper release scheme attributes - Separated Celery into worker, beat and monitor containers - Added additional health checks to steer the ordering of container-startup There was 1 container reserved for all Celery related things: worker, beat and monitoring. According to Celery documentation it's best to have a separate Beat process so you can scale separately. Also, combining monitoring with the events itself could cause issues. Everything is separated now. Additional health checks and dependancies are introduced to Docker-compose so Celery nicely waits for the database to be prepped. --- Dockerfile | 51 +++++++++++++++++----------- bin/celery_beat.sh | 17 ++++++++++ bin/celery_monitor.sh | 14 ++++++++ bin/celery_worker.sh | 10 ++++-- bin/docker_start.sh | 18 ++++------ bin/start_celery.sh | 9 ----- bin/wait_for_db.sh | 2 +- docker-compose.yml | 69 +++++++++++++++++++++++++++++++++++--- src/open_inwoner/celery.py | 48 ++++++++++++++++++++++++-- 9 files changed, 189 insertions(+), 49 deletions(-) create mode 100755 bin/celery_beat.sh create mode 100755 bin/celery_monitor.sh delete mode 100755 bin/start_celery.sh mode change 100644 => 100755 bin/wait_for_db.sh diff --git a/Dockerfile b/Dockerfile index cb4f39ff8d..b8e316e53b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ # includes compilers and build tooling to create the environment FROM python:3.11-slim-bookworm AS backend-build -RUN apt-get update && apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \ pkg-config \ build-essential \ git \ @@ -24,21 +24,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -RUN mkdir /app/src -# Ensure we use the latest version of pip -RUN pip install pip>=24 setuptools -U +# Use uv to install dependencies +RUN pip install uv -U COPY ./requirements /app/requirements -RUN pip install -r requirements/production.txt - -# Stage 2 - Install frontend deps and build assets -FROM node:20-buster AS frontend-build +RUN uv pip install --system -r requirements/production.txt RUN apt-get update && apt-get install -y --no-install-recommends \ git \ && rm -rf /var/lib/apt/lists/* +# Stage 2 - Install frontend deps and build assets +FROM node:20-bookworm-slim AS frontend-build + WORKDIR /app # copy configuration/build files @@ -54,19 +53,17 @@ COPY ./src /app/src # build frontend RUN npm run build - # Stage 3 - Build docker image suitable for production - FROM python:3.11-slim-bookworm # Stage 3.1 - Set up the needed production dependencies # Note: mime-support becomes media-types in Debian Bullseye (required for correctly serving mime-types for images) # Also install the dependencies for GeoDjango - RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \ curl \ procps \ - vim \ + nano \ + mime-support \ postgresql-client \ libgdal32 \ libgeos-c1v5 \ @@ -75,8 +72,8 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-reco libxmlsec1-openssl \ libgdk-pixbuf2.0-0 \ libffi-dev \ + gettext \ shared-mime-info \ - mime-support \ # weasyprint deps (https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#debian-11) libpango-1.0-0 \ libpangoft2-1.0-0 \ @@ -86,15 +83,19 @@ WORKDIR /app COPY ./bin/docker_start.sh /start.sh COPY ./bin/wait_for_db.sh /wait_for_db.sh COPY ./bin/celery_worker.sh /celery_worker.sh -COPY ./bin/check_celery_worker_liveness.py ./bin/ +COPY ./bin/celery_beat.sh /celery_beat.sh +COPY ./bin/celery_monitor.sh /celery_monitor.sh COPY ./bin/setup_configuration.sh /setup_configuration.sh -RUN mkdir /app/log -RUN mkdir /app/media +RUN mkdir /app/log /app/media /app/private_media /app/tmp +COPY ./bin/check_celery_worker_liveness.py ./bin/ + +# prevent writing to the container layer, which would degrade performance. +# This also serves as a hint for the intended volumes. +VOLUME ["/app/log", "/app/media", "/app/private_media"] # copy backend build deps COPY --from=backend-build /usr/local/lib/python3.11 /usr/local/lib/python3.11 COPY --from=backend-build /usr/local/bin/uwsgi /usr/local/bin/uwsgi -COPY --from=backend-build /app/src/ /app/src/ COPY --from=backend-build /usr/local/bin/celery /usr/local/bin/celery # copy frontend build statics @@ -109,16 +110,26 @@ RUN chown -R maykin /app # drop privileges USER maykin -ARG COMMIT_HASH +ARG RELEASE COMMIT_HASH ENV GIT_SHA=${COMMIT_HASH} +ENV RELEASE=${RELEASE} + ENV DJANGO_SETTINGS_MODULE=open_inwoner.conf.docker + ENV DIGID_MOCK=True ENV EHERKENNING_MOCK=True ARG SECRET_KEY=dummy -# Run collectstatic, so the result is already included in the image -RUN python src/manage.py collectstatic --noinput +LABEL org.label-schema.vcs-ref=$COMMIT_HASH \ + org.label-schema.vcs-url="https://github.com/maykinmedia/open-inwoner" \ + org.label-schema.version=$RELEASE \ + org.label-schema.name="Open Inwoner" + +# Run collectstatic and compilemessages, so the result is already included in +# the image +RUN python src/manage.py collectstatic --noinput \ + && python src/manage.py compilemessages EXPOSE 8000 CMD ["/start.sh"] diff --git a/bin/celery_beat.sh b/bin/celery_beat.sh new file mode 100755 index 0000000000..96be41047b --- /dev/null +++ b/bin/celery_beat.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +LOGLEVEL=${CELERY_LOGLEVEL:-INFO} + +mkdir -p celerybeat + +# Adding the database scheduler will also convert the CELERY_BEAT_SCHEDULE to +# database entries. + +echo "Starting celery beat" +exec celery --workdir src --app "open_inwoner.celery" beat \ + -l $LOGLEVEL \ + -s ../celerybeat/beat \ + --scheduler django_celery_beat.schedulers:DatabaseScheduler \ + --pidfile= # empty on purpose, see https://github.com/open-formulieren/open-forms/issues/1182 diff --git a/bin/celery_monitor.sh b/bin/celery_monitor.sh new file mode 100755 index 0000000000..71f3b7dcab --- /dev/null +++ b/bin/celery_monitor.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +LOGLEVEL=${CELERY_LOGLEVEL:-INFO} + +# This monitors the tasks executed by Celery. The Celery worker needs to be +# started with the -E option to sent out the events. + +echo "Starting celery events" +exec celery --workdir src --app "open_inwoner.celery" events \ + -l $LOGLEVEL \ + --camera django_celery_monitor.camera.Camera \ + --frequency=2.0 diff --git a/bin/celery_worker.sh b/bin/celery_worker.sh index 570057f555..ef6590225a 100755 --- a/bin/celery_worker.sh +++ b/bin/celery_worker.sh @@ -15,5 +15,11 @@ if [[ "$ENABLE_COVERAGE" ]]; then fi echo "Starting celery worker $WORKER_NAME with queue $QUEUE" -exec $_binary --workdir src -A "open_inwoner" events -l info --camera django_celery_monitor.camera.Camera --frequency=2.0 & -exec $_binary --workdir src -A "open_inwoner" worker -l $LOGLEVEL -c $CONCURRENCY -Q $QUEUE -n $WORKER_NAME -E --max-tasks-per-child=50 -l info -B --scheduler django_celery_beat.schedulers:DatabaseScheduler +exec $_binary --workdir src --app "open_inwoner.celery" worker \ + -Q $QUEUE \ + -n $WORKER_NAME \ + -l $LOGLEVEL \ + -O fair \ + -c $CONCURRENCY \ + -E \ + --max-tasks-per-child=50 diff --git a/bin/docker_start.sh b/bin/docker_start.sh index 8b36948cfd..620f00d04e 100755 --- a/bin/docker_start.sh +++ b/bin/docker_start.sh @@ -2,24 +2,20 @@ set -ex -# Wait for the database container +# Figure out abspath of this script +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "$SCRIPT") + +# wait for required services # See: https://docs.docker.com/compose/startup-order/ -export PGHOST=${DB_HOST:-db} -export PGPORT=${DB_PORT:-5432} +${SCRIPTPATH}/wait_for_db.sh -fixtures_dir=${FIXTURES_DIR:-/app/fixtures} +# fixtures_dir=${FIXTURES_DIR:-/app/fixtures} uwsgi_port=${UWSGI_PORT:-8000} uwsgi_processes=${UWSGI_PROCESSES:-4} uwsgi_threads=${UWSGI_THREADS:-1} -until pg_isready; do - >&2 echo "Waiting for database connection..." - sleep 1 -done - ->&2 echo "Database is up." - # Apply database migrations >&2 echo "Apply database migrations" python src/manage.py migrate diff --git a/bin/start_celery.sh b/bin/start_celery.sh deleted file mode 100755 index 6beffa25ad..0000000000 --- a/bin/start_celery.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -. env/bin/activate - -LOGLEVEL=${CELERY_LOGLEVEL:-INFO} -CONCURRENCY=${CELERY_WORKER_CONCURRENCY:-1} - -exec celery --workdir src -A "open_inwoner" events -l info --camera django_celery_monitor.camera.Camera --frequency=2.0 & -exec celery --workdir src -A "open_inwoner" worker -l $LOGLEVEL -c $CONCURRENCY -E --max-tasks-per-child=50 -l info -B --scheduler django_celery_beat.schedulers:DatabaseScheduler diff --git a/bin/wait_for_db.sh b/bin/wait_for_db.sh old mode 100644 new mode 100755 index f389947589..89e15e6a1b --- a/bin/wait_for_db.sh +++ b/bin/wait_for_db.sh @@ -12,4 +12,4 @@ until pg_isready; do sleep 1 done ->&2 echo "Database is up." \ No newline at end of file +>&2 echo "Database is up." diff --git a/docker-compose.yml b/docker-compose.yml index 44e792b726..39246ce2cf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,17 @@ -# Inspired by https://docs.docker.com/compose/django/ -version: '3' +# +# Docker-compose for full Open Inwoner stack. +# +# DISCLAIMER: THIS IS FOR DEVELOPMENT PURPOSES ONLY AND NOT SUITABLE FOR PRODUCTION. +# +# You can use this docker-compose to spin up a local Open Inwoner stack for demo/try-out +# purposes, or to get some insight in the various components involved (e.g. to build +# your Helm charts from). Note that various environment variables are UNSAFE and merely +# specified so that you can get up and running with the least amount of friction. +# +# Before deploying to production, please review the environment configuration reference: +# https://open-inwoner.readthedocs.io/ +# +version: '3.4' services: db: @@ -44,6 +56,8 @@ services: web: build: &web_build context: . + args: + RELEASE: ${TAG:-latest} container_name: open-inwoner-web image: maykinmedia/open-inwoner:${TAG:-latest} environment: &web_env @@ -60,9 +74,22 @@ services: - CELERY_RESULT_BACKEND=redis://redis:6379/0 - CELERY_LOGLEVEL=DEBUG - ES_HOST=elasticsearch + # Needed for Celery Flower to match the TIME_ZONE configured in the + # settings used by workers and beat containers. + - TZ=Europe/Amsterdam + # WARNING: Strictly for development! - DISABLE_2FA=${DISABLE_2FA:-True} - DEBUG=True - IS_HTTPS=no + healthcheck: + test: ["CMD", "python", "-c", "import requests; exit(requests.head('http://localhost:8000/admin/').status_code not in [200, 302])"] + interval: 30s + timeout: 5s + retries: 3 + # This should allow for enough time for migrations to run before the max + # retries have passed. This healthcheck in turn allows other containers + # to wait for the database migrations. + start_period: 60s volumes: &web_volumes - media:/app/media - private_media:/app/private_media @@ -91,10 +118,44 @@ services: image: maykinmedia/open-inwoner:${TAG:-latest} environment: *web_env command: /celery_worker.sh + healthcheck: + test: ["CMD", "python", "/app/bin/check_celery_worker_liveness.py"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s volumes: *web_volumes depends_on: - - db - - redis + web: + # This health check condition is needed because Celery Beat will + # try to convert the CELERY_BEAT_SCHEDULE into database entries. For + # this, migrations need to be finished. If Celery tasks were still + # pending, the database also needs to be ready for Celery itself. We + # therefore have the health check here, and make Celery beat and + # monitor containers depend on the celery container. + condition: service_healthy + redis: + condition: service_started + networks: + - openinwoner-dev + + celery-beat: + build: *web_build + image: maykinmedia/open-inwoner:${TAG:-latest} + environment: *web_env + command: /celery_beat.sh + depends_on: + - celery + networks: + - openinwoner-dev + + celery-monitor: + build: *web_build + image: maykinmedia/open-inwoner:${TAG:-latest} + environment: *web_env + command: /celery_monitor.sh + depends_on: + - celery networks: - openinwoner-dev diff --git a/src/open_inwoner/celery.py b/src/open_inwoner/celery.py index 2abfff4103..29620c429b 100644 --- a/src/open_inwoner/celery.py +++ b/src/open_inwoner/celery.py @@ -1,7 +1,9 @@ +from pathlib import Path + from django.conf import settings -from celery import Celery -from celery.signals import setup_logging +from celery import Celery, bootsteps +from celery.signals import setup_logging, worker_ready, worker_shutdown from .setup import setup_env @@ -26,3 +28,45 @@ def config_loggers(*args, **kwargs): from logging.config import dictConfig dictConfig(settings.LOGGING) + + +HEARTBEAT_FILE = Path(settings.BASE_DIR) / "tmp" / "celery_worker_heartbeat" +READINESS_FILE = Path(settings.BASE_DIR) / "tmp" / "celery_worker_ready" + + +# +# Utilities for checking the health of celery workers +# +class LivenessProbe(bootsteps.StartStopStep): + requires = {"celery.worker.components:Timer"} + + def __init__(self, worker, **kwargs): + self.requests = [] + self.tref = None + + def start(self, worker): + self.tref = worker.timer.call_repeatedly( + 10.0, + self.update_heartbeat_file, + (worker,), + priority=10, + ) + + def stop(self, worker): + HEARTBEAT_FILE.unlink(missing_ok=True) + + def update_heartbeat_file(self, worker): + HEARTBEAT_FILE.touch() + + +@worker_ready.connect +def worker_ready(**_): + READINESS_FILE.touch() + + +@worker_shutdown.connect +def worker_shutdown(**_): + READINESS_FILE.unlink(missing_ok=True) + + +app.steps["worker"].add(LivenessProbe) From ffda3f52f4c5dc0d5b9c189ee7a98ee1b36a3431 Mon Sep 17 00:00:00 2001 From: Joeri Bekker Date: Wed, 17 Jul 2024 15:50:14 +0200 Subject: [PATCH 2/4] :lipstick: Updated favicon. --- src/open_inwoner/static/ico/favicon-32x32.png | Bin 0 -> 866 bytes src/open_inwoner/static/ico/favicon-96x96.png | Bin 0 -> 2322 bytes src/open_inwoner/static/ico/favicon.png | Bin 457 -> 494 bytes src/open_inwoner/static/ico/favicon.svg | 30 ++++++++++++++++++ 4 files changed, 30 insertions(+) create mode 100644 src/open_inwoner/static/ico/favicon-32x32.png create mode 100644 src/open_inwoner/static/ico/favicon-96x96.png create mode 100644 src/open_inwoner/static/ico/favicon.svg diff --git a/src/open_inwoner/static/ico/favicon-32x32.png b/src/open_inwoner/static/ico/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..69f4d53abb6b23eb8304d2e598922f5cb363e33d GIT binary patch literal 866 zcmV-o1D*VdP)pI6iGxuR9J=WS5HV3Q5gT;+tJ-N(?z_rNr)$jI!LRu)S-neBD{2~ zL;pN<3BrizpD||l`y#|5zxXUItRu#Yf;hkz z92f=Is8O7Qb8s%sDbOReN)S)}M(-G24`90xPuvq4TuZ`y1yfT2OjENtWK1}1jOD>dcSpYvnYKw>;gaQ-4sbZ_u=v`MWEHNyd2khlCc_jKwtb737*5Z3?P6 z328R)(okTDUp`o$fC|Xf`#)RjsTO!uJnP_=niQ%4ewQb@_dh@5Hs2L~){BowHJnvB zz`+PS-h4)-K+d%<;_MAPWXIxj~4z`+R#40@rs!|j^BMEmo2RGM5ZOlMJ9*tg0+EIu_7u?JV zWn=jGF1sDw;n3B!aOg6~=<&3j#+@?lsxP?3sR*WKL%!q{Fbyhz5jIe013biCao_42 z2HV0eDAqs+GIi+H71{5D$<)De=BdS%_h4tC4ZUcWo+VOC{U6F|o7{b(P1rTAP4PI? zAy;P`Dy*?A38;oM3l<192B8w1+*$uP*Y>mvO0pn^5{v!gUbsANL)F04Ke78;h~5Q? zSHrzOm*1_ohUR$tTl&_VS02v}#6i^|4W5N9P}pIZ8L0pB7Y_wFWCWZG48L{*3zFNs ztt-LRN`(HrreZ-dBGzL;QasDKWz0g;39BTFrv_lVz{|Z&OELlWQB{urpxR s>8DG6OwzSGfE+}>%w{RQWng9R*07*qoM6N<$g2E4tbN~PV literal 0 HcmV?d00001 diff --git a/src/open_inwoner/static/ico/favicon-96x96.png b/src/open_inwoner/static/ico/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..bfcc2cbebf0461af81a99f90373ebb9166f6f976 GIT binary patch literal 2322 zcmV+t3GMcYP)q=b72ro!MPjEEbE!VzF2( z7K_C)uV8h_<y{F(`!wWH0eP{@K!JxiXo;>YJ6sh!YJgWdtW<=f=V z+hM5~{rwA3%B_RL?xLk{QnV{YrsL~J#2|7pUr|)fnwhlf|^CQ7YN}OAjNu2MP*WzD`r^PO{ zfm%zo1314aa6Q9iT)O@buw2bp^V2j}G&$)!K|!zs3Po|s9b7$e{yM(2CdNT%o**^h zuLY)Y2t*C`EN=y@qt#yV{>nZRI=?*PVQS3ex=7u23wtF_^-XhnP)39|{k z*-3{TXB?l<8al4Hn%f>LbD<57ccILIA#iHgbuB;mxuo|qxqQ*r5GH;DF~$J`3Z93P z%wI%5)zjaBK^Wx#qN8)gqg#^7e4>5Pc8LB9gD}kjgmVDst^4oVwCeBzs`qCfGyuECn+9MQ@&g80i3Fb=L}Nt<;Ihe_y^221dWY zR0oJ==|0(NnIUUh54BK{GBWxF#yWsl<+oa9M02jZlRlQfP)v3JM5{&A-?eTpqo3<8 z6VE(3Vk1nR@-vh%j-T_40b=h)H+>I(#M^rsG zz;M#w05FCJ_C94sE*n7taL%8E81SXDp~x<0a^F)LQ1sJWf8xg3 z0L`CA5-^Nv(jJi7UW4ZVF@pER>2`S!z|yIL%3Bi7{)_~09R49^I1p~hw|kL(HS62@ zRz-<^=D6QSQgFPgNnMN9sS|jyc!$*5A2scuFen2HPSbf3_b6quQIpAeyt|+u32~*= z^h^4<6k@i3Wy{k#R;msYU5#OvEs6spyPic-j5VLqmI9y~j31X;3(ZOU=&c|z7}s^S zB{?W-cG1{2yHmF`2&|D5$*scZ~Qt&8Gj0!Z+j65 zGgWFjNFVQom}M)@|2tUx?_rm&hXzM?N4jljM&vtRkXi}N7~C-Ps3o8T$DKq2@Jm5o zm>r!LY`bm6Pgi%f|Kuj|JSq8ioVf)JAZjVdaQ7j& z*&iT0`p*_e|CN073xq~OD{)&F57#%&neY<&%fCefkfng*i7-3P_*OARu=_61>!J~4 zGQUHN4j_l>EGoehO>oOA=?E?E|2?g=7AI(hS31xDvKhCJDTjOi4+r5vbhbG1{?lj# zo;J5?Ecz)L?vz>!%}IN&=;rgHz8aC!k>TgC^vbKsa{OMt>N=ni}69 zaQfn&cSy{`akpdO2O1mwwULevnQ~SPTmLY!J;PhgqvKB^1*F0OgJbt!AXR@Ic>@lv%vpNs{{Pajld5{*f<5fOegE3^oRV6a7Nw%)^HEagfIp4y_$PfBKjt$k zsj7nJBGv)3jCH^)V;wNdSO?59)&aAOb-*lB%LAKoaW`S$-=GsH?T~SoJAXripp!N+ z;^Mf@Mm(@7e#Y^&spWx9vG2PY7}@nQ45B!?Q#iZ+4j0;}9@tc^26hgqZqU#S6K6&} z?!_o{4}!{M-w9eB?0|fS7@@4XsI@j|ocp{-Xu_CkF=lV5=4 zYFekZN^OE*>brl`4q#k8G=;IpaH80-@j=GpX`vZV>?&_+Q6Gdk6N6d5qDXB+hW`a8 z2kpbV<-@zV{^8v&{-{b)KVwlma(y9xTUo58BaRvG`rm(re5bLGh^dLfpy-qSy1(>s zL~lWkV}i9~OGn_?CUq4gHgK^Y(GfprnVcA3h`EOMpO*PkjOIJruM%INKNDsX2dIpk zf~7X3b|3s$XQFq27&XnC@1UHXfh8_aN$tFm=Ssq_1&Ox+MmH_r4DUgxsq0&=6aI_bFiee=)832RI%D01Z(n5? sm4sepXt7u<7K_DVu~;k?%X|X(4~sR!d_MBOIsgCw07*qoM6N<$f}q@N<^TWy literal 0 HcmV?d00001 diff --git a/src/open_inwoner/static/ico/favicon.png b/src/open_inwoner/static/ico/favicon.png index 3c97c10a076abea686d96452b9e31e07d7ab3ef5..f02701f8fd7eeca99f56bcf691e249031adcf806 100644 GIT binary patch delta 479 zcmV<50U-X#1MUNm8Gi-<001BJ|6u?C010qNS#tmY4#NNd4#NS*Z>VGd00E#$L_t(I zjipk*OF~f;{_gc^84@AXU{Vrp(qw@}LvL(oizbI?4a90_?GKQwhW>)4rna_TQIPlw zf{2y~3zI;Qh{*8AyPf-9riPCKKe*g;&-u>Jd(bV|k92VBfq(x!1lPwCH0`q^Ti1J0 z?;AnMm&0PDqEy^AWP%thKS1y!pg-uGk8FygxXPy)IlBbiIKzK&Vw~dGSXQF26q5VF zWL}Ar!`nAZBIM%c=tX|5q;ylkEq~qQkCGv0JSWE?QK0Sznl1c-1bnqRUv0eWlCLXW zC$4a+k})Ksfq&EvuX+V!HQ~e)&@X2wXB<);VAf_ah*^(ln^=d19^qN2&@$M31ZXg?wy0pO zrN~fkWg5#IwCH`ubox~oFlpVHmqrtV7R%caNkGv%MuvIdE$>{gvJppdl~4Boz5s=> Visdg`H%kBj002ovPDHLkV1k?%-tzze delta 442 zcmV;r0Y(1q1IYuB8Gi%-006c6H|hWY00(qQO+^RU0vQV&2Ca3wy8r+H32;bRa{vGr z5dZ)e5dq33^FIIp00d`2O+f$vv5yPK)a{vGU07*qoM6N<$f)hW$DgXcg diff --git a/src/open_inwoner/static/ico/favicon.svg b/src/open_inwoner/static/ico/favicon.svg new file mode 100644 index 0000000000..039c88c1e0 --- /dev/null +++ b/src/open_inwoner/static/ico/favicon.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fe0c358fc2406ac6f43c64f058c83a74acd32e66 Mon Sep 17 00:00:00 2001 From: Joeri Bekker Date: Thu, 25 Jul 2024 19:18:53 +0200 Subject: [PATCH 3/4] :wrench: Update nvm version to match the Docker version. --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 48082f72f0..209e3ef4b6 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -12 +20 From 52928c8e17bdbb999c8180cd6f9456124ec32d59 Mon Sep 17 00:00:00 2001 From: Joeri Bekker Date: Thu, 25 Jul 2024 19:19:26 +0200 Subject: [PATCH 4/4] :bug: Define scriptpath for setup_configuration.sh --- bin/setup_configuration.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/setup_configuration.sh b/bin/setup_configuration.sh index 628a63cc54..ba5b09089d 100644 --- a/bin/setup_configuration.sh +++ b/bin/setup_configuration.sh @@ -3,7 +3,12 @@ # setup initial configuration using environment variables # Run this script from the root of the repository -#set -e +set -e + +# Figure out abspath of this script +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "$SCRIPT") + ${SCRIPTPATH}/wait_for_db.sh src/manage.py migrate