IssueOps with GitHub Script

IssueOps with GitHub Script


What is GitHub Script

This is an action created by GitHub that can be used inside your workflows to script easily and quickly that interacts with GitHub API and workflow run context.

The cool thing about this action is that it offers a complete octokit library, pre-authenticated and ready to use inside your workflows. You can read more here.

How to use GitHub Script

The GitHub Script action is super simple to use, all you need to do is create a repository on GitHub and inside that create a workflow. To do that, you’ll create a file in this path: .github/workflows/my-first-workflow.yml.

Now for this demo, we’re going to create a simple IssueOps solution, that will help us create repositories.

Setting up the workflow

Now that the workflow file is created, we’re going to modify it and add the following content, this is to set up the events that drive the workflow and more, and a job that will contain our GitHub Script action steps. Note that the event that drives this workflow is Issues that are opened and edited, this is crucial for an IssueOps solution.

name: Create repo IssueOps Sample
on:
  issues:
    types: [opened, edited]


jobs:
  prepare:
    runs-on: ubuntu-latest

Now that we have an empty job, let’s add a couple of steps to it. One step that we’re going to add is the actions/checkout GitHub action, we’re doing this to checkout your repository in the workflow so we can work with any potential files. Another step we’re adding for debugging purposes is dumping the GitHub context. The last step we’re adding is an action that can fetch an Access Token on behalf of a GitHub App for us. If you’re unsure how this works, check out our previous post about GitHub Apps

...


if: github.event_name == 'issues' &&
      (github.event.action == 'opened' || github.event.action == 'edited')


    steps:
      - name: Check out scripts
        uses: actions/checkout@v3


      - name: Dump GitHub context
        env:
          GITHUB_CONTEXT: ${{ toJson(github) }}
        run: echo "$GITHUB_CONTEXT"
        
      - name: Get token
        id: sign-token
        uses: machine-learning-apps/actions-app-token@2d92b2a2bb7030dca3dd14975ae44799debed2e8
        with:
          APP_PEM: ${{ secrets.APP_PEM }}
          APP_ID: ${{ secrets.APP_ID }}  

Now it’s time to add our first GitHub Script step, which we’ll use to parse the issue that triggers the workflow. For the issue itself, we’ll show you how to set up an issue template later in this post.

...
    - name: Parse Issue
      id: parse-issue
      uses: actions/github-script@v6
      with:
        script: |
            const issueBody = context.payload.issue.body;
            cconst parsedName = issueBody.match(/### Repository name\s+(?<repository>[^\s]+)/);
            if (core) {
              if (parsedName) {
                  core.setOutput('reponame', parsedName.groups.repository.trim());
              }
            }
            return parsedName


...

Now that we’ve parsed the issue and returned it as an output to the workflow, we can use this value to name our repository. For the next step we’re going to use the GitHub Script action again, to create the API for us.

       - name: Create a Repository
         uses: actions/github-script@v6
          github-token: ${{ steps.sign-token.outputs.app_token }}
         with:
           script: |       
               var org = context.payload.repository.owner.login
               var name = ${{ $steps.parse-issue-output.reponame }}
               github.rest.repos.createInOrg({
               org,
               name,
               });

Note that we need to add the parameter github-token to pass in credentials with more permissions, as our pre-authenticated GitHub Script is locked to our workflow by default. To do this you can either supply a PAT or use a GitHub App, we recommend using a GitHub App and are using this for this example. The App’s scope for this needs to have Administration under Repository set to Read and Write.

To finish up the workflow, we’ll add a last step that reports back on the created issue, that the requested repository was successfully created or if something went wrong.

- uses: actions/github-script@v6
  with:
  script: |
    github.rest.issues.createComment({
      issue_number: context.issue.number,
      owner: context.repo.owner,
      repo: context.repo.repo,
      body: '👋 Repository has been created!'
    })

Issue template

To get the workflow to interact properly with issues, we’ll use Issue Templating. In this example we’re ussing Issue Forms templates, from where we’ll parse the requested repository name.

What is an Issue template

Issue templates allow you to customize and standardize the information you would like your contributor to provide when they open issues in your repository. More about issue and pull request templates - GitHub Docs

Creating an issue template

To get started with this we need to create .yml file into the following folder structure .github/ISSUE_TEMPLATE/myissue.yml

An example template would like this:

name: Request repository creation
description: Create a repository
title: "Request repository creation"
body:
  - type: "input"
    attributes:
      label: "Repository name"
      description: "Requested repository name"
      placeholder: "my-new-repo"
    validations:
      required: true

Summary

We learned what is github-script
We learned how to use it with IssueOps and in a workflow We briefly looked at Issue Templates Full source code for this can be found GitHub - SolidifyDemo/issueops-demo

This blog post was co-authored with @Mathias Bidstrup