以下の内容はhttps://7rikazhexde-techlog.hatenablog.com/entry/2025/04/01/000300より取得しました。


Pythonの安定版バージョンをGitHub APIを使用して取得する方法

概要

Pythonでパッケージ公開するプロジェクトでは、安定版バージョンのサポートも重要です。

GitHubリポジトリを管理している場合、多くはGitHub Actionsを使用してCI/CDで更新管理していると思います。

例えば、Pythonではsetup-pythonアクションを使用して、複数のOS,Version情報をmatrix構文を指定して、テストを実行することでサポートバージョンで開発、保守することが挙げられます。

github.com

docs.github.com

しかし、matrix構文ではバージョン情報を静的に記述しなければならず、新しい安定板バージョンが公開されても、ユーザー自身でバージョンを更新管理する必要があるため手間が発生します。

一方でGitHubでは、GitHub API(以降API)が公開されており、APIを活用すれば、Pythonの安定版バージョンを取得することができます。

この記事では、GitHub APIcurlコマンドを使用してPythonの安定版バージョンを取得する方法を紹介し、バージョン情報(安定板/最新版)を静的/動的更新に、且つ、複数言語に対応した高機能な自作のGitHub Actionであるjson2vars-setterについて紹介します。

GitHub APIの基本

GitHub APIは、GitHubで管理するデータやリソース情報を取得できます。バージョン情報はリポジトリのタグ情報から取得します。そして取得するためにRest APIを使用します。

エンドポイント

GET /repos/{owner}/{repo}/tags

このエンドポイントは、指定したリポジトリのすべてのタグを一覧表示します。

基本的なcurlコマンド

curl -s https://api.github.com/repos/{owner}/{repo}/tags

認証付きの場合:

export GITHUB_TOKEN=pat_hoge
curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/{owner}/{repo}/tags

APIレート制限について

GitHub APIにはレート制限があります。認証方法によって制限回数が異なります。比較のため他のAPIタイプも記載します。

API タイプ エンドポイント APIレート(認証なし) APIレート(認証あり)
REST API https://api.github.com 60リクエスト/時間 5,000リクエスト/時間
Search API https://api.github.com/search 10リクエスト/分 30リクエスト/分
GraphQL API https://api.github.com/graphql 利用不可 5,000リクエスト/時間

APIレートを確認する方法

# 環境変数を使った認証
export GITHUB_TOKEN=pat_hoge
curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/rate_limit | jq '.rate'

# 認証なしの場合
curl -s https://api.github.com/rate_limit | jq '.rate'

レート制限を超えると、APIは403エラーを返します。安定版の取得処理では複数のリクエストが必要になる場合があるため、認証付きでのリクエストが必要になります。

タグから安定版バージョンを取得する

Pythonはタグを使ってリリースを管理しています。安定版バージョンを取得するには、以下のステップに従います。

  1. リポジトリのタグ一覧を取得する
  2. 安定版と見なせるタグをフィルタリングする
  3. 必要に応じてバージョン情報を解析・ソートする

安定版の判断基準

Pythonの安定版バージョンは一般的に以下のパターンに従います:

  • セマンティックバージョニング(例: v3.10.0
  • プレリリース識別子がない(alpha, beta, rc などを含まない)
  • 通常 v から始まり、その後にメジャー.マイナー.パッチ番号が続く

Pythonの安定版取得用curlコマンド

Pythonの安定版バージョンを効率的に取得するためのcurlコマンドを紹介します。このコマンドはシェルスクリプトなどに組み込んで利用できます。

環境変数の設定

まず、GitHub APIトークンを環境変数に設定します。 APIトークンはGitHubの設定から取得してください。

export GITHUB_TOKEN=pat_xxx

トークンは個人アクセストークン(PAT)を使用します。これにより、レート制限が大幅に緩和されます。

基本的なPython安定版取得コマンド

Pythonの最新5つの安定版バージョンを取得:

curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/python/cpython/tags?per_page=100" | \
  jq '[.[] | select(.name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))] | sort_by(.name | sub("^v"; "") | split(".") | map(tonumber)) | reverse | .[0:5]'

このコマンドでは以下の処理を行なっています:

  1. per_page=100 パラメータでページあたり100件のタグを取得
  2. 正規表現 ^v[0-9]+\.[0-9]+\.[0-9]+$ でセマンティックバージョニング形式のタグのみ選択(例: v3.10.0
  3. バージョン番号によるソートとリバース処理で最新版順に配列
  4. 最新5つのバージョンのみ取得

出力フォーマットのカスタマイズ

必要な情報のみを抽出する方法

curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/python/cpython/tags?per_page=100" | \
  jq '[.[] | select(.name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))] | sort_by(.name | sub("^v"; "") | split(".") | map(tonumber)) | reverse | .[0:5] | map({version: .name, url: .zipball_url, commit: .commit.sha})'

このコマンドでは、各バージョンの名前、ZIPダウンロードURL、コミットハッシュを抽出しています。

エラーハンドリングの実装

実際の運用では、エラーハンドリングを適切に実装することが重要です。以下にエラーハンドリングを組み込んだコマンドを示します。

curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/python/cpython/tags?per_page=100" | \
  jq 'if type=="object" and has("message") then 
        {error: .message, documentation_url: .documentation_url} 
      else 
        [.[] | select(.name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))] | 
        sort_by(.name | sub("^v"; "") | split(".") | map(tonumber)) | 
        reverse | .[0:5] 
      end'

このコマンドでは、GitHub APIがエラーを返した場合(レート制限超過など)にエラー情報を適切に表示できます。

実行結果の例

適切に実行された場合、以下のような出力が得られます。

[
  {
    "name": "v3.13.2",
    "zipball_url": "https://api.github.com/repos/python/cpython/zipball/refs/tags/v3.13.2",
    "tarball_url": "https://api.github.com/repos/python/cpython/tarball/refs/tags/v3.13.2",
    "commit": {
      "sha": "4f8bb3947cfbc20f970ff9d9531e1132a9e95396",
      "url": "https://api.github.com/repos/python/cpython/commits/4f8bb3947cfbc20f970ff9d9531e1132a9e95396"
    },
    "node_id": "MDM6UmVmODE1OTg5NjE6cmVmcy90YWdzL3YzLjEzLjI="
  },
  {
    "name": "v3.13.1",
    "zipball_url": "https://api.github.com/repos/python/cpython/zipball/refs/tags/v3.13.1",
    "tarball_url": "https://api.github.com/repos/python/cpython/tarball/refs/tags/v3.13.1",
    "commit": {
      "sha": "067145177975eadd61a0c907d0d177f7b6a5a3de",
      "url": "https://api.github.com/repos/python/cpython/commits/067145177975eadd61a0c907d0d177f7b6a5a3de"
    },
    "node_id": "MDM6UmVmODE1OTg5NjE6cmVmcy90YWdzL3YzLjEzLjE="
  },
  ...
]

補足: APIレート制限の確認

APIレート使用状況は以下で確認できます。

# レート制限の確認
curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/rate_limit | jq '.resources.core'

参考: workflowによるAPIレートの確認結果

ファイル(check_github_api_rate_limits.yml)
name: Check GitHub API Rate Limits
on:
  workflow_dispatch:
permissions:
  contents: read
jobs:
  check_rate_limits:
    runs-on: ubuntu-latest
    steps:
      - name: Check GitHub API Rate Limits
        run: |
          echo "=== GitHub API Rate Limits with Token ==="
          curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/rate_limit | jq '.rate'

          echo -e "\n=== Search API Rate Limits with Token ==="
          curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/rate_limit | jq '.resources.search'

          echo -e "\n=== GraphQL API Rate Limits with Token ==="
          curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/rate_limit | jq '.resources.graphql'

          echo -e "\n=== GitHub API Rate Limits without Token ==="
          curl -s https://api.github.com/rate_limit | jq '.rate'

          echo -e "\n=== Search API Rate Limits without Token ==="
          curl -s https://api.github.com/rate_limit | jq '.resources.search'

          echo -e "\n=== GraphQL API Rate Limits without Token ==="
          curl -s https://api.github.com/rate_limit | jq '.resources.graphql'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
実行結果
Run echo "=== GitHub API Rate Limits with Token ==="
=== GitHub API Rate Limits with Token ===
{
  "limit": 5000,
  "used": 0,
  "remaining": 5000,
  "reset": 1742012041
}

=== Search API Rate Limits with Token ===
{
  "limit": 30,
  "used": 0,
  "remaining": 30,
  "reset": 1742008501
}

=== GraphQL API Rate Limits with Token ===
{
  "limit": 5000,
  "used": 0,
  "remaining": 5000,
  "reset": 1742012041
}

=== GitHub API Rate Limits without Token ===
{
  "limit": 60,
  "remaining": 54,
  "reset": 1742008504,
  "used": 6,
  "resource": "core"
}

=== Search API Rate Limits without Token ===
{
  "limit": 10,
  "remaining": 10,
  "reset": 1742008501,
  "used": 0,
  "resource": "search"
}

=== GraphQL API Rate Limits without Token ===
{
  "limit": 0,
  "remaining": 0,
  "reset": 1742012041,
  "used": 0,
  "resource": "graphql"
}

GitHub Actionsでの使用例

GitHub Actionsでは、ワークフローの中でPythonの安定版バージョンを取得して活用することができます。以下に具体的な例を示します。

Pythonの最新安定版を取得するワークフロー

name: Get Python Stable Versions
on:
  workflow_dispatch:
  schedule:
    - cron: '0 0 * * 1'  # 毎週月曜日に実行

permissions:
  contents: read

jobs:
  get-python-versions:
    runs-on: ubuntu-latest
    steps:
      - name: Check API Rate Limits
        run: |
          curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/rate_limit | jq '.resources.core'
      
      - name: Get Latest Python Stable Versions
        id: get_versions
        run: |
          # 最新の5つの安定版バージョンを取得
          VERSIONS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            "https://api.github.com/repos/python/cpython/tags?per_page=100" | \
            jq -c 'if type=="object" and has("message") then 
                {error: .message, documentation_url: .documentation_url} 
              else 
                [.[] | select(.name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))] | 
                sort_by(.name | sub("^v"; "") | split(".") | map(tonumber)) | 
                reverse | .[0:5] | map(.name) 
              end')
          
          # 結果を出力
          echo "Python stable versions: $VERSIONS"
          
          # 安定板バージョンの内の最新バージョンを環境変数に設定
          LATEST=$(echo $VERSIONS | jq -r '.[0]')
          echo "LATEST_PYTHON_VERSION=${LATEST#v}" >> $GITHUB_ENV
          echo "latest_version=${LATEST#v}" >> $GITHUB_OUTPUT
      
      - name: Use Latest Python Version
        run: |
          echo "Latest stable Python version: ${{ env.LATEST_PYTHON_VERSION }}"
          echo "This information can be used for further steps in the workflow"
      
      - name: Check API Rate Remaining
        run: |
          curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/rate_limit | jq '.resources.core'

このワークフローについて

  1. GitHub Actionsの GITHUB_TOKEN を使用して認証
  2. 最新の5つの安定版Pythonバージョンを取得
  3. 取得した安定バージョンの内の最新バージョンを環境変数とワークフロー出力に設定
  4. APIレート制限の使用状況を確認

実用的な応用例:最新バージョンでのテスト実行

name: Test with Latest Python
on:
  workflow_dispatch:
  push:
    branches: [ main ]

jobs:
  get-version:
    runs-on: ubuntu-latest
    outputs:
      python_version: ${{ steps.get_version.outputs.latest_version }}
    steps:
      - name: Get Latest Python Version
        id: get_version
        run: |
          LATEST=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            "https://api.github.com/repos/python/cpython/tags?per_page=100" | \
            jq -r '[.[] | select(.name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))] | 
                sort_by(.name | sub("^v"; "") | split(".") | map(tonumber)) | 
                reverse | .[0].name' | sed 's/^v//')
          echo "latest_version=$LATEST" >> $GITHUB_OUTPUT
          echo "Latest Python version: $LATEST"
  
  test:
    needs: get-version
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ needs.get-version.outputs.python_version }}
      
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
      
      - name: Test with pytest
        run: |
          pytest

この例では、最初のジョブで最新のPythonバージョンを取得し、それを使用して次のジョブでテストを実行しています。

より高度な選択肢

ここまで説明したcurlコマンドやGitHub Actionsの実装はPython専用であればこれでも十分です。しかし、実際のプロジェクトでは、python以外の言語を使用していることもあると思います。

また、これは私の場合ですが、workflowの内容に応じて、件数の指定や、バージョンを静的/動的に管理したいことや、毎回APIを呼びたくないなど、バージョン管理機能として満足できないことがありました。

そこで私はこれらの機能を考慮したGitHub Actionsの専用カスタムアクションとして、「json2vars-setter」を作ることにしました。

このアクションは上記不満点を解決し、CLIにも対応しています。より使い勝手の良いバージョン管理機能となっていますので、是非以下の内容を確認して、気になれば使ってみてください。

json2vars-setter - 複数言語対応のjsonファイルによるバージョン管理ツール

github.com

json2vars-setterドキュメント

7rikazhexde.github.io

主な特長
  • 複数言語サポート: Python, Node.js, Ruby, Go, Rust など複数の言語に対応
  • 柔軟なバージョン取得:
    • 静的定義: 明示的にバージョンを指定
    • 動的定義: stable, latest タグから自動取得
    • 件数指定: 最新N件の取得が可能
  • キャッシュ管理: API制限を回避するインテリジェントなキャッシュ機能
  • JSON統合: すべてのバージョン情報をJSONで管理
  • 簡単設定: 複雑なJQフィルタなしで簡単に設定可能
使用例
name: Example workflow with json2vars-setter
on:
  workflow_dispatch:

jobs:
  setup:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Variables with json2vars-setter
        uses: 7rikazhexde/json2vars-setter@v1
        with:
          json-file-path: 'versions.json'
          cache-path: 'cached-versions.json'
          token: ${{ secrets.GITHUB_TOKEN }}
          
      - name: Use Python Version
        run: |
          echo "Python version: ${{ env.PYTHON_VERSION }}"
          # その他の処理...
json2vars-setterの利点
  • 実装の手間削減: 本記事で説明したような複雑なJQフィルタ処理を自分で実装する必要がない
  • レート制限対策: キャッシュ機能によりGitHub APIのレート制限問題を解決
  • 複数言語対応: 1つのツールで複数言語のバージョン管理が可能
  • CI/CD安定化: バージョン管理を安定させ、CI/CDパイプラインの信頼性を向上

このカスタムアクションはGitHub Actionsのワークフローをシンプルかつ堅牢にし、バージョン管理の煩わしさから解放されます。ぜひ試してみてください。また、良いと感じたら、是非GitHubでスターもいただけると嬉しいです。

まとめ

GitHub APIを使用すると、Pythonの安定版バージョン情報を効率的に取得できます。この記事で紹介した方法を活用すれば、CI/CDパイプラインの構築、互換性チェック、開発環境の整備など、様々な用途に役立てることができます。

実装ポイントをまとめ。

  1. 環境変数 export GITHUB_TOKEN=pat_hoge を使って認証情報を管理する
  2. curlとjqを組み合わせてGitHub APIからタグ情報を取得・フィルタリングする
  3. Python命名規則に合わせた正規表現^v[0-9]+\.[0-9]+\.[0-9]+$)で安定版を特定する
  4. APIレート制限を考慮し、ページネーションパラメータ(per_page=100)を活用する
  5. エラーハンドリングを実装し、APIエラーに適切に対応する
  6. GitHub Actionsのワークフローに組み込み、自動化プロセスに活用する

これらの点に注意すれば、シンプルなcurlコマンドだけで、信頼性の高いPython安定版バージョン取得システムを構築できます。

なお、他の言語やフレームワークでも同様のアプローチは適用可能ですが、タグの命名規則が異なるため、正規表現やフィルタリングのロジックを調整する必要があります。




以上の内容はhttps://7rikazhexde-techlog.hatenablog.com/entry/2025/04/01/000300より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14