Add Netlify deploy workflow and unify edge handler
Introduces a new GitHub Actions workflow for deploying to Netlify, updates the Vercel workflow name, and refactors the edge function handler to support both Netlify and Vercel platforms with runtime detection. Adds Netlify-specific configuration and redirect files to enable shared handler logic, reducing code duplication and simplifying multi-platform deployments.
This commit is contained in:
1 parent
18ec41125f
commit
0e7aad4755
3 files changed
+113
-36
No files matched your search
@@ -0,0 +1,41 @@
|
|||||||
|
name: Deploy to Netlify
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Sync to Pages and Functions"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
deployments: write
|
||||||
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout functions branch
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
ref: functions
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install Netlify CLI
|
||||||
|
run: npm install --global netlify-cli@latest
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
run: netlify deploy --prod --dir=. --auth=${{ secrets.NETLIFY_AUTH_TOKEN }} --site=${{ secrets.NETLIFY_SITE_ID }}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Deploy to Vercel Functions
|
name: Deploy to Vercel
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
workflow_run:
|
||||||
|
|||||||
+71
-35
@@ -212,7 +212,7 @@ jobs:
|
|||||||
cp package-lock.json /tmp/functions-conversion/ 2>/dev/null || true
|
cp package-lock.json /tmp/functions-conversion/ 2>/dev/null || true
|
||||||
cp LICENSE /tmp/functions-conversion/
|
cp LICENSE /tmp/functions-conversion/
|
||||||
|
|
||||||
- name: Create Vercel Edge Function handler
|
- name: Create Edge Function handler
|
||||||
run: |
|
run: |
|
||||||
mkdir -p /tmp/functions-conversion/api
|
mkdir -p /tmp/functions-conversion/api
|
||||||
cat > /tmp/functions-conversion/api/index.js << 'EOF'
|
cat > /tmp/functions-conversion/api/index.js << 'EOF'
|
||||||
@@ -237,51 +237,56 @@ jobs:
|
|||||||
import { handleRequest } from '../src/index.js';
|
import { handleRequest } from '../src/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vercel Edge Function handler for all routes.
|
* Edge Function handler.
|
||||||
*
|
*
|
||||||
* This adapter enables Xget to run on Vercel's Edge Runtime by mapping
|
* @param {Request} request - Standard Web API Request object
|
||||||
* Vercel's environment model to Cloudflare Workers' expected format.
|
* @param {Object} [context] - Platform-specific context (Netlify only)
|
||||||
*
|
* @param {Object} [context.geo] - Geolocation data (Netlify)
|
||||||
* The Vercel Edge Runtime uses standard Web APIs (Request, Response, fetch),
|
* @param {string} [context.ip] - Client IP address (Netlify)
|
||||||
* making it compatible with the existing Cloudflare Workers code.
|
* @param {Object} [context.env] - Environment variables (Netlify)
|
||||||
*
|
* @param {Function} [context.waitUntil] - Background task extension (Netlify)
|
||||||
* @param {Request} request - Standard Web API Request
|
|
||||||
* @returns {Promise<Response>} Standard Web API Response
|
* @returns {Promise<Response>} Standard Web API Response
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // This is called automatically by Vercel Edge Runtime
|
* // Netlify invokes with context
|
||||||
* // Runtime invokes: handler(request)
|
* handler(request, { geo: {...}, ip: '1.2.3.4', env: {...}, waitUntil: fn })
|
||||||
* // Returns: Response with proxied content
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Environment variables usage
|
* // Vercel invokes without context
|
||||||
* // Vercel dashboard or vercel.json: TIMEOUT_SECONDS = "60"
|
* handler(request)
|
||||||
* // process.env contains: { TIMEOUT_SECONDS: "60" }
|
|
||||||
* // Mapped to env object and passed to handleRequest
|
|
||||||
*/
|
*/
|
||||||
export default async function handler(request) {
|
export default async function handler(request, context) {
|
||||||
// Map process.env to Cloudflare Workers env format
|
// Detect runtime environment
|
||||||
|
const isNetlify = context && (context.geo !== undefined || context.ip !== undefined);
|
||||||
|
|
||||||
|
// Normalize environment variables
|
||||||
|
const envSource = isNetlify && context.env ? context.env : process.env;
|
||||||
const env = {
|
const env = {
|
||||||
TIMEOUT_SECONDS: process.env.TIMEOUT_SECONDS,
|
TIMEOUT_SECONDS: envSource.TIMEOUT_SECONDS,
|
||||||
MAX_RETRIES: process.env.MAX_RETRIES,
|
MAX_RETRIES: envSource.MAX_RETRIES,
|
||||||
RETRY_DELAY_MS: process.env.RETRY_DELAY_MS,
|
RETRY_DELAY_MS: envSource.RETRY_DELAY_MS,
|
||||||
CACHE_DURATION: process.env.CACHE_DURATION,
|
CACHE_DURATION: envSource.CACHE_DURATION,
|
||||||
ALLOWED_METHODS: process.env.ALLOWED_METHODS,
|
ALLOWED_METHODS: envSource.ALLOWED_METHODS,
|
||||||
ALLOWED_ORIGINS: process.env.ALLOWED_ORIGINS,
|
ALLOWED_ORIGINS: envSource.ALLOWED_ORIGINS,
|
||||||
MAX_PATH_LENGTH: process.env.MAX_PATH_LENGTH,
|
MAX_PATH_LENGTH: envSource.MAX_PATH_LENGTH,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create minimal execution context
|
// Create normalized execution context
|
||||||
// Note: Vercel Edge Runtime doesn't support waitUntil or passThroughOnException
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
waitUntil: (promise) => {
|
waitUntil: isNetlify && context.waitUntil
|
||||||
// No-op: Vercel doesn't support background tasks
|
? (promise) => context.waitUntil(promise)
|
||||||
// Cache writes will run synchronously instead
|
: (promise) => {
|
||||||
console.warn('waitUntil is not supported in Vercel Edge Runtime');
|
// No-op on Vercel: background tasks not supported
|
||||||
},
|
// Cache writes will run synchronously instead
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.warn('waitUntil is not supported in Vercel Edge Runtime');
|
||||||
|
}
|
||||||
|
},
|
||||||
passThroughOnException: () => {
|
passThroughOnException: () => {
|
||||||
// No-op: Vercel-specific error handling
|
// Not supported on either platform in this context
|
||||||
console.warn('passThroughOnException is not supported in Vercel Edge Runtime');
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.warn('passThroughOnException is not universally supported');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -289,7 +294,7 @@ jobs:
|
|||||||
return handleRequest(request, env, ctx);
|
return handleRequest(request, env, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vercel Edge Runtime configuration
|
// Vercel Edge Runtime configuration (ignored by Netlify)
|
||||||
export const config = {
|
export const config = {
|
||||||
runtime: 'edge',
|
runtime: 'edge',
|
||||||
};
|
};
|
||||||
@@ -323,6 +328,37 @@ jobs:
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
- name: Create netlify.toml
|
||||||
|
run: |
|
||||||
|
cd /tmp/functions-conversion
|
||||||
|
cat > netlify.toml << 'EOF'
|
||||||
|
[[edge_functions]]
|
||||||
|
function = "edge-handler"
|
||||||
|
path = "/*"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
publish = "."
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Create Netlify Edge Function redirect
|
||||||
|
run: |
|
||||||
|
cd /tmp/functions-conversion
|
||||||
|
mkdir -p netlify/edge-functions
|
||||||
|
cat > netlify/edge-functions/edge-handler.js << 'EOF'
|
||||||
|
/**
|
||||||
|
* Netlify Edge Function entry point.
|
||||||
|
*
|
||||||
|
* This file serves as a redirect to the edge function handler
|
||||||
|
* located at /api/index.js. Both Netlify and Vercel can use the same
|
||||||
|
* handler code, with platform detection handling the differences.
|
||||||
|
*
|
||||||
|
* Netlify requires edge functions to be in netlify/edge-functions/,
|
||||||
|
* while Vercel uses /api/ directory. This approach maintains a single
|
||||||
|
* source of truth at /api/index.js.
|
||||||
|
*/
|
||||||
|
export { default, config } from '../../api/index.js';
|
||||||
|
EOF
|
||||||
|
|
||||||
- name: Export handleRequest from src/index.js
|
- name: Export handleRequest from src/index.js
|
||||||
run: |
|
run: |
|
||||||
cd /tmp/functions-conversion
|
cd /tmp/functions-conversion
|
||||||
|
|||||||
Reference in new issue
Block a user