Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing GitHub CI #13

Merged
merged 14 commits into from
Jun 15, 2023
Merged
55 changes: 55 additions & 0 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
push:
pull_request:
branches: [ "master", "develop" ]

permissions:
contents: read

jobs:
test-runner:

runs-on: ubuntu-latest
services:
redis-stack:
image: redis/redis-stack-server
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r test-requirements.txt
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Lint with black
run: |
black --check --verbose -- .
- name: Test with pytest
run: |
pytest
env:
REDIS_URL: localhost
REDIS_PORT: 6379
FAIR_COMBINE_ENV: test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/redis_data/.testfile
/redis_data/dump.rdb
/app/test_main.http
/.coverage
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/ambv/black
rev: 22.3.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.0.0
hooks:
- id: flake8
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,14 @@ Endpoints are accessible at `http://localhost:8000`.

If you have redis-cli or RedisInsight installed, the redis endpoint can be accessed at `http://localhost:6379`

# Testing

First install test requirements.
```shell
pip install -r test-requirements.txt
```

Then, you can simply run all tests using pytest.
```shell
pytest
```
15 changes: 13 additions & 2 deletions app/dependencies/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
from pydantic import BaseSettings
from typing import List


class Config(BaseSettings):
app_name: str = "FAIR Combine API"
redis_db_number: int = 0
indicators_path = "app/metrics/metrics.csv"

allowed_origins: List[str] = []
# List of indicators that applied to archive (if no archive, their statuses will be set to 'failed')
archive_indicators: List[str] = [
Expand Down Expand Up @@ -81,7 +85,10 @@ class Config(BaseSettings):
# Mapping of indicators with their direct parent. Until parent status is 'success', children cannot be set.
# Not happy with this, as it means that the Config is dynamically set
assessment_dependencies: dict[str, dict] = {
"CA-RDA-I3-02Archive": {"condition": "or", "indicators": ["CA-RDA-I3-01Archive"]},
"CA-RDA-I3-02Archive": {
"condition": "or",
"indicators": ["CA-RDA-I3-01Archive"],
},
"CA-RDA-I3-02Model": {"condition": "or", "indicators": ["CA-RDA-I3-01Model"]},
"CA-RDA-I3-03MA": {"condition": "or", "indicators": ["CA-RDA-I3-01MA"]},
"CA-RDA-I3-03MM": {"condition": "or", "indicators": ["CA-RDA-I3-01MM"]},
Expand All @@ -101,8 +108,12 @@ class ProdConfig(Config):
pass


class TestConfig(Config):
redis_db_number = 15


@lru_cache()
def get_settings():
env = os.environ.get("FAIR_COMBINE_ENV", "dev")
config = {"dev": DevConfig, "prod": ProdConfig}.get(env)()
config = {"dev": DevConfig, "prod": ProdConfig, "test": TestConfig}.get(env)()
return config
16 changes: 9 additions & 7 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@
tags_metadata = [
{
"name": "Indicators",
"description": "FAIR Combine assessments. Endpoints to retrieve the descriptions of the assessments done by the application "
"to evaluate how FAIR a resource is/"
"description": "FAIR Combine assessments. Endpoints to retrieve the descriptions of the assessments done by "
"the application "
"to evaluate how FAIR a resource is/",
},
{
"name": "Tasks",
"description": "FAIR Combine tasks. Endpoints allow to retrieve the details of a specific assessment associated with a session, "
"to update an assessment status or to retrieve the documentation of FAIR Combine assessments."
"description": "FAIR Combine tasks. Endpoints allow to retrieve the details of a specific assessment "
"associated with a session, "
"to update an assessment status or to retrieve the documentation of FAIR Combine assessments.",
},
{
"name": "Sessions",
"description": "FAIR Combine assessment session. Endpoints to create a new session, to load a previously exported session, "
"or to display the details of an existing session."
"description": "FAIR Combine assessment session. Endpoints to create a new session, to load a previously "
"exported session, "
"or to display the details of an existing session.",
},

]

description = """
Expand Down
8 changes: 5 additions & 3 deletions app/metrics/assessments_lifespan.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from fastapi import FastAPI
from csv import DictReader

from app.dependencies.settings import get_settings
import app.models as models

fair_indicators = {}
Expand All @@ -18,7 +19,8 @@ async def get_tasks_definitions(app: FastAPI):
:param app: The FastAPI application that will use the content of `metrics.csv`
:return: None
"""
regex = re.compile("^CA\-RDA\-([FAIR][1-9](\.[0-9])?)\-")
regex = re.compile(r"^CA-RDA-([FAIR][1-9](\.[0-9])?)-")
config = get_settings()

def parse_line(line):
sub_group = regex.search(line["TaskName"]).groups()[0]
Expand All @@ -31,12 +33,12 @@ def parse_line(line):
priority=line["TaskPriority"].lower(),
question=line["TaskQuestion"],
short=line["TaskShortDescription"],
description=line["TaskDetails"]
description=line["TaskDetails"],
)
}

# Get the list of tasks and their definitions from internal file
with open("app/metrics/metrics.csv", "r") as file_handler:
with open(config.indicators_path, "r") as file_handler:
csv_reader = DictReader(file_handler, dialect="unix")
[fair_indicators.update(parse_line(line)) for line in csv_reader]

Expand Down
5 changes: 3 additions & 2 deletions app/metrics/base_example.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from fair_test import FairTest, FairTestEvaluation


class MetricTest(FairTest):
metric_path = "fair-test-example"
metric_version = "0.1.0"
Expand All @@ -14,7 +15,7 @@ def execute_metric(self, object):

def evaluate(self, eval: FairTestEvaluation):
eval.info(
f"Running FairCombine example. This test will pass",
"Running FairCombine example. This test will pass",
)

# Retrieving subject of the evaluation (a model or an archive)
Expand All @@ -31,4 +32,4 @@ class ManualMetricTest(FairTest):


class AutomaticMetricTest(FairTest):
pass
pass
10 changes: 8 additions & 2 deletions app/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
from .session import Session, SessionStatus, SessionHandler, SessionSubjectIn, SubjectType
from .session import (
Session,
SessionStatus,
SessionHandler,
SessionSubjectIn,
SubjectType,
)
from .tasks import Task, TaskStatus, Indicator, TaskPriority, IndicatorDependency

__all__ = [
Expand All @@ -12,4 +18,4 @@
SessionSubjectIn,
SubjectType,
IndicatorDependency,
]
]
Loading