# FILE: .gitea/workflows/deploy.yml # # deploy to production which is an ubuntu co-lo server with nginx + postgres # # note to AI - the order in this file matters - also, minor changes to this file can have big impacts and is easy to break name: Deploy to Web Server flyer-crawler.projectium.com on: push: branches: - main # This pipeline runs only on a push to the 'main' branch. jobs: deploy: runs-on: projectium.com # This job runs on your self-hosted Gitea runner. # Environment variables are used to pass secrets and configuration to the steps below. # These must be configured as secrets in your Gitea repository settings. env: # Public keys needed for the React build process. # (Empty in original, assuming secrets are injected below) steps: - name: Checkout Code uses: actions/checkout@v3 # Add this NEW STEP FOR DEBUGGING - name: Show Git REF run: | echo "Gitea ref: ${{ gitea.ref }}" echo "Gitea ref_name: ${{ gitea.ref_name }}" # often more useful (e.g., 'main' or 'my-feature-branch') echo "Gitea ref_type: ${{ gitea.ref_type }}" # 'branch' or 'tag' echo "Gitea SHA: ${{ gitea.sha }}" echo "Triggering actor: ${{ gitea.actor }}" echo "Repository: ${{ gitea.repository }}" - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '20' cache: 'npm' # Re-enable the cache. If this fails, we will remove it again. cache-dependency-path: '**/package-lock.json' # The setup-node action with caching handles installation correctly. # If dependencies are not found in cache, it will run 'npm ci' automatically. # If they are found, it restores them. This is the standard, reliable way. - name: Install Dependencies run: npm ci # 'ci' is faster and safer for CI/CD than 'install'. # ----------------------------------------------------------------------- # UPDATED STEP: Fixes server startup and test file naming # ----------------------------------------------------------------------- - name: Fix Package Scripts and Install TSX run: | # 1. Install tsx to handle running the server (it handles ESM automatically) npm install -D tsx # 2. Update the server start script to use tsx npm pkg set scripts.start:server="tsx server.ts" # 3. Ensure the integration test command uses the correct config npm pkg set scripts.test:integration="vitest run -c vitest.config.integration.ts" # 4. SAFETY NET: Rename test files if they haven't been renamed in Git yet. # This ensures Vitest finds them regardless of your local git state. if [ -f src/services/db.test.ts ]; then echo "Renaming db.test.ts to db.integration.test.ts" mv src/services/db.test.ts src/services/db.integration.test.ts fi if [ -f src/services/shopping-list.test.ts ]; then echo "Renaming shopping-list.test.ts to shopping-list.integration.test.ts" mv src/services/shopping-list.test.ts src/services/shopping-list.integration.test.ts fi # ----------------------------------------------------------------------- # --- NEW DEBUGGING STEPS --- - name: Verify Project Structure run: | echo "--- Current Working Directory ---" pwd echo "--- Listing Root Directory ---" ls -alF echo "--- Listing SRC Directory ---" ls -alF src - name: Lint TypeScript Code run: npm run lint # Run the linter to check for code quality issues. continue-on-error: true # Allows the workflow to proceed even if linting fails. - name: Run Unit Tests # We override the production DB variables for this step only. # The 'global-setup.ts' will use these to connect to the test database, # create the schema, and seed data before tests run. env: DB_HOST: ${{ secrets.DB_HOST }} DB_PORT: ${{ secrets.DB_PORT }} DB_USER: ${{ secrets.DB_USER }} DB_PASSWORD: ${{ secrets.DB_PASSWORD }} DB_DATABASE: "flyer-crawler-test" # Hardcode the test database name DB_NAME: "flyer-crawler-test" # REQUIRED: Used by connection.ts to match the test setup run: npm test # Run the test suite against the temporary test database. # also Run the test suite to ensure code correctness. - name: Run Integration Tests # This step runs tests that require a live backend server. env: DB_HOST: ${{ secrets.DB_HOST }} DB_PORT: ${{ secrets.DB_PORT }} DB_USER: ${{ secrets.DB_USER }} DB_PASSWORD: ${{ secrets.DB_PASSWORD }} DB_DATABASE: "flyer-crawler-test" DB_NAME: "flyer-crawler-test" JWT_SECRET: "test-secret-for-ci" # Auth dummies (Previous fix) GOOGLE_CLIENT_ID: "dummy_client_id" GOOGLE_CLIENT_SECRET: "dummy_client_secret" GITHUB_CLIENT_ID: "dummy_github_id" GITHUB_CLIENT_SECRET: "dummy_github_secret" FRONTEND_URL: "http://localhost:3000" # ✅ NEW: Backend requires this to start GEMINI_API_KEY: ${{ secrets.VITE_GOOGLE_GENAI_API_KEY }} run: npm run test:integration - name: Archive Code Coverage Report # This action saves the generated HTML coverage report as a downloadable artifact. uses: actions/upload-artifact@v3 with: name: code-coverage-report path: coverage/ # --- Frontend Deployment --- - name: Build React Application # We set the environment variable directly in the command line for this step. # This maps the Gitea secret to the environment variable the application expects. run: VITE_API_KEY=${{ secrets.VITE_GOOGLE_GENAI_API_KEY }} npm run build - name: Deploy Application to Server run: | echo "Deploying application files to /var/www/flyer-crawler.projectium.com..." APP_PATH="/var/www/flyer-crawler.projectium.com" # Ensure the destination directory exists mkdir -p "$APP_PATH" # 1. Copy the backend source code and project files first. # We exclude node_modules, .git, and the build output (dist). rsync -avz --delete --exclude 'node_modules' --exclude '.git' --exclude 'dist' ./ "$APP_PATH/" # 2. Copy the built frontend assets into the same directory. # This will correctly place index.html and the assets/ folder in the webroot. rsync -avz --exclude '.env.local' dist/ "/var/www/flyer-crawler.projectium.com" echo "Application deployment complete." - name: Install Backend Dependencies and Restart Server run: | echo "Installing production dependencies and restarting server..." cd /var/www/flyer-crawler.projectium.com npm install --omit=dev # Install only production dependencies # Use `startOrReload` with the ecosystem file. This is the standard, idempotent way to deploy. # It will START the process if it's not running, or RELOAD it if it is. pm2 startOrReload ecosystem.config.cjs --env production echo "Backend server reloaded successfully."