UNPKG

gcx

Version:

An API and CLI for deploying Google Cloud Functions in Node.js.

233 lines (209 loc) 8.84 kB
#!/usr/bin/env node import fs from 'node:fs'; import path from 'node:path'; import process from 'node:process'; import util from 'node:util'; import meow from 'meow'; import ora from 'ora'; import updateNotifier from 'update-notifier'; import { Deployer, ProgressEvent } from './index.js'; const package_ = JSON.parse(fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf8')); updateNotifier({ pkg: package_ }).notify(); const cli = meow(` Usage $ gcx deploy FUNCTION_NAME Positional arguments FUNCTION_NAME ID of the function or fully qualified identifier for the function. This positional must be specified if any of the other arguments in this group are specified. Flags --description=DESCRIPTION User-provided description of a function. --region=REGION The Cloud region for the function. --runtime=RUNTIME The runtime in which to run the function. Defaults to nodejs14. ◆ nodejs10: Node.js 10nodejs12: Node.js 12nodejs14: Node.js 14python37: Python 3.7python38: Python 3.8python39: Python 3.9go111: Go 1.11go113: Go 1.13java11: Java 11dotnet3: .NET Framework 3ruby26: Ruby 2.6 --target-dir The directory that contains the sources to be deployed. Defaults to the current working directory. --retry If specified, then the function will be retried in case of a failure. --memory=MEMORY Limit on the amount of memory the function can use. Allowed values are: 128MB, 256MB, 512MB, 1024MB, and 2048MB. By default, a new function is limited to 256MB of memory. When deploying an update to an existing function, the function will keep its old memory limit unless you specify this flag. --project=PROJECT_ID Project Id of the GCP project. --trigger-bucket=BUCKET Google Cloud Storage bucket name. Every change in files in this bucket will trigger function execution. --trigger-http Function will be assigned an endpoint, which you can view by using the describe command. Any HTTP request (of a supported type) to the endpoint will trigger function execution. Supported HTTP request types are: POST, PUT, GET, DELETE, and OPTIONS. --trigger-topic=TRIGGER_TOPIC Name of Pub/Sub topic. Every message published in this topic will trigger function execution with message contents passed as input data. --trigger-event=EVENT_TYPE Specifies which action should trigger the function. For a list of acceptable values, call functions event-types list. --trigger-resource=RESOURCE Specifies which resource from --trigger-event is being observed. E.g. if --trigger-event is providers/cloud.storage/eventTypes/object.change, --trigger-resource must be a bucket name. For a list of expected resources, call functions event-types list. --timeout=TIMEOUT The function execution timeout, e.g. 30s for 30 seconds. Defaults to original value for existing function or 60 seconds for new functions. Cannot be more than 540s. --entryPoint=ENTRYPOINT By default when a Google Cloud Function is triggered, it executes a JavaScript function with the same name. Or, if it cannot find a function with the same name, it executes a function named function. You can use this flag to override the default behavior, by specifying the name of a JavaScript function that will be executed when the Google Cloud Function is triggered. --network=NETWORK The VPC Network that this cloud function can connect to. It can be either the fully-qualified URI, or the short name of the network resource. If the short network name is used, the network must belong to the same project. Otherwise, it must belong to a project within the same organization. The format of this field is either projects/{project}/global/networks/{network} or {network}, where {project} is a project id where the network is defined, and {network} is the short name of the network. --max-instances=MAX_INSTANCES The limit on the maximum number of function instances that may coexist at a given time. This feature is currently in alpha, available only for whitelisted users. --vpc-connector=VPC_CONNECTOR Name of VPC connector. Connector name must be in the fully-qualified format of projects/{project}/locations/{region}/connectors/{connector_name} or {connector_name} Select a VPC connector to access a Serverless VPC network --help Show this command. Examples $ gcx deploy some-cloud-function `, { importMeta: import.meta, flags: { description: { type: 'string' }, entryPoint: { type: 'string' }, runtime: { type: 'string' }, timeout: { type: 'string' }, network: { type: 'string' }, retry: { type: 'boolean' }, memory: { type: 'string' }, project: { type: 'string' }, projectId: { type: 'string' }, triggerBucket: { type: 'string' }, triggerHttp: { type: 'boolean' }, triggerTopic: { type: 'string' }, triggerResource: { type: 'string' }, triggerEvent: { type: 'string' }, targetDir: { type: 'string' }, region: { type: 'string' }, maxInstances: { type: 'string' }, vpcConnector: { type: 'string' }, }, }); async function main() { if (cli.input.length !== 2) { cli.showHelp(); return; } switch (cli.input[0]) { case 'deploy': { const start = Date.now(); const options = cli.flags; options.name = cli.input[1]; const targetDirectory = options.targetDir || process.cwd(); const hasIgnore = await hasIgnoreFile(targetDirectory); if (!hasIgnore) { await generateIgnoreFile(targetDirectory); } const spinny = ora('Initializing deployment...').start(); const deployinator = new Deployer(options); deployinator .on(ProgressEvent.PACKAGING, () => { spinny.stopAndPersist({ symbol: '🤖', text: 'Deployment initialized.', }); spinny.start('Packaging sources...'); }) .on(ProgressEvent.UPLOADING, () => { spinny.stopAndPersist({ symbol: '📦', text: 'Source code packaged.', }); spinny.start('Uploading source...'); }) .on(ProgressEvent.DEPLOYING, () => { spinny.stopAndPersist({ symbol: '🛸', text: 'Source uploaded to cloud.', }); spinny.start('Deploying function...'); }) .on(ProgressEvent.COMPLETE, () => { const seconds = (Date.now() - start) / 1000; spinny.stopAndPersist({ symbol: '🚀', text: `Function deployed in ${seconds} seconds.`, }); }); await deployinator.deploy(); break; } default: { cli.showHelp(); } } } async function generateIgnoreFile(targetDirectory) { console.log(` 🤖 I generated a '.gcloudignore' file in the target directory. This file contains a list of glob patterns that should be ingored in your deployment. It works just like a .gitignore file 💜 `); await new Promise((resolve, reject) => { // eslint-disable-next-line unicorn/prefer-module fs.createReadStream(path.join(__dirname, '../../src/.gcloudignore')) .pipe(fs.createWriteStream(path.join(targetDirectory, '.gcloudignore'))) .on('error', reject) .on('close', resolve); }); } /** * Checks to see if a given directory has a `.gcloudignore` file. * @param targetDir The directory with the sources to deploy. */ async function hasIgnoreFile(targetDirectory) { const ignoreFile = path.join(targetDirectory, '.gcloudignore'); try { await util.promisify(fs.stat)(ignoreFile); return true; } catch { return false; } } await main();