This blogpost will guide you through connecting a Middleman project to Bitrise, triggering a Middleman build and deploying the generated static site to Heroku on every git push to the repository of the Middleman project. This can be achieved with either Bitrise CLI or on bitrise.io.
For this, you will need the following:
- a git repository with a Middleman project (can be hosted anywhere)
- a Heroku account - you will create a Heroku App which will host the static site. Optionally you can create another Heroku App which will host the static site in staging mode.
By the end, you will be able to:
- deploy a generated static site to your Heroku staging git repository by every git push to your Middleman project's git repository's develop branch
- deploy a generated static site to your Heroku production git repository by every git push to your Middleman project's git repository's master branch
1. Create & configure a Heroku repository
On Heroku, create a new App. For this tutorial, I will use bitrise-test-heroku-production.
Go to the Settings tab and select Add buildpack. Add a buildpack with the following URL: https://github.com/heroku/heroku-buildpack-static. This is a cool buildpack for static sites, it only requires a static.json configuration file in the root directory of the repository, and you can store your static site in a directory named public_html, also located in the root directory.
Clone this repository, then have your first commit by adding a static.json file without any configuration: {}.
You can repeat the same process creating another Heroku App for staging. For this tutorial, I will use bitrise-test-heroku-staging.
2. Create a Bitrise App
Sign in (or sign up if you haven't already) to Bitrise, then on the Dashboard, select Add new App.

On the Add new App page, specify the git repository of your Middleman project by either selecting it from one of the lists (you will need to connect your GitHub or Bitbucket account if you would like Bitrise to be able to list your repositories - you can do this on the Account Settings page), or by specifying the git clone URL for it. For this tutorial, I will use bitrise-test-middleman-project, selected from my connected provider's repository list.
In the Setup repository access section, auto-add the SSH keypair generated by Bitrise, by selecting Auto-add this key.

In the Validation setup section, because we won't need Bitrise to scan for valid project configurations, select Configure manually.
In the Project Build Configuration section, select Android for project type, since we are going to need Ubuntu set up on the worker machine which will run our Builds and Bitrise assigns worker machines with Ubuntu to Android projects. Enter master for branch name, enter . for gradle file, gradle task and gradlew path.

In the Webhook setup section, select Register a Webhook for me. The webhook registration is needed so that everytime you push to this repository, your repository host will trigger a Build on Bitrise.
Your App is created, yay! Select it from the Dashboard to view its details.
3. Configure Workflow pipeline & triggers
Select the Workflow tab, then select Manage Workflows. This is where we will configure the Workflows which will be triggered by our git host on every git push. The process will consist of the followings:
- clone the repository of the Middleman project (if ran on bitrise.io, otherwise - in CLI mode - the project is already given)
- clone the Heroku repository, store it in a temporary directory
- build Middleman project
- clear the previous static page from the Heroku repository, move the new build to this location
- git push the changes to the Heroku repository
Remove all the steps from the primary Workflow, then rename it to deploy. This will be the triggered Workflow by every git push... sort of. The beginning _ character means this is a utility Workflow, meaning it will not be triggered directly. Create two another Workflows, deploy-production and deploy-staging. These will be the actual Workflows triggered by the git pushes. They will trigger our utility Workflow afterwards. For this, you need to do the following for both Workflows: on the bottom of the Workflow's page, where it says *No other Workflows will run after this Workflow*, select *Add* and select the deploy Workflow, then save.

Select Triggers in the side menu. Remove all the triggers, then add one. The pattern should be master, the Workflow should be deploy-production, the pull request trigger checkbox should be disabled - by this, every git push (not pull requests) on the master branch will trigger the deploy-production Workflow. Add another one with the pattern develop and with the Workflow deploy-staging, pull request trigger checkbox disabled, then save.

4. Configure Workflows
Now that we've got our Bitrise App trigger-configured, time to configure the actual work we would like Bitrise to do for us. For this, select the _deploy Workflow. Add a Step called Script. In this step, you can write your own Bash script. Rename the Step to Prepare Temporary Directories. Paste the following code snippet to the script content:
This script will create temporary directories for the copy of our netrc file and for our Heroku App git target path. It will also use envman to save these paths as Environment Variables, so later we will be able to access them in other Steps.
Add another Step called Git Clone Repository, then rename it to Git Clone Middleman Project Repository. We don't need any other configuration for this Step.
Add another Script Step, then rename it to Prepare Heroku Git Clone. The script content should be the following:
This script will copy the original netrc file to our previously created temporary directory, then set it up with required data for the upcoming Heroku git clone. This consists of an arbitrary email, and our Heroku API token. The latter is a yet undefined Environment Variable - we need to add this. You can get your Heroku API token in the Manage account menu on the Heroku website. Since this is private data, you should add it as a secret Environment Variable in the Secret Env Vars menu in the side menu. The key should be HEROKU_API_TOKEN, the value should be the API token.
Add another Git Clone Repository Step, then rename it to Git Clone Heroku Repository. By default, this step tries to clone with the initially set values (URL, commit hash, tag, branch, etc.) which is not what we want - they point to our Middleman project. The repository URL should be https://git.heroku.com/$HEROKU_APP_ID.git - this is the generic form of the Heroku git urls. Notice that this URL needs a yet undefined Environment Variable, the $HEROKU_APP_ID. We will deal with this later. The commit and the tag fields should be empty, the branch should be master, the pull request ID should be empty, the target directory should be our temporary directory $TEMP_HEROKU_PATH, the SSH private key should be empty since we are using the public URL.
Add another Script Step, then rename it to Build Middleman Project. The script content should be the following:
This script will install bundler and Node.js (if not found), runs a Middleman build, moves the generated static site to the public_html directory of the Heroku temporary directory.
Add another Step called Change Working Directory for subsequent Steps - for the rest of the Steps we will be using the Heroku temporary directory as working directory, so set it to $TEMP_HEROKU_PATH.
Add another Script step and rename it to Prepare Heroku Deploy. The script content should be the following:
This script configures the git with arbitrary user data, stages & adds all diffs in the Heroku repository, then commits it with the commit message of our Middleman project commit.
Add another Step called Heroku Deploy. No need for additional configuration, it uses our previously set Heroku API token, and our soon-to-be-set Heroku APP ID by default. This step deploys the working directory to the specified App's master branch. This is exactly what we need - remember: the working directory has been set to the Heroku temporary directory.
Add the last step, another Script step, renamed to Cleanup, with the following content:
This script will remove our Heroku temporary directory, restore our original netrc file, and remove the temporary netrc directory. This step should run even if any of the previous steps have failed, so turn on Should this step run even if a previous step failed.

We're almost ready. The only thing left is setting the $HEROKU_APP_ID Environment Variable. Since we're using two different Heroku Apps for production and staging, we should have this Environment Variable set in the deploy-production and in the deploy-staging differently. The deploy Workflow will run after both, so depending on the triggered Workflow, the Environment Variable used in the deploy Workflow will either be the one set in deploy-production or the one set in deploy-staging. For the former, it should be the name of the Heroku App used for production (in my case, bitrise-test-heroku-production), for the latter, it should be the one for staging (in my case, bitrise-test-heroku-staging). You can set Environment Variables for a specific Workflow by selecting the Workflow and at the top, Manage env. vars.
Remove the $BITRISE_PROJECT_PATH, $GRADLE_TASK and $GRADLEW_PATH App Environment Variables: we don't need them, and it makes our bitrise.yml shorter. Speaking of which, we still have one last thing to do, which only can be done in console mode, so select bitrise.yml in the side menu. If you would like to run this configuration in CLI mode, the Git Clone Heroku Repository and the Change Working Directory for subsequent Steps Steps would be skipped by default, since they are rarely needed in CLI mode. But in our case, both should run in either mode. For this, add run_if: '' for both steps in the YML file - this tells Bitrise to run the Step regardless of the environment it is ran in (by default, its value is ".IsCI" for these Steps).

5. Try it out!
We are ready. To test it, push a commit to your Middleman project's git repository's master branch - its generated build should be deployed to the Heroku production App. Push another commit to your Middleman project's git repository's develop branch - its generated build should be deployed to the Heroku staging App. Note: if you trigger a Build on Bitrise which generates a static site with no difference from the previous version on Heroku, the Build will fail, since there is no diff to commit to the Heroku repository. This can occur if you trigger a Build manually, or when changes in your Middleman project does not affect the generated static site.

6. Try it out in CLI mode!
You can also test this configuration in CLI mode. For this, you need to have Bitrise CLI installed. You can find more information about this here.
After installed, navigate to your Middleman project's directory. Download the bitrise.yml and paste in in this directory. Then, create a file named .bitrise.secrets.yml, with the following content:
Finally, run bitrise run deploy-staging if you want to deploy the current state to the Heroku staging App, or bitrise run deploy-production if you would like to deploy the current state to the Heroku production App.
