From 9a3da8530a4ef569bc8e4631eef959a164f0975d Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 17:30:55 -0500 Subject: [PATCH 1/8] docker changes --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5c55611b..11626353 100644 --- a/Dockerfile +++ b/Dockerfile @@ -67,9 +67,9 @@ RUN echo "=== DEBUG: Static File Structure ===" && \ echo "--- React frontend files ---" && \ ls -la /app/backend/static && \ echo "--- JS files ---" && \ - find /app/backend/static -name "*.js" | grep -v "node_modules" && \ + find /app/backend/static -name "*.js" | grep -v "node_modules" || true && \ echo "--- CSS files ---" && \ - find /app/backend/static -name "*.css" | grep -v "node_modules" && \ + find /app/backend/static -name "*.css" | grep -v "node_modules" || true && \ echo "=== END DEBUG ===" # Set environment variables From 231f906a0072b652e2e47832723bdb0f6e6dab7d Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 17:48:14 -0500 Subject: [PATCH 2/8] changed docker registry from lifee77/ to jeevanbhatta/ --- .github/workflows/azure-webapps-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/azure-webapps-python.yml b/.github/workflows/azure-webapps-python.yml index 62fe0300..a71593a4 100644 --- a/.github/workflows/azure-webapps-python.yml +++ b/.github/workflows/azure-webapps-python.yml @@ -4,7 +4,7 @@ env: AZURE_WEBAPP_NAME: instantapply # set this to the name of your Azure Web App PYTHON_VERSION: '3.11' DOCKER_REGISTRY: ghcr.io - DOCKER_IMAGE_NAME: lifee77/instantapply + DOCKER_IMAGE_NAME: jeevanbhatta/instantapply on: push: From 1e0837b96f206965ec55a54c44835a156f0b2c27 Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 18:08:12 -0500 Subject: [PATCH 3/8] static file location fixes --- Dockerfile | 8 +++++--- backend/app.py | 48 +++++++++++++----------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/Dockerfile b/Dockerfile index 11626353..8ac80200 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,13 +59,15 @@ RUN mkdir -p instance && \ # Copy the React frontend build directly to backend/static - this is the main location COPY react-frontend/build/ backend/static/ -# No need to create nested static structure - use the files as they are -# This is important: do NOT move files around, leave them where React put them +# Create a symbolic link for backwards compatibility +RUN ln -s /app/backend/static /app/static # Display detailed debug information about static files RUN echo "=== DEBUG: Static File Structure ===" && \ - echo "--- React frontend files ---" && \ + echo "--- Backend static files ---" && \ ls -la /app/backend/static && \ + echo "--- Root static files ---" && \ + ls -la /app/static && \ echo "--- JS files ---" && \ find /app/backend/static -name "*.js" | grep -v "node_modules" || true && \ echo "--- CSS files ---" && \ diff --git a/backend/app.py b/backend/app.py index edd745db..7425b68e 100644 --- a/backend/app.py +++ b/backend/app.py @@ -79,11 +79,10 @@ def create_app(config_class=Config): # Create Flask app with explicit instance path and React build directory # Point Flask to serve React build files directly - react_build_path = os.path.join(os.path.dirname(__file__), '..', 'react-frontend', 'build') app = Flask(__name__, instance_relative_config=True, instance_path=instance_path, - static_folder=react_build_path, + static_folder='static', # Changed to use the correct static folder static_url_path='') # Load configuration @@ -348,42 +347,16 @@ def serve_static(filename): # Simple 404 handler for static files that logs path for debugging # Add route for root to serve index.html (React app entry point) - @app.route('/') - def index(): - """Serve the React app entry point""" - return app.send_static_file('index.html') - - # Custom 404 handler for non-static routes - @app.errorhandler(404) - def not_found(e): - path = request.path - - # For API routes, return JSON - if path.startswith('/api/'): - return jsonify({"error": "API endpoint not found"}), 404 - - # For static file requests, let Flask handle them naturally (don't override) - if path.startswith('/static/'): - # Re-raise the 404 to let Flask's static file handler try - raise e - - # For everything else, serve the React app (SPA routing) - return app.send_static_file('index.html') - - # Serve React App for all non-static, non-API routes + @app.route('/', defaults={'path': ''}) @app.route('/') def serve(path): - # Skip API routes - let them be handled by their blueprints if path.startswith('api/'): - return jsonify({'error': 'API route not found'}), 404 - - # Skip static routes completely - Flask will handle them with static_folder config - if path.startswith('static/'): - from flask import abort - abort(404) # Let Flask's native static handling take over - - # For all other paths, serve the React app (SPA routing) - return app.send_static_file('index.html') + return {'error': 'Not Found'}, 404 + try: + # First try to serve from static directory + return app.send_static_file('index.html') + except: + return app.send_static_file('index.html') # Serve markdown files from react-frontend/public/content for React to fetch @app.route('/content/') @@ -470,6 +443,11 @@ def unauthorized_handler(): return jsonify({'error': 'Authentication required'}), 401 return redirect(url_for('auth.login')) + # Add a health check endpoint + @app.route('/health') + def health_check(): + return {"status": "healthy"}, 200 + return app # Create the app instance for deployment (needed for gunicorn/Azure) From bd7bfceaf0aa216abe56b1a06f1e920380b181f3 Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 18:19:46 -0500 Subject: [PATCH 4/8] fixes to ensure react app is build before backend/static so they are ready to be served --- .github/workflows/azure-webapps-python.yml | 35 +++++++++++++--------- Dockerfile | 10 +++++-- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/.github/workflows/azure-webapps-python.yml b/.github/workflows/azure-webapps-python.yml index a71593a4..952a12e4 100644 --- a/.github/workflows/azure-webapps-python.yml +++ b/.github/workflows/azure-webapps-python.yml @@ -22,18 +22,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python version - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - cache: 'pip' - cache-dependency-path: '**/requirements.txt' - - - name: Install Python dependencies - run: | - python -m pip install --upgrade pip - pip install -r backend/requirements.txt - - name: Set up Node.js uses: actions/setup-node@v3 with: @@ -41,7 +29,7 @@ jobs: cache: 'npm' cache-dependency-path: '**/package-lock.json' - - name: Build React frontend with CI=false to prevent warnings as errors + - name: Build React frontend run: | cd react-frontend npm ci @@ -49,10 +37,29 @@ jobs: npm run build echo "React build completed successfully" + - name: Copy React build to backend/static + run: | + rm -rf backend/static/* + cp -r react-frontend/build/* backend/static/ + echo "React build files copied to backend/static" + ls -la backend/static + + - name: Set up Python version + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: 'pip' + cache-dependency-path: '**/requirements.txt' + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install -r backend/requirements.txt + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - name: Log in to GitHub Container Registry + - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ${{ env.DOCKER_REGISTRY }} diff --git a/Dockerfile b/Dockerfile index 8ac80200..8ed92f89 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,11 +56,15 @@ RUN mkdir -p backend/uploads RUN mkdir -p instance && \ chmod 777 instance -# Copy the React frontend build directly to backend/static - this is the main location -COPY react-frontend/build/ backend/static/ +# Ensure static directory exists and is writable +RUN mkdir -p backend/static && \ + chmod 777 backend/static + +# Copy the React frontend build files +COPY backend/static/ backend/static/ # Create a symbolic link for backwards compatibility -RUN ln -s /app/backend/static /app/static +RUN ln -sf /app/backend/static /app/static # Display detailed debug information about static files RUN echo "=== DEBUG: Static File Structure ===" && \ From 70b3d3ebaa5e6176d94d451dfe2ab68a9fb134bf Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 18:24:55 -0500 Subject: [PATCH 5/8] health check --- .github/workflows/azure-webapps-python.yml | 21 +++++++++++++++++++++ Dockerfile | 10 ++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/azure-webapps-python.yml b/.github/workflows/azure-webapps-python.yml index 952a12e4..81a03f78 100644 --- a/.github/workflows/azure-webapps-python.yml +++ b/.github/workflows/azure-webapps-python.yml @@ -126,3 +126,24 @@ jobs: SECRET_KEY="${{ secrets.SECRET_KEY }}" \ DATABASE_URL="${{ secrets.DATABASE_URL }}" \ GEMINI_API_KEY="${{ secrets.GEMINI_API_KEY }}" + + - name: 'Configure Health Check' + uses: azure/cli@v1 + with: + azcliversion: latest + inlineScript: | + # Configure health check settings + az webapp config set \ + --resource-group ${{ secrets.AZURE_RESOURCE_GROUP }} \ + --name ${{ env.AZURE_WEBAPP_NAME }} \ + --health-check-path /health \ + --health-check-maxretries 3 \ + --health-check-interval 10 + + # Enable container health check monitoring + az webapp config container set \ + --resource-group ${{ secrets.AZURE_RESOURCE_GROUP }} \ + --name ${{ env.AZURE_WEBAPP_NAME }} \ + --enable-app-service-storage true \ + --docker-registry-server-url https://${{ env.DOCKER_REGISTRY }} \ + --health-check-path /health diff --git a/Dockerfile b/Dockerfile index 8ed92f89..5194b0f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,12 @@ FROM python:3.11-slim # Add Azure compatibility label LABEL "com.microsoft.azure.webapp"="true" +# Add health check label +LABEL "health.check.path"="/health" +LABEL "health.check.interval"="30s" +LABEL "health.check.timeout"="10s" +LABEL "health.check.retries"="3" + WORKDIR /app # Install system dependencies for psycopg2, playwright, and other packages @@ -88,5 +94,5 @@ ENV DATABASE_URL="sqlite:////app/instance/instant_apply.db" # Expose the port the app runs on EXPOSE 8000 -# Command to run the application -CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--log-level=debug", "app:app"] \ No newline at end of file +# Add health check configuration to gunicorn +CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--log-level=debug", "--timeout", "120", "--workers", "4", "--threads", "2", "--worker-class", "gthread", "--worker-tmp-dir", "/dev/shm", "--access-logfile", "-", "--error-logfile", "-", "app:app"] \ No newline at end of file From c454cc7027c7e4e394a31b9aa9962d96c2784e4d Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 18:28:25 -0500 Subject: [PATCH 6/8] created backend/static file --- .github/workflows/azure-webapps-python.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/azure-webapps-python.yml b/.github/workflows/azure-webapps-python.yml index 81a03f78..ed6301d6 100644 --- a/.github/workflows/azure-webapps-python.yml +++ b/.github/workflows/azure-webapps-python.yml @@ -39,6 +39,7 @@ jobs: - name: Copy React build to backend/static run: | + mkdir -p backend/static rm -rf backend/static/* cp -r react-frontend/build/* backend/static/ echo "React build files copied to backend/static" From 34a68322c9044f1ee9fe1aa72db38c9f1506087a Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 18:35:12 -0500 Subject: [PATCH 7/8] fixed health check errors with azure cli --- .github/workflows/azure-webapps-python.yml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/azure-webapps-python.yml b/.github/workflows/azure-webapps-python.yml index ed6301d6..dd648dfa 100644 --- a/.github/workflows/azure-webapps-python.yml +++ b/.github/workflows/azure-webapps-python.yml @@ -133,18 +133,26 @@ jobs: with: azcliversion: latest inlineScript: | - # Configure health check settings + # Configure health check settings using generic-configurations az webapp config set \ --resource-group ${{ secrets.AZURE_RESOURCE_GROUP }} \ --name ${{ env.AZURE_WEBAPP_NAME }} \ - --health-check-path /health \ - --health-check-maxretries 3 \ - --health-check-interval 10 + --generic-configurations '{"healthCheckPath": "/health"}' \ + --always-on true - # Enable container health check monitoring + # Configure container settings az webapp config container set \ --resource-group ${{ secrets.AZURE_RESOURCE_GROUP }} \ --name ${{ env.AZURE_WEBAPP_NAME }} \ --enable-app-service-storage true \ - --docker-registry-server-url https://${{ env.DOCKER_REGISTRY }} \ - --health-check-path /health + --docker-registry-server-url https://${{ env.DOCKER_REGISTRY }} + + # Set application settings for health check + az webapp config appsettings set \ + --resource-group ${{ secrets.AZURE_RESOURCE_GROUP }} \ + --name ${{ env.AZURE_WEBAPP_NAME }} \ + --settings \ + WEBSITES_CONTAINER_START_TIME_LIMIT=1800 \ + WEBSITES_ENABLE_APP_SERVICE_STORAGE=true \ + WEBSITE_HEALTHCHECK_MAXPINGFAILURES=3 \ + WEBSITE_HEALTHCHECK_PATH=/health From 9e78bae5a04e2383d3b3ed124ce13054be46857e Mon Sep 17 00:00:00 2001 From: lifee77 Date: Thu, 26 Jun 2025 21:00:52 -0500 Subject: [PATCH 8/8] auto migrate for axure deployed version --- azure-deploy/startup.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/azure-deploy/startup.sh b/azure-deploy/startup.sh index fcda7dd0..5a9fa5fc 100644 --- a/azure-deploy/startup.sh +++ b/azure-deploy/startup.sh @@ -22,6 +22,27 @@ echo "Installed Python packages:" pip freeze | head -n 20 echo "(package list truncated)..." +echo "Running database migrations..." +# Run database migrations (continue even if migrations fail to avoid breaking the app) +cd $SITE_ROOT +python -c " +import sys +sys.path.insert(0, '$SITE_ROOT') +sys.path.insert(0, '$SITE_ROOT/backend') +try: + from backend.app import create_app + from flask_migrate import upgrade + print('Creating app for migrations...') + app = create_app() + with app.app_context(): + print('Running migrations...') + upgrade() + print('✅ Database migrations completed successfully!') +except Exception as e: + print('⚠️ Migration warning (app will still start):', str(e)) + # Don't exit - continue to start the app even if migrations fail +" || echo "⚠️ Migrations failed but continuing startup..." + echo "Starting Gunicorn server..." # Start the Gunicorn server exec gunicorn --bind=0.0.0.0:8000 --timeout 600 app:app \ No newline at end of file