diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f0520083c..32fd81183 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,26 +2,29 @@ name: Flask CI on: push: - branches: [ main ] + branches: [ main, develop ] pull_request: - branches: [ main ] + branches: [ main, develop ] jobs: build: - runs-on: ubuntu-latest services: - mysql: - image: mysql:5.7 + mariadb: + image: mariadb:latest env: - MYSQL_ROOT_PASSWORD: fmlibrootpass - MYSQL_DATABASE: fmlibdb - MYSQL_USER: fmlibuser - MYSQL_PASSWORD: fmlibpass + MARIADB_DATABASE: uvlhubdb_test + MARIADB_USER: uvlhub + MARIADB_PASSWORD: uvlhub_password + MARIADB_ROOT_PASSWORD: uvlhub_root_password ports: - 3306:3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + options: >- + --health-cmd="mysqladmin ping -h localhost -u root --password=vRwgXWu0ns" + --health-interval=10s + --health-timeout=5s + --health-retries=5 steps: - uses: actions/checkout@v2 @@ -37,10 +40,12 @@ jobs: pip install -r requirements.txt - name: Run Tests + env: + FLASK_ENV: testing + MARIADB_HOSTNAME: 127.0.0.1 + MARIADB_PORT: 3306 + MARIADB_DATABASE: uvlhubdb_test + MARIADB_USER: uvlhub_user + MARIADB_PASSWORD: uvlhub_password run: | - export MYSQL_HOSTNAME=127.0.0.1 - export MYSQL_PORT=3306 - export MYSQL_DATABASE=fmlibdb - export MYSQL_USER=fmlibuser - export MYSQL_PASSWORD=fmlibpass - pytest app/blueprints/ + rosemary test diff --git a/Dockerfile.prod b/Dockerfile.prod index 5bd264051..caffdad3e 100644 --- a/Dockerfile.prod +++ b/Dockerfile.prod @@ -1,8 +1,9 @@ -# Use an official Python runtime as a parent image +# Use an official Python runtime as a parent image, Alpine version for a lighter footprint FROM python:3.11-alpine -# Install the MySQL client to be able to use it in the standby script. -RUN apk add --no-cache mysql-client +# Install MySQL client and temporary build dependencies +RUN apk add --no-cache mysql-client \ + && apk add --no-cache --virtual .build-deps gcc musl-dev python3-dev libffi-dev openssl-dev # Set the working directory in the container to /app WORKDIR /app @@ -10,17 +11,16 @@ WORKDIR /app # Copy the contents of the local app/ directory to the /app directory in the container COPY app/ ./app -# Copy requirements.txt at the /app working directory +# Copy requirements.txt into the working directory /app COPY requirements.txt . # Copy the wait-for-db.sh script and set execution permissions COPY --chmod=+x scripts/wait-for-db.sh ./scripts/ -# Install any needed packages specified in requirements.txt -RUN pip install --no-cache-dir -r requirements.txt - -# Update pip -RUN pip install --no-cache-dir --upgrade pip +# Install any needed packages specified in requirements.txt and upgrade pip +RUN pip install --no-cache-dir -r requirements.txt \ + && pip install --no-cache-dir --upgrade pip \ + && apk del .build-deps # Copy the migration scripts to the /app directory in the container COPY migrations/ ./migrations @@ -28,5 +28,8 @@ COPY migrations/ ./migrations # Expose port 5000 EXPOSE 5000 +# Set environment variables for production +ENV FLASK_ENV=production + # Run the database migrations and then start the application with Gunicorn -CMD sh ./scripts/wait-for-db.sh && flask db upgrade && gunicorn --bind 0.0.0.0:5000 app:app --log-level debug --timeout 3600 +CMD sh ./scripts/wait-for-db.sh && flask db upgrade && gunicorn --bind 0.0.0.0:5000 app:app --log-level info --timeout 3600 diff --git a/README.md b/README.md index f39987be5..e280cff17 100644 --- a/README.md +++ b/README.md @@ -56,14 +56,6 @@ flask db migrate flask db upgrade ``` -### Tests - -To run unit test, please enter inside `web` container: - -``` -pytest app/tests/units.py -``` - ## Using Rosemary CLI `Rosemary` is a CLI tool developed to facilitate project management and development tasks. @@ -116,13 +108,25 @@ This command creates a new directory under `app/blueprints/` with the name of yo This feature is designed to streamline the development process, making it easy to add new features to the project. +### Testing All Modules -### Available Commands +To run tests across all modules in the project, you can use the following command: -- `rosemary update`: Updates all project dependencies and the `requirements.txt` file. -- `rosemary info`: Displays information about the Rosemary CLI, including version and author. -- `rosemary make:module <module_name>`: Generates a new module with the specified name. -- `rosemary env`: Displays the current environment variables from the `.env` file. +``` +rosemary test +``` + +This command will execute all tests found within the app/blueprints directory, covering all the modules of the project. + +### Testing a Specific Module + +If you're focusing on a particular module and want to run tests only for that module, you can specify the module +name as an argument to the rosemary test command. For example, to run tests only for the zenodo module, you would +use: + +``` +rosemary test zenodo +``` ## Deploy in production (Docker Compose) diff --git a/app/__init__.py b/app/__init__.py index 6dd06d712..e7fd9aab6 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -56,6 +56,10 @@ class ProductionConfig(Config): def create_app(config_name='development'): app = Flask(__name__) + # If config_name is not provided, use the environment variable FLASK_ENV + if config_name is None: + config_name = os.getenv('FLASK_ENV', 'development') + # Load configuration if config_name == 'testing': app.config.from_object(TestingConfig) diff --git a/app/blueprints/auth/routes.py b/app/blueprints/auth/routes.py index 26ddc57b0..b8bfae92f 100644 --- a/app/blueprints/auth/routes.py +++ b/app/blueprints/auth/routes.py @@ -1,4 +1,4 @@ -from flask import (render_template, redirect, url_for, flash, request) +from flask import (render_template, redirect, url_for, request) from flask_login import current_user, login_user, logout_user from app.blueprints.auth import auth_bp diff --git a/rosemary/cli.py b/rosemary/cli.py index a0c28fe3e..13cecfd24 100644 --- a/rosemary/cli.py +++ b/rosemary/cli.py @@ -1,14 +1,24 @@ -# rosemary/cli.py - import click from rosemary.commands.update import update from rosemary.commands.info import info from rosemary.commands.make_module import make_module from rosemary.commands.env import env +from rosemary.commands.test import test + + +class RosemaryCLI(click.Group): + def get_command(self, ctx, cmd_name): + rv = super().get_command(ctx, cmd_name) + if rv is not None: + return rv + click.echo(f"No such command '{cmd_name}'.") + click.echo("Try 'rosemary --help' for a list of available commands.") + return None -@click.group() +@click.group(cls=RosemaryCLI) def cli(): + """A CLI tool to help with project management.""" pass @@ -16,6 +26,7 @@ def cli(): cli.add_command(info) cli.add_command(make_module) cli.add_command(env) +cli.add_command(test) if __name__ == '__main__': cli() diff --git a/rosemary/commands/test.py b/rosemary/commands/test.py new file mode 100644 index 000000000..465f392c6 --- /dev/null +++ b/rosemary/commands/test.py @@ -0,0 +1,24 @@ +import click +import subprocess +import os + + +@click.command('test', help="Runs pytest on the blueprints directory or a specific module.") +@click.argument('module_name', required=False) +def test(module_name): + base_path = 'app/blueprints' + test_path = base_path + + if module_name: + test_path = os.path.join(base_path, module_name) + if not os.path.exists(test_path): + click.echo(f"Module '{module_name}' does not exist.") + return + click.echo(f"Running tests for the '{module_name}' module...") + else: + click.echo("Running tests for all modules...") + + try: + subprocess.run(['pytest', '-v', test_path], check=True) + except subprocess.CalledProcessError as e: + click.echo(f"Error running tests: {e}")