Files
nas-tools/.gitea/workflows/deploy.yml
T
Gan, Jimmy 6c08fc007a
Deploy Dashboard (Dev) / Backend Tests (push) Successful in 20m13s
Deploy Dashboard (Dev) / Frontend Tests (push) Successful in 52s
Run Tests / Secret Detection (pull_request) Successful in 2m42s
Run Tests / Backend Tests (pull_request) Successful in 35m32s
Run Tests / Frontend Tests (pull_request) Failing after 47s
Deploy Dashboard (Dev) / Deploy to Dev (push) Failing after 3s
fix: configure npm registry mirror (npmmirror) in CI workflows
CI runner can't reach npmjs.org through GFW. Use npmmirror.com
mirror for npm package installs, same pattern as pip uses
Tsinghua mirror for backend deps.
2026-05-07 00:03:09 +08:00

250 lines
9.1 KiB
YAML

name: Deploy Dashboard (Main)
on:
push:
branches: [main]
paths:
- 'dashboard/**'
- '.gitea/workflows/deploy.yml'
concurrency:
group: deploy-dashboard-main
cancel-in-progress: true
jobs:
backend-tests:
name: Backend Tests
runs-on: ubuntu-latest
env:
SECRET_KEY: test-secret-key-for-ci-environment-32chars-minimum
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup Python
run: |
python3 --version
python3 -c "import sys; assert sys.version_info[:2] == (3, 12), f'Expected Python 3.12, got {sys.version}'; print('Python 3.12 confirmed')"
pip3 --version
- name: Cache Python dependencies
id: cache-python
run: |
CACHE_KEY="python-$(cat dashboard/backend/requirements.txt dashboard/backend/requirements-dev.txt | md5sum | cut -d' ' -f1)"
CACHE_DIR="/tmp/pytest-cache/$CACHE_KEY"
PIP_CACHE_DIR="/tmp/pip-cache"
echo "CACHE_DIR=$CACHE_DIR" >> $GITHUB_ENV
echo "CACHE_KEY=$CACHE_KEY" >> $GITHUB_ENV
echo "PIP_CACHE_DIR=$PIP_CACHE_DIR" >> $GITHUB_ENV
mkdir -p "$PIP_CACHE_DIR"
if [ -d "$CACHE_DIR" ]; then
echo "Cache hit for $CACHE_KEY"
echo "cache-hit=true" >> $GITHUB_OUTPUT
else
echo "Cache miss for $CACHE_KEY"
echo "cache-hit=false" >> $GITHUB_OUTPUT
mkdir -p "$CACHE_DIR"
fi
- name: Install dependencies
run: |
cd dashboard/backend
if [ "${{ steps.cache-python.outputs.cache-hit }}" = "true" ]; then
echo "Restoring venv from cache $CACHE_KEY..."
if cp -a $CACHE_DIR/venv . && [ -f venv/bin/activate ]; then
echo "Cache restored successfully"
else
echo "Cache corrupted, installing fresh..."
rm -rf venv
python3 -m venv venv
. venv/bin/activate
pip install --cache-dir=$PIP_CACHE_DIR -r requirements.txt || pip install -r requirements.txt
pip install --cache-dir=$PIP_CACHE_DIR -r requirements-dev.txt || pip install -r requirements-dev.txt
pip install --cache-dir=$PIP_CACHE_DIR pytest-timeout pytest-cov || pip install pytest-timeout pytest-cov
fi
else
echo "Installing fresh dependencies..."
python3 -m venv venv
. venv/bin/activate
pip install --cache-dir=$PIP_CACHE_DIR -r requirements.txt || pip install -r requirements.txt
pip install --cache-dir=$PIP_CACHE_DIR -r requirements-dev.txt || pip install -r requirements-dev.txt
pip install --cache-dir=$PIP_CACHE_DIR pytest-timeout pytest-cov || pip install pytest-timeout pytest-cov
echo "Saving venv to cache $CACHE_KEY..."
cp -a venv $CACHE_DIR/ || echo "Warning: cache save failed"
fi
- name: Run tests with coverage
run: |
cd dashboard/backend
. venv/bin/activate
pytest tests/ -v --timeout=60 \
--cov=. --cov-report=xml --cov-report=term \
--junit-xml=test-results.xml \
--cov-fail-under=49
if [ $? -ne 0 ]; then
echo "❌ Backend tests failed!"
exit 1
fi
echo "✅ Backend tests passed"
frontend-tests:
name: Frontend Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup Node.js
run: |
node --version
echo "Node $(node --version) detected"
npm --version
- name: Cache Node dependencies
id: cache-node
run: |
CACHE_KEY="node-$(md5sum dashboard/frontend/package-lock.json | cut -d' ' -f1)"
CACHE_DIR="/tmp/npm-cache/$CACHE_KEY"
echo "CACHE_DIR=$CACHE_DIR" >> $GITHUB_ENV
echo "CACHE_KEY=$CACHE_KEY" >> $GITHUB_ENV
if [ -d "$CACHE_DIR" ]; then
echo "Cache hit for $CACHE_KEY"
echo "cache-hit=true" >> $GITHUB_OUTPUT
else
echo "Cache miss for $CACHE_KEY"
echo "cache-hit=false" >> $GITHUB_OUTPUT
mkdir -p "$CACHE_DIR"
fi
- name: Install dependencies
env:
NODE_OPTIONS: "--max-old-space-size=2048"
run: |
cd dashboard/frontend
npm config set registry https://registry.npmmirror.com || true
if [ "${{ steps.cache-node.outputs.cache-hit }}" = "true" ]; then
echo "Restoring from cache $CACHE_KEY..."
if cp -a $CACHE_DIR/node_modules . && [ -d node_modules ]; then
echo "Cache restored successfully"
else
echo "Cache corrupted, installing fresh..."
rm -rf node_modules
npm ci
fi
else
echo "Installing fresh dependencies..."
npm ci
echo "Saving to cache $CACHE_KEY..."
cp -a node_modules $CACHE_DIR/ || echo "Warning: cache save failed"
fi
- name: Run tests
env:
NODE_OPTIONS: "--max-old-space-size=2048"
run: |
cd dashboard/frontend
npm run test:coverage -- --reporter=verbose --run --pool=forks --poolOptions.forks.maxForks=2
if [ $? -ne 0 ]; then
echo "❌ Frontend tests failed!"
exit 1
fi
echo "✅ Frontend tests passed"
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
needs: [backend-tests, frontend-tests]
container:
volumes:
- /var/packages/ContainerManager/target/usr/bin/docker:/usr/bin/docker
- /volume1/docker/nas-dashboard:/nas-dashboard
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Warm mirror cache for base images
run: |
set -u
mirror_host="100.78.131.124:5501"
if command -v curl >/dev/null 2>&1; then
if curl -fsS "http://${mirror_host}/v2/" >/dev/null; then
echo "Registry mirror is healthy at ${mirror_host}"
else
echo "Warning: registry mirror health check failed at ${mirror_host}; continuing with normal pull path"
fi
else
echo "Warning: curl is unavailable; skipping explicit mirror health check"
fi
prewarm_base_image() {
image_ref="$1"
# Skip if image already exists locally
if docker image inspect "${image_ref}" >/dev/null 2>&1; then
echo "Image ${image_ref} already exists locally, skipping pre-pull"
return 0
fi
mirror_ref="${mirror_host}/library/${image_ref}"
echo "Attempting mirror pre-pull: ${mirror_ref}"
if timeout 120 docker pull "${mirror_ref}"; then
docker tag "${mirror_ref}" "${image_ref}"
echo "Mirror pre-pull succeeded for ${image_ref}"
else
echo "Warning: mirror pre-pull failed for ${image_ref}; continuing with normal pull during build"
fi
}
prewarm_base_image "node:20-alpine"
prewarm_base_image "python:3.12-slim"
- name: Build
run: |
set -e
export DOCKER_API_VERSION=1.43
# DOCKER_BUILDKIT=0 is required for Synology ContainerManager's Docker daemon,
# which does not support BuildKit syntax. Remove when Synology updates to a
# Docker Engine version with full BuildKit support (currently 24.x, needs 23+).
# --cache-to type=inline is a no-op while BuildKit is disabled; it activates
# automatically when DOCKER_BUILDKIT=0 is removed.
if ! DOCKER_BUILDKIT=0 docker build --cache-from nas-dashboard:latest -t nas-dashboard:latest dashboard/; then
echo "Build failed. Checking for network issues..."
curl -I https://registry.npmmirror.com || echo "npmmirror unreachable"
curl -I https://pypi.tuna.tsinghua.edu.cn || echo "Tsinghua PyPI unreachable"
exit 1
fi
- name: Sync runtime compose file
run: cp dashboard/docker-compose.yml /nas-dashboard/docker-compose.yml
- name: Deploy
run: |
set -e
export DOCKER_API_VERSION=1.43
docker compose -f /nas-dashboard/docker-compose.yml up -d --pull never
- name: Wait for container to be healthy
run: |
echo "Waiting for container to be healthy..."
for i in {1..30}; do
STATUS=$(docker inspect --format='{{.State.Health.Status}}' nas-dashboard 2>/dev/null || echo "starting")
if [ "$STATUS" = "healthy" ]; then
echo "✅ Container is healthy"
exit 0
fi
echo "Waiting... ($i/30) Status: $STATUS"
sleep 2
done
echo "❌ Container failed to become healthy"
docker logs nas-dashboard --tail 50
exit 1