7rikazhexde’s tech log

技術的な興味関心、備忘録、アウトプットなどを書いています。

【Chrome拡張機能】選択したテキストをURLに連結して検索するContext Menu Searchについて

はじめに

ブラウジング中にテキストをコピーして検索する、という作業は意外と多いものです。

特に、開発においては、自社開発環境内で、オンプレサーバーやクラウド上のデータソースにアクセスするためにWeb検索することは多いです。

このような場面で選択した文字列をURLのクエリとして渡して検索できれば、僅かでも作業効率は上がります。

実際に調べると、このような用途に適したChrome拡張機能が複数公開されています。

本記事では、それらの拡張機能の内、個人的に良いなと感じた「Context Menu Search」 について紹介します。

Context Menu Searchについて

「Context Menu Search」は、右クリックメニュー(コンテキストメニュー)に任意の検索エンジンやURLテンプレートを追加できる拡張機能です。

chromewebstore.google.com

特徴は以下の通りです。

  • 選択したテキストをそのままURLに埋め込める
  • 複数の検索先を登録可能
  • 軽量でシンプル、UIも邪魔にならない

使用方法

例えば、以下のような用途を考えます。

https://hogehoge?id=bar

この場合「bar」の部分を選択したテキストに置き換えたいとします。

その場合の設定と使用手順は以下の通りです。

  1. Chrome右上の拡張機能アイコン
  2. Context Menu Search の「オプション」を開く
  3. 右クリック時にURLアクセスするための、タイトルとURLを入力します
  4. Addボタンで新規リストを追加
  5. タイトルを入力(例:Hogehoge Search
  6. URLを入力(例: https://hogehoge?id=%s
    %sが選択したテキストに置き換わります。
  7. Saveボタンで保存。
  8. Webページ上で検索したいテキストを選択(例:「issue25」)
  9. 右クリック → 「Hogehoge Search」を選択

これで、個別にコピー&ペースト、検索操作が不要で、即座に指定のURL(https://hogehoge?id=issue25)にアクセスできます。

Context Menu SearchのOption機能

まとめ

選択したテキストをURLに連結して検索する「Context Menu Search」について紹介しました。

この拡張機能はシンプルですがあると便利だと思います。

例えば、特定のサービスに文字列を渡して検索したい、社内システムのチケット番号などで直リンクしたい、といった用途に最適だと思います。

そのような用途があれば、追加して使用することをお勧めします。

以上です。

【Windows】PowerShellスクリプトを実行するショートカットを作成するスクリプトについて

経緯

ChatGPT等の生成AIにより、PowerShellスクリプトシェルスクリプトを作成する機会が増えました。一方でスクリプトの実行には、ターミナルアプリやPowerShellコマンドで実行する必要があります。

都度実行するのは手間ですが、WindowsではPowerShellスクリプトを実行するショートカットを作成できます。しかし、作成するためにはいくつか操作が必要です。

そこで、PowerShell実行用のスクリプトを簡単に作成するためのGUIツールを作成したので本記事で紹介します。

スクリプトと内部処理について

スクリプトの概要

スクリプト名は create-ps1-shortcut.ps1 で、GUIインターフェースを通じて以下の機能を提供します。

  • ファイル選択: Show-FileDialog関数を使用して.ps1ファイルを選択。
  • ショートカット作成: New-ScriptShortcut関数で、選択したスクリプトと同じディレクトリにショートカット(.lnk)を生成。
  • カスタムダイアログ: Show-CustomDialog関数で、作成完了後ガイドを表示し、保存先を開くオプションを提供。

また、スクリプトは下記GitHubにもコミットしています。

github.com

内部処理の詳細

  • PowerShell環境の検出: Get-PowerShellPath関数で、PowerShell Core(pwsh)が利用可能か確認し、なければ powershell.exeにフォールバック。
  • WScript.Shellの利用: COMオブジェクトを使用してショートカットを作成し、ターゲットパスや引数を設定。
  • WPFベースのGUI: XAMLを使用してカスタムダイアログを生成し、ボタンイベントで保存先を開く機能を実装。
  • デバッグ対応: -Debugパラメータで詳細ログを表示可能。

使用方法

create-ps1-shortcut.ps1 > 右クリック > PoweShellで実行 > ショートカットを作成したいPowerShellスクリプトを選択

なお、本スクリプト自体もショートカット化できるため、作成したショートカットを例えばタスクバーにピン留めすることで簡単に実行することもできます。

PowerShellスクリプトショートカット作成結果

まとめ

WindowsPowerShellスクリプトを実行するショートカットを作成するPowerShellスクリプトについて紹介しました。

生成AIを活用することで、アプリやスクリプトが作成しやすくなりましたが、それを効率的に実行していく方法も必要だと思います。本スクリプトがそのようなケースの一助となれば幸いです。

以上です。

iOSショートカットアプリでDiscordにWebhook経由でメッセージを送る方法

はじめに

個別に電車の運行情報を通知するShortcutを作成しました。取得した情報はShortcutsアプリの通知アクション(バナー通知)などで通知可能ですが、ネットの情報やGitHub Actionsの通知などはDiscordで個別に作成したチャンネルにまとめているため、電車の運行情報もDiscordで通知管理することを考えました。

そして、Discord通知は電車の運行情報以外にも使用できると考えたため、通知部分のみ個別のShortcutとして切り出すことにしました。本記事はその方法とShortcutについての紹介記事になります。

免責事項

本記事に記載された内容やShortcutによって生じたいかなる損害についても責任を負いません。使用する際は自己責任でお願いします。

Discordの設定(Webhook)

Discordで通知先のチャンネルでWebhookを作成し、そのURLを使用します。

Webhookについては以下の記事を確認ください。

kintone-blog.cybozu.co.jp

Webookの設定は以下のDiscordの公式ドキュメントを確認ください。

support.discord.com

Shortcutsアプリの設定

以下内容でheaderとbodyを指定してWebhook URLにPOST送信します。 Shortcutsのアプリでは、URLの内容を取得アクションではキーテキスト指定で設定します。

  • header: Key(Content-Type),Value(application/json)
  • body: Key(Content),Value(送信したいテキスト)

指定内容としては以下記事が参考になりますので合わせて確認ください。(Discord公式のDocsのURLも記載されています。)

qiita.com

作成したShortcutの実行結果例

Discord通知ショートカット(Notify Discord (Webhook))

取得したWebhook URLはテキストに入力します。

Notify Discord (Webhook)

電車運行情報通知ショートカット

Discordに通知したいメッセージ(テキスト)を電車運行情報通知ショートカットの入力としてアクションを設定します。

電車運行情報通知ショートカット

Discordへの通知結果

入力されたテキストがDiscordのチャネルに投稿されていることを確認できました。

Discord / train-info-bot

まとめ

iOSショートカットアプリでDiscordにWebhook経由でメッセージを送る方法を紹介しました。

紹介した内容ではテキストのみで内容をリッチにしなくても良いので最低限の情報のみで紹介しました。

汎用性を考えれば、headerとbodyの内容を選択式にすると良いかもしれません。

以上です。

Shortcutsアプリを使用したObsidianのノート作成方法について

免責事項

本記事に記載された内容やShortcutによって生じたいかなる損害についても責任を負いません。使用する際は自己責任でお願いします。

前置き

Obsidianを利用されている方は、ノートをどのように作成し、管理していますか?
多くの場合は保存先のフォルダを作成し、新規ノートから作成しているのではないでしょうか?

一方で、フォルダ管理しない方が良いという主張もあります。
個人でノートを管理している方はわかるかもしれませんが、フォルダ作成のルールを決めないと、管理が煩雑になったり、重複したりして、正しくノートを管理できなくなる場合があります。

私はどうしているかというと、性格的にフォルダ管理しないと気持ちがわるく、フォルダを作成して、ノートを作成/管理しています。

また、Obsidianでは、タグ管理ができるので、タグ指定で検索してファイルを探すことができます。また、ノートのリンク機能によりノート同士を関連付けることができるため、それらの機能と併用することでノート管理の一貫性を担保できます。詳細は公式ドキュメントを参照ください。

publish.obsidian.md

タグ作成も、以下の記事で紹介しているテンプレート機能を使用すれば簡単に作成できるのでお勧めです。

7rikazhexde-techlog.hatenablog.com

さて、ここまで前置きが長くなりましたが、ここからが本題です。

上記のように機能は良いのですが、しばらく使用していたところ、
フォルダが増えると階層が深くなるのでノート作成がしづらいという不満に当たりました。

これはフォルダ管理の性質であり、ドキュメント管理の仕様なので仕方がないことですが、Obsisidanではノート作成すると一番上の階層で固定となっているので、フォルダ管理する場合は、ノートを指定のフォルダに移動しなければならずストレスを感じることがありました。

つまり、一部のUXが悪いのです。もしかすると設定やプラグインで変更できるかもしれませんが、選択や移動させることは機能として問題はないので、仕方ないことだとは思ってます。

そこで、ノート作成方法(操作)を良くすることできないかと考えたところ、Shortcutsアプリを使用することで実現できました。

本記事では実現方法と実際に作成したShortcutを公開しましたので紹介します。

Obsidianのノート作成方法をShortcutsアプリを使用して改良する方法について

結論から言うと、Shortcutsアプリを使用して空のMarkdownファイルを作成し、それを指定のフォルダに保存する方法で実現しました。

Obsidian VaultをiCoudやiPhone/iPad内に設定している場合は、フォルダアプリでアクセス可能1なため、保存されたMarkdownファイルはObsidianアプリ上でも確認できます。

方法自体はシンプルですが、Obsidianでノート作成しないのでファイル移動などしなくて済む点がメリットです。

処理内容(キャプチャ)

キャプチャの通りですが、ポイントは空のテキスト指定でファイル作成し、拡張子を.txtから.mdに変更している部分です。

ファイル作成ではデフォルトでは.txtとなるのでそこだけ変換して保存するアクションで対応しています。

また、保存処理では、保存アクションを使用してテキスト指定で、保存先を訪ねるを有効にします。

これでフォルダアプリから保存先を指定することで、作成時に保存先を指定し、保存後のファイル移動を省略しています。

Create_Markdown_Shortcut

Shortcut(iCloudリンク)

作成したshortcutは下記iCloudリンクから取得可能です。気になれば使用してみてください。

※リンクから追加画面に遷移しない場合はメモにURLを貼り付けてからアクセスしてください。

www.icloud.com

まとめ

Shortcutsアプリを使用したObsidianのノート作成方法について紹介しました。

公開したショートカットをホーム画面などに追加すれば、即起動できるので使い勝手は良いと思います。

1点不満な点として、shortcutの機能で作成したノートをObsidianから起動できれば良かったんだですが、そこまでは実現できませんでした。

それでもObsidianアプリからノート移動よりは楽なので許容範囲です。

Obsidianアプリは気に入っているので、今後も改良できる機能やプラグインなど考えたい思います。

以上です。


  1. ⚠️Macでは未確認です。

a-Shellとobsidian-gitを使用してプライベートリポジトリで管理するMarkdownファイル(Mkdocs)をマルチデバイス(Windows/Mac/iPhone/iPad)で更新する方法

経緯

  • 技術系のTips記事(静的サイト)をMaterial for Mkdocs(以降MkDocsと表現する)で作成したドキュメント(Markdown)をGitHubで管理し、Netlifyでデプロイすることでwebサイトとして公開していた。
  • 個人の作業ログやメモはObsidianアプリを使用して管理していた。
  • データはWindows/Mac/iPhone/iPadで参照、更新するため、データの保存先(保管庫:Obsidian vault)はiCloudを指定して保存していた。
  • MkDocsはWebページとして生成されるが、materialテーマにより統一的なデザインで構成されるためスマートフォンやPCで見やすい。ただし、ドキュメント更新は主にPCでVSCodeから行う必要があった。
  • 文章量が多い場合はPCでも良いが、毎回起動するのは手間だと感じていた。そこで、スマートフォンでもドキュメントを更新する方法がないか検討していた。
  • 一例として、はてなブログでは、スマートフォン向けもアプリが公開されており、PC、スマートフォンで両方で更新可能な例も存在する。

仕様検討

要件

  • ドキュメント表示はMkDocs、更新はObsidian、または、VSCodeとする。
  • ドキュメント(コード)はGitで管理し、セキュリティを考慮してGitHubのプライベートリポジトリで管理する。
  • 費用はなるべく抑えたい。希望は無料で利用できること。

技術選定

  • Obsidianでは、ウェブサイト上に公開するサービスとしてObsidian Publishが提供されているが、月額制のサービスであるため対象から除いた。1

  • マルチデバイスで更新可能にするために保管庫はiCloudで設定することが前提になる。ローカル保管庫の変更を自動的に同期するサービス(リモートでも設定次第で可能)として、Obsidian Syncが提供されているが、こちらも有料の月額サービスであるため対象から除いた。2

  • ObsidianでGitを利用する方法として、Obsidian-Gitプラグインを利用することで、元データをgitのリポジトリの情報で設定できる。PCでは任意のローカルディレクトリを指定可能なので問題なし。iPhone,iPadの場合は、ファイル(ローカル)のobsidianフォルダ以下のみ対象であるため、ここにgit cloneする必要があるが、これはa-Shellアプリを使用すれば対応可能であった。3

設定方法

以降の内容は以下のページを参照ください。

7rikazhexde-pkm-obsidian-mkdocs.netlify.app

以上です。


  1. 興味はあるので今後使用する可能性はある。調べると、tadashi-aikawaのPKMとして公開されているMinervaではObsidian Publishを使用して運用されている。使用する場合は内容が参考になるため共有させていただきます。
  2. Obsidian Syncに記載の通り、機能も充実しているので利用価値は高いと言える。
  3. gitコマンドのインストールが必要(インストール方法詳細)

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安定版バージョン取得システムを構築できます。

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

GitHubのスパムIssueを自動削除するスクリプト/ワークフローについて

はじめに

最近、GitHubのissuesでスパムが登録されるようになったので、タイトル、本文で指定キーワードに該当したらissueを削除するworkflowを作成したので紹介します。

注意事項

  • 本記事は2025/03/16時点の情報です。
  • 本記事に記載された内容やコードによって生じたいかなる損害についても責任を負いません。使用する際は自己責任でお願いします。
  • 使用する場合は、事前にローカルでspam_issue_deleter.pyを実行して動作確認することを推奨します。

使用方法

スクリプト/ワークフローファイルではGitHub APIのアクセストークンが必要になります。詳細はスクリプトを参照してください。

スクリプト(spam_issue_deleter.py)

コマンド例:python scripts/spam_issue_deleter.py

ワークフロー(delete-spam-issues.yml)

  • スクリプトとワークフローファイルコミット後にActions > Delete Spam Issues > Run workflow > mainで手動実行できます。
  • 定期実行(cron)もサポートしています。必要に応じて変更してください。

実行例

実行結果(左:issueの削除結果, 右:workflow実行結果)

まとめ

  • GitHubのissuesでスパムが登録されるようになったので、タイトル、本文で指定キーワードに該当したらissueを削除するスクリプトとワークフローを紹介しました。
  • issueはブラウザであれば手動削除も可能ですが、iOSスマホアプリでは対応していません。正直、この状況は良くないので、ブラウザ同等に削除できるように機能要望を出したいと考えています。
  • また、スパムは報告することも可能ですが、運営はすぐレスポンスしてくれるとは限りません。見るよりもまず削除することが大事だと思いますので、リスクは排除し安全は自分で守ることにしましょう。

以上。