badges/shields

New Feature Request: Github release (latest on a specified branch)

Open

#7929 opened on May 6, 2022

View on GitHub
 (4 comments) (2 reactions) (0 assignees)JavaScript (22,337 stars) (5,423 forks)batch import
good first issueservice-badge

Description

:clipboard: Description

A clear and concise description of the new badge.

  • Which service is this badge for: GitHub
  • What sort of information should this badge show?
    • It should display the latest release in a github repo at a specified branch in the repo. It should look like this:
    • Release  
    • <specified_branch> will be replaced by the branch specified by the user
    • <version_number> will be replaced by the value in the tag_name field of the desired release object in the response returned by the Github API's List Releases endpoint. A sample JSON response from invoking this endpoint for the Laravel framework repo to get the most recent two releases (https://api.github.com/repos/laravel/framework/releases?per_page=2) is shown below:
[
   {
      "url":"https://api.github.com/repos/laravel/framework/releases/65953046",
      "assets_url":"https://api.github.com/repos/laravel/framework/releases/65953046/assets",
      "upload_url":"https://uploads.github.com/repos/laravel/framework/releases/65953046/assets{?name,label}",
      "html_url":"https://github.com/laravel/framework/releases/tag/v9.11.0",
      "id":65953046,
      "author":{
         "login":"TBlindaruk",
         "id":12684601,
         "node_id":"MDQ6VXNlcjEyNjg0NjAx",
         "avatar_url":"https://avatars.githubusercontent.com/u/12684601?v=4",
         "gravatar_id":"",
         "url":"https://api.github.com/users/TBlindaruk",
         "html_url":"https://github.com/TBlindaruk",
         "followers_url":"https://api.github.com/users/TBlindaruk/followers",
         "following_url":"https://api.github.com/users/TBlindaruk/following{/other_user}",
         "gists_url":"https://api.github.com/users/TBlindaruk/gists{/gist_id}",
         "starred_url":"https://api.github.com/users/TBlindaruk/starred{/owner}{/repo}",
         "subscriptions_url":"https://api.github.com/users/TBlindaruk/subscriptions",
         "organizations_url":"https://api.github.com/users/TBlindaruk/orgs",
         "repos_url":"https://api.github.com/users/TBlindaruk/repos",
         "events_url":"https://api.github.com/users/TBlindaruk/events{/privacy}",
         "received_events_url":"https://api.github.com/users/TBlindaruk/received_events",
         "type":"User",
         "site_admin":false
      },
      "node_id":"RE_kwDOAHMwOs4D7l0W",
      "tag_name":"v9.11.0",
      "target_commitish":"9.x",
      "name":"",
      "draft":false,
      "prerelease":false,
      "created_at":"2022-05-03T14:47:20Z",
      "published_at":"2022-05-03T19:11:49Z",
      "assets":[
         
      ],
      "tarball_url":"https://api.github.com/repos/laravel/framework/tarball/v9.11.0",
      "zipball_url":"https://api.github.com/repos/laravel/framework/zipball/v9.11.0",
      "body":"### Added\r\n- Added Illuminate/Collections/Arr::join() ([#42197](https://github.com/laravel/framework/pull/42197))\r\n- Added has and missing methods to ValidatedInput ([#42184](https://github.com/laravel/framework/pull/42184))\r\n- Added deprecation stack trace config option ([#42235](https://github.com/laravel/framework/pull/42235))\r\n\r\n### Fixed\r\n- Fix deprecation issue with translator and empty rules ([#42216](https://github.com/laravel/framework/pull/42216), [#42213](https://github.com/laravel/framework/pull/42213))\r\n\r\n### Changed\r\n- Improve EventFake::assertListening() support for subscribers ([#42193](https://github.com/laravel/framework/pull/42193))\r\n"
   },
   {
      "url":"https://api.github.com/repos/laravel/framework/releases/65953258",
      "assets_url":"https://api.github.com/repos/laravel/framework/releases/65953258/assets",
      "upload_url":"https://uploads.github.com/repos/laravel/framework/releases/65953258/assets{?name,label}",
      "html_url":"https://github.com/laravel/framework/releases/tag/v8.83.11",
      "id":65953258,
      "author":{
         "login":"TBlindaruk",
         "id":12684601,
         "node_id":"MDQ6VXNlcjEyNjg0NjAx",
         "avatar_url":"https://avatars.githubusercontent.com/u/12684601?v=4",
         "gravatar_id":"",
         "url":"https://api.github.com/users/TBlindaruk",
         "html_url":"https://github.com/TBlindaruk",
         "followers_url":"https://api.github.com/users/TBlindaruk/followers",
         "following_url":"https://api.github.com/users/TBlindaruk/following{/other_user}",
         "gists_url":"https://api.github.com/users/TBlindaruk/gists{/gist_id}",
         "starred_url":"https://api.github.com/users/TBlindaruk/starred{/owner}{/repo}",
         "subscriptions_url":"https://api.github.com/users/TBlindaruk/subscriptions",
         "organizations_url":"https://api.github.com/users/TBlindaruk/orgs",
         "repos_url":"https://api.github.com/users/TBlindaruk/repos",
         "events_url":"https://api.github.com/users/TBlindaruk/events{/privacy}",
         "received_events_url":"https://api.github.com/users/TBlindaruk/received_events",
         "type":"User",
         "site_admin":false
      },
      "node_id":"RE_kwDOAHMwOs4D7l3q",
      "tag_name":"v8.83.11",
      "target_commitish":"9.x",
      "name":"",
      "draft":false,
      "prerelease":false,
      "created_at":"2022-05-03T14:47:00Z",
      "published_at":"2022-05-03T19:14:52Z",
      "assets":[
         
      ],
      "tarball_url":"https://api.github.com/repos/laravel/framework/tarball/v8.83.11",
      "zipball_url":"https://api.github.com/repos/laravel/framework/zipball/v8.83.11",
      "body":"### Fixed\r\n- Fix refresh during down in the stub ([#42217](https://github.com/laravel/framework/pull/42217))\r\n- Fix deprecation issue with translator ([#42216](https://github.com/laravel/framework/pull/42216))\r\n",
      "reactions":{
         "url":"https://api.github.com/repos/laravel/framework/releases/65953258/reactions",
         "total_count":9,
         "+1":0,
         "-1":0,
         "laugh":0,
         "hooray":9,
         "confused":0,
         "heart":0,
         "rocket":0,
         "eyes":0
      }
   }
]

More Details

In the versions section (https://shields.io/category/version), can we create a new badge named Github release (latest on a specified branch) on https://shields.io/category/version? It will accept three parameters:

  1. user
  2. repo
  3. branch

It will generate a badge with the latest release tagged to the specified branch. I have written a PHP script querying Github API's List Releases endpoint to grab release data for a repo & parse through that data to get the latest release tagged to a specified branch. Below is the php script:

<?php
/**
 * 
 * @param string $githubUserOrOrganizationName a specific github user or organization name
 * @param string $githubRepoName name of a repo associated with the specified github user or organization
 * @param string $branchName name of the branch we will be searching for the latest release
 * @return string|null return the latest release associated with the specified branch or null if api error occured
 */
function getLatestReleaseByBranch(
    string $githubUserOrOrganizationName, 
    string $githubRepoName, 
    string $branchName
): ?string{
    // Cache below caches entries for the duration of a single run of this script
    static $apiResultsCache;
    
    if(!$apiResultsCache){ $apiResultsCache = []; }
    
    $releaseToReturn = '';
    
    ////////////////////////////////////////////////////////////////////////////////
    // build api call url & do the api call & convert result to a php data structure
    ////////////////////////////////////////////////////////////////////////////////
    $opts = ['http' => ['method'=>'GET', 'header'=>['User-Agent: PHP']]];
    $context = \stream_context_create($opts);
    $releasesApiUrl = "https://api.github.com/repos/{$githubUserOrOrganizationName}/{$githubRepoName}/releases?per_page=100";
    $releasesJson = 
        !\array_key_exists($releasesApiUrl, $apiResultsCache)
            ? @\file_get_contents($releasesApiUrl, false, $context) // get data from github
            : $apiResultsCache[$releasesApiUrl]; // use cached data
    
    if(!\array_key_exists($releasesApiUrl, $apiResultsCache)){
        
        $apiResultsCache[$releasesApiUrl] = $releasesJson; // cache this result
    }
    
    if($releasesJson !== false){
        
        $arrayOfReleaseObjectsOfTypeStdClass = \json_decode($releasesJson);
        $apiRequestPage=1;

        do{
            foreach ($arrayOfReleaseObjectsOfTypeStdClass as $releaseObj){
                if(\trim($branchName) === $releaseObj->target_commitish){
                    $releaseToReturn = $releaseObj->tag_name;
                    break;
                } // if(\trim($branchName) === $releaseObj->target_commitish)
            } // foreach ($arrayOfReleaseObjectsOfTypeStdClass as $releaseObj)

            if($releaseToReturn===''){
                //We haven't found a release for the specified branch yet,
                //do api call for next page of data.
                $apiRequestPage++;
                $apiUrlForNextPageofData = $releasesApiUrl."&page=".$apiRequestPage;
                $releasesJson = 
                    !\array_key_exists($apiUrlForNextPageofData, $apiResultsCache)
                        ? @\file_get_contents($apiUrlForNextPageofData, false, $context)
                        : $apiResultsCache[$apiUrlForNextPageofData];
                
                if($releasesJson !== false){
                    
                    if(!\array_key_exists($apiUrlForNextPageofData, $apiResultsCache)){
                        //cache this result
                        $apiResultsCache[$apiUrlForNextPageofData] = $releasesJson;
                    } // if(!\array_key_exists($apiUrlForNextPageofData, $apiResultsCache))
                    
                    $arrayOfReleaseObjectsOfTypeStdClass = \json_decode($releasesJson);
                    
                } else {
                    // error occured during api call to the github server
                    $releaseToReturn = null;
                    break;
                } // if($releasesJson !== false)
            } // if($releaseToReturn==='')
        } while($releaseToReturn==='' && \count($arrayOfReleaseObjectsOfTypeStdClass) > 0);
    } else {
        // error occured during api call to the github server
        $releaseToReturn = null;
    } // if($releasesJson !== false)
    return $releaseToReturn;
}

// As at Thursday May 5th 2022 when this issue was created:
// getLatestReleaseByBranch('laravel', 'framework', 'master') returns an empty string ""
// getLatestReleaseByBranch('laravel', 'framework', '9.x') returns v9.11.0
// getLatestReleaseByBranch('laravel', 'framework', '8.x') returns v8.82.0
// getLatestReleaseByBranch('laravel', 'framework', '7.x') returns v7.27.0
// getLatestReleaseByBranch('laravel', 'framework', '6.x') returns v6.17.1
// getLatestReleaseByBranch('laravel', 'framework', '5.8') returns v5.8.34
// getLatestReleaseByBranch('laravel', 'framework', '5.7') returns v5.7.27

:link: Data

:microphone: Motivation

Please explain why this feature should be implemented and how it would be used.

  • What is the specific use case?
    • I maintain various branches in my github repos that I use to tag releases for various versions of my projects. For example, I could have the following branches in a repo: 1.X, 2.X & master. I commit all code related to version 1.X of my project to the 1.X branch & all code related to version 2.X of my project to the 2.X branch & all code related to the latest version of my project (in this case 3.X) to the master branch. In the README.md files in each branch, I want to put a badge that fethces the latest version released for the branch.

Contributor guide