Add And Update GitHub Tags With Node.js

Written by Khalid Abuhakmeh
5
This post is days old.

In a previous post, Leveling up our project management, I mentioned that we had settled on base set of tags for across our GitHub organization. We thought we had found a tool to allow us to do this, but it turns out that tool didn’t work. We didn’t want to resort to manually updating all of our repositories, so I wrote this Node.js script.

/*
    How To Run
    1. npm install unirest
    2. set the apiToken (get from GitHub)
    3. update the defaultOwner to the organization or account
    4. update the repositories array
    5. update the labels with names and colors
 */
/*
    Configuration
*/
var unirest = require("unirest");
var githubApi = "https://api.github.com";

var apiToken = ""; // your api token
var defaultOwner = ""; // your account / organization
// all the repositories
var repositories = [
    // { name : "", owner : "" }
    { name : "test-labels" }
];
// the labels
// target is used to "replace"
var labels = {
    values : [
        { name : "test", color : "ff0000", target : "" },
        { name: "world", color : "00ff00", target : "Hello" }
    ]
}
/*
    Code & Logic
*/
function getOwner(repo) {
    return repo.owner == null ? defaultOwner : repo.owner;
}

repositories.forEach(function (repo) {

   var labelsUrl =`${githubApi}/repos/${getOwner(repo)}/${repo.name}/labels`;

   // get existing labels on repository   
    unirest
        .get(labelsUrl)
        .headers("Authorization", `Token ${apiToken}`)
        .headers("User-Agent", "script")
        .end(function (response) {
            var repoLabels = response.body;
            console.log(`successfully retrieved ${repoLabels.length} labels from ${repo.name}`);

            // loop through labels
            // - If label doesn't exist create it
            // - If label exists and has replaces, replace it
            // - If label exists and doesn't have replace, update it
            labels.values.forEach(function (label) {    
                var exists = repoLabels
                    .findIndex(x => x.name.toLowerCase() === label.name.toLowerCase()) > -1;
                var targetExists = repoLabels
                    .findIndex(x => x.name.toLowerCase() === label.target.toLowerCase()) > -1;

                var updateLabel = function(name) {
                     unirest.patch(`${labelsUrl}/${name}`)
                        .headers("Authorization", `Token ${apiToken}`)
                        .headers("User-Agent", "script")
                        .type('json')
                        .send(label)
                        .end(function (response) {
                            console.log(`succesfully UPDATED ${name} on ${repo.name}.`)
                        });  
                }; // updateLabel

                if (targetExists) {                                             
                   updateLabel(label.target);                                         
                }                
                else if (exists) {
                   updateLabel(label.name)
                } else {
                   // create label
                    unirest.post(labelsUrl)
                        .headers("Authorization", `Token ${apiToken}`)
                        .headers("User-Agent", "script")
                        .type('json')
                        .send(label)
                        .end(function (response) {
                            console.log(`succesfully ADDED ${label.name} on ${repo.name}.`)
                        });    
                }          
            }); // labels forEach
   });
}); // repositories forEach

Save this script, make the necessary modifications, and then run it via the command line.

$ node app.js

Hope the script helps other teams looking to normalize the tags across their GitHub repositories.

Suggested reading

Comments