Use postDeploy and preUndeploy scripts to automate configurations for your Project and external systems. It is common for any integration to require the creation of specific resources during the deployment lifecycle in the Composable Commerce API, such as [Types](https://docs.commercetools.com/connect/api/projects/types), [API Extensions](https://docs.commercetools.com/connect/api/projects/api-extensions), or [Subscriptions](https://docs.commercetools.com/connect/api/projects/subscriptions). You can define scripts in `connect.yaml` that run on different deployment stages, which allows Connect to create and modify those resources. ## JavaScript/TypeScript ### postDeploy `postDeploy` runs after a successful deployment of the Connect application and is useful when you need to set up an API Extension or Subscription required to trigger your Connector endpoint. `postDeploy` has access to extra environment variables depending on the application type. (a CSV formatted table follows. The first line are the column names.) Environment variable,Application type,Description `CONNECT_SERVICE_URL`,Service,The public URL of the Connect application, should be used when setting up an [API Extension](https://docs.commercetools.com/connect/api/projects/api-extensions) in the Composable Commerce API. `CONNECT_SUBSCRIPTION_DESTINATION`,Event,The subscription destination type for the Connect Deployment. Should be used when setting up a [Subscription](https://docs.commercetools.com/connect/api/projects/subscriptions) in the Composable Commerce API. Supported values are `SNS` and `GoogleCloudPubSub`. `CONNECT_GCP_PROJECT_ID`,Event,Google Cloud Platform (GCP) project ID. Should be used when setting up a [Subscription](https://docs.commercetools.com/connect/api/projects/subscriptions) in the Composable Commerce API. `CONNECT_GCP_TOPIC_NAME`,Event,GCP [Pub/Sub](https://docs.commercetools.com/connect/api/projects/subscriptions#googlecloudpubsubdestination) topic name. Should be used when setting up a Subscription in the Composable Commerce API . `CONNECT_AWS_TOPIC_ARN`,Event,AWS [SNS](https://docs.commercetools.com/connect/api/projects/subscriptions#snsdestination) topic ARN. Should be used when setting up a Subscription in the Composable Commerce API. ### preUndeploy `preUndeploy` runs before the Connector is undeployed and is useful when deleting unused resources from the Composable Commerce API. ### Example service application ```yaml # connect.yaml # ... applicationType: service scripts: postDeploy: node post-deploy.js preUndeploy: node pre-undeploy.js # ... ``` ```javascript // post-deploy.js async function run() { try { const EXTENSION_KEY = 'myconnector-extension-key'; const serviceUrl = process.env.CONNECT_SERVICE_URL; // ... const result = await apiRoot .extensions() .post({ body: { key: EXTENSION_KEY, destination: { type: 'HTTP', url: serviceUrl, }, triggers: [ { resourceTypeId: 'cart', actions: ['Update'], }, ], }, }) .execute(); } catch (error) { process.stderr.write(`Post-deploy failed: ${error.message}\n`); process.exitCode = 1; } } run(); ``` ```javascript // pre-undeploy.js async function run() { try { const EXTENSION_KEY = 'myconnector-extension-key'; const serviceUrl = process.env.CONNECT_SERVICE_URL; // ... const result = await apiRoot .extensions() .delete({ body: { key: EXTENSION_KEY, }, }) .execute(); } catch (error) { process.stderr.write(`Post-deploy failed: ${error.message}\n`); process.exitCode = 1; } } run(); ``` ### Example event application ```yaml # connect.yaml # ... applicationType: event scripts: postDeploy: node post-deploy.js preUndeploy: node pre-undeploy.js # ... ``` ```javascript // post-deploy.js async function run() { try { await createSubscription(); } catch (error) { process.stderr.write(`Post-deploy failed: ${error.message}\n`); process.exitCode = 1; } } async function createSubscription() { const SUBSCRIPTION_KEY = 'myconnector-subscription-key'; const subscriptionDestination = process.env.CONNECT_SUBSCRIPTION_DESTINATION; // Check if subscription already exists const { body: { results: subscriptions }, } = await apiRoot .subscriptions() .get({ queryArgs: { where: `key = "${SUBSCRIPTION_KEY}"`, }, }) .execute(); // Delete existing subscription if found if (subscriptions.length > 0) { const subscription = subscriptions[0]; await apiRoot .subscriptions() .withKey({ key: SUBSCRIPTION_KEY }) .delete({ queryArgs: { version: subscription.version, }, }) .execute(); } // Google Cloud Pub/Sub subscription if ( subscriptionDestination === null || subscriptionDestination === 'GoogleCloudPubSub' ) { const topicName = process.env.CONNECT_GCP_TOPIC_NAME; const projectId = process.env.CONNECT_GCP_PROJECT_ID; await apiRoot .subscriptions() .post({ body: { key: SUBSCRIPTION_KEY, destination: { type: 'GoogleCloudPubSub', topic: topicName, projectId, }, messages: [ { resourceTypeId: 'customer', types: ['CustomerCreated'], }, ], }, }) .execute(); return; } // AWS SNS subscription if (subscriptionDestination === 'SNS') { const topicArn = process.env.CONNECT_AWS_TOPIC_ARN; await apiRoot .subscriptions() .post({ body: { key: SUBSCRIPTION_KEY, destination: { type: 'SNS', topicArn, authenticationMode: 'IAM', }, messages: [ { resourceTypeId: 'customer', types: ['CustomerCreated'], }, ], }, }) .execute(); return; } throw new Error( `Unknown subscription destination type: ${subscriptionDestination}` ); } run(); ``` ```javascript // pre-undeploy.js async function run() { try { const SUBSCRIPTION_KEY = 'myconnector-subscription-key'; // ... const result = await apiRoot .subscriptions() .delete({ body: { key: SUBSCRIPTION_KEY } }) .execute(); } catch (error) { process.stderr.write(`Post-deploy failed: ${error.message}\n`); process.exitCode = 1; } } run(); ```