Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
interval: "weekly"
reviewers:
- "GabrielPalmar"
4 changes: 2 additions & 2 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Build the Docker image
run: docker build . --file Dockerfile --tag pommed3rre/hivebox:$(cat version.txt)
run: docker build . --file docker/Dockerfile --tag pommed3rre/hivebox:$(cat version.txt)

- name: Run Docker container
run: docker run -d -p 5000:5000 pommed3rre/hivebox:$(cat version.txt)
Expand All @@ -36,7 +36,7 @@ jobs:

- name: Run tests
run: |
python test_main.py
python tests/test_main.py
TEST_EXIT_CODE=$?
if [ $TEST_EXIT_CODE -ne 0 ]; then
echo "Tests failed!"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/hadolint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
- uses: actions/checkout@v4
- uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: Dockerfile
dockerfile: docker/Dockerfile
6 changes: 5 additions & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ jobs:
pip install prometheus_client
- name: Analysing the code with pylint
run: |
pylint $(git ls-files '*.py')
# Set PYTHONPATH so pylint can find the app module
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
pylint app/ --ignore=__pycache__
env:
PYTHONPATH: ${{ github.workspace }}
26 changes: 16 additions & 10 deletions .github/workflows/sonarqube.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
name: SonarQube analysis

on:
on:
push:
branches: [ "main", "test" ]
branches:
- main
pull_request:
branches: [ "main" ]
workflow_dispatch:
branches:
- main

permissions:
pull-requests: read
Expand All @@ -18,7 +19,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Disable shallow clones for better analysis
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
Expand All @@ -33,9 +34,12 @@ jobs:

- name: Run tests with coverage
run: |
coverage run test_main.py
coverage xml

export PYTHONPATH="${GITHUB_WORKSPACE}:${PYTHONPATH}"
coverage run --source=app -m pytest tests/test_modules.py -v
coverage xml -o coverage.xml
coverage report --show-missing
working-directory: ${{ github.workspace }}

- name: Analyze with SonarQube
uses: SonarSource/sonarqube-scan-action@master
env:
Expand All @@ -45,5 +49,7 @@ jobs:
args: >
-Dsonar.projectKey=GabrielPalmar_HiveBox-Project
-Dsonar.organization=gabrielpalmar
-Dsonar.sources=.
-Dsonar.exclusions=**/*test*/**,**/fixtures/**,**/__pycache__/**,**/venv/**,**/.git/**
-Dsonar.sources=app
-Dsonar.tests=tests
-Dsonar.python.coverage.reportPaths=coverage.xml
-Dsonar.exclusions=**/fixtures/**,**/__pycache__/**,**/venv/**,**/.git/**,docker/**,k8s/**,scripts/**
17 changes: 4 additions & 13 deletions main.py → app/main.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
'''Module containing the main function of the app.'''
import os
from flask import Flask, Response
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST
import opensense
#import test_main
from app import opensense

app = Flask(__name__)

@app.route('/version')
def print_version():
'''Function printing the current version of the app.'''
version_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'version.txt')

with open('version.txt', 'r', encoding="utf-8") as f:
with open(version_file, 'r', encoding="utf-8") as f:
version = f.read()

return f"Current app version: {version}\n"
Expand All @@ -25,15 +26,5 @@ def metrics():
'''Function to return Prometheus metrics.'''
return Response(generate_latest(), mimetype=CONTENT_TYPE_LATEST)

### Test module ###
# @app.route('/test')
# def test():
# '''Function to test the app.'''
# success = test_main.run_all_tests()
# if success:
# return "All tests passed!\n", 200
# else:
# return "Some tests failed. Check the logs for details.\n", 500

if __name__ == "__main__":
app.run()
File renamed without changes.
35 changes: 18 additions & 17 deletions Dockerfile → docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
FROM python:3.13.5-alpine@sha256:9b4929a72599b6c6389ece4ecbf415fd1355129f22bb92bb137eea098f05e975

RUN addgroup -S appgroup && adduser -S -G appgroup appuser

WORKDIR /app

COPY main.py opensense.py version.txt requirements.txt /app/

RUN pip install --no-cache-dir -r /app/requirements.txt --require-hashes && \
chown -R appuser:appgroup /app

ENV FLASK_APP=main.py \
PYTHONUNBUFFERED=1

USER appuser

ENTRYPOINT [ "flask" ]
FROM python:3.13.5-alpine@sha256:9b4929a72599b6c6389ece4ecbf415fd1355129f22bb92bb137eea098f05e975

RUN addgroup -S appgroup && adduser -S -G appgroup appuser

WORKDIR /app

COPY app/ /app/app/
COPY version.txt requirements.txt /app/

RUN pip install --no-cache-dir -r /app/requirements.txt --require-hashes && \
chown -R appuser:appgroup /app

ENV FLASK_APP=app.main.py:app \
PYTHONUNBUFFERED=1

USER appuser

ENTRYPOINT [ "flask" ]
CMD [ "run", "--host=0.0.0.0" ]
7 changes: 7 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[tool:pytest]
testpaths = tests
pythonpath = .
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = --verbose --tb=short
4 changes: 2 additions & 2 deletions test_main.py → tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'''This module contains the test cases for the opensense module.'''
'''This module contains the test cases for the main module.'''
import sys
import re
import os
Expand All @@ -8,7 +8,7 @@
API_HOST = os.environ.get('API_HOST', 'http://127.0.0.1:5000')

my_vcr = vcr.VCR(
cassette_library_dir='fixtures/vcr_cassettes',
cassette_library_dir='tests/fixtures/vcr_cassettes',
record_mode='once',
match_on=['uri', 'method'],
)
Expand Down
32 changes: 32 additions & 0 deletions tests/test_modules.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'''This module contains tests for the Flask and OpenSense modules.'''
from app.main import app
from app import opensense

def test_app_exists():
"""Test that the Flask app exists"""
assert app is not None

def test_version_endpoint():
"""Test version endpoint with test client"""
client = app.test_client()
response = client.get('/version')
assert response.status_code == 200

def test_temperature_endpoint():
"""Test temperature endpoint with test client"""
client = app.test_client()
response = client.get('/temperature')
assert response.status_code in [200, 500]

def test_metrics_endpoint():
"""Test metrics endpoint"""
client = app.test_client()
response = client.get('/metrics')
assert response.status_code == 200

# Add a simple test for the opensense module
def test_opensense_get_temperature():
"""Test that opensense.get_temperature returns a string"""
result = opensense.get_temperature()
assert isinstance(result, str)
assert "Average temperature:" in result