Skip to content

Commit 1be5672

Browse files
committed
Merge remote-tracking branch 'origin/main' into features/feeds_oceans_continents
2 parents a88deeb + c3d62db commit 1be5672

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+674
-518
lines changed

.github/workflows/ci.yml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ on:
66
pull_request:
77
branches: [ "main" ]
88

9+
permissions:
10+
pull-requests: write # allow posting comments on PRs by actions
911
jobs:
1012
unittests:
1113
runs-on: ubuntu-24.04
12-
14+
1315
strategy:
1416
max-parallel: 4
1517
matrix:
@@ -57,9 +59,25 @@ jobs:
5759
run: |
5860
python manage.py loaddata fixtures/test_data.json
5961
62+
- name: Run deploy checks
63+
run: |
64+
python -Wa manage.py check --deploy
65+
6066
- name: Run Tests
6167
run: |
62-
python -Wa manage.py test tests
68+
coverage run --source='publications' --omit='*/migrations/**' manage.py test tests
69+
70+
- name: Check coverage and save it to files
71+
run: |
72+
coverage html
73+
coverage xml
74+
coverage report --show-missing --fail-under=70
75+
76+
#- name: Post code coverage
77+
# uses: orgoro/coverage@v3.2
78+
# with:
79+
# coverageFile: coverage.xml
80+
# token: ${{ secrets.GITHUB_TOKEN }}
6381

6482
uitests:
6583
# disable until UI tests are fixed, see https://github.com/GeoinformationSystems/optimap/issues/142

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,15 @@ geodjango/
133133

134134
tests-ui/screenshots/
135135

136-
static/
136+
/static/
137137

138138
# nano's edit files on the server
139139
*.swp
140+
141+
*.docx#
142+
143+
publications/static/OPTIMAP_Data-Privacy-Concept.docx
144+
145+
certbot/conf/
146+
147+
certbot/www/

Dockerfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ RUN set -ex && \
3434
pip install --no-cache-dir -r /tmp/requirements.txt && \
3535
rm -rf /root/.cache/
3636

37-
COPY . /code/
37+
COPY . /code
3838

39-
RUN python manage.py collectstatic --noinput
39+
RUN chmod a+x /code/etc/manage-and-run.sh
4040

4141
EXPOSE 8000
4242

4343
#CMD ["gunicorn", "--bind", ":8000", "--workers", "2", "optimap.wsgi"]
44-
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000" ]
44+
#CMD ["python", "manage.py", "runserver", "0.0.0.0:8000" ]
45+
ENTRYPOINT [ "/code/etc/manage-and-run.sh" ]

README.md

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,37 +29,38 @@ A complete list of existing parameters is provided in the file `optimap/.env.exa
2929

3030
## Run with Docker
3131

32-
The project is containerized using Docker, with services defined in `docker-compose.yml`. To start all services, run:
32+
The project is containerized using Docker, with services defined in `docker-compose.(deploy.)yml`. To start all services, run:
3333

3434
```bash
3535
docker compose up
36-
```
3736

38-
### Initial Setup
37+
docker compose run --entrypoint python app manage.py loaddata fixtures/test_data.json
38+
```
3939

40-
After starting the containers, apply database migrations:
40+
The database migrations are applied as part of the startup script, see file `etc/manage-and-run.sh`.
41+
You can still run the commands below manually if need be, e.g., during development.
4142

4243
```bash
43-
# run migrations, in the directory where docker-compose is to resolve the name "web"
44-
docker compose run app python manage.py makemigrations # should not detect and changes, otherwise your local config might be outdated
45-
docker compose run app python manage.py migrate
46-
docker compose run app python manage.py collectstatic --noinput
47-
docker compose run app python manage.py loaddata fixtures/test_data.json
44+
docker compose run --entrypoint python app manage.py makemigrations # should not detect and changes, otherwise your local config might be outdated
45+
docker compose run --entrypoint python app manage.py migrate
46+
docker compose run --entrypoint python app manage.py collectstatic --noinput
4847
```
4948

5049
Now open a browser at <http://localhost:80/>.
5150

52-
#### Services Overview
51+
### Services Overview
5352

5453
- db: Runs a PostgreSQL database with PostGIS extensions. Data is persisted in a Docker volume named db_data.
5554
- app: Our primary Django web application.
5655
- webserver: An Nginx server for serving static files and test files.
5756

58-
#### Ports
57+
### Ports
5958

60-
- 5434: Database (PostgreSQL/PostGIS)
61-
- 8000: App (Django server)
62-
- 8080: Webserver (Nginx)
59+
Not all of these ports are exposed by default, but they are available for local development - just uncomment the matching lines in the `docker-compose.yml` file.
60+
61+
- `5432`: Database (PostgreSQL/PostGIS)
62+
- `8000`: App (Django server)
63+
- `80`: Webserver (Nginx)
6364

6465
## Development
6566

@@ -137,6 +138,9 @@ python manage.py createcachetable
137138
# Collect static files
138139
python manage.py collectstatic --noinput
139140

141+
# If you need to run tasks (harvesting, data export) then start a cluster in a separate shell
142+
python manage.py qcluster
143+
140144
# Start the Django development server
141145
python manage.py runserver
142146

@@ -256,14 +260,33 @@ python manage.py test tests
256260
python -Wa manage.py test
257261

258262
# configure logging level for cleaner test progress output
259-
OPTIMAP_LOGGING_CONSOLE_LEVEL=WARNING python manage.py test tests
263+
OPTIMAP_LOGGING_LEVEL=WARNING python manage.py test tests
264+
```
265+
266+
### Run UI tests
260267

261-
# running UI tests needs either compose configuration or a manage.py runserver in a seperate shell
268+
Running UI tests needs either compose configuration or a manage.py runserver in a seperate shell.
269+
270+
```bash
262271
docker-compose up --build
263272

264273
python -Wa manage.py test tests-ui
265274
```
266275

276+
### Check test coverage
277+
278+
```bash
279+
# run the tests and capture coverage
280+
coverage run --source='publications' --omit='*/migrations/**' manage.py test tests
281+
282+
# show coverage report
283+
coverage report --show-missing --fail-under=70
284+
285+
# save the reports
286+
coverage html
287+
coverage xml
288+
```
289+
267290
### Develop tests
268291

269292
For developing the UI tests, you can remove the `headless=True` in the statements for starting the browsers so you can "watch along" and inspect the HTML when a breakpoint is hit as the tests are executed.
@@ -309,7 +332,7 @@ The changelog follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0
309332

310333
The version is managed in `optimap/__init__.py`.
311334

312-
### Design colours and logos
335+
## Design colours and logos
313336

314337
Optimeta colour = _primary colour_: #158F9B
315338

@@ -323,7 +346,8 @@ The **logos** and favicon are in the repository in the folder [`publications/sta
323346

324347
## Deploy
325348

326-
Deploy using `docker-compose` or see [`fly.io.md`](fly.io.md) for notes on deploying to Fly.io.
349+
The app is deployed in the TUD Enterprise Cloud.
350+
HTTPS certificate is retrieved via `certbot`, see `docker-compose.deploy.yml` for the configuration and documentation links.
327351

328352
## Operation
329353

@@ -344,6 +368,32 @@ Deploy using `docker-compose` or see [`fly.io.md`](fly.io.md) for notes on deplo
344368
- Go to `/admin/auth/user/`
345369
- Select users → Choose **"Delete user and block email/domain"** → Click **Go**.
346370

371+
### Tasks
372+
373+
We use [Django Q2](https://django-q2.readthedocs.io/) for scheduling (repeated) tasks.
374+
375+
#### Run the cluster
376+
377+
```bash
378+
python manage.py qcluster
379+
```
380+
381+
#### Monitor
382+
383+
Details: <https://django-q2.readthedocs.io/en/master/monitor.html>
384+
385+
tl;dr:
386+
387+
```bash
388+
python manage.py qmonitorq
389+
390+
python manage.py qinfo
391+
```
392+
393+
### Trigger creation of data export files
394+
395+
TODO
396+
347397
## License
348398

349399
This software is published under the GNU General Public License v3.0 (see file `LICENSE`).

certbot/.keepdir

Whitespace-only changes.

docker-compose.deploy.yml

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,57 @@ services:
66
POSTGRES_USER: optimap
77
POSTGRES_PASSWORD: optimap
88
#POSTGRES_PASSWORD_FILE: database_password
9-
ports:
10-
- "5434:5432"
9+
#ports:
10+
# - "5432:5432"
1111
volumes:
1212
- optimap-volume:/var/lib/postgresql/data
1313
#secrets:
1414
# - database_password
1515

1616
app:
17-
build:
18-
context: .
19-
dockerfile: Dockerfile
17+
build: .
2018
environment:
2119
#see local .env file on the server
2220
DATABASE_URL: postgis://optimap:optimap@db:5432/optimap?sslmode=disable
2321
OPTIMAP_DEBUG: "False"
2422
volumes:
25-
- ".:/code" # need to run collectstatic
26-
- "./fixtures:/fixtures"
27-
ports:
28-
- "8000:8000"
23+
- "./optimap/.env:/code/optimap/.env:ro"
24+
#ports:
25+
# - "8000:8000"
26+
depends_on:
27+
- db
28+
29+
djangoq:
30+
build: .
31+
environment:
32+
#see local .env file on the server
33+
DATABASE_URL: postgis://optimap:optimap@db:5432/optimap?sslmode=disable
34+
entrypoint: ["python"] # do not run manage-and-run.sh script
35+
command: ["manage.py", "qcluster"]
36+
volumes:
37+
- "./optimap/.env:/code/optimap/.env:ro"
2938
depends_on:
3039
- db
40+
- app
3141

3242
webserver:
3343
image: nginx:1.27-alpine
3444
volumes:
3545
- "./etc/nginx.deploy.conf:/etc/nginx/nginx.conf:ro"
46+
- "./certbot/www/:/var/www/certbot/:ro"
47+
- "./certbot/conf/:/etc/nginx/ssl/:ro"
3648
ports:
3749
- "80:80"
50+
- "443:443"
3851
depends_on:
39-
- app
52+
- app
53+
restart: always
54+
55+
certbot:
56+
image: certbot/certbot:latest
57+
volumes:
58+
- "./certbot/www/:/var/www/certbot/:rw"
59+
- "./certbot/conf/:/etc/letsencrypt/:rw"
4060

4161
volumes:
4262
optimap-volume:

docker-compose.yml

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,36 @@ services:
55
POSTGRES_DB: optimap
66
POSTGRES_USER: optimap
77
POSTGRES_PASSWORD: optimap
8-
ports:
9-
- "5434:5432"
8+
#ports:
9+
# - "5434:5432"
1010
volumes:
1111
- db_data:/var/lib/postgresql/data
1212

1313
app:
14-
build:
15-
context: .
16-
dockerfile: Dockerfile
14+
build: .
1715
environment:
1816
DATABASE_URL: postgis://optimap:optimap@db:5432/optimap?sslmode=disable
1917
OPTIMAP_CACHE: "dummy"
20-
OPTIMAP_DEBUG: "True"
2118
volumes:
22-
- ".:/code:ro"
19+
- ".:/code" # mount the code for development and testing
2320
- "./fixtures:/fixtures:ro"
24-
ports:
25-
- "8000:8000"
21+
#ports:
22+
# - "8000:8000"
23+
depends_on:
24+
- db
25+
26+
djangoq:
27+
build: .
28+
environment:
29+
DATABASE_URL: postgis://optimap:optimap@db:5432/optimap?sslmode=disable
30+
OPTIMAP_CACHE: "dummy"
31+
entrypoint: ["python"] # do not run manage-and-run.sh script
32+
command: ["manage.py", "qcluster"]
33+
volumes:
34+
- ".:/code:ro"
2635
depends_on:
2736
- db
37+
- app
2838

2939
webserver:
3040
image: nginx:1.27-alpine

etc/manage-and-run.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Collect static files
5+
echo "OPTIMAP ENTRYPOINT | Collect static files"
6+
python manage.py collectstatic --noinput
7+
8+
# Create a cache table
9+
echo "OPTIMAP ENTRYPOINT | Create cache table"
10+
python manage.py createcachetable
11+
12+
# Apply database migrations
13+
echo "OPTIMAP ENTRYPOINT | Apply database migrations"
14+
python manage.py migrate
15+
16+
# Start server
17+
echo "OPTIMAP ENTRYPOINT | Starting server"
18+
# make the next process the main process, cf. https://www.baeldung.com/ops/docker-exec-process-replacement
19+
exec python manage.py runserver 0.0.0.0:8000
20+
21+
# TODO: revisit entrypoint approach if there are any issues, e.g., by using an extra migration container, cf. https://stackoverflow.com/questions/33992867/how-do-you-perform-django-database-migrations-when-using-docker-compose, or by manually running selected commands after installation, cf. https://www.baeldung.com/ops/django-database-migrations-docker-compose

etc/nginx.deploy.conf

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
worker_processes 1;
2+
worker_processes auto;
33

44
events {
55
worker_connections 1024;
@@ -18,6 +18,30 @@ http {
1818

1919
server {
2020
listen 80;
21+
listen [::]:80;
22+
server_name optimap.geo.tu-dresden.de;
23+
24+
# https://xavierz.dev/blog/posts/certbot-docker
25+
location /.well-known/acme-challenge/ {
26+
root /var/www/certbot;
27+
}
28+
29+
location / {
30+
return 301 https://$host$request_uri;
31+
}
32+
33+
}
34+
35+
server {
36+
listen 443 ssl;
37+
listen [::]:443 ssl;
38+
http2 on; # https://aruljohn.com/blog/nginx-listen-http2-directive-deprecated/
39+
server_name optimap.geo.tu-dresden.de;
40+
41+
# via certbot, see https://xavierz.dev/blog/posts/certbot-docker
42+
ssl_certificate /etc/nginx/ssl/live/optimap.geo.tu-dresden.de/fullchain.pem;
43+
ssl_certificate_key /etc/nginx/ssl/live/optimap.geo.tu-dresden.de/privkey.pem;
44+
2145
server_name optimap.geo.tu-dresden.de;
2246

2347
location / {

0 commit comments

Comments
 (0)