Merge branch 'e2e-testing'
Signed-off-by: Arian Nasr <arian@2ari.ca>
This commit was merged in pull request #25.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
name: Build Debian Package
|
||||
name: Build and Test Debian Package
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -10,7 +10,9 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
deb_filename: ${{ steps.get_deb_name.outputs.filename }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -35,3 +37,26 @@ jobs:
|
||||
name: ${{ steps.get_deb_name.outputs.filename }}
|
||||
path: output/${{ steps.get_deb_name.outputs.filename }}
|
||||
retention-days: 5
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build # only run tests if the build job succeeded
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create output directory
|
||||
run: mkdir -p output
|
||||
|
||||
- name: Download Build Artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ needs.build.outputs.deb_filename }}
|
||||
path: output/
|
||||
|
||||
- name: Build Test Docker Image
|
||||
run: docker build -t uploader-tester -f Dockerfile.test .
|
||||
|
||||
- name: Run E2E Test Suite
|
||||
run: docker run --rm uploader-tester
|
||||
@@ -0,0 +1,36 @@
|
||||
# Navidome-Uploader Dockerfile for testing .deb packages
|
||||
# Arian Nasr
|
||||
# May 31, 2026
|
||||
|
||||
FROM debian:stable
|
||||
|
||||
# Prevent interactive prompts
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
python3 \
|
||||
python3-venv \
|
||||
python3-pip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy the built deb package into the container
|
||||
COPY output/*.deb /tmp/navidrome-uploader.deb
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y -f /tmp/navidrome-uploader.deb && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir -p /opt/navidrome/music && \
|
||||
chown -R navidrome-uploader:navidrome-uploader /opt/navidrome/music
|
||||
|
||||
COPY e2e/ /e2e/
|
||||
|
||||
RUN python3 -m venv /e2e/venv && \
|
||||
/e2e/venv/bin/pip install --no-cache-dir -r /e2e/requirements.txt
|
||||
|
||||
RUN chmod +x /e2e/test-entrypoint.sh
|
||||
|
||||
WORKDIR /e2e
|
||||
|
||||
ENTRYPOINT ["/e2e/test-entrypoint.sh"]
|
||||
@@ -0,0 +1,3 @@
|
||||
Werkzeug==3.1.8
|
||||
pytest==9.0.3
|
||||
requests==2.34.2
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
export NAVIDROME_MUSIC_FOLDER="/opt/navidrome/music"
|
||||
export BASE_URL="http://127.0.0.1:5001"
|
||||
|
||||
# Start the app manually since systemd isn't running in the container
|
||||
cd /opt/navidrome-uploader
|
||||
su -s /bin/sh navidrome-uploader -c "/opt/navidrome-uploader/venv/bin/gunicorn --no-control-socket -c gunicorn.conf.py main:app" &
|
||||
|
||||
APP_PID=$!
|
||||
|
||||
TIMEOUT=30
|
||||
SERVICE_UP=0
|
||||
|
||||
while [ $TIMEOUT -gt 0 ]; do
|
||||
if curl -s $BASE_URL/ping | grep -q "pong"; then
|
||||
SERVICE_UP=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
TIMEOUT=$((TIMEOUT-1))
|
||||
done
|
||||
|
||||
if [ $SERVICE_UP -eq 0 ]; then
|
||||
echo "Error: Service failed to start within the timeout period"
|
||||
kill $APP_PID
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd /e2e
|
||||
|
||||
/e2e/venv/bin/pytest unit/api/test_api.py
|
||||
|
||||
# Capture the exit code of pytest
|
||||
TEST_EXIT_CODE=$?
|
||||
|
||||
kill $APP_PID
|
||||
|
||||
exit $TEST_EXIT_CODE
|
||||
@@ -0,0 +1,22 @@
|
||||
import pytest
|
||||
import requests
|
||||
import io
|
||||
import os
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
|
||||
def test_api_ping(base_url):
|
||||
response = requests.get(f'{base_url}/ping')
|
||||
assert response.status_code == 200
|
||||
assert response.text == 'pong'
|
||||
|
||||
def test_api_upload_non_audio_file(base_url, upload_folder):
|
||||
files = {'file': ('test.txt', io.BytesIO(b'not an audio file'))}
|
||||
expected_filename = os.path.join(upload_folder, secure_filename('test.txt'))
|
||||
response = requests.post(f'{base_url}/', files=files)
|
||||
assert response.status_code == 400
|
||||
assert "not allowed" in response.json().get("error", "")
|
||||
assert not os.path.exists(expected_filename)
|
||||
|
||||
if os.path.exists(expected_filename):
|
||||
os.remove(expected_filename)
|
||||
@@ -0,0 +1,10 @@
|
||||
import pytest
|
||||
import os
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def base_url():
|
||||
return os.getenv('BASE_URL', 'http://127.0.0.1:5001')
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def upload_folder():
|
||||
return os.getenv('NAVIDROME_MUSIC_FOLDER', '/opt/navidrome/music')
|
||||
Reference in New Issue
Block a user