paint-brush
Building my Github Action to Deliver Doggoes to PRsโ€‚by@stanleynguyen
143 reads

Building my Github Action to Deliver Doggoes to PRs

by Stanley NguyenMay 9th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

GitHub's GitHub Action feature is finally out of beta and ready to be present in every repository. Building a GitHub Action to deliver doggo gifs to PRs is the first step of the GitHub hackathon. I created a GitHub action to deliver good boys to good boys on pull requests. It's obvious to go with TypeScript action template. The main run file will be run from a main entrypoint (think running a Node process for web applications, etc). The dogggo generator works properly, I can retrieve an URL of a doggoo gif, create a comment on pull request.

Company Mentioned

Mention Thumbnail
featured image - Building my Github Action to Deliver Doggoes to PRs
Stanley Nguyen HackerNoon profile picture
Because who doesn't want good boys to show up whenever they push?
The long awaited GitHub Action feature is finally out of beta and ready to be present in every repositories. GitHub even organized through out March to encourage folks to create more awesome and useful actions. While browsing through the submissions, I found that posts cat gifs on pull requests. Shout out to with his cool idea ๐Ÿ‘๐Ÿ‘๐Ÿ‘.It'll only do justice to dogs if there's an action that deliver them good boys to our PRs. That moment I knew exactly what my next Github Action project would be. Time to get to work.

The gist of creating a GitHub Action

are basically premade (with โค๏ธ) units of work to be used GitHub workflows (think 's builds). Github actions can be either built with or . An advantage to creating a GitHub action with JS/TS is readily available modules from . With such integration support, it's much easier to connect with GitHub services (C'mon ๐Ÿ™„ Who wanna write

curl
commands to make API calls). It's obvious to go with . With that decision made, let's get down to writing .

The main run file

In a JS/TS GitHub action, workload will be started out from a main entrypoint (think running

node src/index.js
to start a Node process for web applications, etc). For action-dogs, this is my basic setup for the main program

import * as core from "@actions/core";
import * as github from "@actions/github";
import { generate } from "./doggo/generator";

(async function run(): Promise<void> {
  try {
    const ctx = github.context;
    if (!ctx.payload.pull_request) {
      throw new Error("Not in the context of a PR!");
    }

    const ghCli = new github.GitHub(core.getInput("github-token"));
    const doggo = generate();
    ghCli.issues.createComment({
      ...ctx.repo,
      issue_number: ctx.payload.pull_request.number,
      body: `![Doggo](${doggo})`
    });
  } catch (e) {
    core.setFailed(e.message);
  }
})();

During an event that can trigger GitHub workflows, we are provided with a context object that can be accessed through

@actions/github
module. Using that, I'm able to check whether my payload is coming from a
pull_request
and reject otherwise. Next up, I need to post a comment to the corresponding pull request with content of a doggo gif. Given that my doggo generator (of which I will explain in the next section) works properly, I can retrieve an URL of a doggo gif, creating a comment on pull requests is super simple as I just need to pass in the repo's information from our context object and the PR's number. Also, in case we get any errors during these operations, calling
core.setFailed(e.message)
will mark the build as failed with the error message.

The doggo generator

After much research with the intention to use one of the public APIs to get random doggo gifs, I couldn't find one that's public (like ) and also serves gifs (like ). Since there's no avenue for me to store my GIPHY API key securely to be used in action-dogs, I fell back to the good-ol-way of static JSON array.Wanna know how I obtained my array full of doggo awesomeness (from โค๏ธ โค๏ธ) without any API key generated in the process? I actually went to GIPHY site, searched for doggoes, and scrolled down util a good amount of "giffy-boys" got rendered before pulling up my console
And with these few lines of JS
const dogsData = [];
document
  .querySelectorAll("a._2SwDiFPqIlZmUDkxHNOeqU")
  .forEach(e => dogsData.push(e.href));
var dataStr =
  "data:text/json;charset=utf-8," +
  encodeURIComponent(JSON.stringify(dogsData));
var dlAnchorElem = document.createElement("a");
dlAnchorElem.setAttribute("href", dataStr);
dlAnchorElem.setAttribute("download", "dogs.json");
dlAnchorElem.click();
which basically grab `href` values from all "copy link" elements on the search results page, stream them to a JSON array and fill in a file for me to "download", "generating" is simply picking a random URL from the array.
import dogs from "./dogs.json";

export function generate(): string {
  return dogs[Math.floor(Math.random() * dogs.length)];
}

Testing

I wrote a unit test for my doggo generator using jest (but actually mainly as an avenue for funny descriptions).
import { generate } from "../../src/doggo/generator";

describe("doggo generator", () => {
  test("to return a good boy", () => {
    Math.random = jest.fn().mockReturnValue(0);
    const good = "//media3.giphy.com/media/mCRJDo24UvJMA/giphy.gif";
    const boy = generate();
    expect(boy).toBe(good);
  });
});

But the real test is a workflow using

action-dogs
itself (Yes, you can use a GitHub action on its own repo ๐Ÿคฏ).

name: "doggo"

on: pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: stanleynguyen/action-dogs@master
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

Now I can see

action-dogs
in action with . Hurray ๐Ÿ™Œ๐Ÿ™Œ๐Ÿ™Œ!! Now I can safely .

Outtro

So that's my story of creating

action-dogs 
for fun and learning. You can find source code right on (well, because where else could it be ๐Ÿคทโ€โ™‚๏ธ) and
action-dogs
on .


๋ฐ”์นด๋ผ์‚ฌ์ดํŠธ ๋ฐ”์นด๋ผ์‚ฌ์ดํŠธ ์˜จ๋ผ์ธ๋ฐ”์นด๋ผ