diff --git a/.gitea/workflow/test.yml b/.gitea/workflow/test.yml new file mode 100644 index 0000000..81cd995 --- /dev/null +++ b/.gitea/workflow/test.yml @@ -0,0 +1,194 @@ +name: Flask CI/CD Pipeline + +on: + push: + branches: [ main ] + +env: + IMAGE_NAME: 10.0.2.109:3000/gitea/arcade + +jobs: + format-and-auto-fix: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install formatting dependencies + run: | + python -m venv venv + . venv/bin/activate + pip install --upgrade pip + pip install -r requirements.txt + pip install ruff + + - name: Run Ruff auto-fix and formatting + run: | + . venv/bin/activate + python -m ruff check . --fix --exclude venv,.venv + python -m ruff format . --exclude venv,.venv + + - name: Commit and push formatting changes + run: | + if [ -n "$(git status --porcelain)" ]; then + git config --global user.name "gitea-actions[bot]" + git config --global user.email "gitea-actions[bot]@local" + git add . + git commit -m "Auto-fix code style" + git push + else + echo "No formatting changes to commit" + fi + + test-and-verify: + needs: format-and-auto-fix + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Scan repository and git history for leaked secrets with Gitleaks + run: | + docker run --rm \ + -v "$PWD":/repo \ + ghcr.io/gitleaks/gitleaks:latest \ + git /repo --verbose + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install test and security dependencies + run: | + python -m venv venv + . venv/bin/activate + pip install --upgrade pip + pip install -r requirements.txt + pip install pytest pytest-cov pip-audit + + - name: Run pytest with coverage + run: | + . venv/bin/activate + PYTHONPATH=. pytest --cov=. --cov-report=term-missing + + - name: Run lightweight input fuzzing against Flask test client + run: | + . venv/bin/activate + python - <<'PY' + import random + import string + from app import app + + client = app.test_client() + + samples = [ + "", + "abc", + "🔥", + "één test", + "", + "\x00", + " " * 100, + "a" * 10000, + "🙂🙃😅", + "漢字かなカナ", + "\n\t\r", + ] + + alphabet = string.ascii_letters + string.digits + string.punctuation + " 🙂🔥éäöü漢字\n\t" + + for _ in range(100): + size = random.randint(0, 512) + samples.append("".join(random.choice(alphabet) for _ in range(size))) + + for value in samples: + response = client.post("/", data={"tekst": value}) + assert response.status_code == 200, f"Unexpected status code for input length {len(value)}" + body = response.get_data(as_text=True) + assert "Spiegelbeeld:" in body, "Expected response marker not found" + + print(f"Lightweight fuzzing completed successfully for {len(samples)} inputs.") + PY + + - name: Scan Python dependencies with pip-audit + run: | + . venv/bin/activate + pip-audit + + - name: Start Flask app and run smoke test + run: | + . venv/bin/activate + python app.py & + APP_PID=$! + sleep 5 + curl -f http://127.0.0.1:5000 + kill $APP_PID + + build-scan-and-push-image: + needs: test-and-verify + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Log in to Gitea container registry + run: | + echo "${{ secrets.DOCKER_PASSWORD }}" | docker login 10.0.2.109:3000 -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin + + - name: Build Docker images + run: | + docker build --pull -t $IMAGE_NAME:latest . + docker build --pull -t $IMAGE_NAME:${{ gitea.sha }} . + + - name: Verify Flask is available in container image + run: | + docker run --rm $IMAGE_NAME:latest python -c "import flask" + + - name: Clean up old test containers + run: | + docker stop arcade-test || true + docker rm -f arcade-test || true + + - name: Install Trivy + run: | + sudo apt-get update + sudo apt-get install -y wget gnupg lsb-release apt-transport-https + wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - + echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/trivy.list + sudo apt-get update + sudo apt-get install -y trivy + + - name: Scan container image with Trivy + run: | + trivy image --exit-code 0 --severity HIGH,CRITICAL $IMAGE_NAME:latest + + - name: Push container images + run: | + docker push $IMAGE_NAME:latest + docker push $IMAGE_NAME:${{ gitea.sha }} + + deploy-updated-container: + needs: build-scan-and-push-image + runs-on: ubuntu-latest + steps: + - name: Redeploy container over SSH + uses: appleboy/ssh-action@master + with: + host: 10.0.2.109 + username: ${{ secrets.SSH_USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + cd ~/docker-compose/arcade/ + docker compose -f docker-compose.stable.yml down + docker compose -f docker-compose.ci.yml pull + docker compose -f docker-compose.ci.yml up -d \ No newline at end of file