Skip to content

ci: bump actions/upload-artifact from 4 to 6 #584

ci: bump actions/upload-artifact from 4 to 6

ci: bump actions/upload-artifact from 4 to 6 #584

Workflow file for this run

name: CI - Comprehensive Pipeline

Check failure on line 1 in .github/workflows/ci.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/ci.yml

Invalid workflow file

(Line: 537, Col: 19): Unexpected symbol: '?'. Located at position 32 within expression: needs.lint.result == 'success' ? '✅' : '❌'
on:
pull_request:
branches:
- main
- develop
- dev
push:
branches:
- main
- develop
- dev
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
checks: write
pull-requests: write
jobs:
install:
name: Install Dependencies
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install backend dependencies
run: npm ci
- name: Cache backend node_modules
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install webapp dependencies
working-directory: ./webapp
run: npm ci
- name: Cache webapp node_modules
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
lint:
name: Lint (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: install
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Restore backend cache
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install backend dependencies (if cache miss)
run: npm ci --prefer-offline || npm ci
- name: Run backend ESLint
run: npm run lint
# TODO: Remove continue-on-error once lint issues are fixed (see issue #TBD)
# Currently 122 linting problems (17 errors, 105 warnings) exist in the codebase
continue-on-error: true
- name: Restore webapp cache
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
- name: Install webapp dependencies (if cache miss)
working-directory: ./webapp
run: npm ci --prefer-offline || npm ci
- name: Run webapp ESLint
run: npm run lint:webapp
# TODO: Remove continue-on-error once lint issues are fixed (see issue #TBD)
# Currently has linting warnings that need to be addressed
continue-on-error: true
typecheck:
name: Type Check (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: install
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Restore backend cache
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install backend dependencies (if cache miss)
run: npm ci --prefer-offline || npm ci
- name: Run backend type check
run: npm run type-check
- name: Restore webapp cache
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
- name: Install webapp dependencies (if cache miss)
working-directory: ./webapp
run: npm ci --prefer-offline || npm ci
- name: Run webapp type check
run: npm run type-check:webapp
unit-tests-backend:
name: Backend Tests (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: [lint, typecheck]
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Restore backend cache
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install backend dependencies (if cache miss)
run: npm ci --prefer-offline || npm ci
- name: Run backend tests
run: npm test
env:
NODE_ENV: test
JEST_TIMEOUT: 30000
- name: Upload backend coverage
uses: actions/upload-artifact@v6
if: matrix.node-version == 20
with:
name: backend-coverage
path: coverage/
retention-days: 7
if-no-files-found: ignore
- name: Upload test results
if: always()
uses: actions/upload-artifact@v6
with:
name: backend-test-results-node-${{ matrix.node-version }}
path: |
coverage/
test-results/
retention-days: 7
if-no-files-found: ignore
unit-tests-webapp:
name: Webapp Tests (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: [lint, typecheck]
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: webapp/package-lock.json
- name: Restore webapp cache
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
- name: Install webapp dependencies (if cache miss)
working-directory: ./webapp
run: npm ci --prefer-offline || npm ci
- name: Run webapp tests
run: npm run test:webapp
continue-on-error: true
env:
NODE_ENV: test
- name: Upload webapp coverage
uses: actions/upload-artifact@v6
if: matrix.node-version == 20
with:
name: webapp-coverage
path: webapp/coverage/
retention-days: 7
if-no-files-found: ignore
coverage-merge:
name: Merge Coverage & Upload
runs-on: ubuntu-latest
needs: [unit-tests-backend, unit-tests-webapp]
if: always()
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '20'
- name: Download backend coverage
uses: actions/download-artifact@v7
with:
name: backend-coverage
path: coverage/
continue-on-error: true
- name: Download webapp coverage
uses: actions/download-artifact@v7
with:
name: webapp-coverage
path: webapp/coverage/
continue-on-error: true
- name: Merge coverage reports
run: bash scripts/merge-coverage.sh
continue-on-error: true
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/merged/lcov.info,./coverage/lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
verbose: true
continue-on-error: true
health-check:
name: Health Check Tests (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: [build]
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version: [20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Restore backend cache
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install backend dependencies (if cache miss)
run: npm ci --prefer-offline || npm ci
- name: Download backend build artifacts
uses: actions/download-artifact@v7
with:
name: backend-dist
path: dist/
- name: Restore webapp cache
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
- name: Install webapp dependencies (if cache miss)
working-directory: ./webapp
run: npm ci --prefer-offline || npm ci
- name: Download webapp build artifacts
uses: actions/download-artifact@v7
with:
name: webapp-build
path: webapp/.next/
continue-on-error: true
- name: Validate build artifacts
run: bash scripts/validate-build.sh
- name: Test environment configuration
run: bash scripts/env-sync-check.sh
continue-on-error: true
- name: Verify health check script
run: |
# Create minimal .env for testing
cat > .env << EOF
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
WALLET_PRIVATE_KEY=test_key_placeholder_not_real
JWT_SECRET=test_jwt_secret_for_ci_only
ADMIN_USERNAME=admin
ADMIN_PASSWORD=test_password
EOF
# Run health check in dry-run mode
bash scripts/health-check.sh || echo "Health check completed with warnings (expected in CI)"
security-scan:
name: Security Scan (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: install
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Restore backend cache
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install backend dependencies (if cache miss)
run: npm ci --prefer-offline || npm ci
- name: Run npm audit (backend)
run: npm audit --audit-level=high || echo "⚠️ Security vulnerabilities found - review required"
continue-on-error: true
- name: Restore webapp cache
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
- name: Install webapp dependencies (if cache miss)
working-directory: ./webapp
run: npm ci --prefer-offline || npm ci
- name: Run npm audit (webapp)
working-directory: ./webapp
run: npm audit --audit-level=high || echo "⚠️ Security vulnerabilities found - review required"
continue-on-error: true
build:
name: Build (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
needs: [lint, typecheck]
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Restore backend cache
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-backend-${{ hashFiles('package-lock.json') }}
- name: Install backend dependencies (if cache miss)
run: npm ci --prefer-offline || npm ci
- name: Build backend
run: npm run build:backend
- name: Upload backend build artifacts
uses: actions/upload-artifact@v6
if: matrix.node-version == 20
with:
name: backend-dist
path: dist/
retention-days: 3
- name: Restore webapp cache
uses: actions/cache@v5
with:
path: webapp/node_modules
key: ${{ runner.os }}-node-${{ matrix.node-version }}-webapp-${{ hashFiles('webapp/package-lock.json') }}
- name: Install webapp dependencies (if cache miss)
working-directory: ./webapp
run: npm ci --prefer-offline || npm ci
- name: Build webapp
run: npm run build:webapp
env:
NEXT_PUBLIC_RPC_URL: ${{ secrets.NEXT_PUBLIC_RPC_URL || 'https://api.mainnet-beta.solana.com' }}
- name: Upload webapp build artifacts
uses: actions/upload-artifact@v6
if: matrix.node-version == 20
with:
name: webapp-build
path: webapp/.next/
retention-days: 3
if-no-files-found: ignore
ci-summary:
name: CI Summary
runs-on: ubuntu-latest
needs:
- lint
- typecheck
- unit-tests-backend
- unit-tests-webapp
- coverage-merge
- security-scan
- build
- health-check
if: always()
steps:
- name: Check CI status
run: |
echo "## CI Pipeline Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Type Check | ${{ needs.typecheck.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Backend Tests | ${{ needs.unit-tests-backend.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Webapp Tests | ${{ needs.unit-tests-webapp.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Coverage Merge | ${{ needs.coverage-merge.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Security Scan | ${{ needs.security-scan.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Health Check | ${{ needs.health-check.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "${{ needs.lint.result }}" == "failure" ]] || \
[[ "${{ needs.typecheck.result }}" == "failure" ]] || \
[[ "${{ needs.unit-tests-backend.result }}" == "failure" ]] || \
[[ "${{ needs.build.result }}" == "failure" ]] || \
[[ "${{ needs.health-check.result }}" == "failure" ]]; then
echo "❌ CI checks failed!" >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "✅ All CI checks passed!" >> $GITHUB_STEP_SUMMARY
fi
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
with:
script: |
const summary = `## 🔍 CI Pipeline Results
| Job | Status |
|-----|--------|
| Lint | ${{ needs.lint.result == 'success' ? '✅' : '❌' }} |
| Type Check | ${{ needs.typecheck.result == 'success' ? '✅' : '❌' }} |
| Backend Tests | ${{ needs.unit-tests-backend.result == 'success' ? '✅' : '❌' }} |
| Webapp Tests | ${{ needs.unit-tests-webapp.result == 'success' ? '✅' : '⚠️' }} |
| Coverage | ${{ needs.coverage-merge.result == 'success' ? '✅' : '⚠️' }} |
| Security Scan | ${{ needs.security-scan.result == 'success' ? '✅' : '⚠️' }} |
| Build | ${{ needs.build.result == 'success' ? '✅' : '❌' }} |
| Health Check | ${{ needs.health-check.result == 'success' ? '✅' : '❌' }} |
${needs.lint.result == 'failure' || needs.typecheck.result == 'failure' || needs.unit-tests-backend.result == 'failure' || needs.build.result == 'failure' || needs.health-check.result == 'failure' ? '❌ **CI checks failed!** Please review the errors above.' : '✅ **All CI checks passed!**'}
`;
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: summary
});