Search code examples
bashapirestshellgithub-api

How to fetch the content from same tag from GitHub Api using bash


I want to get the data of tag_name from this link

https://api.github.com/repos/checkstyle/checkstyle/releases

but as we have a lot of releases. How can I get a particular tag_name

I do

LATEST_RELEASE_TAG=$(curl -s https://api.github.com/repos/checkstyle/checkstyle/releases/latest \
                       | jq ".tag_name")

to get the latest tag_name but how to fetch the second tag_name?

eg:

[   {
    "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/73283356",
    "assets_url": "https://api.github.com/repos/checkstyle/checkstyle/releases/73283356/assets",
    "upload_url": "https://uploads.github.com/repos/checkstyle/checkstyle/releases/73283356/assets{?name,label}",
    "html_url": "https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.3.2",
    "id": 73283356,
    "author": {
      "login": "romani",
      "id": 812984,
      "node_id": "MDQ6VXNlcjgxMjk4NA==",
      "avatar_url": "https://avatars.githubusercontent.com/u/812984?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/romani",
      "html_url": "https://github.com/romani",
      "followers_url": "https://api.github.com/users/romani/followers",
      "following_url": "https://api.github.com/users/romani/following{/other_user}",
      "gists_url": "https://api.github.com/users/romani/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/romani/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/romani/subscriptions",
      "organizations_url": "https://api.github.com/users/romani/orgs",
      "repos_url": "https://api.github.com/users/romani/repos",
      "events_url": "https://api.github.com/users/romani/events{/privacy}",
      "received_events_url": "https://api.github.com/users/romani/received_events",
      "type": "User",
      "site_admin": false
    },
    "node_id": "RE_kwDOAL65M84EXjcc",
    "tag_name": "checkstyle-10.3.2",
    "target_commitish": "master",
    "name": "",
    "draft": false,
    "prerelease": false,
    "created_at": "2022-07-31T13:38:47Z",
    "published_at": "2022-07-31T13:54:14Z",
    "assets": [
      {
        "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/assets/73245332",
        "id": 73245332,
        "node_id": "RA_kwDOAL65M84EXaKU",
        "name": "checkstyle-10.3.2-all.jar",
        "label": "",
        "uploader": {
          "login": "romani",
          "id": 812984,
          "node_id": "MDQ6VXNlcjgxMjk4NA==",
          "avatar_url": "https://avatars.githubusercontent.com/u/812984?v=4",
          "gravatar_id": "",
          "url": "https://api.github.com/users/romani",
          "html_url": "https://github.com/romani",
          "followers_url": "https://api.github.com/users/romani/followers",
          "following_url": "https://api.github.com/users/romani/following{/other_user}",
          "gists_url": "https://api.github.com/users/romani/gists{/gist_id}",
          "starred_url": "https://api.github.com/users/romani/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/romani/subscriptions",
          "organizations_url": "https://api.github.com/users/romani/orgs",
          "repos_url": "https://api.github.com/users/romani/repos",
          "events_url": "https://api.github.com/users/romani/events{/privacy}",
          "received_events_url": "https://api.github.com/users/romani/received_events",
          "type": "User",
          "site_admin": false
        },
        "content_type": "application/zip",
        "state": "uploaded",
        "size": 16208747,
        "download_count": 505,
        "created_at": "2022-07-31T13:54:16Z",
        "updated_at": "2022-07-31T13:55:12Z",
        "browser_download_url": "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-10.3.2/checkstyle-10.3.2-all.jar"
      }
    ],
    "tarball_url": "https://api.github.com/repos/checkstyle/checkstyle/tarball/checkstyle-10.3.2",
    "zipball_url": "https://api.github.com/repos/checkstyle/checkstyle/zipball/checkstyle-10.3.2",
    "body": "https://checkstyle.org/releasenotes.html#Release_10.3.2\r\n\r\nBug fixes:\r\n\r\n  #11736 - MissingJavadocType: Support qualified annotation names\r\n  #11655 - Update google_checks.xml to have the SuppressionCommentFilter and SuppressWarningsHolder modules in the config by default (and by extension, SuppressWarningsFilter)\r\n\r\n<details>\r\n<summary>Other Changes:</summary>\r\n<br>\r\n  Update releasenotes to use GitHub Pages execution\r\n<br />\r\n  Allow SuppressWarningHolder to suppress the violation with NameCheck\r\n<br />\r\n  Pitest: Kill all surviving mutations\r\n<br />\r\n  Pitest: Activate \"ALL\" mutator group\r\n<br />\r\n  Use Shellcheck to resolve violations code in Shell Script\r\n<br />\r\n  pitest: increase mutation coverage for pitest-imports profile to 100% \r\n<br />\r\n  Update GitHub Action for bump-license-year.sh\r\n<br />\r\n  Solve fb-contrib errors\r\n<br />\r\n  Remove pitest mutation checking HTML model\r\n<br />\r\n  automate execution by Github action bump-license-year.sh on first day of month\r\n<br />\r\n  update code base to have javadoc tag to explain noinspection tag content\r\n<br />\r\n  doc: put example of enableExternalDtdLoad to xdoc\r\n<br />\r\n  update doc for SuppressWarningsHolder\r\n<br />\r\n  releasenotes script generated empty commit\r\n<br />\r\n  Include CDG Accelerator Plugin to boost pitest performance\r\n<br />\r\n  Enforce file size on Java inputs\r\n<br />\r\n  Expand XPath IT Regression Testing\r\n<br />\r\n There are semantic problems in the Chinese error message of keyword `design.forExtension` .\r\n<br />\r\n  prepare-settings.sh fails to create settings.xml\r\n<br />\r\n  Use groovy version provided by `apt` in pitest.yml\r\n<br />\r\n  tweet-releasenotes.sh does not check env variables\r\n<br />\r\n  download of m2 cache from sourceforge.io is slow \r\n<br />\r\n  infra: turns off create dependency reduced pom for shade plugin\r\n<br />\r\n  Update Tests to use new 'verifyXxxxxx' method or 'execute' that use inlined config in Input files\r\n<br />\r\n  Specify violation messages in input files.\r\n<br />\r\n  pitest: increase mutation coverage for javadoc profile to 100%\r\n<br />\r\n</details>",
    "reactions": {
      "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/73283356/reactions",
      "total_count": 10,
      "+1": 0,
      "-1": 0,
      "laugh": 0,
      "hooray": 6,
      "confused": 0,
      "heart": 2,
      "rocket": 2,
      "eyes": 0
    }   },   {
    "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/70647006",
    "assets_url": "https://api.github.com/repos/checkstyle/checkstyle/releases/70647006/assets",
    "upload_url": "https://uploads.github.com/repos/checkstyle/checkstyle/releases/70647006/assets{?name,label}",
    "html_url": "https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.3.1",
    "id": 70647006,
    "author": {
      "login": "romani",
      "id": 812984,
      "node_id": "MDQ6VXNlcjgxMjk4NA==",
      "avatar_url": "https://avatars.githubusercontent.com/u/812984?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/romani",
      "html_url": "https://github.com/romani",
      "followers_url": "https://api.github.com/users/romani/followers",
      "following_url": "https://api.github.com/users/romani/following{/other_user}",
      "gists_url": "https://api.github.com/users/romani/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/romani/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/romani/subscriptions",
      "organizations_url": "https://api.github.com/users/romani/orgs",
      "repos_url": "https://api.github.com/users/romani/repos",
      "events_url": "https://api.github.com/users/romani/events{/privacy}",
      "received_events_url": "https://api.github.com/users/romani/received_events",
      "type": "User",
      "site_admin": false
    },
    "node_id": "RE_kwDOAL65M84ENfze",
    "tag_name": "checkstyle-10.3.1",
    "target_commitish": "master",
    "name": "",
    "draft": false,
    "prerelease": false,
    "created_at": "2022-06-27T13:50:30Z",
    "published_at": "2022-06-27T14:07:12Z",
    "assets": [
      {
        "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/assets/69790751",
        "id": 69790751,
        "node_id": "RA_kwDOAL65M84EKOwf",
        "name": "checkstyle-10.3.1-all.jar",
        "label": "",
        "uploader": {
          "login": "romani",
          "id": 812984,
          "node_id": "MDQ6VXNlcjgxMjk4NA==",
          "avatar_url": "https://avatars.githubusercontent.com/u/812984?v=4",
          "gravatar_id": "",
          "url": "https://api.github.com/users/romani",
          "html_url": "https://github.com/romani",
          "followers_url": "https://api.github.com/users/romani/followers",
          "following_url": "https://api.github.com/users/romani/following{/other_user}",
          "gists_url": "https://api.github.com/users/romani/gists{/gist_id}",
          "starred_url": "https://api.github.com/users/romani/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/romani/subscriptions",
          "organizations_url": "https://api.github.com/users/romani/orgs",
          "repos_url": "https://api.github.com/users/romani/repos",
          "events_url": "https://api.github.com/users/romani/events{/privacy}",
          "received_events_url": "https://api.github.com/users/romani/received_events",
          "type": "User",
          "site_admin": false
        },
        "content_type": "application/zip",
        "state": "uploaded",
        "size": 15396315,
        "download_count": 3577,
        "created_at": "2022-06-27T14:07:13Z",
        "updated_at": "2022-06-27T14:08:06Z",
        "browser_download_url": "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-10.3.1/checkstyle-10.3.1-all.jar"
      }
    ],
    "tarball_url": "https://api.github.com/repos/checkstyle/checkstyle/tarball/checkstyle-10.3.1",
    "zipball_url": "https://api.github.com/repos/checkstyle/checkstyle/zipball/checkstyle-10.3.1",
    "body": "https://checkstyle.org/releasenotes.html#Release_10.3.1",
    "reactions": {
      "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/70647006/reactions",
      "total_count": 8,
      "+1": 0,
      "-1": 0,
      "laugh": 0,
      "hooray": 7,
      "confused": 0,
      "heart": 1,
      "rocket": 0,
      "eyes": 0
    }   },

This has 2 tag_name and I want to fetch the data of the second tag_name. Now It's like I always want the 2nd number tag_name only.

-> I want to use this tag_name as the previous release so I want the latest tag_name as the latest tag and the 2nd tag "tag_name" as the previous tag. I want to use these in a shell script.


Solution

  • Fetching the Two Most Recent Release

    You can have the Github releases API respond with the two most recent releases, and then use jq to access all .tag_name fields in the array objects and then read them into separate bash variables, like so:

    #!/bin/bash
    
    # You only care about the latest release and previous, so you can
    # pass the per_page query parameter
    github_rsp="$(curl -s https://api.github.com/repos/checkstyle/checkstyle/releases?per_page=2)"
    
    # jq lets you access multiple objects in a list
    # using different syntaxes. Here, ".[].tag_name" will just
    # access every tag_name field in each object of the response array
    # and then we put those into an array that we then join with ";'
    
    # We then read jq's output into two separate shell variables
    # using ";' as our separator
    
    IFS=";" read latest previous < <(jq -r '[.[].tag_name] | join(";")' <<< $github_rsp)
    
    echo "  Latest version: $latest"
    echo "Previous version: $previous"
    

    With this as output

    ❯ ./parse.sh
      Latest version: checkstyle-10.3.2
    Previous version: checkstyle-10.3.1
    

    Also see the following for even more info about how my script works, if you need explanation beyond my notes:

    Fetching a Single Release

    Since you asked about getting any arbitrary release, if you have a tag name, you can use the Github Release-by-Tag API, where you put a specific tag into the releases API URL.

    #!/bin/bash
    
    function get_release() {
        local repo="$1"
        local tag="$2"
        local release_url="https://api.github.com/repos/${repo}/releases/tags/${tag}"
        rsp=$(curl -s -H 'Accept: application/vnd.github+json' "$release_url")
        echo "$rsp"
    }
    
    get_release "checkstyle/checkstyle" "checkstyle-10.1" | jq
    

    And running this script I get...

    ❯ ./single-release.sh
    {
      "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/62869604",
      "assets_url": "https://api.github.com/repos/checkstyle/checkstyle/releases/62869604/assets",
      "upload_url": "https://uploads.github.com/repos/checkstyle/checkstyle/releases/62869604/assets{?name,label}",
      "html_url": "https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.1",
      "id": 62869604,
      "author": {
        "login": "romani",
        "id": 812984,
        "node_id": "MDQ6VXNlcjgxMjk4NA==",
        "avatar_url": "https://avatars.githubusercontent.com/u/812984?v=4",
        "gravatar_id": "",
        "url": "https://api.github.com/users/romani",
        "html_url": "https://github.com/romani",
        "followers_url": "https://api.github.com/users/romani/followers",
        "following_url": "https://api.github.com/users/romani/following{/other_user}",
        "gists_url": "https://api.github.com/users/romani/gists{/gist_id}",
        "starred_url": "https://api.github.com/users/romani/starred{/owner}{/repo}",
        "subscriptions_url": "https://api.github.com/users/romani/subscriptions",
        "organizations_url": "https://api.github.com/users/romani/orgs",
        "repos_url": "https://api.github.com/users/romani/repos",
        "events_url": "https://api.github.com/users/romani/events{/privacy}",
        "received_events_url": "https://api.github.com/users/romani/received_events",
        "type": "User",
        "site_admin": false
      },
      "node_id": "RE_kwDOAL65M84Dv1Bk",
      "tag_name": "checkstyle-10.1",
      "target_commitish": "master",
      "name": "",
      "draft": false,
      "prerelease": false,
      "created_at": "2022-03-27T14:51:31Z",
      "published_at": "2022-03-27T15:06:48Z",
      "assets": [
        {
          "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/assets/60754101",
          "id": 60754101,
          "node_id": "RA_kwDOAL65M84Dnwi1",
          "name": "checkstyle-10.1-all.jar",
          "label": "",
          "uploader": {
            "login": "romani",
            "id": 812984,
            "node_id": "MDQ6VXNlcjgxMjk4NA==",
            "avatar_url": "https://avatars.githubusercontent.com/u/812984?v=4",
            "gravatar_id": "",
            "url": "https://api.github.com/users/romani",
            "html_url": "https://github.com/romani",
            "followers_url": "https://api.github.com/users/romani/followers",
            "following_url": "https://api.github.com/users/romani/following{/other_user}",
            "gists_url": "https://api.github.com/users/romani/gists{/gist_id}",
            "starred_url": "https://api.github.com/users/romani/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/romani/subscriptions",
            "organizations_url": "https://api.github.com/users/romani/orgs",
            "repos_url": "https://api.github.com/users/romani/repos",
            "events_url": "https://api.github.com/users/romani/events{/privacy}",
            "received_events_url": "https://api.github.com/users/romani/received_events",
            "type": "User",
            "site_admin": false
          },
          "content_type": "application/zip",
          "state": "uploaded",
          "size": 13403044,
          "download_count": 6227,
          "created_at": "2022-03-27T15:06:49Z",
          "updated_at": "2022-03-27T15:07:35Z",
          "browser_download_url": "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-10.1/checkstyle-10.1-all.jar"
        }
      ],
      "tarball_url": "https://api.github.com/repos/checkstyle/checkstyle/tarball/checkstyle-10.1",
      "zipball_url": "https://api.github.com/repos/checkstyle/checkstyle/zipball/checkstyle-10.1",
      "body": "https://checkstyle.org/releasenotes.html#Release_10.1",
      "reactions": {
        "url": "https://api.github.com/repos/checkstyle/checkstyle/releases/62869604/reactions",
        "total_count": 4,
        "+1": 1,
        "-1": 0,
        "laugh": 0,
        "hooray": 3,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
      }
    }