badges/shields
View on GitHubNew Feature Request: Github release (latest on a specified branch)
Open
#7929 opened on May 6, 2022
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:
- <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:
- user
- repo
- 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
- Where can we get the data from?
- From the github api https://docs.github.com/en/rest/releases/releases#list-releases
- Is there a public API?
- Yes, but you would have to parse the data returned from the Github API's List Releases endpoint to get the desired data. I have provided a code sample above written in PHP.
- Does the API requires an API key?
- No
- Link to the API documentation:
: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.