<?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: Matteus Deloge</title>
    <description>The latest articles on DEV Community by Matteus Deloge (@mdeloge).</description>
    <link>https://dev.to/mdeloge</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%2F493622%2Fdb481bd4-0097-40ed-86eb-d5127978c62f.png</url>
      <title>DEV Community: Matteus Deloge</title>
      <link>https://dev.to/mdeloge</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mdeloge"/>
    <language>en</language>
    <item>
      <title>How to trigger a manual redeploy on Heroku from code - A killer feature to update your Gatsby setup that isn't documented </title>
      <dc:creator>Matteus Deloge</dc:creator>
      <pubDate>Wed, 28 Oct 2020 08:25:56 +0000</pubDate>
      <link>https://dev.to/mdeloge/how-to-trigger-a-manual-redeploy-on-heroku-from-code-a-killer-feature-to-update-your-gatsby-setup-that-isn-t-documented-4jge</link>
      <guid>https://dev.to/mdeloge/how-to-trigger-a-manual-redeploy-on-heroku-from-code-a-killer-feature-to-update-your-gatsby-setup-that-isn-t-documented-4jge</guid>
      <description>&lt;p&gt;&lt;em&gt;TL;DR: You can easily retrigger an Heroku build for your Gatsby service to ingest Strapi CMS data, you only need to execute a POST request on an undocumented weird subdomain from Heroku called **kolkrabbi.heroku.com&lt;/em&gt;&lt;em&gt;. See further down for API call details and Strapi CMS example implementation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I got a request from &lt;a href="https://www.conversationstarter.net/" rel="noopener noreferrer"&gt;Conversation Starter&lt;/a&gt;, a customer from one of my freelance assignments (I'm a tech lead at &lt;a href="https://www.craftworkz.be" rel="noopener noreferrer"&gt;Craftworkz&lt;/a&gt; by day and an IT freelancer by night), that they wanted to setup a headless CMS system to manage and host their blog posts for their existing website, built with the amazing &lt;a href="https://www.gatsbyjs.com/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; framework. &lt;/p&gt;

&lt;p&gt;The choice was immediately made to use &lt;a href="https://strapi.io/" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt; as the CMS system, mainly because of the great reviews it gets in the community and the many &lt;a href="https://strapi.io/blog/building-a-static-website-using-gatsby-and-strapi" rel="noopener noreferrer"&gt;tutorials&lt;/a&gt; that are available.&lt;/p&gt;

&lt;p&gt;Development went smoothly but then, deployment time had arrived. Both Strapi and the Gatsby website run happily on Heroku dynos, but due to the nature of Gatsby (static hosting of content) we need to rebuild the website on each change to the published blog post articles in the CMS.&lt;/p&gt;

&lt;p&gt;One would think that a simple rebuild of an existing deployment on Heroku is a simple and well documented thing, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Well, it's not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After a long search, even considering pushing empty git commits from the Strapi CMS to the Gatsby repository to trigger a new build, I found a breadcrumb that would lead me to the solution for my problem: a &lt;strong&gt;manual redeploy button&lt;/strong&gt; on Heroku itself.&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%2F8o984dfirgal9hce8uze.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%2F8o984dfirgal9hce8uze.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well isn't this nice! That's exactly the feature I needed. However, this is documented nowhere in the official Heroku docs (send me the link if you would find it).&lt;/p&gt;

&lt;p&gt;Using my trusted Chrome dev tools I luckily was able to document the API call myself, and again lucky: it was very easy to replicate without doing too much weird stuff. The only weird thing here is that you need to call an unknown Heroku subdomain, called &lt;strong&gt;kolkrabbi.heroku.com&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The API call looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://kolkrabbi.heroku.com/apps/&amp;lt;HEROKU_APP_ID&amp;gt;/github/push

Headers: {
    "Authorization": "Bearer &amp;lt;USER_AUTH_TOKEN&amp;gt;"
}

Body: {
    "branch": "master"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HEROKU_APP_ID&lt;/strong&gt; = your app's UUID which you can fetch using the &lt;code&gt;heroku apps:info --json&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USER_AUTH_TOKEN&lt;/strong&gt; = your own user's access token. Go to &lt;a href="https://dashboard.heroku.com/account" rel="noopener noreferrer"&gt;https://dashboard.heroku.com/account&lt;/a&gt; and navigate to the &lt;strong&gt;API Key&lt;/strong&gt; section&lt;/li&gt;
&lt;li&gt;Within the body of your call you can then choose which branch to build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note that if you have multiple instances of your application (such as development and production), you will have a different App ID.&lt;/p&gt;

&lt;p&gt;And as a cherry on the cake, I'll post my Strapi config here as well. The idea is that every time an &lt;strong&gt;Article&lt;/strong&gt; model instance is being created, updated or deleted, the Heroku build function is being triggered so that Gatsby can ingest the new changes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;./api/articles/models/article.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Lifecycle callbacks for the `Article` model.
 */&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;deployUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://kolkrabbi.heroku.com/apps/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HEROKU_APP_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/github/push`&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;axiosConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CS_HEROKU_BUILD_TOKEN&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callDeployEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;branch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;branch&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;axiosConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;strapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Executed build trigger for branch &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;strapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Caught error for branch &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;triggerDeploy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;strapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Triggered redeploy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;strapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axiosConfig: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;axiosConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callDeployEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;master&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;lifecycles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;afterCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;triggerDeploy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;afterUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;triggerDeploy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;afterDestroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;triggerDeploy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>gatsby</category>
      <category>strapi</category>
      <category>heroku</category>
      <category>build</category>
    </item>
  </channel>
</rss>
