<?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>Forem: Dan Croak</title>
    <description>The latest articles on Forem by Dan Croak (@croaky).</description>
    <link>https://forem.com/croaky</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%2F356446%2F0f020b4e-3d48-4d2b-abfb-5b52cf06456f.jpeg</url>
      <title>Forem: Dan Croak</title>
      <link>https://forem.com/croaky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/croaky"/>
    <language>en</language>
    <item>
      <title>Postgres concat_ws() function</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Fri, 28 Aug 2020 18:30:55 +0000</pubDate>
      <link>https://forem.com/croaky/postgres-concatws-function-1e27</link>
      <guid>https://forem.com/croaky/postgres-concatws-function-1e27</guid>
      <description>&lt;p&gt;Postgres provides a &lt;a href="https://www.postgresql.org/docs/current/functions-string.html"&gt;&lt;code&gt;concat_ws()&lt;/code&gt;&lt;/a&gt; string function with this signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;concat_ws(sep text, str "any" [, str "any" [, ...] ])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider a schema where the &lt;code&gt;projects.second_user_id&lt;/code&gt; and &lt;code&gt;project.third_user_id&lt;/code&gt; columns can be &lt;code&gt;NULL&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              Table "public.projects"
     Column     |            Type        | Nullable |
----------------+------------------------+-----------
 id             | bigint                 | not null |
 name           | character varying(255) | not null |
 lead_user_id   | bigint                 | not null |
 second_user_id | bigint                 |          |
 third_user_id  | bigint                 |          |

                Table "public.users"
     Column     |            Type        | Nullable |
----------------+------------------------+-----------
 id             | bigint                 | not null |
 initials       | character varying(255) | not null |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider a query to get the "team" for a project by each user's initials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;concat_ws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' / '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;projects&lt;/span&gt;
  &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;u1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lead_user_id&lt;/span&gt;
  &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second_user_id&lt;/span&gt;
  &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;u3&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;u3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;third_user_id&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;team&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     name     |     team    
-------------------+--------------
Private Beta  | AB / CD
SLA           | EF / GH / IJ
Treasury Ops  | KL
(3 rows)

Time: 1 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;concat_ws()&lt;/code&gt; instead of &lt;code&gt;concat()&lt;/code&gt; avoids ugly output like &lt;code&gt;AB / / CD&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>sql</category>
    </item>
    <item>
      <title>Schedule Netlify Builds with GitHub Actions</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Wed, 05 Aug 2020 19:45:31 +0000</pubDate>
      <link>https://forem.com/croaky/schedule-netlify-builds-with-github-actions-5cdc</link>
      <guid>https://forem.com/croaky/schedule-netlify-builds-with-github-actions-5cdc</guid>
      <description>&lt;p&gt;I use a &lt;a href="https://github.com/croaky/blog"&gt;custom static site generator&lt;/a&gt; to publish my blog. It automatically deploys to Netlify when I merge new articles into my Git repository's &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;To support a "scheduled article" feature, I have configured a &lt;a href="https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#onschedule"&gt;GitHub Actions scheduled workflow&lt;/a&gt;:&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;daily publish&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt; &lt;span class="c1"&gt;# every day at midnight UTC&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&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;Trigger Netlify build&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;NETLIFY_BUILD_HOOK&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NETLIFY_BUILD_HOOK }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -X POST -d {} "$NETLIFY_BUILD_HOOK"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every day at midnight UTC, GitHub runs the workflow, deploying the site using a &lt;a href="https://docs.netlify.com/configure-builds/build-hooks/"&gt;Netlify build hook&lt;/a&gt;. The build hook is a URL which I've stored as a &lt;a href="https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#using-encrypted-secrets-in-a-workflow"&gt;GitHub encrypted secret&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When there are articles whose scheduled date matches the new UTC date, they are automatically published by this workflow.&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>static</category>
      <category>github</category>
      <category>actions</category>
    </item>
    <item>
      <title>Postgres \set variable</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Tue, 04 Aug 2020 15:57:02 +0000</pubDate>
      <link>https://forem.com/croaky/postgres-set-variable-21ld</link>
      <guid>https://forem.com/croaky/postgres-set-variable-21ld</guid>
      <description>&lt;p&gt;Within &lt;code&gt;psql&lt;/code&gt;, you can &lt;code&gt;\set&lt;/code&gt; variables and reference them with &lt;code&gt;:'var-name'&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="s1"&gt;'%SaaS%'&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="s1"&gt;'https://example.com/companies/'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;companies&lt;/span&gt;
  &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;company_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt;
  &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt;
  &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="k"&gt;ILIKE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to &lt;a href="https://dev.to/croaky/format-sql-on-save-run-sql-with-leader-r-296d"&gt;run scripts from Vim through &lt;code&gt;psql&lt;/code&gt; with this config&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>vim</category>
    </item>
    <item>
      <title>SSH Key with Ed25519</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Tue, 04 Aug 2020 15:55:28 +0000</pubDate>
      <link>https://forem.com/croaky/ssh-key-with-ed25519-4lc6</link>
      <guid>https://forem.com/croaky/ssh-key-with-ed25519-4lc6</guid>
      <description>&lt;p&gt;With my last team, at the request of &lt;a href="https://r.32k.io/"&gt;Ryan&lt;/a&gt;, our CTO, I stopped using RSA for my public keys and started using Ed25519.&lt;/p&gt;

&lt;p&gt;Ed25519 uses elliptic curve cryptography with good security and performance. That's the real reason to use it.&lt;/p&gt;

&lt;p&gt;My favorite thing, though, is when the whole team uses Ed25519, a server's &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file looks 😍:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIAePksB5aPc6sww+RMzJwpVuDhRAgzOKP1Q/o3suIbw alice@home.local
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEB/O/VwAvqWIV/EN9aHjHAg/9JYsX/Ce2yvr5wPI3gZ bob@work.local
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAYG1rgF4YSSBwtinbhFLR/Qeah11jYcQpf6lX4yql60 carol@home.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "$(whoami)@$(hostname)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the SSH agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval "$(ssh-agent -s)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Host github.com
  Hostname ssh.github.com
  Port 443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the private key to the SSH agent on macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-add -K ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>unix</category>
      <category>macos</category>
      <category>ssh</category>
    </item>
    <item>
      <title>Format and run SQL on save in Vim</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Tue, 04 Aug 2020 02:11:03 +0000</pubDate>
      <link>https://forem.com/croaky/format-sql-on-save-run-sql-with-leader-r-296d</link>
      <guid>https://forem.com/croaky/format-sql-on-save-run-sql-with-leader-r-296d</guid>
      <description>&lt;p&gt;Install and configure &lt;a href="https://github.com/dense-analysis/ale"&gt;ALE&lt;/a&gt; in &lt;code&gt;~/.vimrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;call&lt;/span&gt; plug#begin&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'~/.vim/plugged'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  Plug &lt;span class="s1"&gt;'dense-analysis/ale'&lt;/span&gt; " &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;help&lt;/span&gt; ale
&lt;span class="k"&gt;call&lt;/span&gt; plug#end&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;~/.vim/ftplugin/sql.vim&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" Auto-fix&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;b:ale_fixers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'pgformatter'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_fix_on_save&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;b:ale_sql_pgformatter_options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'--function-case 1 --keyword-case 2 --spaces 2'&lt;/span&gt;

&lt;span class="c"&gt;" Run current file&lt;/span&gt;
nmap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;r&lt;/span&gt; &lt;span class="p"&gt;:!&lt;/span&gt;clear &amp;amp;&amp;amp; psql &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;d&lt;/span&gt; $&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;cat&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;db&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;f&lt;/span&gt; %&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my &lt;a href="https://github.com/croaky/laptop"&gt;laptop.sh&lt;/a&gt;, I have a variant of the following that is idempotent; it will install or update &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; and &lt;a href="https://github.com/darold/pgFormatter"&gt;pgFormatter&lt;/a&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;# pgformatter&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;pgformatter

&lt;span class="c"&gt;# Vim plugins&lt;/span&gt;
curl &lt;span class="nt"&gt;-fLo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.vim/autoload/plug.vim"&lt;/span&gt; &lt;span class="nt"&gt;--create-dirs&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.vimrc"&lt;/span&gt; +PlugUpdate +PlugClean! +qa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In each of my projects, I have a &lt;code&gt;.db&lt;/code&gt; file that contains only my database name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example_development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I save a &lt;code&gt;.sql&lt;/code&gt; file in Vim, it auto-formats it with &lt;code&gt;pgformatter&lt;/code&gt; using the flags from my &lt;code&gt;ftplugin/sql.vim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When I run &lt;code&gt;&amp;lt;Leader&amp;gt;r&lt;/code&gt; from a &lt;code&gt;.sql&lt;/code&gt; file in Vim, it runs the file against my &lt;code&gt;.db&lt;/code&gt; Postgres database through &lt;code&gt;psql&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>vim</category>
    </item>
    <item>
      <title>caffeinate -u -d</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Sat, 01 Aug 2020 18:57:44 +0000</pubDate>
      <link>https://forem.com/croaky/caffeinate-u-d-2277</link>
      <guid>https://forem.com/croaky/caffeinate-u-d-2277</guid>
      <description>&lt;p&gt;My MacBook Pro running Catalina has been crashing when:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;attached to an external monitor (an LG UltraFine 5K Display),&lt;/li&gt;
&lt;li&gt;in clamshell mode, and&lt;/li&gt;
&lt;li&gt;it goes to sleep&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This looks like a known bug according to forum posts like &lt;a href="https://discussions.apple.com/thread/250715149?page=25"&gt;this&lt;/a&gt; and &lt;a href="https://forums.macrumors.com/threads/constant-kernel-panics-userspace-watchdog-timeout-no-successful-checkins-from-com-apple-windowserver.2222878/page-18?post=28629447#post-28629447"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My workaround for now has been:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;manually put the computer to sleep when I step away or&lt;/li&gt;
&lt;li&gt;not use the monitor or&lt;/li&gt;
&lt;li&gt;when running a long-running process and I want to step away, running &lt;a href="https://github.com/uasi/caffeinate"&gt;&lt;code&gt;caffeinate&lt;/code&gt;&lt;/a&gt; in a shell to prevent idle sleep:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;caffeinate -u -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>macos</category>
      <category>unix</category>
    </item>
    <item>
      <title>Heroku to Slack with AWS Lambda</title>
      <dc:creator>Dan Croak</dc:creator>
      <pubDate>Thu, 30 Jul 2020 17:34:54 +0000</pubDate>
      <link>https://forem.com/croaky/heroku-to-slack-with-aws-lambda-1kd9</link>
      <guid>https://forem.com/croaky/heroku-to-slack-with-aws-lambda-1kd9</guid>
      <description>&lt;p&gt;When my production app processes change state on Heroku, I want to be notified in Slack:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vPLOsyR9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dancroak.com/images/heroku-to-slack.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vPLOsyR9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dancroak.com/images/heroku-to-slack.png" alt="Screenshot of Slack notification"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17:38:52 clock.1 `bundle exec ruby schedule/clock.rb` up
17:39:03 web.1 `bundle exec puma -p $PORT -C ./config/puma.rb` up
17:39:05 web.2 `bundle exec puma -p $PORT -C ./config/puma.rb` up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pager-notifying events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17:38:52 queuenote.1 `bundle exec ruby queue/note.rb` crashed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://devcenter.heroku.com/articles/app-webhooks"&gt;Heroku has webhooks&lt;/a&gt; for these events but their payloads aren't in the format needed for &lt;a href="https://api.slack.com/messaging/webhooks"&gt;Slack incoming webhooks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;AWS Lambda is the perfect glue to transform the Heroku webhook's JSON payload into a useful JSON payload for Slack's incoming webhook.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slack config
&lt;/h2&gt;

&lt;p&gt;Create an &lt;a href="https://api.slack.com/messaging/webhooks"&gt;incoming webhook&lt;/a&gt;. Copy the URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lambda config
&lt;/h2&gt;

&lt;p&gt;Create a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html"&gt;Lambda function&lt;/a&gt;. AWS' supported runtimes include Node, Python, Ruby, and Go. You can alternatively implement a custom runtime.&lt;/p&gt;

&lt;p&gt;Here's an example in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"net/http"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"time"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"uri"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
  &lt;span class="n"&gt;dyno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dyno&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dyno&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;

  &lt;span class="n"&gt;ignored_states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"starting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"down"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;term_one_off&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"crashed"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"scheduler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;any?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ignored_states&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;term_one_off&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;statusCode: &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;headers: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SLACK_URL"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_ssl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request_uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt;

  &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;text: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dyno&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;getlocal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-07:00"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'%H:%M:%S'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;dyno&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;state&lt;/span&gt;
    &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&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="nf"&gt;to_json&lt;/span&gt;

  &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;statusCode: &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;headers: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/json"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the Slack incoming webhook URL as an environment variable, which is encrypted at rest.&lt;/p&gt;

&lt;p&gt;Create an &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html"&gt;API Gateway&lt;/a&gt; to make the Lambda function accessible in the Heroku web UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heroku config
&lt;/h2&gt;

&lt;p&gt;Go to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://dashboard.heroku.com/apps/YOUR-APP-NAME/webhooks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a webhook with event type "dyno". Paste the API Gateway URL as the Payload URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modify to taste
&lt;/h2&gt;

&lt;p&gt;Edit and save the code in Lambda's web-based text editor. Trigger a webhook to test the function. View the auto-created CloudWatch logs for each function call.&lt;/p&gt;

</description>
      <category>heroku</category>
      <category>slack</category>
      <category>aws</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
