diff --git a/.github/workflows/deployment-e2e.yml b/.github/workflows/deployment-e2e.yml index b1ca84a78a..b99ca75f61 100644 --- a/.github/workflows/deployment-e2e.yml +++ b/.github/workflows/deployment-e2e.yml @@ -9,8 +9,16 @@ jobs: strategy: fail-fast: false matrix: - plan: ['cf-worker', 'azure-function', 'aws-lambda', 'vercel-function'] + plan: + [ + 'cf-worker', + 'cf-modules', + 'azure-function', + 'aws-lambda', + 'vercel-function', + ] name: e2e / ${{ matrix.plan }} + runs-on: ubuntu-latest if: github.event.pull_request.head.repo.full_name == github.repository steps: diff --git a/e2e/index.ts b/e2e/index.ts index d2bfe857a4..e27b40d647 100644 --- a/e2e/index.ts +++ b/e2e/index.ts @@ -2,6 +2,7 @@ import { LocalWorkspace } from '@pulumi/pulumi/automation' import { awsLambdaDeployment } from './tests/aws-lambda' import { azureFunctionDeployment } from './tests/azure-function' import { cloudFlareDeployment } from './tests/cf-worker' +import { cfModulesDeployment } from './tests/cf-modules' import { dockerDeployment } from './tests/docker' import { DeploymentConfiguration } from './types' import { env, getCommitId } from './utils' @@ -9,6 +10,7 @@ import { vercelDeployment } from './tests/vercel' const AVAILABLE_TEST_PLANS = { 'cf-worker': cloudFlareDeployment, + 'cf-modules': cfModulesDeployment, 'azure-function': azureFunctionDeployment, 'aws-lambda': awsLambdaDeployment, 'vercel-function': vercelDeployment, diff --git a/e2e/tests/cf-modules.ts b/e2e/tests/cf-modules.ts new file mode 100644 index 0000000000..1ca548e64d --- /dev/null +++ b/e2e/tests/cf-modules.ts @@ -0,0 +1,6 @@ +import { createCFDeployment } from './create-cf-deployment' + +export const cfModulesDeployment = createCFDeployment( + 'cloudflare-modules', + true, +) diff --git a/e2e/tests/cf-worker.ts b/e2e/tests/cf-worker.ts index aec04cea03..8d6f943a39 100644 --- a/e2e/tests/cf-worker.ts +++ b/e2e/tests/cf-worker.ts @@ -1,80 +1,3 @@ -import { Stack } from '@pulumi/pulumi/automation' -import { DeploymentConfiguration } from '../types' -import * as cf from '@pulumi/cloudflare' -import { - assertGraphiQL, - assertQuery, - env, - execPromise, - fsPromises, - waitForEndpoint, -} from '../utils' -import * as pulumi from '@pulumi/pulumi' -import { version } from '@pulumi/cloudflare/package.json' +import { createCFDeployment } from './create-cf-deployment' -export const cloudFlareDeployment: DeploymentConfiguration<{ - workerUrl: string -}> = { - prerequisites: async (stack: Stack) => { - console.info('\t\tℹ️ Installing Pulumi CF plugin...') - // Intall Pulumi CF Plugin - await stack.workspace.installPlugin('cloudflare', version, 'resource') - - // Build and bundle the worker - console.info('\t\tℹ️ Bundling the CF Worker....') - await execPromise('yarn build', { - cwd: '../examples/service-worker', - }) - }, - config: async (stack: Stack) => { - // Configure the Pulumi environment with the CloudFlare credentials - // This will allow Pulummi program to just run without caring about secrets/configs. - // See: https://www.pulumi.com/registry/packages/cloudflare/installation-configuration/ - await stack.setConfig('cloudflare:apiToken', { - value: env('CLOUDFLARE_API_TOKEN'), - }) - await stack.setConfig('cloudflare:accountId', { - value: env('CLOUDFLARE_ACCOUNT_ID'), - }) - }, - program: async () => { - const stackName = pulumi.getStack() - const workerUrl = `e2e.graphql-yoga.com/${stackName}` - - // Deploy CF script as Worker - const workerScript = new cf.WorkerScript('worker', { - content: await fsPromises.readFile( - '../examples/service-worker/dist/index.js', - 'utf-8', - ), - secretTextBindings: [ - { - name: 'GRAPHQL_ROUTE', - text: `/${stackName}`, - }, - { - name: 'DEBUG', - text: 'true', - }, - ], - name: stackName, - }) - - // Create a nice route for easy testing - new cf.WorkerRoute('worker-route', { - scriptName: workerScript.name, - pattern: workerUrl, - zoneId: env('CLOUDFLARE_ZONE_ID'), - }) - - return { - workerUrl: `https://${workerUrl}`, - } - }, - test: async ({ workerUrl }) => { - console.log(`ℹ️ CloudFlare Worker deployed to URL: ${workerUrl.value}`) - await waitForEndpoint(workerUrl.value, 5, 10000) - await assertGraphiQL(workerUrl.value) - await assertQuery(workerUrl.value) - }, -} +export const cloudFlareDeployment = createCFDeployment('service-worker') diff --git a/e2e/tests/create-cf-deployment.ts b/e2e/tests/create-cf-deployment.ts new file mode 100644 index 0000000000..6a1752a06f --- /dev/null +++ b/e2e/tests/create-cf-deployment.ts @@ -0,0 +1,86 @@ +import { Stack } from '@pulumi/pulumi/automation' +import { DeploymentConfiguration } from '../types' +import * as cf from '@pulumi/cloudflare' +import { + assertGraphiQL, + assertQuery, + env, + execPromise, + fsPromises, + waitForEndpoint, +} from '../utils' +import * as pulumi from '@pulumi/pulumi' +import { version } from '@pulumi/cloudflare/package.json' + +export function createCFDeployment( + projectName: string, + isModule = false, +): DeploymentConfiguration<{ + workerUrl: string +}> { + return { + prerequisites: async (stack: Stack) => { + console.info('\t\tℹ️ Installing Pulumi CF plugin...') + // Intall Pulumi CF Plugin + await stack.workspace.installPlugin('cloudflare', version, 'resource') + + // Build and bundle the worker + console.info('\t\tℹ️ Bundling the CF Worker....') + await execPromise('yarn build', { + cwd: '../examples/' + projectName, + }) + }, + config: async (stack: Stack) => { + // Configure the Pulumi environment with the CloudFlare credentials + // This will allow Pulummi program to just run without caring about secrets/configs. + // See: https://www.pulumi.com/registry/packages/cloudflare/installation-configuration/ + await stack.setConfig('cloudflare:apiToken', { + value: env('CLOUDFLARE_API_TOKEN'), + }) + await stack.setConfig('cloudflare:accountId', { + value: env('CLOUDFLARE_ACCOUNT_ID'), + }) + }, + program: async () => { + const stackName = pulumi.getStack() + const workerUrl = `e2e.graphql-yoga.com/${stackName}` + + // Deploy CF script as Worker + const workerScript = new cf.WorkerScript('worker', { + content: await fsPromises.readFile( + `../examples/${projectName}/dist/index.js`, + 'utf-8', + ), + module: isModule, + secretTextBindings: [ + { + name: 'GRAPHQL_ROUTE', + text: `/${stackName}`, + }, + { + name: 'DEBUG', + text: 'true', + }, + ], + name: stackName, + }) + + // Create a nice route for easy testing + new cf.WorkerRoute('worker-route', { + scriptName: workerScript.name, + pattern: workerUrl, + zoneId: env('CLOUDFLARE_ZONE_ID'), + }) + + return { + workerUrl: `https://${workerUrl}`, + } + }, + test: async ({ workerUrl }) => { + console.log(`ℹ️ CloudFlare Worker deployed to URL: ${workerUrl.value}`) + await waitForEndpoint(workerUrl.value, 5, 10000) + await assertGraphiQL(workerUrl.value) + await assertQuery(workerUrl.value) + }, + } +} diff --git a/examples/cloudflare-modules/src/index.ts b/examples/cloudflare-modules/src/index.ts index 89dcd729aa..a054eae02b 100644 --- a/examples/cloudflare-modules/src/index.ts +++ b/examples/cloudflare-modules/src/index.ts @@ -1,4 +1,6 @@ // src/index.mjs import { createServer } from '@graphql-yoga/common' -export default createServer() +const { fetch } = createServer() + +export default { fetch }