Github Workflow with octokit.js using GHES plugin

Table of Contents


Github Workflow with octokit.js using GHES plugin

Recently I had a project where I needed to create GItHub IssueOps solution using GitHub workflows to automate a migration process. With GitHub Workflows and actions its really simple and awesome to do.

Background of the requirements

For this instances what I needed to do was to migrated data from a GitHub Enterprise server to the Github.com cloud using GitHub’s open source tool GH-GEI CLI.

What is GH-GEI

The GitHub Enterprise Importer (GEI, formerly Octoshift) is a highly customizable API-first migration tool that helps you move your enterpise to GitHub Enterprise cloud.

What was needed

The requirement was that when the migration process was triggered I needed to “lock” (archive, set to readonly mode ) the repositories on the source organisation to avoid any accidental updates being pushed while the repositories were being migrated.

Solution

The tricky part was to understand how to do send request to GHES server through a custom Javascript action. Sending requests to Github Cloud using oktokit is supper simple and straight forward but using oktokit to send requests to GHES needed a little bit of a different approach.

For that I create a JavaScript file that can be called from the action to do the repository locking. The caveat was that its not so clear how to call the GHAS APIs.

const { Octokit } = require('@octokit/core');
const { enterpriseServer35 } = require("@octokit/plugin-enterprise-server");

var lockRepository = async function (octokit, owner, repo) {
    try {
        return await octokit.repos.update({
            owner,
            repo,
            archived: true
        })
    } catch (e) {
        console.log(e);
        return
        // Repository was archived so is read-only.
    }
};

module.exports = async ({ github, context, options }) => {
    const ghesApiUrl = options.ghesApiUrl;
    const OctokitEnterpriseServer35 = Octokit.plugin(enterpriseServer35);
    const octokit = new OctokitEnterpriseServer35({
        auth: `${options.adminToken}`,
        baseUrl: `${ghesApiUrl}`,
    });
    
    const repo = "my-reposisotry";
    const owner = "my-organisaton";
    console.log(`Locking repository (${repo})`);
    lockRepository(octokit, owner, repo);
    
    const body = `
      ## 🎉 Locked repository
      \`\`\`
      ${repo}
      \`\`\`
    `
    await github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: body.replace(/  +/g, '')
    });
}

I needed to import two package @ooctokit/core and a plugin that exposes GHAS API endpoints @octokit/plugin-enterprise-server. The source code and documentation for this plugin can be found here.

use github-script to execute the script

To run the script in the workflow I will use github-script action step to call the script file.

Note that before I can use the github-script step I need to install depndencies that are not part of the action step by default.


...

name: Install Node dependencies
run: npm install --no-save @octokit/core @octokit/plugin-enterprise-server

    
name: Lock repositories
uses: actions/github-script@v6
with:
   script: |
      const options = { adminToken: '${{ secrets.MY_GHES_ADMIN_TOKEN }}', ghesApiUrl: '${{ secrets.GHES_API_URL }}' }
            await require('./.github/scripts/lock-repositories.js')({github, context, options})
            

Now that I have implemented my workflow step to lock the repository, I am good to continue.