Skip to content

Latest commit

 

History

History
175 lines (136 loc) · 7.74 KB

02.8_actions-hackathon-case-study.md

File metadata and controls

175 lines (136 loc) · 7.74 KB

GitHub Actions Hackathon {docsify-ignore-all}

GitHub Hackathon

Hackathon case study

In March of 2020, in an effort to boost the number of actions on the community marketplace, GitHub hosted a month long actions Hackathon. This virtual Hackathon lasted only four weeks but the community generated over 1000 submissions during that month.

Some of the highlighted rules of the Hackthon were:

  • No teams! All Actions for the GitHub Actions Hackathon will need to be submitted by an individual.
  • There is no limit to the number of submissions any individual could contribute.
  • There is no specific topic or theme. You are welcome to create any type of Action that you’d like! Be creative and think outside the box.
  • GitHub employees, contractors, and immediate family members cannot compete.

Problem

The team tasked with running this Hackathon went into the project with a lot of unknowns that needed solutions for a smooth Hackathon experience.

  • Unsure of how many developers would participate.
  • As a global event time zones made it difficult to quickly provide feedback for submissions.
  • Protecting the employees from angry developers who submissions had been turned away.
  • What techniques would bad actors use to slip bad submissions through the cracks.

This truncated list of problems would need to be addressed for every submissions that came through the Hackthon, which would equate to quite a few hours if done manually. Because of this, the team needed a way to be notified as submissions came in as well as process those submissions in a repeatable and reliable manner.

Unfortunately, as the Hackathon went on, more unknowns crept up. Let's take a look at how the Hackathon team solved these workflow automation problems, to include the unknowns, using GitHub Actions.

Solution

Handling a submission:

Because the Hackthon was a static site, the team needed to use a repository_dispatch event to kickoff their handle-submission.yml workflow.

name: "Handle Submission"
on:
  repository_dispatch:
    types: handle-submission

jobs:
  create-pr:
    name: Create PR
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Use Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ env.NODE_VERSION }}
      - name: Process input
        run: |
          node utils/actions/process-input.js
      - name: Run prettier
        run: |
          npx prettier data/**/*.json --write
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN_PERSONAL }}
          branch: create-pull-request/submission/${{ github.event.client_payload.repo }}
          title: ${{ github.event.client_payload.id }} - ${{ github.event.client_payload.repo }}
          body: |
            Submitter: ${{ github.event.client_payload.user }}
            Repository: ${{ github.event.client_payload.repo }}
            Link: https://github.com/${{ github.event.client_payload.repo }}
            > ${{ github.event.client_payload.description }}
          labels: ${{ github.event.client_payload.id }}, submission

Since this was a submission based event, the ability to handle each submission in an automated manner saved the Hackathon team from needing to spend their time processing every submission and turning it into JSON. Once the JSON was properly created the final step of this workflow was to open a new pull request for that submission, which would trigger another workflow which was designed to run a series of validation checks.


Validating a submission:

Things that needed to be validated on a per submission basis included...

  • Verify the submitter of the action
  • Ensure the submitted action was in a public repository
  • Ensure the submission was accompanied by a license
  • Validate that the action was actually an action.
  • Check the commit history to ensure the action was developed according to the rules of the Hackathon

Take a look at the workflow snippet below as it uses GitHub Actions in a somewhat unique way. What you should notice is that the Hackathon team created workflows which used a series of run commands to execute multiple JavaScript files rather than building a complex series of contained acitons.

jobs:
  validate-submitter:
    name: Validate submitter
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Use Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ env.NODE_VERSION }}
      - name: Get PR info
        run: |
          node utils/actions/dist/get-pr-info
      - name: Validate submitter
        run: |
          node utils/actions/dist/validate-submitter

The accompanying utils/actions/dist/validate-submitter file can be seen below

const { setFailed } = require("./comment");
const github = require("@actions/github");
const octokit = new github.GitHub(process.env.GITHUB_TOKEN);

if (process.env.PR_SUBMITTER !== process.env.PR_REPO_OWNER) {
  setFailed("Submitter does not own the repository");
}

octokit.repos
  .getContents({
    owner: "github-hackathon",
    repo: "hackathon",
    path: "banned.txt",
  })
  .then((res) => {
    const bannedList = Buffer.from(res.data.content, "base64")
      .toString()
      .toLowerCase();
    if (bannedList.includes(process.env.PR_SUBMITTER.toLowerCase())) {
      return setFailed("User has been marked as ineligible.");
    }
  })
  .catch((e) => setFailed(e));

Protecting employees:

By automating the processing and validation of a submission the team was able to find the necessary bandwidth to manually review each submission at this point. The manual process of reviewing the open pull requests was by design to allow the team to prevent bad actors as well as perform a quick "quality" check to decide if the action was a "bare-minimum" attempt or if it should be featured.

Once a decision was made, the reviewer would apply a label to the pull request and GitHub Actions took over from there yet again. Any comments or feedback on the action were provided by the GitHub Actions bot, a special actor that exists within the feature, thus removing any one employee's name and profile from comments that could be received in a negative way.

To accomplish this a unique public action name GitHub Script was consumed. We will cover more on GitHub Script later in a hands-on lab.

For now, here is a quick look at what one of their many GitHub Script steps looked like.

- uses: actions/[email protected]
  name: Fork
  if: github.event.label.name == 'fork'
  with:
    script: |
      await github.issues.createComment({
        owner: "github-hackathon",
        repo: "hackathon",
        issue_number: context.payload.number,
        body: "Submission is a fork and does not represent the submitter as the author."
      });

      await github.pulls.update({
        owner: "github-hackathon",
        repo: "hackathon",
        pull_number: context.payload.number,
        state: "closed"
      });

Outcome

The unintended outcome of what the Hackathon team did was create a way to validate that actions were written within a set of rules and adhered to an internal standard. This same practice can find itself useful to an organization by allowing teams to write their own actions, which are then put through an automated vetting process.

Although for the Hackathon the teams main purpose was making sure rules were followed, your organization may consider adopting this practice and expanding it to ensure that actions meet security compliance, have necessary components to develop an audit trail, or simply conform to specific coding standards and use-cases.