Implement ErrorBoundary and LazyPage components for improved error ha… #26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy to PythonAnywhere | |
| on: | |
| push: | |
| branches: | |
| - main | |
| jobs: | |
| build_and_deploy: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Install dependencies and build | |
| run: npm ci && npm run build | |
| - name: Deploy to PythonAnywhere | |
| env: | |
| PA_API_TOKEN: ${{ secrets.PA_API_TOKEN }} | |
| PA_USERNAME: ${{ secrets.PA_USERNAME }} | |
| PA_DOMAIN: ${{ secrets.PA_DOMAIN }} | |
| run: | | |
| set -e | |
| API_BASE="https://www.pythonanywhere.com/api/v0/user/${PA_USERNAME}" | |
| # Clear the existing static files directory on PythonAnywhere | |
| REMOTE_DIR="/home/${PA_USERNAME}/mysite/static" | |
| # Delete old files | |
| echo "Cleaning remote directory..." | |
| file_list=$(curl -s -H "Authorization: Token ${PA_API_TOKEN}" \ | |
| "${API_BASE}/files/path${REMOTE_DIR}/") | |
| upload_file() { | |
| local file="$1" | |
| local url="$2" | |
| local max_retries=3 | |
| for attempt in $(seq 1 $max_retries); do | |
| response=$(curl -s -w "\n%{http_code}" -X POST \ | |
| -H "Authorization: Token ${PA_API_TOKEN}" \ | |
| -F "content=@\"${file}\"" \ | |
| "$url") | |
| http_code=$(echo "$response" | tail -1) | |
| body=$(echo "$response" | sed '$d') | |
| if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then | |
| return 0 | |
| elif echo "$body" | grep -q "throttled"; then | |
| wait_time=$(echo "$body" | python3 -c " | |
| import sys, json, re | |
| try: | |
| data = json.load(sys.stdin) | |
| match = re.search(r'(\d+)', data.get('detail', '')) | |
| print(int(match.group(1)) + 2 if match else 60) | |
| except: print(60)" 2>/dev/null) | |
| echo " Throttled, waiting ${wait_time}s (attempt ${attempt}/${max_retries})..." | |
| sleep "$wait_time" | |
| else | |
| echo " Upload failed (HTTP ${http_code}): ${body}" | |
| return 1 | |
| fi | |
| done | |
| echo " Max retries reached for ${file}" | |
| return 1 | |
| } | |
| # Upload WSGI file for SPA routing | |
| WSGI_REMOTE="/home/${PA_USERNAME}/mysite/wsgi.py" | |
| echo "Uploading wsgi.py..." | |
| upload_file "wsgi.py" "${API_BASE}/files/path${WSGI_REMOTE}" | |
| echo "Uploading new build..." | |
| find dist -type f -print0 | while IFS= read -r -d '' file; do | |
| relative_path="${file#dist/}" | |
| remote_path="${REMOTE_DIR}/${relative_path}" | |
| encoded_path=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "$remote_path") | |
| echo "Uploading ${relative_path}..." | |
| upload_file "$file" "${API_BASE}/files/path${encoded_path}" | |
| done | |
| echo "Reloading web app..." | |
| reload_response=$(curl -s -X POST \ | |
| -H "Authorization: Token ${PA_API_TOKEN}" \ | |
| "${API_BASE}/webapps/${PA_DOMAIN}/reload/") | |
| echo "Reload response: ${reload_response}" | |
| echo "Deployment complete!" |