Files
alexpolo1andClaude Sonnet 5 4c4092099e fix: don't fail deploy jobs when diagnostic artifact upload hits quota
The prod deploy just failed at Unit Tests even though all 226 tests
passed - the job died on `Upload coverage report` hitting the GitHub
Actions artifact storage quota. ci.yml already treats artifact uploads
as best-effort for this exact reason (comment: "Artifact upload must
never fail the job (storage quota can be full)"), but deploy-prod.yml
and deploy-test.yml were missing the same continue-on-error on their
diagnostic report/screenshot/coverage uploads.

Leaves the actual deployable build artifact uploads (deploy-package-*)
blocking, since a failed deploy really should stop there.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-20 13:49:32 +02:00

266 lines
7.9 KiB
YAML

name: Deploy to Test Environment
on:
push:
branches: [ develop ]
workflow_dispatch:
inputs:
branch:
description: 'Branch to deploy'
required: true
default: 'develop'
env:
NODE_VERSION: '22'
TEST_SERVER_HOST: ${{ secrets.TEST_SERVER_HOST }}
TEST_SERVER_USER: ${{ secrets.TEST_SERVER_USER }}
TEST_SERVER_PATH: ${{ secrets.TEST_SERVER_PATH }}
TEST_APP_URL: ${{ secrets.TEST_APP_URL }}
jobs:
# ============================================
# Build & Test
# ============================================
build:
name: Build Application
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
ref: ${{ github.event.inputs.branch || github.ref }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Generate version
id: version
run: |
VERSION="test-$(date +'%Y%m%d-%H%M%S')-${GITHUB_SHA::7}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
- name: Install dependencies
run: |
npm ci
cd frontend && npm ci
cd ../backend && npm ci
- name: Run backend tests
working-directory: backend
run: npm test -- --passWithNoTests
continue-on-error: true
- name: Build frontend
working-directory: frontend
env:
CI: false
REACT_APP_ENV: test
REACT_APP_VERSION: ${{ steps.version.outputs.version }}
run: npm run build
- name: Create deployment package
run: |
mkdir -p deploy-package
cp -r frontend/build deploy-package/frontend-build
cp -r backend deploy-package/backend
cp ecosystem.config.js deploy-package/
cp package.json deploy-package/
rm -rf deploy-package/backend/node_modules
echo "${{ steps.version.outputs.version }}" > deploy-package/VERSION
- name: Upload deployment package
uses: actions/upload-artifact@v7
with:
name: deploy-package-test
path: deploy-package
retention-days: 3
# ============================================
# Deploy to Test Server
# ============================================
deploy:
name: Deploy to Test Server
runs-on: ubuntu-latest
needs: build
environment:
name: test
url: ${{ env.TEST_APP_URL }}
steps:
- name: Download deployment package
uses: actions/download-artifact@v8
with:
name: deploy-package-test
path: deploy-package
- name: Setup SSH
uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.TEST_SSH_PRIVATE_KEY }}
- name: Add server to known hosts
run: |
mkdir -p ~/.ssh
ssh-keyscan -H ${{ env.TEST_SERVER_HOST }} >> ~/.ssh/known_hosts
- name: Deploy to test server
run: |
# Create deployment directory
ssh ${{ env.TEST_SERVER_USER }}@${{ env.TEST_SERVER_HOST }} "mkdir -p ${{ env.TEST_SERVER_PATH }}/releases/${{ needs.build.outputs.version }}"
# Upload deployment package
scp -r deploy-package/* ${{ env.TEST_SERVER_USER }}@${{ env.TEST_SERVER_HOST }}:${{ env.TEST_SERVER_PATH }}/releases/${{ needs.build.outputs.version }}/
# Run deployment script on server
ssh ${{ env.TEST_SERVER_USER }}@${{ env.TEST_SERVER_HOST }} << 'DEPLOY_SCRIPT'
set -e
DEPLOY_PATH="${{ env.TEST_SERVER_PATH }}"
VERSION="${{ needs.build.outputs.version }}"
RELEASE_PATH="$DEPLOY_PATH/releases/$VERSION"
echo "=== Deploying version: $VERSION ==="
# Install backend dependencies
cd $RELEASE_PATH/backend
npm ci --production
# Copy environment file
cp $DEPLOY_PATH/shared/.env $RELEASE_PATH/backend/.env
# Copy frontend build to correct location
mkdir -p $RELEASE_PATH/backend/../frontend
mv $RELEASE_PATH/frontend-build $RELEASE_PATH/frontend/build
# Update symlink
ln -sfn $RELEASE_PATH $DEPLOY_PATH/current
# Restart PM2
cd $DEPLOY_PATH/current
pm2 restart ecosystem.config.js --env test || pm2 start ecosystem.config.js --env test
# Cleanup old releases (keep last 5)
cd $DEPLOY_PATH/releases
ls -t | tail -n +6 | xargs -r rm -rf
echo "=== Deployment complete ==="
DEPLOY_SCRIPT
# ============================================
# Post-Deploy Verification
# ============================================
verify:
name: Verify Deployment
runs-on: ubuntu-latest
needs: deploy
steps:
- name: Wait for server startup
run: sleep 15
- name: Health check
run: |
MAX_RETRIES=5
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ env.TEST_APP_URL }}/api/health || echo "000")
if [ "$HTTP_STATUS" = "200" ]; then
echo "Health check passed!"
exit 0
fi
RETRY_COUNT=$((RETRY_COUNT + 1))
echo "Health check failed (HTTP $HTTP_STATUS), retry $RETRY_COUNT/$MAX_RETRIES..."
sleep 10
done
echo "Health check failed after $MAX_RETRIES retries"
exit 1
- name: API smoke tests
run: |
echo "Testing API endpoints..."
# Test health endpoint
curl -f ${{ env.TEST_APP_URL }}/api/health
# Test materials endpoint
curl -f ${{ env.TEST_APP_URL }}/api/materials || true
# Test smart packages endpoint
curl -f ${{ env.TEST_APP_URL }}/api/smart-packages/ || true
echo "Smoke tests completed!"
- name: Notify deployment success
if: success()
run: |
echo "Test deployment successful!"
echo "Version: ${{ needs.build.outputs.version }}"
echo "URL: ${{ env.TEST_APP_URL }}"
- name: Notify deployment failure
if: failure()
run: |
echo "Test deployment failed!"
echo "Please check the logs for more details."
exit 1
# ============================================
# Run E2E Tests on Test Environment
# ============================================
e2e-tests:
name: E2E Tests on Test Environment
runs-on: ubuntu-latest
needs: verify
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install test dependencies
working-directory: tests
run: npm ci
- name: Install Playwright browsers
working-directory: tests
run: npx playwright install --with-deps chromium
- name: Run Playwright tests
working-directory: tests
env:
PLAYWRIGHT_BASE_URL: ${{ env.TEST_APP_URL }}
run: npx playwright test --project=chromium --reporter=html
continue-on-error: true
- name: Upload test report
uses: actions/upload-artifact@v7
if: always()
# Artifact upload must never fail the job (storage quota can be full)
continue-on-error: true
with:
name: e2e-test-report
path: tests/playwright-report
retention-days: 3
- name: Upload test screenshots
uses: actions/upload-artifact@v7
if: failure()
# Artifact upload must never fail the job (storage quota can be full)
continue-on-error: true
with:
name: e2e-test-screenshots
path: tests/test-results
retention-days: 3