Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/post-avail…
Browse files Browse the repository at this point in the history
…ability

# Conflicts:
#	app/app.py
  • Loading branch information
Azakh993 committed Feb 15, 2024
2 parents 77da2ab + 648b539 commit 8f7e9a5
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 102 deletions.
90 changes: 73 additions & 17 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,25 @@ name: CI/CD Pipeline
on:
push:
branches:
- '*'
- '**'
pull_request:
branches:
- '*'
- '**'

jobs:
build-and-test:
linting:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.9'

- name: Cache dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/.cache/pip
Expand All @@ -41,26 +40,83 @@ jobs:
run: |
flake8 app --output-file=flake8report.txt
- name: Upload linting report
uses: actions/upload-artifact@v4
with:
name: linting-report
path: flake8report.txt

static_analysis:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'

- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/pip
.mypy_cache
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt', '**/requirements-dev.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: pip install -r requirements.txt

- name: Install development dependencies
run: pip install -r requirements-dev.txt

- name: Run static analysis and generate report
run: |
mypy app --html-report mypy_report
- name: Run pytest with coverage
run: |
pytest --cov=app --cov-report=xml:coverage.xml
- name: Upload static analysis report
uses: actions/upload-artifact@v4
with:
name: static-analysis-report
path: mypy_report

tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Upload linting, static analysis, and security reports
uses: actions/upload-artifact@v3
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'

- name: Cache dependencies
uses: actions/cache@v4
with:
name: code-quality-reports
path: |
flake8report.txt
mypy_report/*
~/.cache/pip
.mypy_cache
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt', '**/requirements-dev.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: pip install -r requirements.txt

- name: Install development dependencies
run: pip install -r requirements-dev.txt

- name: Run pytest with coverage
run: |
pytest --cov=app --cov-report=xml:coverage.xml
- name: Upload test results and coverage report
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-and-coverage-results
path: |
report.xml
coverage.xml
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: gunicorn app.app:create_app() --bind 0.0.0.0:$PORT
web: gunicorn app.app:application --log-file -
25 changes: 15 additions & 10 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os

from flask import Flask
from flask_cors import CORS

from app import jwt_handlers
from app.extensions import database, jwt
Expand All @@ -21,6 +22,8 @@ def create_app() -> Flask:
application_form_api = Flask(__name__)
application_form_api.config.from_pyfile('config.py')

CORS(application_form_api)

setup_logging(application_form_api)
setup_extensions(application_form_api)
register_blueprints(application_form_api)
Expand All @@ -37,15 +40,15 @@ def setup_logging(application_form_api: Flask) -> None:

log_dir = application_form_api.config.get('LOG_DIR', 'logs')
os.makedirs(
log_dir, exist_ok=True)
log_dir, exist_ok=True)

logging.basicConfig(
level=application_form_api.config.get('LOG_LEVEL', logging.INFO),
format=application_form_api.config.get(
'LOG_FORMAT',
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'),
filename=application_form_api.config.get(
'LOG_FILE', os.path.join(log_dir, 'app.log'))
level=application_form_api.config.get('LOG_LEVEL', logging.INFO),
format=application_form_api.config.get(
'LOG_FORMAT',
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'),
filename=application_form_api.config.get(
'LOG_FILE', os.path.join(log_dir, 'app.log'))
)


Expand All @@ -69,18 +72,20 @@ def register_blueprints(application_form_api: Flask) -> None:
"""

application_form_api.register_blueprint(
personal_info_bp,
url_prefix='/api/application-form/applicant/personal-info')
personal_info_bp,
url_prefix='/api/application-form/applicant/personal-info')
application_form_api.register_blueprint(
applicant_competences_bp,
url_prefix='/api/application-form/applicant/competences')
application_form_api.register_blueprint(
applicant_availabilities_bp,
url_prefix='/api/application-form/applicant/availabilities')
application_form_api.register_blueprint(
competences_bp, url_prefix='/api/application-form/competences')
competences_bp, url_prefix='/api/application-form/competences')


if __name__ == "__main__":
app = create_app()
app.run(debug=True)

application = create_app()
11 changes: 9 additions & 2 deletions app/config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import os

JWT_SECRET_KEY = os.environ.get('JWT_SECRET')
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///app.db')
JWT_IDENTITY_CLAIM = 'id'

LOG_LEVEL = 'INFO'
database_url = os.environ.get('DATABASE_URL', 'sqlite:///app.db')
if database_url.startswith('postgres://'):
database_url = database_url.replace(
'postgres://', 'postgresql://', 1)

SQLALCHEMY_DATABASE_URI = database_url

LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')
LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
LOG_DIR = os.environ.get('LOG_DIR', 'logs')
LOG_FILENAME = os.environ.get('LOG_FILENAME', 'app.log')
Expand Down
4 changes: 2 additions & 2 deletions app/routes/applicant/competences_route.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from flask import Blueprint, Response, jsonify, request
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_jwt_extended import jwt_required, get_jwt

from app.services.applicant.competences_service import \
store_applicant_competences
Expand All @@ -25,7 +25,7 @@ def add_applicant_competences() -> tuple[Response, int]:
return jsonify({'error': 'INVALID_JSON_PAYLOAD'}), 400

competences = request.json
current_user = get_jwt_identity().get('id')
current_user = get_jwt()['id']

result = store_applicant_competences(current_user, competences)

Expand Down
6 changes: 3 additions & 3 deletions app/routes/applicant/personal_info_route.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from flask import Blueprint, Response, current_app, jsonify
from flask_jwt_extended import get_jwt_identity, jwt_required
from flask_jwt_extended import jwt_required, get_jwt
from sqlalchemy.exc import NoResultFound, SQLAlchemyError

from app.services.applicant.personal_info_service import fetch_personal_info
Expand All @@ -16,12 +16,12 @@ def get_personal_info() -> tuple[Response, int]:
:return: A tuple containing the response and the status code.
"""

current_user = get_jwt_identity().get('id')
current_user = get_jwt()['id']

try:
personal_info = fetch_personal_info(current_user)
current_app.logger.info(
f'Responded with personal info for {current_user}.')
f'Responded with personal info for id: {current_user}.')
return jsonify(personal_info), 200
except NoResultFound:
return jsonify({
Expand Down
9 changes: 9 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
blinker==1.7.0
click==8.1.7
exceptiongroup==1.2.0
flake8==7.0.0
Flask==3.0.1
Flask-Cors==4.0.0
Flask-JWT-Extended==4.6.0
Flask-SQLAlchemy==3.1.1
Flask-Testing==0.8.1
Expand All @@ -10,12 +12,19 @@ install==1.3.5
itsdangerous==2.1.2
Jinja2==3.1.3
MarkupSafe==2.1.4
mccabe==0.7.0
mypy==1.8.0
mypy-extensions==1.0.0
packaging==23.2
pluggy==1.4.0
psycopg2==2.9.9
pycodestyle==2.11.1
pyflakes==3.2.0
PyJWT==2.8.0
pytest==8.0.0
SQLAlchemy==2.0.25
tomli==2.0.1
typing_extensions==4.9.0
Werkzeug==3.0.1
gunicorn==21.2.0
types-Flask-Cors==4.0.0.20240106
6 changes: 3 additions & 3 deletions tests/repositories/applicant/test_competences_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from app.repositories.applicant.competences_repository import \
insert_competences_in_db
from tests.utilities.test_utilities import remove_competences_from_db, \
remove_test_user_from_db, setup_competences_in_db
remove_test_user_1_from_db, setup_competences_in_db


def test_insert_competences_in_db_success(app_with_client):
Expand All @@ -19,11 +19,11 @@ def test_insert_competences_in_db_success(app_with_client):
with app.app_context():
insert_competences_in_db(competence_profile)
inserted_profile = CompetenceProfile.query.filter_by(
person_id=1).first()
person_id=1).first()
assert inserted_profile is not None
assert inserted_profile.years_of_experience == 5

remove_test_user_from_db(app)
remove_test_user_1_from_db(app)
remove_competences_from_db(app)


Expand Down
10 changes: 5 additions & 5 deletions tests/repositories/applicant/test_personal_info_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@

from app.repositories.applicant.personal_info_repository import \
get_person_from_db
from tests.utilities.test_utilities import remove_test_user_from_db, \
setup_test_user_in_db
from tests.utilities.test_utilities import remove_test_user_1_from_db, \
setup_test_user_1_in_db


def test_get_person_from_db_success(app_with_client):
app, _ = app_with_client
setup_test_user_in_db(app)
setup_test_user_1_in_db(app)
with app.app_context():
person = get_person_from_db(1)
assert person.name == 'test'
assert person.surname == 'tester'

remove_test_user_from_db(app)
remove_test_user_1_from_db(app)


def test_get_person_from_db_no_result(app_with_client):
Expand All @@ -34,7 +34,7 @@ def test_get_person_from_db_sqlalchemy_error(app_with_client):
with patch('app.models.applicant.person.Person.query') as mock_query:
mock_filter_by = mock_query.filter_by.return_value
mock_filter_by.one.side_effect = SQLAlchemyError(
"A database error occurred")
"A database error occurred")
with pytest.raises(SQLAlchemyError) as exception_info:
get_person_from_db(1)

Expand Down
Loading

0 comments on commit 8f7e9a5

Please sign in to comment.