2

Introduction

Currently, I'm programming a GitHub Action to facilitate the publishing of JavaDoc to a static web page.

The GitHub repo link of the GitHub Action: https://github.com/MathieuSoysal/Javadoc-publisher.yml

In this project I have this badge Public workflows that use this action. to show how many GitHub project uses the GitHub Action.

URL of the badge:

https://img.shields.io/endpoint?url=https%3A%2F%2Fapi-endbug.vercel.app%2Fapi%2Fgithub-actions%2Fused-by%3Faction%3DMathieuSoysal%2FJavadoc-publisher%26badge%3Dtrue

The badge uses this data:

https://api-endbug.vercel.app/api/github-actions/used-by?action=MathieuSoysal/Javadoc-publisher&badge=true

Here is the source code of this service: https://github.com/EndBug/api/blob/main/api/github-actions/used-by.ts

Problem

The badge shows 7 users of GitHub Actions but in fact, is 64.

Question

Does someone know how to make a badge to show how many repos use a GitHub Action?

A.L
  • 10,259
  • 10
  • 67
  • 98
ThrowsError
  • 1,169
  • 1
  • 11
  • 43

1 Answers1

0

Your current code used-by.ts is using Vercel (previously called Zeit) to create a serverless function to return badge data.
I would recommend having a more precise search query. For example, searching for the exact file (filename:javadoc-publisher.yml) might yield more accurate results than a general search.
And do add proper error handling to avoid potential issues when making requests to the GitHub API.

import { VercelRequest, VercelResponse } from '@vercel/node';
import { Octokit } from '@octokit/core';

const octokit = new Octokit({
  auth: process.env.GITHUB_SEARCH_TOKEN
});

/**
 * Fetches the number of repositories using the specified GitHub Action.
 * 
 * @param action - The GitHub Action to search for.
 * @returns - The number of repositories using the action.
 */
async function getUsageCount(action: string): Promise<number> {
  // Replace special characters and build the search query
  const searchQuery = `${action.replace(
    /[\.,:;/\\`'"=*!?#$&+^|~<>(){}\[\]]/g, 
    '+'
  )} filename:javadoc-publisher.yml path:.github/workflows/ language:YAML fork:true`;

  const response = await octokit.request('GET /search/code', { q: searchQuery });
  return response.data.total_count;
}

export default async (req: VercelRequest, res: VercelResponse) => {
  const { action, badge, ...badgeStuff } = req.query;

  if (!action || typeof action !== 'string') {
    return res.status(400).send("Invalid action parameter.");
  }
  
  try {
    const count = await getUsageCount(action);

    if (badge === 'true') {
      res.send({
        schemaVersion: 1,
        label: 'used by',
        message: `${count}`,
        color: '#2088FF',
        namedLogo: 'GitHub Actions',
        logoColor: 'white',
        ...badgeStuff
      });
    } else {
      res.send(count.toString());
    }
  } catch (error) {
    console.error("Error fetching GitHub data:", error.message);
    res.status(500).send("Error fetching data from GitHub.");
  }
};

But if it is still incorrect, try a more hard-coded getUsageCount(), just for testing/debugging:

const { Octokit } = require('@octokit/core');

const octokit = new Octokit({
  auth: 'YOUR_GITHUB_TOKEN' // Replace with your actual token or better yet, use an environment variable.
});

async function getUsageCount() {
  try {
    const response = await octokit.request('GET /search/code', {
      q: 'MathieuSoysal+javadoc-publisher filename:javadoc-publisher.yml path:.github/workflows/ language:YAML'
    });
    return response.data.total_count;
  } catch (error) {
    throw new Error('Failed to fetch data from GitHub: ' + error.message);
  }
}

// To test
getUsageCount()
  .then(count => console.log(count))
  .catch(err => console.error(err));
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250