<?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: John Bohannon</title>
    <description>The latest articles on DEV Community by John Bohannon (@imjohnbo).</description>
    <link>https://dev.to/imjohnbo</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%2F609087%2Fe1ba241d-9a5d-45dd-83de-0fa6716cc2b7.jpeg</url>
      <title>DEV Community: John Bohannon</title>
      <link>https://dev.to/imjohnbo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imjohnbo"/>
    <language>en</language>
    <item>
      <title>How to Build GitHub Apps For Fun and Profit</title>
      <dc:creator>John Bohannon</dc:creator>
      <pubDate>Tue, 06 Apr 2021 00:32:42 +0000</pubDate>
      <link>https://dev.to/github/building-github-apps-for-fun-and-profit-4mid</link>
      <guid>https://dev.to/github/building-github-apps-for-fun-and-profit-4mid</guid>
      <description>&lt;p&gt;Hi there, GitHub developer! So you host your code on GitHub, and you've seen some comments like this:&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%2Fuser-images.githubusercontent.com%2F2993937%2F113446246-6d81de00-93c5-11eb-9e4e-80a5f687f869.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%2Fuser-images.githubusercontent.com%2F2993937%2F113446246-6d81de00-93c5-11eb-9e4e-80a5f687f869.png" alt="dependabot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dependabot and thousands of bots like it are what are called &lt;a href="https://docs.github.com/en/developers/apps/about-apps#about-github-apps" rel="noopener noreferrer"&gt;GitHub Apps&lt;/a&gt;. Today, I'll teach you how to make a GitHub App and how to list it for purchase in GitHub Marketplace. GitHub Apps have been around for several years but are worth another look as the GitHub Platform expands and improves.&lt;/p&gt;

&lt;h2&gt;
  
  
  About GitHub Apps
&lt;/h2&gt;

&lt;p&gt;GitHub Apps are a great way to programmatically interact with GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flexible, first class actors on GitHub&lt;/li&gt;
&lt;li&gt;Secure, fine-grained permissions model&lt;/li&gt;
&lt;li&gt;Scalable, dedicated rate limits&lt;/li&gt;
&lt;li&gt;Built-in webhooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might need a GitHub App for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Integrating&lt;/em&gt; with GitHub, potentially via the &lt;a href="https://partner.github.com/technology-partners" rel="noopener noreferrer"&gt;GitHub Technology Partner Program&lt;/a&gt;. Your software product can connect, augment, and inspire developers right where they work in GitHub, the &lt;a href="https://github.com/home" rel="noopener noreferrer"&gt;largest and most advanced development platform in the world&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Interacting&lt;/em&gt; with GitHub on a programmatic basis, for example, from team-based tools or CLI-driven workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub Apps replace &lt;a href="https://docs.github.com/en/developers/apps/migrating-oauth-apps-to-github-apps#reasons-for-switching-to-github-apps" rel="noopener noreferrer"&gt;OAuth apps&lt;/a&gt;, are used to build &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;, and work on GitHub.com and &lt;a href="https://github.com/enterprise" rel="noopener noreferrer"&gt;GitHub Enterprise&lt;/a&gt; alike. Some APIs are exclusive to GitHub Apps – for example, &lt;a href="https://docs.github.com/en/rest/reference/checks" rel="noopener noreferrer"&gt;Checks&lt;/a&gt; and &lt;a href="https://docs.github.com/en/developers/apps/using-content-attachments" rel="noopener noreferrer"&gt;Content Attachments&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A GitHub App can be programmed to act &lt;a href="https://docs.github.com/en/developers/apps/authenticating-with-github-apps#authenticating-as-a-github-app" rel="noopener noreferrer"&gt;as itself&lt;/a&gt;, &lt;a href="https://docs.github.com/en/developers/apps/authenticating-with-github-apps#authenticating-as-an-installation" rel="noopener noreferrer"&gt;as a (scoped) "installation"&lt;/a&gt;, or &lt;a href="https://docs.github.com/en/developers/apps/identifying-and-authorizing-users-for-github-apps" rel="noopener noreferrer"&gt;as one of its users&lt;/a&gt;, if permitted.&lt;/p&gt;

&lt;p&gt;Also, &lt;a href="https://docs.github.com/en/actions/creating-actions/about-actions#comparing-github-actions-to-github-apps" rel="noopener noreferrer"&gt;GitHub Apps fit together with GitHub Actions&lt;/a&gt; like peanut butter and jelly, which is rad. So let's build one! Today, I'll build the &lt;strong&gt;simplest thing possible&lt;/strong&gt;, a bot that approves a pull request if "🤖" is in the title.&lt;/p&gt;

&lt;p&gt;What will &lt;strong&gt;you&lt;/strong&gt; build 👀?&lt;/p&gt;

&lt;h2&gt;
  
  
  Probot, the helper framework
&lt;/h2&gt;

&lt;p&gt;Know JavaScript? Great. Probot is a trusty Node.js framework for building GitHub Apps, and we'll use it to make the following steps easier:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create the App&lt;/strong&gt; by registering a set of permissions, webhook events, and metadata&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the App&lt;/strong&gt; on as few or as many repositories as you want&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the App&lt;/strong&gt; to make GitHub API requests&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create the App
&lt;/h3&gt;

&lt;p&gt;In a terminal with Node.js installed, type &lt;code&gt;npx create-probot-app pr-bot&lt;/code&gt; and follow the prompts, choosing &lt;code&gt;basic-js&lt;/code&gt; as the template. &lt;code&gt;cd pr-bot&lt;/code&gt; when the installation is done.&lt;/p&gt;

&lt;p&gt;Open up &lt;code&gt;app.yml&lt;/code&gt; in your favorite text editor. This is a one-time use creation spec or "manifest" – of course, App settings can be changed later at &lt;a href="https://github.com/settings/apps" rel="noopener noreferrer"&gt;https://github.com/settings/apps&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Uncomment &lt;code&gt;default_events.pull_request&lt;/code&gt; and change &lt;code&gt;default_permissions.pull_requests&lt;/code&gt; to &lt;code&gt;write&lt;/code&gt;. When you're done it should look like this:&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;default_events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pull_request&lt;/span&gt;
&lt;span class="na"&gt;default_permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;pull_requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A silly pull request bot!&lt;/span&gt;
&lt;span class="na"&gt;public&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now add the logic of the App in &lt;code&gt;index.js&lt;/code&gt;. Add this block just below the line, &lt;code&gt;app.log.info("Yay, the app was loaded!")&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&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;pull_request.opened&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;pull_request.edited&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;pull_request.reopened&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🤖&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;octokit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pulls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createReview&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pullRequest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;APPROVE&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;context.octokit&lt;/code&gt; gives us access to an authenticated &lt;a href="https://octokit.github.io/rest.js/v18/" rel="noopener noreferrer"&gt;octokit/rest.js client&lt;/a&gt; to make GitHub API calls with ease. (Psst: check out the other official and 3rd party &lt;a href="https://docs.github.com/en/rest/overview/libraries" rel="noopener noreferrer"&gt;Octokit libraries&lt;/a&gt;, even if you aren't using Probot!)&lt;/p&gt;

&lt;p&gt;Back in your terminal, run &lt;code&gt;npm run start&lt;/code&gt; and then click "Register GitHub App" at &lt;code&gt;http://localhost:3000&lt;/code&gt;:&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%2Fuser-images.githubusercontent.com%2F2993937%2F113418759-17487700-9394-11eb-9fa1-0563f001572f.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%2Fuser-images.githubusercontent.com%2F2993937%2F113418759-17487700-9394-11eb-9fa1-0563f001572f.png" alt="create the app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the prompts to finish creating the app. Notice that an &lt;code&gt;.env&lt;/code&gt; file has appeared with some secret data only you as App developer have, namely the &lt;code&gt;APP_ID&lt;/code&gt;, &lt;code&gt;PRIVATE_KEY&lt;/code&gt;, and &lt;code&gt;WEBHOOK_SECRET&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the App
&lt;/h3&gt;

&lt;p&gt;Follow the prompts to install the app on all or select repositories. This lets the App "see and respond" to the resources you configured before (&lt;code&gt;pull_requests&lt;/code&gt;), but in only these repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the App
&lt;/h3&gt;

&lt;p&gt;In one of these repositories, open a pull request. The &lt;code&gt;pull_request&lt;/code&gt; webhook was received, but no "🤖" was in the title, so &lt;code&gt;pr-bot&lt;/code&gt; stayed quiet! Now add a "🤖" in the title and notice the approval!&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%2Fuser-images.githubusercontent.com%2F2993937%2F113420930-31845400-9398-11eb-89a2-5d0032410d13.gif" 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%2Fuser-images.githubusercontent.com%2F2993937%2F113420930-31845400-9398-11eb-89a2-5d0032410d13.gif" alt="use the app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But you're not going to use your own machine for long 😉. Probot apps are just Node.js apps, so they can be &lt;a href="https://probot.github.io/docs/deployment/" rel="noopener noreferrer"&gt;deployed&lt;/a&gt; to all the environments you'd expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Probot, no problem
&lt;/h2&gt;

&lt;p&gt;So far we've used Probot as a helper framework to &lt;a href="https://docs.github.com/en/developers/apps/creating-a-github-app" rel="noopener noreferrer"&gt;create&lt;/a&gt;, &lt;a href="https://docs.github.com/en/developers/apps/installing-github-apps" rel="noopener noreferrer"&gt;install&lt;/a&gt;, and &lt;a href="https://docs.github.com/en/rest" rel="noopener noreferrer"&gt;use&lt;/a&gt; the app to extend our experience on GitHub! Did you know you can easily follow this pattern even without Probot?&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the App
&lt;/h3&gt;

&lt;p&gt;Head over to &lt;a href="https://github.com/settings/apps/new" rel="noopener noreferrer"&gt;https://github.com/settings/apps/new&lt;/a&gt; and fill out the fields, with &lt;a href="https://docs.github.com/en/developers/apps/creating-a-github-app" rel="noopener noreferrer"&gt;Creating a GitHub App - GitHub Docs&lt;/a&gt; as your guide. Now you can appreciate the complexity that Probot solves by utilizing the &lt;a href="https://docs.github.com/en/developers/apps/creating-a-github-app-from-a-manifest" rel="noopener noreferrer"&gt;app manifest flow&lt;/a&gt; behind the scenes.&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%2Fuser-images.githubusercontent.com%2F2993937%2F113431040-2554c280-93a9-11eb-83e8-cd321bc7e9a6.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%2Fuser-images.githubusercontent.com%2F2993937%2F113431040-2554c280-93a9-11eb-83e8-cd321bc7e9a6.png" alt="create the app manually"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the App
&lt;/h3&gt;

&lt;p&gt;Visit your App's page at &lt;a href="https://github.com/apps/yourappname" rel="noopener noreferrer"&gt;https://github.com/apps/yourappname&lt;/a&gt; to start an installation process as before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the App
&lt;/h3&gt;

&lt;p&gt;Now you should have a &lt;a href="https://docs.github.com/en/developers/apps/authenticating-with-github-apps#generating-a-private-key" rel="noopener noreferrer"&gt;private key&lt;/a&gt;, App ID (found at the top of your app settings page, &lt;a href="https://github.com/settings/apps/yourappname" rel="noopener noreferrer"&gt;https://github.com/settings/apps/yourappname&lt;/a&gt;), and Installation ID (via API or in post-install URL like &lt;a href="https://github.com/settings/installations/1234567" rel="noopener noreferrer"&gt;https://github.com/settings/installations/1234567&lt;/a&gt;). You can use these to form API requests, either &lt;a href="https://docs.github.com/en/developers/apps/authenticating-with-github-apps" rel="noopener noreferrer"&gt;manually&lt;/a&gt;, via one of the &lt;a href="https://docs.github.com/en/rest/overview/libraries" rel="noopener noreferrer"&gt;Octokit libraries&lt;/a&gt;, or even &lt;a href="https://github.com/marketplace?type=actions&amp;amp;query=github+app+token" rel="noopener noreferrer"&gt;as an action&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out this video for a walkthrough example using Go on GitHub Enterprise Server:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=iaBEWB1As0k" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Listing in GitHub Marketplace
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/marketplace" rel="noopener noreferrer"&gt;GitHub Marketplace&lt;/a&gt; is a one stop shop for &lt;a href="https://docs.github.com/en/developers/github-marketplace/github-marketplace-overview" rel="noopener noreferrer"&gt;sharing your app with the GitHub community&lt;/a&gt; and even allowing developers to pay you for it. See &lt;a href="https://docs.github.com/en/developers/github-marketplace/requirements-for-listing-an-app" rel="noopener noreferrer"&gt;Requirements for listing an app - GitHub Docs&lt;/a&gt; for instructions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Today, we &lt;strong&gt;created, installed, and used&lt;/strong&gt; a simple GitHub App and highlighted some great features about GitHub Apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flexible, powerful integration model to build rich experiences and programmatic access to GitHub&lt;/li&gt;
&lt;li&gt;Can be discovered, purchased, and sold on GitHub Marketplace&lt;/li&gt;
&lt;li&gt;Fully backed by GitHub and extensively used by integrators and developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy developing! See you around!&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional resources:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/github-developer/github-apps-cheat-sheet" rel="noopener noreferrer"&gt;https://github.com/github-developer/github-apps-cheat-sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/rest/overview/libraries" rel="noopener noreferrer"&gt;https://docs.github.com/en/rest/overview/libraries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://probot.github.io/" rel="noopener noreferrer"&gt;https://probot.github.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/developers/apps" rel="noopener noreferrer"&gt;https://docs.github.com/en/developers/apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>github</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
