paint-brush
Git Ahead Dashboard: A Quick Guideby@vdolzhenko
165 reads

Git Ahead Dashboard: A Quick Guide

by Viktoria DolzhenkoAugust 22nd, 2024
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The vast majority of modern systems are built on a microservice architecture. This means that you can be the maintainer of about a hundred services. It is important for you to monitor the relevance of the master branch of all projects. Check how much your main project branch lags behind the test branch after the release.
featured image - Git Ahead Dashboard: A Quick Guide
Viktoria Dolzhenko HackerNoon profile picture

The vast majority of modern systems are built on a microservice architecture. This means that you can be the maintainer of about a hundred services, which are being worked on by several teams of software engineers. As the person responsible for the system, it is important for you to monitor the relevance of the master branch of all projects.


One of the easiest and fastest ways to do this is to check how much your main project branch lags behind the test branch after the release. Thanks to this simple check, you will be sure that the teams have brought all the services to production.


Also, a quick report on the lag of the master branch from dev will be useful for understanding the state of development. If more than a few hundred commits have accumulated in the dev branch, then this is a red flag and you, as a team lead, should raise this issue at the sprint retro, because it is obvious that there were interruptions in the process of delivering improvements to production.


To solve the problem of quickly viewing ahead/behind my projects, I use the rest API for GitLab (https://docs.gitlab.com/ee/api/rest/), which provides me with all the necessary capabilities.


As a language, I chose JavaScript without frameworks, because we have a fast development for ourselves, which should not require a special environment.

As a result of the script's work, I want to see a table with columns in the console:

  • group_id - gitlab project group id
  • group_name - the name of the project group
  • id - project id
  • name - project name
  • behind - how many commits is the master branch ahead of the dev
  • ahead - how many commits is the dev branch ahead of the master


To access the data, I will use a personal access token, which can be obtained in the settings of my GitLab profile.


First, I'll get a list of groups using the/api/v4/groups method.


After that, I need to get a list of project repositories using the /api/v4/groups/${group.id}/projects method.


All that remains is to get the number of commits using the /api/v4/projects/${project.id}/repository/compare method.


Next, I collect the data in a table, perform a sorting that is convenient for me, and highlight problematic lines.


To perform REST requests, I use axios, and to output a table with data, I use the console-table-printer project. As a result, I got the following script.


const { Table } = require('console-table-printer');
const axios = require('axios');

const token = token';
const baseUrl = 'https://git.my-company.net';
const from = 'master';
const to = 'dev';

(async () => {
    let data = [];
    const groups = await axios
        .get(`${baseUrl}/api/v4/groups?private_token=${token}`)
        .then(res => res.data);

    await Promise.all(groups.map(async (group) => {
        const projects = await axios
            .get(`${baseUrl}/api/v4/groups/${group.id}/projects?per_page=100&private_token=${token}`)
            .then(res => res.data);

        await Promise.all(projects.map(async (project) => {
            const behind = await axios
                .get(`${baseUrl}/api/v4/projects/${project.id}/repository/compare?from=${from}&to=${to}&private_token=${token}`)
                .then(res => res.data)
                .catch(err => {});
            const ahead = await axios
                .get(`${baseUrl}/api/v4/projects/${project.id}/repository/compare?from=${to}&to=${from}&private_token=${token}`)
                .then(res => res.data)
                .catch(err => {});
            if (behind && behind.commits && ahead && ahead.commits){
                data.push({
                    group_id: group.id,
                    group_name: group.name,
                    id: project.id,
                    name: project.name,
                    behind: behind.commits.length,
                    ahead: ahead.commits.length,
                });
            }
        }));
    }))

    data = data
        .sort((a,b) =>
            (a.group_name > b.group_name)
                ? 1
                : ((b.group_name > a.group_name) ? -1
                    : (a.name > b.name)
                        ? 1
                        : ((b.name > a.name) ? -1 : 0)));

    const table = new Table();
    data.forEach((row) => {
        table.addRow(row, {
            color: row.behind ? 'red' : undefined,
        });
    });
    table.printTable();
})();


After its execution, the following table is output to the console:

group_id

group_name

id

name

behind

ahead

235

common

34

common_service

5

2

235

common

455

master_data

0

0

379

core

453

core_service

7

0

379

core

344

core_tasks

3

1