<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Corey Sutphin</title>
    <description>The latest articles on DEV Community by Corey Sutphin (@coreysutphin).</description>
    <link>https://dev.to/coreysutphin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F350703%2F004a6b51-a337-4bc7-aa8f-3b97af4cb7d4.jpeg</url>
      <title>DEV Community: Corey Sutphin</title>
      <link>https://dev.to/coreysutphin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coreysutphin"/>
    <language>en</language>
    <item>
      <title>How to automatically create and destroy Heroku Apps using Bitbucket Pipelines</title>
      <dc:creator>Corey Sutphin</dc:creator>
      <pubDate>Mon, 30 Mar 2020 15:03:19 +0000</pubDate>
      <link>https://dev.to/thinknimble/how-to-automatically-create-and-destroy-heroku-apps-using-bitbucket-pipelines-2509</link>
      <guid>https://dev.to/thinknimble/how-to-automatically-create-and-destroy-heroku-apps-using-bitbucket-pipelines-2509</guid>
      <description>&lt;p&gt;You may have heard of &lt;a href="https://www.heroku.com/platform" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;, a service that greatly simplifies the process of building, deploying, and hosting your web applications. If you've already used Heroku, then you know that deploying is as easy as running &lt;code&gt;git push heroku master&lt;/code&gt;. In 2016 Heroku launched a feature called &lt;a href="https://devcenter.heroku.com/articles/github-integration-review-apps" rel="noopener noreferrer"&gt;Review Apps&lt;/a&gt;, which are temporary, disposable apps that are created whenever a pull request is opened. They integrate directly with your Github repository, and are created when the pull request is opened and destroyed when it is closed. They provide you with a temporary and isolated environment to test your changes in, which becomes very useful in situations where multiple changes are being committed to a repository at once.  If you are using Bitbucket as your version control platform then unfortunately Review Apps are not available to you, however with a little effort we can mimic their functionality. In this guide we will learn how to use the Heroku CLI along with Bitbucket Pipelines to listen for pull requests and programatically create and destroy copies of your application!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that for the rest of this guide when we say app, we are referring to a Heroku app.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Read This If...
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;You are an individual who wants the ability to host multiple versions of an application with different versions at one time.&lt;/li&gt;
&lt;li&gt;You are a team working on multiple features at once, and you want to be able to test the different features in isolation of each other.&lt;/li&gt;
&lt;li&gt;If you were looking to use Review Apps for your project, but are using Bitbucket!&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Over at &lt;a href="https://www.thinknimble.com/" rel="noopener noreferrer"&gt;ThinkNimble&lt;/a&gt; we needed a tool to dynamically spin up versions of our applications containing new features to test them in isolation. Because Review Apps are not integrated with Bitbucket, we had to get creative and chose to create a script that creates an app when a pull request is opened and destroys that app when the pull request is merged. We use Bitbucket Pipelines, a CI/CD platform that integrates directly with your repository, to hook into the pull-request lifecycle of Bitbucket. Pipelines allows you to run services such as automated testing or deployments whenever branches are updated or pull requests are created. These services are configured using a YAML file included at the root of your Bitbucket repository called &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt;. We also utilize the Heroku CLI through a bash script to interact with the Heroku API for managing apps. At the end of the guide we share the full &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; configuration file and bash script necessary to get this automation configured.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;A Heroku API Key with the ability to create and delete apps. You can generate an API key for yourself on your &lt;a href="https://dashboard.heroku.com/account" rel="noopener noreferrer"&gt;Heroku account page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A Bitbucket repository(repo) with &lt;a href="https://bitbucket.org/blog/an-introduction-to-bitbucket-pipelines" rel="noopener noreferrer"&gt;Bitbucket Pipelines&lt;/a&gt; enabled.&lt;/li&gt;
&lt;li&gt;A Bitbucket app password with the ability to read pull request and commit history for your repo. This can be generated by going to the Settings screen of your Bitbucket account. From there go to Access Management -&amp;gt; App Passwords and generate a new password with at least &lt;code&gt;read&lt;/code&gt; permissions for repositories and pull-requests. Concatenate this with your username in the format &lt;code&gt;BitbucketUsername:AppPassword&lt;/code&gt; and save it somewhere secure you can access later. This will be your authentication string to use the Bitbucket API.&lt;/li&gt;
&lt;li&gt;A pre-configured Heroku app for your application.&lt;/li&gt;
&lt;li&gt;Some previous experience with bash is recommended, but not required.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Setting up Heroku and Bitbucket
&lt;/h1&gt;

&lt;p&gt;We need to allow Pipelines to access our Heroku API key, Heroku app name, and Bitbucket authentication string when running our various automation scripts. In the settings section of your repo navigate to Settings -&amp;gt; Pipelines -&amp;gt; Repository Variables. Add a &lt;code&gt;HEROKU_API_KEY&lt;/code&gt;, &lt;code&gt;HEROKU_APP_NAME&lt;/code&gt;, and &lt;code&gt;BITBUCKET_AUTH_STRING&lt;/code&gt; repository variable, filling in the appropriate values. Make sure you check 'Secured' when adding sensitive variables so their values will be masked from any log outputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj8i2exxe7oh6ojyyxl6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj8i2exxe7oh6ojyyxl6u.png" alt="Repository Variables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will allow us to access these variables in our pipeline scripts as &lt;code&gt;$HEROKU_API_KEY&lt;/code&gt;. Since these repository variables are set as environment variables, this &lt;code&gt;HEROKU_API_KEY&lt;/code&gt; variable will also be used to authenticate our requests through the Heroku CLI.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bitbucket Pipelines
&lt;/h1&gt;

&lt;p&gt;First let's take a look at a bare-bones Pipelines configuration file that pushes code to an app whenever the &lt;code&gt;master&lt;/code&gt; branch of our repository is updated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# bitbucket-pipelines.yml&lt;/span&gt;

&lt;span class="c1"&gt;# Change this to your project's node version&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:12.0.0&lt;/span&gt;

&lt;span class="na"&gt;clone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;full&lt;/span&gt;

&lt;span class="c1"&gt;# Deploy the master branch to our app.&lt;/span&gt;
&lt;span class="c1"&gt;# Pulls the Heroku API Key and the name of the app from our&lt;/span&gt;
&lt;span class="c1"&gt;# configured environment variables.&lt;/span&gt;
&lt;span class="na"&gt;herokuAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;herokuAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Heroku App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master -f&lt;/span&gt;

&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Deploy the master branch to our app whenever it is updated&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*herokuAppDeployment&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are not going to be covering all of the set-up of a Pipelines configuration file, but at a high-level we are defining a pipeline for the &lt;code&gt;master&lt;/code&gt; branch that will run our &lt;code&gt;herokuAppDeployment&lt;/code&gt; script. This script will push the branch up to the git remote of our app. We now need to add a new pipeline to this file that will run on pull requests created/updated from a branch. This pipeline will create a new app for testing the changes added in the branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;reviewAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "Deploy Review App"&lt;/span&gt;

&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Whenever a pull-request is opened or updated, create/update a Heroku app for the pull-request.&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*reviewAppDeployment&lt;/span&gt;

  &lt;span class="c1"&gt;# Deploy the master branch to our app whenever it is updated&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*herokuAppDeployment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the structure set up to hook into opened and updated pull requests, let's start fleshing out the &lt;code&gt;reviewAppDeployment&lt;/code&gt; script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;reviewAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Download the Heroku CLI&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://cli-assets.heroku.com/install.sh | sh&lt;/span&gt;
    &lt;span class="c1"&gt;# Format the name of the app that will be created.&lt;/span&gt;
    &lt;span class="c1"&gt;# EX: With a branch named 'chatbot-ui' and a repo called 'thinknimble', this will become 'thinknimble-chatbot-ui'.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NEW_APP_NAME=$BITBUCKET_REPO_SLUG-$BRANCH_NAME&lt;/span&gt;
    &lt;span class="c1"&gt;# Export the Heroku authentication token so it can be accessed in other scripts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export HEROKU_API_KEY&lt;/span&gt;
    &lt;span class="c1"&gt;# If an app exists for this branch, push the new code up.&lt;/span&gt;
    &lt;span class="c1"&gt;# Else, create a copy of the main app and push the new branch to it.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;heroku apps:info -a $NEW_APP_NAME &amp;amp;&amp;amp; git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$NEW_APP_NAME.git $BITBUCKET_BRANCH:master -f || /bin/bash copy-app.sh $HEROKU_APP_NAME $NEW_APP_NAME $BITBUCKET_BRANCH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first few steps of the function we download the Heroku CLI and construct the name of the app to be created from the name of the branch and the name of the repo. This name is important as it is later retrieved in order to find the app to delete when the pull request is merged. The final line of the function is where the magic happens. We first poll Heroku to see if the app exists. If it does, push the new code up to the app. If it doesn't, we need to create the new app by copying our main app. We have put the collection of commands required to create a copy of our main app in a bash script called &lt;code&gt;copy-app.sh&lt;/code&gt; located at the root of our application. You ou could include all of the commands in the .yml file itself.&lt;/p&gt;

&lt;p&gt;We now have a script that will run whenever a pull request is opened from a branch, and either update the app created from the branch or create a new app for the branch if it doesn't already exist .In the next section we'll cover the contents of this script and how it creates the new apps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating Apps Using the Heroku CLI
&lt;/h1&gt;

&lt;p&gt;When a pull request is opened for a new branch, we use Heroku CLI commands to create a new app, copy over the configuration and data from the main app, and deploy the source code of the branch. &lt;strong&gt;Some of the steps in this script may not be needed for your specific application, or you may need to add additional steps to configure other services.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# copy-app.sh&lt;/span&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Script to copy an existing app and deploy a specific branch to it.&lt;/span&gt;
&lt;span class="c"&gt;# 1. Creates the new app&lt;/span&gt;
&lt;span class="c"&gt;# 2. Copies over all environment variables from existing app&lt;/span&gt;
&lt;span class="c"&gt;# 3. Provisions a new Postgres database and copies the rows over from the existing app&lt;/span&gt;
&lt;span class="c"&gt;# 4. Deploys the specified branch to the new app&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# USAGE:&lt;/span&gt;
&lt;span class="c"&gt;#   ./copy-app.sh parentApp newApp branchName&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;

&lt;span class="c"&gt;# Defines the parameters passed in to the script. Requires the name of the&lt;/span&gt;
&lt;span class="c"&gt;# parent app, the name of the new app, and the name of the branch to push to the new app to build.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nv"&gt;parentAppName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="nv"&gt;newAppName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;span class="nv"&gt;branchName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;

&lt;span class="c"&gt;# Create the new app&lt;/span&gt;
heroku create &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Add the standard buildpacks for your app. Here we add NodeJS first, then python.&lt;/span&gt;
heroku buildpacks:add heroku/nodejs &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
heroku buildpacks:add heroku/python &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Copy environemnt variables from parent app to new app&lt;/span&gt;
&lt;span class="nv"&gt;configFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"config-temp.txt"&lt;/span&gt;
heroku config &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parentAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; | xargs heroku config:set &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="s2"&gt;"./&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Remove the DATABASE_URL environment variable as it will be set when we provision a new database&lt;/span&gt;
heroku config:unset DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Update the ALLOWED_HOSTS and CURRENT_DOMAIN environment variables&lt;/span&gt;
heroku config:set &lt;span class="nv"&gt;ALLOWED_HOSTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;.herokuapp.com"&lt;/span&gt; &lt;span class="nv"&gt;CURRENT_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;.herokuapp.com"&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Provision new Postgres database&lt;/span&gt;
heroku addons:create heroku-postgresql:hobby-dev &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Push the source code of the branch up to the new app to build&lt;/span&gt;
git push https://heroku:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HEROKU_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;@git.heroku.com/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;.git &lt;span class="nv"&gt;$branchName&lt;/span&gt;:master &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# Copy rows from parent app's database&lt;/span&gt;
heroku pg:copy &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parentAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;::DATABASE_URL DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--confirm&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some of these configuration steps may not make sense for your specific application. Include any additional steps needed to configure your feature app in this file. While we use a pre-existing main app to copy over environment variables and testing data, you could include the testing configuration and seed data for the application in the source code itself to remove this dependency. This main app also does not need to be an app running the production version of your application as well, it could be a staging app itself where changes are vetted before being pushed to the production environment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Destroying Apps
&lt;/h1&gt;

&lt;p&gt;At this point we have a Pipelines configuration file and bash script that will create apps for us to test changes on whenever a pull request is opened, but as of now you will have to go in and manually delete the new apps once the PR from the branch is merged. To fix this we have implemented a script that uses the Bitbucket API to retrieve the pull request when it is merged, find the name of the created app for the branch, and subsequently delete that app. The only modifications needed are to the &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# bitbucket-pipelines.yml&lt;/span&gt;

&lt;span class="c1"&gt;# Change this to your project's node version&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:12.0.0&lt;/span&gt;

&lt;span class="na"&gt;clone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;full&lt;/span&gt;


&lt;span class="c1"&gt;# Deploy the master branch to our app.&lt;/span&gt;
&lt;span class="c1"&gt;# Pulls the Heroku API Key and the name of the app from our&lt;/span&gt;
&lt;span class="c1"&gt;# configured environment variables.&lt;/span&gt;
&lt;span class="na"&gt;herokuAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;herokuAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Heroku App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master -f&lt;/span&gt;

&lt;span class="na"&gt;reviewAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Download the Heroku CLI&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://cli-assets.heroku.com/install.sh | sh&lt;/span&gt;
    &lt;span class="c1"&gt;# Format the name of the app that will be created.&lt;/span&gt;
    &lt;span class="c1"&gt;# EX: With a branch named 'chatbot-ui' and a repo called 'thinknimble', this will become 'thinknimble-chatbot-ui'.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NEW_APP_NAME=$BITBUCKET_REPO_SLUG-$BRANCH_NAME&lt;/span&gt;
    &lt;span class="c1"&gt;# Export the Heroku authentication token so it can be accessed in other scripts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export HEROKU_API_KEY&lt;/span&gt;
    &lt;span class="c1"&gt;# If an app exists for this branch, push the new code up.&lt;/span&gt;
    &lt;span class="c1"&gt;# Else, create a copy of the main app and push the new branch to it.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;heroku apps:info -a $NEW_APP_NAME &amp;amp;&amp;amp; git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$NEW_APP_NAME.git $BITBUCKET_BRANCH:master -f || /bin/bash copy-app.sh $HEROKU_APP_NAME $NEW_APP_NAME $BITBUCKET_BRANCH&lt;/span&gt;

&lt;span class="na"&gt;reviewAppCleanup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppCleanup&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cleanup a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://cli-assets.heroku.com/install.sh | sh&lt;/span&gt;
    &lt;span class="c1"&gt;# Pull the commit that triggered this script, which for a pull request will be the merge commit. &lt;/span&gt;
    &lt;span class="c1"&gt;# Retrieve the associated pull-request to get the review app name to delete.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BRANCH=`curl -X GET -G "https://$BITBUCKET_AUTH_STRING@api.bitbucket.org/2.0/repositories/thinknimble/$BITBUCKET_REPO_SLUG/pullrequests" --data-urlencode 'q=merge_commit.hash="'"$BITBUCKET_COMMIT"'"' | python -c "import json,sys;obj=json.loads(sys.stdin.read());value=obj.get('values', [{}])[0].get('source', {}).get('branch', {}).get('name', '');print(value)"`&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BRANCH_NAME=`echo $BRANCH | egrep "(.*)" -o`&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FEATURE_APP_NAME=$BITBUCKET_REPO_SLUG-$BRANCH_NAME&lt;/span&gt;
    &lt;span class="c1"&gt;# Poll Heroku to see if an app with the constructed name exists.&lt;/span&gt;
    &lt;span class="c1"&gt;# If it does than delete it, if it does not then just return.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;heroku apps:info -a $FEATURE_APP_NAME &amp;amp;&amp;amp; heroku apps:destroy -a $FEATURE_APP_NAME -c $FEATURE_APP_NAME || echo "No feature server to cleanup"&lt;/span&gt;

&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Whenever a pull-request is opened or updated, create/update a Heroku app for the pull-request.&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*reviewAppDeployment&lt;/span&gt;
  &lt;span class="c1"&gt;# Deploy the master branch to our main app whenever it is updated.&lt;/span&gt;
  &lt;span class="c1"&gt;# Then, update any Review Apps associated with the pull-request merged into `master`.&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;develop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*herokuAppDeployment&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*revewAppCleanup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a closer look at this &lt;code&gt;review                                                       AppCleanup&lt;/code&gt; script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;reviewAppCleanup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppCleanup&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cleanup a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://cli-assets.heroku.com/install.sh | sh&lt;/span&gt;
    &lt;span class="c1"&gt;# Pull the commit that triggered this script, which for a pull request will be the merge commit. &lt;/span&gt;
    &lt;span class="c1"&gt;# Retrieve the associated pull-request to get the review app name to delete.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BRANCH=`curl -X GET -G "https://$BITBUCKET_AUTH_STRING@api.bitbucket.org/2.0/repositories/thinknimble/$BITBUCKET_REPO_SLUG/pullrequests" --data-urlencode 'q=merge_commit.hash="'"$BITBUCKET_COMMIT"'"' | python -c "import json,sys;obj=json.loads(sys.stdin.read());value=obj.get('values', [{}])[0].get('source', {}).get('branch', {}).get('name', '');print(value)"`&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BRANCH_NAME=`echo $BRANCH | egrep "(.*)" -o`&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FEATURE_APP_NAME=$BITBUCKET_REPO_SLUG-$BRANCH_NAME&lt;/span&gt;
    &lt;span class="c1"&gt;# Poll Heroku to see if an app with the constructed name exists.&lt;/span&gt;
    &lt;span class="c1"&gt;# If it does than delete it, if it does not then just return.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;heroku apps:info -a $FEATURE_APP_NAME &amp;amp;&amp;amp; heroku apps:destroy -a $FEATURE_APP_NAME -c $FEATURE_APP_NAME || echo "No feature server to cleanup"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We utilize Bitbucket's REST API to retrieve the pull-request associated with a specific commit. This commit is provided by Pipelines, and when the pipeline was triggered by a pull-request being merged the commit will be the merge commit. Once we have the name of the pull-request, we construct the name of the created app, looking for the name that was constructed in the &lt;code&gt;reviewAppDeployment&lt;/code&gt; script. We poll Heroku to see if an app with the constructed name exists. If it does, destroy it. Otherwise just print out that there is no app to cleanup and return.&lt;/p&gt;

&lt;p&gt;Now you can merge you pull-request, check Heroku, and see that the created app has been taken down! We now have an automated pipeline to create apps for pull requests, and then destroy them when the branch is merged.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security Considerations
&lt;/h1&gt;

&lt;p&gt;Since you are destroying apps, you have to ensure that no important apps are accidentally destroyed. The script has a very specific naming convention for naming these review apps, so the risk of deleting an app would require an unfortunate naming error. In our organization we've nullified this risk by using a Heroku account that only has permission to delete apps from a separate Heroku team created solely for the purpose of housing these temporary review apps and other playground environments. You can modify the commands in the &lt;code&gt;copy-app.sh&lt;/code&gt; command above to create apps only for a specific team by including the &lt;code&gt;-t team-name&lt;/code&gt; flag to the commands to create the app and associated pipeline. The scripts in &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; will simply return if the user does not have access to delete or create an app. See the &lt;a href="https://devcenter.heroku.com/categories/command-line" rel="noopener noreferrer"&gt;Heroku CLI documentation&lt;/a&gt; for more configuration options.&lt;/p&gt;

&lt;h1&gt;
  
  
  Looking Ahead
&lt;/h1&gt;

&lt;p&gt;While an integrated solution such as Review Apps for Github would have been preferred, this combination of Bitbucket Pipelines and Heroku CLI commands does the job for our team. There are some known limitations and improvements we would like to make going forward.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heroku app names are limited to a maximum of 30 characters, so if your constructed app name is longer than that the script will error out. We could store a shortened slug or just simply truncate names when they reach the character limit.&lt;/li&gt;
&lt;li&gt;Some Heroku app configuration must be done manually, for instance copying over scheduled background tasks. This means that for a basic application in our stack this is fully automatic, but becomes more manual as app architecture becomes more complicated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;You can test this for your own application by including this Pipelines configuration file and bash script at the root of your repository, and opening up a pull request. You should now see a new app named after your branch! Let me know if you were able to use the information in this post to automate the creation and deletion of apps for Heroku.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# bitbucket-pipelines.yml&lt;/span&gt;

&lt;span class="c1"&gt;# Place this at the root of your repository&lt;/span&gt;

&lt;span class="c1"&gt;# Change this to your project's node version&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:12.0.0&lt;/span&gt;

&lt;span class="na"&gt;clone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;full&lt;/span&gt;


&lt;span class="c1"&gt;# Deploy the master branch to our app.&lt;/span&gt;
&lt;span class="c1"&gt;# Pulls the Heroku API Key and the name of the app from our&lt;/span&gt;
&lt;span class="c1"&gt;# configured environment variables.&lt;/span&gt;
&lt;span class="na"&gt;herokuAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;herokuAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Heroku App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master -f&lt;/span&gt;

&lt;span class="na"&gt;reviewAppDeployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppDeployment&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Download the Heroku CLI&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://cli-assets.heroku.com/install.sh | sh&lt;/span&gt;
    &lt;span class="c1"&gt;# Format the name of the app that will be created.&lt;/span&gt;
    &lt;span class="c1"&gt;# EX: With a branch named 'chatbot-ui' and a repo called 'thinknimble', this will become 'thinknimble-chatbot-ui'.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NEW_APP_NAME=$BITBUCKET_REPO_SLUG-$BRANCH_NAME&lt;/span&gt;
    &lt;span class="c1"&gt;# Export the Heroku authentication token so it can be accessed in other scripts&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export HEROKU_API_KEY&lt;/span&gt;
    &lt;span class="c1"&gt;# If an app exists for this branch, push the new code up.&lt;/span&gt;
    &lt;span class="c1"&gt;# Else, create a copy of the main app and push the new branch to it.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;heroku apps:info -a $NEW_APP_NAME &amp;amp;&amp;amp; git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$NEW_APP_NAME.git $BITBUCKET_BRANCH:master -f || /bin/bash copy-app.sh $HEROKU_APP_NAME $NEW_APP_NAME $BITBUCKET_BRANCH&lt;/span&gt;

&lt;span class="na"&gt;reviewAppCleanup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;reviewAppCleanup&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cleanup a Review App&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl https://cli-assets.heroku.com/install.sh | sh&lt;/span&gt;
    &lt;span class="c1"&gt;# Pull the commit that triggered this script, which for a pull request will be the merge commit. &lt;/span&gt;
    &lt;span class="c1"&gt;# Retrieve the associated pull-request to get the review app name to delete.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BRANCH=`curl -X GET -G "https://$BITBUCKET_AUTH_STRING@api.bitbucket.org/2.0/repositories/thinknimble/$BITBUCKET_REPO_SLUG/pullrequests" --data-urlencode 'q=merge_commit.hash="'"$BITBUCKET_COMMIT"'"' | python -c "import json,sys;obj=json.loads(sys.stdin.read());value=obj.get('values', [{}])[0].get('source', {}).get('branch', {}).get('name', '');print(value)"`&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BRANCH_NAME=`echo $BRANCH | egrep "(.*)" -o`&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FEATURE_APP_NAME=$BITBUCKET_REPO_SLUG-$BRANCH_NAME&lt;/span&gt;
    &lt;span class="c1"&gt;# Poll Heroku to see if an app with the constructed name exists.&lt;/span&gt;
    &lt;span class="c1"&gt;# If it does than delete it, if it does not then just return.&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;heroku apps:info -a $FEATURE_APP_NAME &amp;amp;&amp;amp; heroku apps:destroy -a $FEATURE_APP_NAME -c $FEATURE_APP_NAME || echo "No feature server to cleanup"&lt;/span&gt;

&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Whenever a pull-request is opened or updated, create/update a Heroku app for the pull-request.&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*reviewAppDeployment&lt;/span&gt;
  &lt;span class="c1"&gt;# Deploy the master branch to our main app whenever it is updated.&lt;/span&gt;
  &lt;span class="c1"&gt;# Then, update any Review Apps associated with the pull-request merged into `master`.&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;develop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*herokuAppDeployment&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*revewAppCleanup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# copy-app.sh&lt;/span&gt;

&lt;span class="c"&gt;# Place this at the root of your repository&lt;/span&gt;

&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Script to copy an existing app and deploy a specific branch to it.&lt;/span&gt;
&lt;span class="c"&gt;# 1. Creates the new app&lt;/span&gt;
&lt;span class="c"&gt;# 2. Copies over all environment variables from existing app&lt;/span&gt;
&lt;span class="c"&gt;# 3. Provisions a new Postgres database and copies the rows over from the existing app&lt;/span&gt;
&lt;span class="c"&gt;# 4. Deploys the specified branch to the new app&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# USAGE:&lt;/span&gt;
&lt;span class="c"&gt;#   ./copy-app.sh parentApp newApp branchName&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;

&lt;span class="c"&gt;# Defines the parameters passed in to the script. Requires the name of the&lt;/span&gt;
&lt;span class="c"&gt;# parent app, the name of the new app, and the name of the branch to push to the new app to build.&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nv"&gt;parentAppName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="nv"&gt;newAppName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;span class="nv"&gt;branchName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;

&lt;span class="c"&gt;# Create the new app&lt;/span&gt;
heroku create &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Add the standard buildpacks for your app. Here we add NodeJS first, then python.&lt;/span&gt;
heroku buildpacks:add heroku/nodejs &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
heroku buildpacks:add heroku/python &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Copy environemnt variables from parent app to new app&lt;/span&gt;
&lt;span class="nv"&gt;configFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"config-temp.txt"&lt;/span&gt;
heroku config &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parentAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; | xargs heroku config:set &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="s2"&gt;"./&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Remove the DATABASE_URL environment variable as it will be set when we provision a new database&lt;/span&gt;
heroku config:unset DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Update the ALLOWED_HOSTS and CURRENT_DOMAIN environment variables&lt;/span&gt;
heroku config:set &lt;span class="nv"&gt;ALLOWED_HOSTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;.herokuapp.com"&lt;/span&gt; &lt;span class="nv"&gt;CURRENT_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;.herokuapp.com"&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Provision new Postgres database&lt;/span&gt;
heroku addons:create heroku-postgresql:hobby-dev &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Push the source code of the branch up to the new app to build&lt;/span&gt;
git push https://heroku:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HEROKU_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;@git.heroku.com/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;.git &lt;span class="nv"&gt;$branchName&lt;/span&gt;:master &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# Copy rows from parent app's database&lt;/span&gt;
heroku pg:copy &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parentAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;::DATABASE_URL DATABASE_URL &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--confirm&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newAppName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>bash</category>
      <category>heroku</category>
      <category>bitbucket</category>
    </item>
  </channel>
</rss>
