Compare commits

...

106 Commits

Author SHA1 Message Date
06caf796cd Merge pull request 'Update dependency flask-migrate to v4' (!111) from renovate/flask-migrate-4.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #111
2024-09-13 13:13:42 +02:00
54326129e4 Merge pull request 'Update python:3.8.20-alpine Docker digest to 3d93b1f' (!127) from renovate/python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #127
2024-09-13 12:48:09 +02:00
32bb81b69b Update dependency flask-migrate to v4
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-13 10:36:05 +00:00
fc8a06e562 Update python:3.8.20-alpine Docker digest to 3d93b1f
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-13 10:35:25 +00:00
b8b713c620 Merge pull request 'Update dependency reuse to v4' (!126) from renovate/reuse-4.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #126
2024-09-13 12:33:44 +02:00
186ab9af43
Migrate REUSE config
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-13 12:30:48 +02:00
0d77c8d637 Update dependency reuse to v4
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-11 11:37:14 +00:00
72fda5df51 Merge pull request 'Update dependency reuse to v2' (!124) from renovate/reuse-2.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #124
2024-09-11 13:30:28 +02:00
739ce0382b Update dependency reuse to v2
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-11 10:37:32 +00:00
4c345ecc5f Merge pull request 'Update dependency sqlalchemy to v1.4.54' (!119) from renovate/sqlalchemy-1.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #119
2024-09-11 12:00:35 +02:00
5882eeaf2e Update dependency sqlalchemy to v1.4.54
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 18:35:55 +00:00
0512bc0dc3 Merge pull request 'Update dependency flask-migrate to v3.1.0' (!88) from renovate/flask-migrate-3.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #88
2024-09-10 19:42:03 +02:00
319bf9b2f5 Update dependency flask-migrate to v3.1.0
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 17:36:22 +00:00
717454e205 Merge pull request 'Update python Docker tag to v3.8.20' (!121) from renovate/patch-python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #121
2024-09-10 15:49:46 +02:00
496550a959 Update python Docker tag to v3.8.20
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 13:35:28 +00:00
7ebf13edf3 Merge pull request 'Update python:3.8.19-alpine Docker digest to 8b53bd2' (!118) from renovate/python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #118
2024-09-10 15:03:37 +02:00
5409bdeaee Merge pull request 'Verify lockfile before installation' (!120) from verify-lockfile into main
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #120
2024-09-10 15:03:14 +02:00
4064a65e63
Verify lockfile before installation
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 14:52:44 +02:00
afe22e13c1 Merge pull request 'Update dependency python-dotenv to v1' (!116) from renovate/python-dotenv-1.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #116
2024-09-10 14:30:41 +02:00
e4d0a89053
Update lock file
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 14:27:54 +02:00
78bdd796e0 Update dependency python-dotenv to v1
Some checks failed
renovate/artifacts Artifact file update failure
continuous-integration/drone/pr Build is passing
2024-09-10 11:36:39 +00:00
c9f83e80b3 Update python:3.8.19-alpine Docker digest to 8b53bd2
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 11:35:27 +00:00
5369de67d8 Merge pull request 'Update dependency pre-commit to v2.21.0' (!89) from renovate/pre-commit-2.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #89
2024-09-10 13:07:34 +02:00
54c5246f0a Merge pull request 'Add dry-run Docker build to Pull Request CI run' (!117) from docker-dry-run into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #117
2024-09-10 13:02:19 +02:00
9a95baf106
Add dry-run Docker build to Pull Request CI run
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-10 12:56:04 +02:00
338380ed93 Update dependency pre-commit to v2.21.0
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-05 09:36:44 +00:00
3d128d771c Merge pull request 'Update dependency flask-cors to v5' (!114) from renovate/flask-cors-5.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #114
2024-09-05 11:26:34 +02:00
6b7517fc7a Update dependency flask-cors to v5
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-04 21:36:04 +00:00
5ceb361da3 Merge pull request 'Update python:3.8.19-alpine Docker digest to c2f31d1' (!113) from renovate/python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #113
2024-09-04 23:03:32 +02:00
4379a06f26 Update python:3.8.19-alpine Docker digest to c2f31d1
All checks were successful
continuous-integration/drone/pr Build is passing
2024-09-04 19:36:16 +00:00
c43f375e4b Merge pull request 'Update dependency flake8 to v7' (!108) from renovate/flake8-7.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #108
2024-09-04 20:44:01 +02:00
621a90b8ab Update dependency flake8 to v7
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 14:36:12 +00:00
033dee7836 Merge pull request 'Update dependency python-dotenv to v0.21.1' (!91) from renovate/python-dotenv-0.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #91
2024-08-28 16:27:46 +02:00
ca81e8bf70
Merge branch 'main' into renovate/python-dotenv-0.x
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 16:02:01 +02:00
d507a20a93 Merge pull request 'Update dependency flake8 to v6' (!107) from renovate/flake8-6.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #107
2024-08-28 15:52:02 +02:00
3f2c23c386
Merge branch 'main' into renovate/flake8-6.x
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 15:46:31 +02:00
b46ac5e379 Merge pull request 'Update dependency pymysql to v1.1.1' (!90) from renovate/pymysql-1.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #90
2024-08-28 15:43:17 +02:00
fa4429b6ef Update dependency flake8 to v6
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 13:37:17 +00:00
7a0f2434db Update dependency python-dotenv to v0.21.1
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 13:36:27 +00:00
8c3fe3fe7d Update dependency pymysql to v1.1.1
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 13:36:11 +00:00
56ade6de68 Merge pull request 'Update dependency flask to v2.3.3' (!87) from renovate/flask-2.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #87
Reviewed-by: Brain <brain@noreply.git.wtf-eg.de>
2024-08-28 15:19:36 +02:00
28cf714217 Update dependency flask to v2.3.3
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 12:35:38 +00:00
9ff56f6676 Merge pull request 'Update dependency yapf to v0.40.2' (!94) from renovate/yapf-0.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #94
2024-08-28 13:46:17 +02:00
2412df4960
Apply yapf and add ignorefile
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 13:43:33 +02:00
469ef511d6 Merge pull request 'Add .python-version file' (!105) from pyenv into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #105
2024-08-28 13:19:28 +02:00
47d2c94b79
Specify license for .python-version
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-28 12:57:31 +02:00
384dd82454 Update dependency yapf to v0.40.2
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-27 17:38:01 +00:00
b0dcfacd25
Add .python-version file
Some checks failed
continuous-integration/drone/pr Build is failing
2024-08-27 19:08:52 +02:00
86edb246bf Merge pull request 'revert f02efab07aeabe02a94efd62fbe498659297b36f' (!102) from revert-python-3.11 into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #102
2024-08-23 15:59:55 +02:00
9424e21edc revert f02efab07a
All checks were successful
continuous-integration/drone/pr Build is passing
revert Merge pull request 'Update python Docker tag to v3.11.9' (!97) from renovate/minor-3.11-python into main

Reviewed-on: #97
2024-08-23 15:50:30 +02:00
f02efab07a Merge pull request 'Update python Docker tag to v3.11.9' (!97) from renovate/minor-3.11-python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #97
2024-08-23 15:33:32 +02:00
08f1104942
Merge branch 'main' into renovate/minor-3.11-python
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-23 15:30:29 +02:00
8dde142f38
Try and use Python 3.11
Some checks failed
continuous-integration/drone/pr Build is failing
2024-08-23 15:26:39 +02:00
d1b1636aa2 Merge pull request 'Update dependency waitress to v2.1.2' (!93) from renovate/waitress-2.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #93
2024-08-23 12:01:59 +02:00
3fcd1fa20e Update python Docker tag to v3.11.9
Some checks failed
continuous-integration/drone/pr Build is failing
2024-08-22 18:37:13 +00:00
8394400e96 Update dependency waitress to v2.1.2
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-22 18:36:55 +00:00
843050f923 Merge pull request 'Update plugins/docker Docker tag to v20.18.4' (!95) from renovate/plugins-docker-20.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #95
2024-08-22 19:53:59 +02:00
812913ffe2 Merge pull request 'Update dependency reuse to v0.14.0' (!92) from renovate/reuse-0.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #92
2024-08-22 19:52:24 +02:00
dee80c7e14 Update plugins/docker Docker tag to v20.18.4
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-22 15:35:49 +00:00
de60ec0d46 Update dependency reuse to v0.14.0
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-22 14:35:41 +00:00
6c6fcea81c Merge pull request 'Update python Docker tag to v3.8.19' (!85) from renovate/patch-python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #85
2024-08-22 13:17:55 +02:00
166e0d40c6 Merge pull request 'Update dependency werkzeug to v2.3.8' (!84) from renovate/werkzeug-2.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #84
2024-08-22 12:39:36 +02:00
c9b5ab62ed Update python Docker tag to v3.8.19
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-22 10:35:35 +00:00
c0005100b4 Update dependency werkzeug to v2.3.8
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-22 10:35:34 +00:00
d614039cdd Merge pull request 'Pin python Docker tag to 0ef73cd' (!83) from renovate/python into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #83
2024-08-22 11:52:25 +02:00
316236a7e5 Merge pull request 'Pin dependencies' (!82) from renovate/pin-dependencies into main
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #82
2024-08-22 11:51:54 +02:00
c15faabd6d
Pinning werkzeug to v2
All checks were successful
continuous-integration/drone/pr Build is passing
Thanks for the hint in #78
2024-08-22 11:46:27 +02:00
53eab74e60 Pin python Docker tag to 0ef73cd
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-22 09:35:43 +00:00
82d908193c Pin dependencies
Some checks failed
continuous-integration/drone/pr Build is failing
2024-08-22 09:35:42 +00:00
6620a6819a Merge pull request 'Configure Renovate' (!81) from renovate/configure into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #81
2024-08-22 11:25:28 +02:00
be6fec18ab
Update Renovate config
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-21 22:12:27 +02:00
9ebae03550 Add renovate.json
Some checks failed
continuous-integration/drone/pr Build is failing
2024-08-21 19:34:54 +00:00
763a6efc9f Merge pull request 'Improve Docker usage' (!80) from docker-improvements into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #80
2024-08-21 21:22:40 +02:00
6f04d23e6c
Add license information to .dockerignore file
All checks were successful
continuous-integration/drone/pr Build is passing
2024-08-21 21:17:33 +02:00
155ddc556c
Add .dockerignore file
Some checks failed
continuous-integration/drone/pr Build is failing
2024-08-21 21:09:12 +02:00
a5a85e6032
Fix Dockerfile warnings 2024-08-21 21:08:52 +02:00
6a3458a596
Pin Docker images in CI 2024-08-21 20:53:59 +02:00
97be8f4667
Ditch builder and base Docker images
This should make dependency upgrades easier and bring more clarity to the CI pipelines
2024-08-21 20:49:47 +02:00
776803fc96 Merge pull request 'Add catalan flag' (!77) from HerHde/ki-backend:add-ca-flag into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #77

> Anything else to consider?

I didn't know myself, but it was interesting to find out. No, this should work as soon as deployed. Catalan already exists in the language DB, and the existance of ca.svg is already tested whenever a catalan icon is requested.
2023-12-10 19:08:48 +01:00
702f4968f6 Merge pull request 'Use Gitea registry' (!76) from gitea-registry into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #76
2023-12-10 18:46:35 +01:00
c1285153ef
Add catalan flag
All checks were successful
continuous-integration/drone/pr Build is passing
2023-12-09 21:36:24 +01:00
fdc81844b5
Push image to Gitea registry
All checks were successful
continuous-integration/drone/pr Build is passing
2023-12-04 19:51:27 +01:00
b804c22a93
Use Gitea registry for base images 2023-12-04 19:45:08 +01:00
9a7a9379e2 Merge pull request 'Add labels to Docker images' (!75) from docker-labels into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #75
2023-11-16 11:18:00 +01:00
5b707ad294 Merge pull request 'Rewrite Drone config' (!74) from drone-config into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #74
2023-11-16 11:17:35 +01:00
c05f040313
Add labels to Docker images
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-11-07 14:36:41 +01:00
68bf505cd0
Merge install, lint and test steps
All checks were successful
continuous-integration/drone/pr Build is passing
2023-11-06 23:30:54 +01:00
2ac03d0c26
Merge install, lint and test steps
All checks were successful
continuous-integration/drone/pr Build is passing
Probably necessary because of the virtualenv
2023-11-06 23:20:44 +01:00
6b46ea5516
Rewrite Drone config
Some checks failed
continuous-integration/drone/pr Build is failing
- Split PR and push to main actions
- Deploy latest main to dev system
- Build image for Git tags
2023-11-06 23:15:58 +01:00
4798263c27 Merge pull request 'qa/seed-refactor' (!73) from qa/seed-refactor into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #73
2023-10-27 15:21:24 +02:00
jaschop
274f984994
minor cleanups
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
removed clutter from models.py
(skill_ids only used for seeding)
changed default value of update_profile handler
(caused a crash during testing)
2023-10-20 16:59:47 +02:00
jaschop
37f57eadea
Refactored seed --dev script
expanded seed_user to handle all user seeding
reordered user seeding, which broke some tests
made tests resistant to seeding order
2023-10-20 12:24:16 +02:00
d7f4acf251 Fix test name (kompetenzinventar/ki-doku#48)
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-10-14 21:01:02 +02:00
c65ef4a95c Add a test to test search (kompetenzinventar/ki-doku#48) 2023-10-14 21:01:02 +02:00
f3840f18b7 Consider real name when searching (kompetenzinventar/ki-doku#48) 2023-10-14 21:01:02 +02:00
da46d01765 Merge pull request 'Update backend base and builder images' (!71) from update-builder into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #71
2023-10-11 17:51:46 +02:00
0f9f807256
Update backend base and builder images
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-10-11 17:40:30 +02:00
66294cd52f Merge pull request 'tune threads to avoid queued tasks in normal situations' (!69) from fix/mehr-waitress-threads into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #69
2023-09-10 15:53:26 +02:00
jaschop
d4a5c8f5eb
Merge branch 'main' into fix/mehr-waitress-threads
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-09-10 15:48:45 +02:00
jaschop
5e4d6d464d
bumped pyyaml version to prevent a ci fail
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-08-24 16:24:34 +02:00
jaschop
6e77647eb9
tune threads to avoid queued tasks in normal situations
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
2023-08-24 14:25:22 +02:00
f7278bf7ea Merge pull request 'Trigger aufteilen' (!67) from feature/tag-trigger into main
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/tag Build is passing
Reviewed-on: #67
2022-02-28 19:29:19 +01:00
cf1a5a532c
split trigger
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/pr Build was killed
2022-02-28 19:28:35 +01:00
0fd04d4797 Merge pull request 'Tag Trigger' (!66) from feature/tag-trigger into main
Some checks reported errors
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build was killed
Reviewed-on: #66
2022-02-28 19:23:06 +01:00
a5bd954bb5
add tag trigger
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-28 19:19:53 +01:00
881c3d3038 Merge pull request 'Code Style reparieren' (!65) from fix/code-style into main
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Reviewed-on: #65
2022-02-28 18:53:14 +01:00
24 changed files with 870 additions and 585 deletions

13
.dockerignore Normal file
View File

@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
*
!Pipfile
!Pipfile.lock
!data/
!ki/
!LICENSES/
!migrations/
!app.py
!run_prod.py

View File

@ -4,31 +4,125 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
kind: pipeline
type: docker
name: default
name: qa
trigger:
event:
- push
- pull_request
branch:
- main
steps:
- name: qa
image: registry.wtf-eg.net/ki-backend-builder:1.0.0
- name: install-lint-test
image: python:3.8.20-alpine@sha256:3d93b1f77efce339aa77db726656872517b0d67837989aa7c4b35bd5ae7e81ba
env:
PYROOT: '/pyroot'
PYTHONUSERBASE: '/pyroot'
commands:
- apk add --no-cache gcc g++ musl-dev python3-dev
- pip3 install pipenv
- pipenv verify
- pipenv install --dev
- pipenv run flake8
- pipenv run reuse lint
- pipenv run python -m unittest discover ki
- name: docker-publish
image: plugins/docker
- name: docker-dry-run
image: plugins/docker:20.18.4@sha256:a8d3d86853c721492213264815f1d00d3ed13f42f5c1855a02f47fa4d5f1e042
settings:
registry: registry.wtf-eg.net
repo: registry.wtf-eg.net/ki-backend
registry: git.wtf-eg.de
repo: git.wtf-eg.de/kompetenzinventar/backend
target: ki-backend
dry_run: true
when:
event:
- pull_request
---
kind: pipeline
type: docker
name: build
trigger:
event:
- push
branch:
- main
depends_on:
- qa
steps:
- name: docker-publish
image: plugins/docker:20.18.4@sha256:a8d3d86853c721492213264815f1d00d3ed13f42f5c1855a02f47fa4d5f1e042
settings:
registry: git.wtf-eg.de
repo: git.wtf-eg.de/kompetenzinventar/backend
target: ki-backend
auto_tag: true
username:
from_secret: "docker_username"
password:
from_secret: "docker_password"
when:
---
kind: pipeline
type: docker
name: deploy
trigger:
event:
- push
branch:
- main
image_pull_secrets:
- dockerconfig
depends_on:
- build
steps:
- name: deploy-dev
image: appleboy/drone-ssh:1.7.5@sha256:995677e073454912f26d4c0fdd2f9df2e1f5a30d6603d3f2ece667311b6babb3
settings:
host:
- dev01.wtf-eg.net
username: drone_deployment
key:
from_secret: "dev01_deployment_key"
command_timeout: 2m
script:
- echo "Executing forced command..."
---
kind: pipeline
type: docker
name: tag-release
trigger:
event:
- tag
steps:
- name: install-lint-test
image: python:3.8.20-alpine@sha256:3d93b1f77efce339aa77db726656872517b0d67837989aa7c4b35bd5ae7e81ba
env:
PYROOT: '/pyroot'
PYTHONUSERBASE: '/pyroot'
commands:
- apk add --no-cache gcc g++ musl-dev python3-dev
- pip3 install pipenv
- pipenv install --dev
- pipenv run flake8
- pipenv run reuse lint
- pipenv run python -m unittest discover ki
- name: docker-publish
image: plugins/docker:20.18.4@sha256:a8d3d86853c721492213264815f1d00d3ed13f42f5c1855a02f47fa4d5f1e042
settings:
registry: git.wtf-eg.de
repo: git.wtf-eg.de/kompetenzinventar/backend
target: ki-backend
auto_tag: true
username:
from_secret: "docker_username"
password:
from_secret: "docker_password"

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.8.20

View File

@ -1,12 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Kompetenzinventar
Upstream-Contact: Michael Weimann <mail@michael-weimann.eu>
Source: https://git.wtf-eg.de/kompetenzinventar/ki-backend
Files: data/imgs/flags/*
Copyright: 2013 Panayiotis Lipiridis <https://flagicons.lipis.dev/>
License: MIT
Files: Pipfile.lock migrations/*
Copyright: WTF Kooperative eG <https://wtf-eg.de/>
License: AGPL-3.0-or-later

5
.yapfignore Normal file
View File

@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
migrations/*.py

View File

@ -2,7 +2,17 @@
#
# SPDX-License-Identifier: AGPL-3.0-or-later
FROM registry.wtf-eg.net/ki-backend-builder:1.0.0 as builder
FROM python:3.8.20-alpine@sha256:3d93b1f77efce339aa77db726656872517b0d67837989aa7c4b35bd5ae7e81ba AS builder
ENV PYROOT=/pyroot
ENV PYTHONUSERBASE=$PYROOT
RUN apk add --no-cache \
gcc \
g++ \
musl-dev \
python3-dev && \
pip3 install pipenv
COPY Pipfile* ./
@ -10,7 +20,10 @@ RUN PIP_USER=1 PIP_IGNORE_INSTALLED=1 pipenv install --system --deploy --ignore-
RUN pip3 uninstall --yes pipenv
FROM registry.wtf-eg.net/ki-backend-base:1.0.0 as ki-backend
FROM python:3.8.20-alpine@sha256:3d93b1f77efce339aa77db726656872517b0d67837989aa7c4b35bd5ae7e81ba AS ki-backend
ENV PYROOT=/pyroot
ENV PYTHONUSERBASE=$PYROOT
# Install six explicitly. Otherwise Python complains about it missing.
RUN pip3 install six
@ -22,4 +35,9 @@ WORKDIR /app
COPY . .
LABEL org.opencontainers.image.source=https://git.wtf-eg.de/kompetenzinventar/ki-backend.git
LABEL org.opencontainers.image.url=https://git.wtf-eg.de/kompetenzinventar/ki-backend
LABEL org.opencontainers.image.documentation=https://git.wtf-eg.de/kompetenzinventar/ki-backend#docker
LABEL org.opencontainers.image.vendor="WTF Kooperative eG"
CMD ["python3", "run_prod.py"]

29
Pipfile
View File

@ -8,22 +8,23 @@ verify_ssl = true
name = "pypi"
[packages]
flask = "~=2.0.1"
python-dotenv = "~=0.17.1"
flask-migrate = "~=3.0.1"
flask-sqlalchemy = "~=2.5.1"
sqlalchemy = "~=1.4.18"
waitress = "~=2.0.0"
pyyaml = "~=5.4.1"
flask-cors = "~=3.0.10"
ldap3 = "~=2.9"
pymysql = "~=1.0.2"
flask = "==2.3.3"
python-dotenv = "==1.0.1"
flask-migrate = "==4.0.7"
flask-sqlalchemy = "==2.5.1"
sqlalchemy = "==1.4.54"
waitress = "==2.1.2"
pyyaml = "==6.0.2"
flask-cors = "==5.0.0"
ldap3 = "==2.9.1"
pymysql = "==1.1.1"
werkzeug = "==2.3.8"
[dev-packages]
flake8 = "~=3.9.2"
yapf = "~=0.31.0"
pre-commit = "~=2.13.0"
reuse = "~=0.13.0"
flake8 = "==7.1.1"
yapf = "==0.40.2"
pre-commit = "==2.21.0"
reuse = "==4.0.3"
[requires]
python_version = "3.8"

959
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -222,25 +222,6 @@ docker-compose up
Dann http://localhost:13337 aufrufen.
### Workaround, falls der Zugriff auf registry.wtf-eg.net nicht möglich ist
Voraussetzung:
[ki-backend-docker](https://git.wtf-eg.de/kompetenzinventar/ki-backend-docker) muss parallel zum `ki-backend` ausgecheckt sein.
```
cd ki-backend-docker
docker build . --target base -t ki-backend-base
docker build . --target builder -t ki-backend-builder
```
Ändern der 2 Einträge im `Dockerfile` des `ki-backend`:
- registry.wtf-eg.net/ki-backend-builder:1.0.0 -> ki-backend-builder
- registry.wtf-eg.net/ki-backend-base:1.0.0 -> ki-backend-base
Danach sollte `docker-compose up` funktionieren.
## Lizenzen
Dieses Projekt erfüllt die [REUSE](https://reuse.software/) Spezifikation.

24
REUSE.toml Normal file
View File

@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: NONE
# SPDX-License-Identifier: CC0-1.0
version = 1
SPDX-PackageName = "Kompetenzinventar Backend"
SPDX-PackageDownloadLocation = "https://git.wtf-eg.de/kompetenzinventar/ki-backend"
[[annotations]]
path = "data/imgs/flags/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2013 Panayiotis Lipiridis <https://flagicons.lipis.dev/>"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = ["Pipfile.lock", "migrations/**"]
precedence = "aggregate"
SPDX-FileCopyrightText = "WTF Kooperative eG <https://wtf-eg.de/>"
SPDX-License-Identifier = "AGPL-3.0-or-later"
[[annotations]]
path = ["renovate.json", ".python-version"]
precedence = "aggregate"
SPDX-FileCopyrightText = "WTF Kooperative eG <https://wtf-eg.de/>"
SPDX-License-Identifier = "AGPL-3.0-or-later"

5
data/imgs/flags/ca.svg Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="810" height="540">
<rect width="810" height="540" fill="#FCDD09"/>
<path stroke="#DA121A" stroke-width="60" d="M0,90H810m0,120H0m0,120H810m0,120H0"/>
</svg>

After

Width:  |  Height:  |  Size: 242 B

View File

@ -25,22 +25,30 @@ def seed_contacttypes():
db.session.add(ContactType(id=int(contacttype["id"]), name=contacttype["name"]))
def seed_user(nickname,
visible=False,
skills=[],
languages=[],
def seed_user(auth_id,
nickname=None,
pronouns="",
visible=True,
volunteerwork="",
availability_status=False,
freetext="",
availability_text="",
availability_hours_per_week=42):
availability_hours_per_week=42,
skills=[],
searchtopics=[],
languages=[],
address=None,
contacts=[]):
if not nickname:
nickname = auth_id
app.logger.info(f"seeding {nickname} \\o/")
user = User(auth_id=nickname)
user = User(auth_id=auth_id)
db.session.add(user)
profile = Profile(nickname=nickname,
pronouns="",
pronouns=pronouns,
volunteerwork=volunteerwork,
availability_status=availability_status,
availability_text=availability_text,
@ -53,10 +61,29 @@ def seed_user(nickname,
skill = ProfileSkill(profile=profile, skill_id=skill_data[0], level=skill_data[1])
db.session.add(skill)
for skill_id in searchtopics:
searchtopic = ProfileSearchtopic(profile=profile, skill_id=skill_id)
db.session.add(searchtopic)
for language_data in languages:
language = ProfileLanguage(profile=profile, language_id=language_data[0], level=language_data[1])
db.session.add(language)
if address:
_address = Address(name=address[0],
street=address[1],
house_number=address[2],
additional=address[3],
postcode=address[4],
city=address[5],
country=address[6],
profile=profile)
db.session.add(_address)
for contact_data in contacts:
contact = Contact(profile=profile, contacttype_id=contact_data[0], content=contact_data[1])
db.session.add(contact)
db.session.add(profile)
@ -92,77 +119,40 @@ def seed(dev: bool):
db.session.add(Language(id=iso["639-1"], name=iso["Sprache"]))
if dev:
app.logger.info("seeding peter :)")
seed_user("klaus", visible=False)
peter = User(auth_id="peter")
db.session.add(peter)
for i in range(1, 20):
seed_user(f"babsi{i}")
peters_profile = Profile(nickname="peternichtlustig",
seed_user("peter",
nickname="peternichtlustig",
visible=False,
pronouns="Herr Dr. Dr.",
volunteerwork="Gartenverein",
availability_status=True,
availability_hours_per_week=42,
availability_text="Immer",
freetext="Ich mag Kaffee",
user=peter)
db.session.add(peters_profile)
matrix_contact = Contact(profile=peters_profile, contacttype_id=4, content="@peter:wtf-eg.de")
db.session.add(matrix_contact)
email_contact = Contact(profile=peters_profile, contacttype_id=1, content="peter@wtf-eg.de")
db.session.add(email_contact)
peters_address = Address(name="Peter Nichtlustig",
street="Waldweg",
house_number="23i",
additional="Hinterhaus",
postcode="13337",
city="Bielefeld",
country="Deutschland",
profile=peters_profile)
db.session.add(peters_address)
peters_python_skill = ProfileSkill(profile=peters_profile, skill_id=3, level=3)
db.session.add(peters_python_skill)
peters_php_skill = ProfileSkill(profile=peters_profile, skill_id=1, level=5)
db.session.add(peters_php_skill)
peters_python_searchtopic = ProfileSearchtopic(profile=peters_profile, skill_id=3)
db.session.add(peters_python_searchtopic)
peters_php_searchtopic = ProfileSearchtopic(profile=peters_profile, skill_id=1)
db.session.add(peters_php_searchtopic)
peter_de = ProfileLanguage(profile=peters_profile, language_id="de", level=5)
db.session.add(peter_de)
peter_fr = ProfileLanguage(profile=peters_profile, language_id="fr", level=3)
db.session.add(peter_fr)
seed_user("klaus")
for i in range(1, 20):
seed_user(f"babsi{i}", visible=True)
skills=[(3, 3), (1, 5)],
searchtopics=[3, 1],
languages=[("de", 5), ("fr", 3)],
address=("Peter Nichtlustig", "Waldweg", "23i", "Hinterhaus", "13337", "Bielefeld", "Deutschland"),
contacts=[(4, "@peter:wtf-eg.de"), (1, "peter@wtf-eg.de")])
seed_user("dirtydieter",
visible=True,
volunteerwork="Müll sammeln",
availability_status=True,
availability_hours_per_week=24,
availability_text="Nur Nachts!",
freetext="1001010010111!!!",
skills=[(Skill.skill_id_php, 5)])
skills=[(1, 5)],
address=("Friedrich Witzig", "", "", "", "", "", ""))
all_skills = Skill.query.all()
all_profile_skills = []
for skill in all_skills:
all_profile_skills.append((skill.id, 3))
all_skills = [(skill.id, 3) for skill in Skill.query.all()]
seed_user("jutta", languages=[("fr", 5)], skills=all_skills)
seed_user("jutta", visible=True, languages=[("fr", 5)], skills=all_profile_skills)
seed_user("giesela", visible=True, skills=[(Skill.skill_id_mysql, 3), (Skill.skill_id_postgresql, 5)])
seed_user("bertha", visible=False, skills=[(Skill.skill_id_sqlite, 3), (Skill.skill_id_postgresql, 5)])
seed_user("monique", visible=True, languages=[("fr", 4)])
seed_user("giesela", skills=[(9, 3), (10, 5)])
seed_user("bertha", visible=False, skills=[(11, 3), (10, 5)])
seed_user("monique", languages=[("fr", 4)])
db.session.commit()

View File

@ -4,7 +4,7 @@
from flask import make_response, request
from ki.models import Profile, ProfileSkill, Skill, ProfileLanguage, Language
from ki.models import Profile, ProfileSkill, Skill, ProfileLanguage, Language, Address
def find_profiles():
@ -25,13 +25,18 @@ def find_profiles():
.order_by(Profile.nickname) \
.filter(Profile.visible.is_(True)) \
.join(Profile.skills, isouter=True).join(ProfileSkill.skill, isouter=True) \
.join(Profile.languages, isouter=True).join(ProfileLanguage.language, isouter=True)
.join(Profile.languages, isouter=True).join(ProfileLanguage.language, isouter=True) \
.join(Address, isouter=True)
if "search" in request.args:
terms = request.args["search"].split(" ")
for term in terms:
query = query.filter(
Profile.nickname.like(f"%{term}%") | Skill.name.like(f"%{term}%") | Language.name.like(f"%{term}%"))
Profile.nickname.like(f"%{term}%") | # noqa: W504
Skill.name.like(f"%{term}%") | # noqa: W504
Language.name.like(f"%{term}%") | # noqa: W504
Address.name.like(f"%{term}%"))
if "nickname" in request.args:
nickname = request.args.get("nickname")

View File

@ -151,11 +151,11 @@ def update_profile(user_id: int):
profile.freetext = request.json.get("freetext", "")
profile.visible = request.json.get("visible", False)
update_address(profile, request.json.get("address", {}))
update_contacts(profile, request.json.get("contacts", {}))
update_skills(profile, request.json.get("skills", {}))
update_searchtopics(profile, request.json.get("searchtopics"))
update_languages(profile, request.json.get("languages", {}))
update_address(profile, request.json.get("address"))
update_contacts(profile, request.json.get("contacts", []))
update_skills(profile, request.json.get("skills", []))
update_searchtopics(profile, request.json.get("searchtopics", []))
update_languages(profile, request.json.get("languages", []))
db.session.commit()

View File

@ -139,13 +139,6 @@ class Address(db.Model):
class Skill(db.Model):
skill_id_php = 1
skill_id_python = 3
skill_id_sqlalchemy = 7
skill_id_mysql = 9
skill_id_postgresql = 10
skill_id_sqlite = 11
__tablename__ = "skill"
id = Column(Integer, primary_key=True)

View File

@ -17,6 +17,7 @@ content_type_png = "image/png"
def token_auth(func):
@wraps(func)
def _token_auth(*args, **kwargs):
auth_header = request.headers.get("Authorization")

View File

@ -8,6 +8,7 @@ from ki.test.ApiTest import ApiTest
class TestContactTypesEndpoint(ApiTest):
def test_skills_options(self):
response = self.client.options("/contacttypes")
self.assertEqual(response.status_code, 200)

View File

@ -8,6 +8,7 @@ from ki.test.ApiTest import ApiTest
class TestFindProfilesEndpoint(ApiTest):
def test_find_profiles_options(self):
response = self.client.options("/users/profiles")
self.assertEqual(response.status_code, 200)
@ -99,6 +100,14 @@ class TestFindProfilesEndpoint(ApiTest):
self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][0])
self.assertDictContainsSubset({"nickname": "monique"}, response.json["profiles"][1])
def test_find_dieter_by_name(self):
token = self.login("peter", "geheim")["token"]
response = self.client.get("/users/profiles?search=friedrich", headers={"Authorization": "Bearer " + token})
self.assertEqual(response.status_code, 200)
self.assertDictContainsSubset({"total": 1}, response.json)
self.assertDictContainsSubset({"nickname": "dirtydieter"}, response.json["profiles"][0])
if __name__ == "main":
unittest.main()

View File

@ -8,6 +8,7 @@ from ki.test.ApiTest import ApiTest
class TestLanguagesEndpoint(ApiTest):
def test_skills_options(self):
response = self.client.options("/languages")
self.assertEqual(response.status_code, 200)

View File

@ -10,6 +10,7 @@ from ki.test.ApiTest import ApiTest
class TestLoginEndpoint(ApiTest):
def test_login(self):
response1_data = self.login("peter", "geheim")
response2_data = self.login("peter", "geheim")

View File

@ -20,7 +20,8 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual(login_response.status_code, 200)
self.assertIn("token", login_response.json)
response = self.client.post("/users/1/profile",
babsi = User.query.filter(User.auth_id == "babsi1").first()
response = self.client.post(f"/users/{babsi.id}/profile",
data=json.dumps({}),
content_type="application/json",
headers={"Authorization": "Bearer " + login_response.json["token"]})
@ -102,14 +103,15 @@ class TestProfileEndpoint(ApiTest):
"level": 2
}]
}
response = self.client.post("/users/1/profile",
peter = User.query.filter(User.auth_id == "peter").first()
response = self.client.post(f"/users/{peter.id}/profile",
data=json.dumps(data),
content_type="application/json",
headers={"Authorization": "Bearer " + token})
self.assertEqual(response.status_code, 200)
with app.app_context():
user = User.query.filter(User.id == 1).first()
user = User.query.filter(User.id == peter.id).first()
profile = user.profile
self.assertEqual("Hebbert", profile.nickname)
self.assertEqual("Monsieur", profile.pronouns)
@ -183,7 +185,8 @@ class TestProfileEndpoint(ApiTest):
def test_get_visible_proifle(self):
token = self.login("peter", "geheim")["token"]
response = self.client.get("/users/3/profile", headers={"Authorization": f"Bearer {token}"})
babsi = User.query.filter(User.auth_id == "babsi1").first()
response = self.client.get(f"/users/{babsi.id}/profile", headers={"Authorization": f"Bearer {token}"})
self.assertEqual(response.status_code, 200)
@ -194,14 +197,15 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual(login_response.status_code, 200)
self.assertIn("token", login_response.json)
response = self.client.get("/users/1/profile",
peter = User.query.filter(User.auth_id == "peter").first()
response = self.client.get(f"/users/{peter.id}/profile",
headers={"Authorization": "Bearer " + login_response.json["token"]})
profile_id = peter.profile.id
self.assertEqual(response.status_code, 200)
self.assertDictEqual(
response.json, {
"profile": {
"user_id": 1,
"user_id": peter.id,
"nickname": "peternichtlustig",
"pronouns": "Herr Dr. Dr.",
"availability_status": True,
@ -218,12 +222,12 @@ class TestProfileEndpoint(ApiTest):
"id": 1,
"name": "Peter Nichtlustig",
"postcode": "13337",
"profile_id": 1,
"profile_id": profile_id,
"street": "Waldweg"
},
"contacts": [{
"id": 1,
"profile_id": 1,
"profile_id": profile_id,
"contacttype": {
"id": 4,
"name": "Matrix"
@ -231,7 +235,7 @@ class TestProfileEndpoint(ApiTest):
"content": "@peter:wtf-eg.de"
}, {
"id": 2,
"profile_id": 1,
"profile_id": profile_id,
"contacttype": {
"id": 1,
"name": "E-Mail"
@ -239,7 +243,7 @@ class TestProfileEndpoint(ApiTest):
"content": "peter@wtf-eg.de"
}],
"skills": [{
"profile_id": 1,
"profile_id": profile_id,
"skill": {
"id": 1,
"name": "PHP",
@ -247,7 +251,7 @@ class TestProfileEndpoint(ApiTest):
},
"level": 5
}, {
"profile_id": 1,
"profile_id": profile_id,
"skill": {
"id": 3,
"name": "Python",
@ -256,14 +260,14 @@ class TestProfileEndpoint(ApiTest):
"level": 3
}],
"searchtopics": [{
"profile_id": 1,
"profile_id": profile_id,
"skill": {
"id": 1,
"name": "PHP",
"icon_url": "/skills/1/icon"
}
}, {
"profile_id": 1,
"profile_id": profile_id,
"skill": {
"id": 3,
"name": "Python",
@ -271,7 +275,7 @@ class TestProfileEndpoint(ApiTest):
}
}],
"languages": [{
"profile_id": 1,
"profile_id": profile_id,
"language": {
"id": "de",
"name": "Deutsch",
@ -279,7 +283,7 @@ class TestProfileEndpoint(ApiTest):
},
"level": 5
}, {
"profile_id": 1,
"profile_id": profile_id,
"language": {
"id": "fr",
"name": "Französisch",

View File

@ -8,6 +8,7 @@ from ki.test.ApiTest import ApiTest
class TestSkillsEndpoint(ApiTest):
def test_skills_options(self):
response = self.client.options("/skills")
self.assertEqual(response.status_code, 200)

18
renovate.json Normal file
View File

@ -0,0 +1,18 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:best-practices",
":disableDependencyDashboard",
":maintainLockFilesMonthly",
":pinVersions",
":separateMultipleMajorReleases"
],
"packageRules": [
{
"matchDepNames": ["python"],
"groupName": "Python",
"separateMinorPatch": true,
"separateMultipleMinor": true
}
]
}

View File

@ -11,4 +11,4 @@ with app.app_context():
config = migrate.get_config()
command.upgrade(config, "head")
serve(app, host="0.0.0.0", port=5000)
serve(app, host="0.0.0.0", port=5000, threads=20)