Files
plex-playlist/.gitea/workflows/cicd.yml
copilotcoder 9d263674f5
Some checks failed
Tests / Build and Push CICD Base Image (pull_request) Failing after 2h59m43s
Tests / Build and Push CICD Complete Image (pull_request) Has been skipped
Tests / Trailing Whitespace Check (pull_request) Has been skipped
Tests / End of File Check (pull_request) Has been skipped
Tests / YAML Syntax Check (pull_request) Has been skipped
Tests / TOML Syntax Check (pull_request) Has been skipped
Tests / Mixed Line Ending Check (pull_request) Has been skipped
Tests / TOML Formatting Check (pull_request) Has been skipped
Tests / Ruff Linting (pull_request) Has been skipped
Tests / Ruff Format Check (pull_request) Has been skipped
Tests / Pyright Type Check (pull_request) Has been skipped
Tests / Darglint Docstring Check (pull_request) Has been skipped
Tests / No Docstring Types Check (pull_request) Has been skipped
Tests / ESLint Check (pull_request) Has been skipped
Tests / Prettier Format Check (pull_request) Has been skipped
Tests / TypeScript Type Check (pull_request) Has been skipped
Tests / TSDoc Lint Check (pull_request) Has been skipped
Tests / Backend Tests (pull_request) Has been skipped
Tests / Frontend Tests (pull_request) Has been skipped
Tests / Backend Doctests (pull_request) Has been skipped
Tests / Integration Tests (pull_request) Has been skipped
Tests / End-to-End Tests (pull_request) Has been skipped
fix: use IP address for registry endpoint to bypass DNS lookup
2026-05-18 16:52:25 -04:00

697 lines
29 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Tests
on:
push:
branches: [ main, develop, feature/* ]
pull_request:
branches: [ main, develop ]
env:
GITEA_SSH_HOST: 10.18.75.2
GITEA_SSH_PORT: "2222"
GITEA_REPO_SSH_URL: ssh://git@10.18.75.2:2222/DarkHelm.org/plex-playlist.git
GITEA_REGISTRY: 10.18.75.2:3001
jobs:
setup-base:
name: Build and Push CICD Base Image
runs-on: ubuntu-act
steps:
- name: Minimal checkout for base Dockerfile
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
umask 077
trap 'rm -f ~/.ssh/id_rsa' EXIT
echo "=== Minimal Repository Checkout for Base Dockerfile ==="
# Set up SSH key securely (temporary file approach)
if [ -n "${SSH_PRIVATE_KEY}" ]; then
mkdir -p ~/.ssh
echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
echo "Loaded SSH key fingerprint: $(ssh-keygen -lf ~/.ssh/id_rsa | awk '{print $2}')"
ssh-keyscan -p "${GITEA_SSH_PORT}" "${GITEA_SSH_HOST}" >> ~/.ssh/known_hosts 2>/dev/null
else
echo "❌ SSH_PRIVATE_KEY is empty"
exit 1
fi
# Clone just enough to get the Dockerfile
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o StrictHostKeyChecking=no" \
git clone --depth 1 --no-checkout \
"${GITEA_REPO_SSH_URL}" .
# Checkout only the base Dockerfile and dockerignore
git checkout HEAD -- Dockerfile.cicd-base .dockerignore
# Clean up SSH key for security
rm -f ~/.ssh/id_rsa
echo "✓ Dockerfile.cicd-base ready for build"
- name: Check if base image needs rebuilding
id: check-base
run: |
echo "=== Computing CICD Base Image Hash ==="
# Always compute hash so downstream steps have a stable tag.
BASE_HASH=$(sha256sum Dockerfile.cicd-base | cut -d' ' -f1 | head -c16)
echo "Base Dockerfile hash: ${BASE_HASH}"
echo "base_hash=${BASE_HASH}" >> $GITHUB_OUTPUT
# Registry blob HEAD requests are currently unstable on this infra,
# so we always build base locally and let downstream steps fallback as needed.
echo "needs_build=true" >> $GITHUB_OUTPUT
- name: Build and push base image
if: steps.check-base.outputs.needs_build == 'true'
env:
PACKAGE_ACCESS_TOKEN: ${{ secrets.PACKAGE_ACCESS_TOKEN }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER || github.actor }}
BASE_HASH: ${{ steps.check-base.outputs.base_hash }}
run: |
echo "=== Building CICD Base Image ==="
# Defensive fallback if output propagation failed for any reason.
BASE_HASH="${BASE_HASH:-$(sha256sum Dockerfile.cicd-base | cut -d' ' -f1 | head -c16)}"
if [ -z "${BASE_HASH}" ]; then
echo "❌ BASE_HASH is empty; refusing to tag/push invalid image references"
exit 1
fi
echo "Base hash: ${BASE_HASH}"
# Enable Docker BuildKit
export DOCKER_BUILDKIT=1
# Build base image (no secrets needed for base dependencies)
echo "Building base image..."
if docker build -f Dockerfile.cicd-base \
--build-arg BASE_IMAGE_VERSION="v1.0.0-${BASE_HASH}" \
-t cicd-base:latest .; then
echo "✓ Base image built successfully"
else
echo "❌ Failed to build base image"
exit 1
fi
BASE_REF_HASH="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd-base:${BASE_HASH}"
BASE_REF_LATEST="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd-base:latest"
ARCHIVE_PATH="/tmp/cicd-base.tar"
# Primary push path (docker); fallback path (skopeo) if daemon registry settings are ignored.
push_ref() {
ref="$1"
for i in 1 2 3; do
echo "Docker push attempt ${i}/3 for ${ref}..."
if docker push "${ref}"; then
echo "✓ Docker push succeeded for ${ref}"
return 0
fi
if [ "${i}" -lt 3 ]; then
sleep 10
fi
done
echo "⚠ Docker push failed for ${ref}; trying skopeo fallback"
if ! command -v skopeo >/dev/null 2>&1; then
if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y skopeo
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache skopeo
fi
fi
if ! command -v skopeo >/dev/null 2>&1; then
echo "❌ skopeo not available for fallback push"
return 1
fi
# Use docker-archive source to avoid docker-daemon API version mismatches.
if [ ! -f "${ARCHIVE_PATH}" ]; then
echo "Creating local image archive for fallback push..."
if ! docker save cicd-base:latest -o "${ARCHIVE_PATH}"; then
echo "❌ Failed to create docker archive for fallback push"
return 1
fi
fi
if skopeo copy \
--dest-creds "${REGISTRY_USER}:${PACKAGE_ACCESS_TOKEN}" \
--dest-tls-verify=false \
"docker-archive:${ARCHIVE_PATH}" \
"docker://${ref}"; then
echo "✓ Skopeo fallback push succeeded for ${ref}"
return 0
fi
echo "❌ Skopeo fallback push failed for ${ref}"
return 1
}
# Login once for docker push path.
if ! echo "${PACKAGE_ACCESS_TOKEN}" | docker login "http://${GITEA_REGISTRY}" -u "${REGISTRY_USER}" --password-stdin; then
echo "⚠ Docker login failed; skopeo fallback will still be attempted"
fi
# Tag and publish both immutable hash and latest.
docker tag cicd-base:latest "${BASE_REF_HASH}"
docker tag cicd-base:latest "${BASE_REF_LATEST}"
if push_ref "${BASE_REF_HASH}" && push_ref "${BASE_REF_LATEST}"; then
echo "✓ Base image published to registry: ${BASE_REF_HASH} and latest"
else
echo "❌ Failed to publish base image to registry"
exit 1
fi
setup:
name: Build and Push CICD Complete Image
runs-on: ubuntu-act
needs: setup-base
steps:
- name: Minimal checkout for Dockerfile
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
umask 077
trap 'rm -f ~/.ssh/id_rsa' EXIT
echo "=== Minimal Repository Checkout for Complete Dockerfile ==="
# Set up SSH key securely (temporary file approach)
if [ -n "${SSH_PRIVATE_KEY}" ]; then
mkdir -p ~/.ssh
echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
echo "Loaded SSH key fingerprint: $(ssh-keygen -lf ~/.ssh/id_rsa | awk '{print $2}')"
ssh-keyscan -p "${GITEA_SSH_PORT}" "${GITEA_SSH_HOST}" >> ~/.ssh/known_hosts 2>/dev/null
else
echo "❌ SSH_PRIVATE_KEY is empty"
exit 1
fi
# Clone just enough to get the Dockerfiles
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o StrictHostKeyChecking=no" \
git clone --depth 1 --no-checkout \
"${GITEA_REPO_SSH_URL}" .
# Checkout Dockerfiles and dockerignore (include base for fallback)
git checkout HEAD -- Dockerfile.cicd Dockerfile.cicd-base .dockerignore
# Clean up SSH key for security
rm -f ~/.ssh/id_rsa
echo "✓ Dockerfile.cicd and fallback base ready for secure build"
- name: Build and push complete CICD image
env:
PACKAGE_ACCESS_TOKEN: ${{ secrets.PACKAGE_ACCESS_TOKEN }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
GITHUB_SHA: ${{ github.sha }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER || github.actor }}
run: |
umask 077
trap 'rm -f /tmp/ssh_key' EXIT
echo "=== Building Complete CICD Image with Secure Secrets ==="
# Login to registry
echo "${PACKAGE_ACCESS_TOKEN}" | docker login "http://${GITEA_REGISTRY}" -u "${REGISTRY_USER}" --password-stdin
# Verify base image availability with fallback strategy
BASE_IMAGE="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd-base:latest"
echo "Checking base image availability: ${BASE_IMAGE}"
# Try to pull from registry (may not be available if push failed)
if timeout 30 docker pull "${BASE_IMAGE}" 2>/dev/null; then
echo "✓ Base image pulled from registry"
else
echo " Base image not in registry (registry push may have failed)"
echo "Building base image locally as fallback..."
# Check if base Dockerfile exists and build it locally
if [ -f "Dockerfile.cicd-base" ]; then
export DOCKER_BUILDKIT=1
docker build -f Dockerfile.cicd-base -t cicd-base-local:latest .
BASE_IMAGE="cicd-base-local:latest"
echo "✓ Base image built locally: ${BASE_IMAGE}"
else
echo "❌ Cannot find Dockerfile.cicd-base for fallback build"
exit 1
fi
fi
# Create temporary SSH key file for BuildKit secrets
echo "${SSH_PRIVATE_KEY}" > /tmp/ssh_key
chmod 600 /tmp/ssh_key
# Enable Docker BuildKit for secrets support
export DOCKER_BUILDKIT=1
# Build complete CICD image using secure BuildKit secrets, inheriting from base
# SSH key is mounted securely and never stored in image layers
echo "Building complete image with base: ${BASE_IMAGE}"
docker build -f Dockerfile.cicd \
--secret id=ssh_private_key,src=/tmp/ssh_key \
--build-arg GITHUB_SHA="$GITHUB_SHA" \
--build-arg CICD_BASE_IMAGE="${BASE_IMAGE}" \
-t cicd:latest .
# Clean up temporary SSH key file
rm -f /tmp/ssh_key
# Tag for Gitea container registry
docker tag cicd:latest "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:latest"
docker tag cicd:latest "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
# Push to registry (may not succeed if registry has issues)
echo "Pushing complete CICD images to registry..."
if docker push "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:latest" && \
docker push "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"; then
echo "✓ Complete CICD image pushed to registry"
else
echo "⚠ Registry push failed, but complete image is built locally"
echo "Other jobs will use local images"
fi
# Pre-commit style checks - General file formatting
trailing-whitespace:
name: Trailing Whitespace Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check trailing whitespace with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run trailing-whitespace --all-files --show-diff-on-failure
"
end-of-file-fixer:
name: End of File Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check end of file with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run end-of-file-fixer --all-files --show-diff-on-failure
"
check-yaml:
name: YAML Syntax Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check YAML files with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run check-yaml --all-files --show-diff-on-failure
"
check-toml:
name: TOML Syntax Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check TOML files with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run check-toml --all-files --show-diff-on-failure
"
mixed-line-ending:
name: Mixed Line Ending Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check line endings with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run mixed-line-ending --all-files --show-diff-on-failure
"
toml-lint:
name: TOML Formatting Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: |
echo "=== Network-Resilient Docker Registry Login ==="
for i in 1 2 3 4 5; do
echo "Login attempt $i/5..."
if echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | timeout 60 docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin; then
echo "✓ Login successful"
break
else
if [ $i -eq 5 ]; then
echo "❌ All login attempts failed after network timeouts"
exit 1
fi
echo "⚠ Login attempt $i failed, waiting 15s before retry..."
sleep 15
fi
done
- name: Check TOML formatting with pre-commit
run: |
echo "=== Network-Resilient Docker Operations ==="
# Resilient docker pull with retries
for i in 1 2 3; do
echo "Docker pull attempt $i/3..."
if timeout 300 docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"; then
echo "✓ Docker pull successful"
break
else
if [ $i -eq 3 ]; then
echo "❌ All docker pull attempts failed"
exit 1
fi
echo "⚠ Docker pull attempt $i failed, waiting 20s before retry..."
sleep 20
fi
done
# Run the actual test
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run pretty-format-toml --all-files --show-diff-on-failure
"
# Backend Python checks
ruff-lint:
name: Ruff Linting
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run ruff linting with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run ruff --all-files --show-diff-on-failure
"
ruff-format:
name: Ruff Format Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check ruff formatting with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run ruff-format --all-files --show-diff-on-failure
"
pyright:
name: Pyright Type Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run pyright type checking with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run pyright --all-files --show-diff-on-failure
"
darglint:
name: Darglint Docstring Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run darglint docstring linting with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run darglint --all-files --show-diff-on-failure
"
no-docstring-types:
name: No Docstring Types Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run no docstring types check with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run no-docstring-types --all-files --show-diff-on-failure
"
# Frontend checks
eslint:
name: ESLint Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run ESLint with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run eslint --all-files --show-diff-on-failure
"
prettier:
name: Prettier Format Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Check Prettier formatting with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run prettier --all-files --show-diff-on-failure
"
typescript-check:
name: TypeScript Type Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run TypeScript type checking with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run typescript-check --all-files --show-diff-on-failure
"
tsdoc-lint:
name: TSDoc Lint Check
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run TSDoc linting with pre-commit
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace &&
pre-commit run tsdoc-lint --all-files --show-diff-on-failure
"
# Unit tests with coverage
backend-tests:
name: Backend Tests
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run backend tests with coverage
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace/backend &&
source .venv/bin/activate &&
uv run pytest -v --tb=short --cov=src --cov-report=term-missing --cov-fail-under=95
"
frontend-tests:
name: Frontend Tests
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run frontend tests with coverage
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace/frontend &&
yarn test:coverage --run --reporter=verbose --coverage.reporter=text --coverage.reporter=text-summary --coverage.thresholds.lines=85 --coverage.thresholds.functions=85 --coverage.thresholds.branches=85 --coverage.thresholds.statements=85
"
# Doctest for backend
xdoctest:
name: Backend Doctests
runs-on: ubuntu-act
needs: setup
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run backend doctests
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace/backend &&
source .venv/bin/activate &&
echo 'Running doctests...' &&
if uv run xdoctest src/ --quiet; then
echo '✓ All doctests passed'
else
echo ' No doctests found or some doctests failed'
# Don't fail the build for missing doctests, only for failed ones
if uv run xdoctest src/ --quiet --verbose 2>&1 | grep -q 'FAILED'; then
exit 1
fi
fi
"
# Integration and E2E tests (run after unit tests complete)
integration-tests:
name: Integration Tests
runs-on: ubuntu-act
needs: [backend-tests, frontend-tests]
steps:
- name: Login to Gitea Container Registry
run: echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin
- name: Run integration tests
run: |
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
docker run --rm "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace/backend &&
source .venv/bin/activate &&
if [ -d 'tests/integration' ]; then
uv run pytest tests/integration/ -v --tb=short
else
echo ' No integration tests found'
fi
"
e2e-tests:
name: End-to-End Tests
runs-on: ubuntu-act
needs: [backend-tests, frontend-tests]
steps:
- name: Login to Gitea Container Registry
run: |
echo "=== Network-Resilient Docker Registry Login ==="
for i in 1 2 3 4 5; do
echo "Login attempt $i/5..."
if echo "${{ secrets.PACKAGE_ACCESS_TOKEN }}" | timeout 60 docker login "http://${GITEA_REGISTRY}" -u ${{ github.actor }} --password-stdin; then
echo "✓ Login successful"
break
else
if [ $i -eq 5 ]; then
echo "❌ All login attempts failed after network timeouts"
exit 1
fi
echo "⚠ Login attempt $i failed, waiting 15s before retry..."
sleep 15
fi
done
- name: Run E2E tests
run: |
echo "=== Network-Resilient E2E Test Execution ==="
# Use the same simple approach as all other successful tests
docker pull "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}"
# Run E2E tests with network resilience
docker run --rm -e CI=true "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-cicd:${GITHUB_SHA:-latest}" bash -c "
cd /workspace/frontend &&
if [ -d 'tests/e2e' ] || grep -q 'playwright' package.json; then
echo 'Running E2E tests with Playwright (Network Resilient)...' &&
export CI=true &&
export NODE_ENV=test &&
# Enhanced network-resilient Playwright setup
echo 'Verifying Playwright installation...' &&
yarn playwright --version &&
echo 'Installing Playwright browser binaries with enhanced retries...' &&
for i in 1 2 3 4; do
echo \"Enhanced browser install attempt \$i/4...\" &&
# Use longer timeout and Chromium-only for CI reliability
if timeout 900 yarn playwright install --with-deps chromium; then
echo \"✓ Playwright Chromium browser installed successfully\" &&
break
else
if [ \$i -eq 4 ]; then
echo \"❌ All enhanced browser install attempts failed\" &&
echo \"Attempting emergency fallback without dependencies...\" &&
if timeout 600 yarn playwright install chromium; then
echo \"✓ Emergency fallback browser install successful\" &&
break
else
echo \"❌ Emergency fallback also failed\" &&
exit 1
fi
fi
echo \"⚠ Enhanced browser install attempt \$i failed, waiting 45s before retry...\" &&
# Clear any partial browser downloads
rm -rf ~/.cache/ms-playwright 2>/dev/null || true &&
sleep 45
fi
done &&
echo 'Running E2E tests with network resilience...' &&
# Set additional network timeout environment variables
export PLAYWRIGHT_TIMEOUT=90000 &&
export NODE_TLS_REJECT_UNAUTHORIZED=0 &&
yarn test:e2e --reporter=list --timeout=90000
else
echo ' No E2E tests found'
fi
"