name: CI and Deploy on: push: branches: - main pull_request: jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.0.x' - name: Setup Node uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: job-tracker-ui/package-lock.json - name: Build backend run: dotnet build JobTrackerApi/JobTrackerApi.csproj --configuration Release - name: Test backend run: dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-build - name: Install frontend deps working-directory: job-tracker-ui run: npm ci - name: Test frontend working-directory: job-tracker-ui run: npm test -- --watchAll=false --runInBand App.test.tsx confirm.test.tsx prompt.test.tsx dialog-flow.test.tsx confirm-flow.test.tsx attachments.test.tsx job-details-generated-drafts.test.tsx admin-system-page.test.tsx profile-page.test.tsx - name: Build frontend working-directory: job-tracker-ui run: npm run build deploy: needs: test if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - name: Run remote deploy uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.PROD_HOST }} username: ${{ secrets.PROD_USER }} key: ${{ secrets.PROD_SSH_KEY }} script: | set -euo pipefail if [ ! -d /opt/job-tracker/app/.git ]; then echo "Expected git checkout at /opt/job-tracker/app but .git was not found." exit 1 fi cd /opt/job-tracker/app if ! git fetch --all --prune; then echo "git fetch failed on server. Check remote auth/URL for /opt/job-tracker/app." exit 1 fi if ! git rev-parse --verify --quiet ${{ github.sha }} >/dev/null; then echo "Commit ${{ github.sha }} is not available in the server checkout after fetch." exit 1 fi git reset --hard ${{ github.sha }} git clean -fd chmod +x deploy/deploy.sh APP_VERSION=${{ github.run_number }} \ APP_COMMIT_SHA=${{ github.sha }} \ APP_BUILD_STAMP="$(date -u +'%Y-%m-%d %H:%M UTC')" \ ./deploy/deploy.sh docker compose ps docker compose exec -T ai-service python - <<'PY' import time import urllib.request last = None for _ in range(30): try: urllib.request.urlopen('http://127.0.0.1:8001/health', timeout=5).read() raise SystemExit(0) except Exception as exc: last = exc time.sleep(2) raise last PY