REST APIでRedmineアクセス(1)
2025/05/01
Redmineの活用はグループ間で差が出てしまう
  • 今回のレポートは、かなり回り道をします。

  • Project管理ではなく、ミニ事業単位の情報共有ツールとしてRedmineを利用する場合、様々な担当グループの人がRedmineに触ります。例えば下記のようなグループです。
    • 営業
    • 生産管理
    • 製造
    • 開発

  • 開発Grや、製造Gr等情報ツールに慣れ親しんでいるメンバが多いグループは、自然とタイトルや記述方法にルールを適用してまとめリンクを作ったりしますが、それ以外のグループは業務チケットの体系付けを苦手としており、重要/有効な情報を持つチケットが離散する(*1)傾向にあるようです。

  • しばらく運用して、グループ間の差を目の当たりにしたとき「我々のグループも有効活用したい」とは思うものの、「まとめ」という「グループの意思」(*2)表現を一担当がやることに心理的障壁が存在するケースも多く、この障壁の感じ方がグループによって大きく異なるというのが私の実感です。

  • もともと「利用の経験やスキルが不足している」と感じていて、サブGrリーダー自身も同じ心理状態の場合、明確な指示や指針を出せないので、グループ単位でその状況になるのは「仕方が無い/やむを得ない」(*3)ことだと思います。

  • この対応ですが、チケットを作成した時、タイトルにキーワードを入れる/コメントにキーワードを入れる/適切なチケットテンプレートを選択する等の一次分類をユーザにお願いするのは必須として、ここから先の体系化がポイントとなります。

体系化/まとめは定型作業なので自動化できる
  • Wikiの記述や体系化/ツリー化の考え方に慣れていない場合、自分たちが作成したチケット/リーフ情報の「まとめ/体系化」作業に「抵抗を感じる/遠慮する」こと、それを先ほど「心理的障壁」という言葉で表現しました。

  • でもこれは、わかってしまえば定型作業と言い換えることもできます。そして定型作業は自動化できるはずなのです。
    • 最初は自動作成されたまとめを利用する
    •  →気に入らないところはキーワードの修正で調整する
    •   →運用やまとめ方に慣れてきたら、自分で作成する/自動作成ツールを改良する

  • そして自動化ということは、人手ではなくイベントやタイムテーブルで駆動するコマンドライクなもの、つまりCLI(*4)からRedmineのデータを参照して体系化データの生成を行うことになります。

  • そのCLI構築手段ですが、RedmineはREST APIを持っているので、これを利用すれば良いですね。

PythonによるRedmine REST API利用方法が揺れてる?
  • Redmine REST APIをPythonから使う方法を調べると、Google先生とCopilot先生で違う検索結果/回答(*5)になります。
    • Google先生: python-redmineライブラリがおすすめ
    • Copilot先生: requestsライブラリがおすすめ

  • この違いについて少し調べた結果から、私はrequestsライブラリを使うことにしました。その理由ですが、python-redmine のドキュメントリソースにアクセスできなくなっていたからです。例を見ればわかるとは思うものの、更新が怪しいライブラリをこれから使う気にはなれませんでした。

  • requestsライブラリ(HTTPリクエスト)を利用する方法は、python-redmineに比べると、ほんの少し(抽象度は)低レベルですが、RedmineだけではないREST API全般への理解が進むので利点もあります。ちなみにRedmine REST APIに記述される説明は、HTTPリクエストを知っていることが前提となっています(が、そんな大層な話ではないです)。

HTTPリクエストとは?
  • HTTPリクエスト...ほぼ全ての人が使用しています。ChromeやEdge等のブラウザでWeb閲覧していますよね。あれは、WebブラウザからHTTPサーバへ「リクエスト」を送って、「レスポンス」を表示しています。HTTPリクエストの代表的な使用例になります。


  • HTTPリクエスト/レスポンスは3種の要素で構成されます。下記はhtmlデータのリクエスト/レスポンス例です。
    • HTTPリクエスト
    • 要素内容例説明
      リクエスト行 GET /index.html メソッドと対象URI(*6)指定
      メッセージ・ヘッダー {'content-type': 'text/html'} ヘッダ/属性設定
      エンティティ・ボディ {'offset': 50, 'limit': 100} パラメータ設定

    • HTTPレスポンス
    • 要素内容例説明
      レスポンス行 200 ステータス戻り値
      メッセージ・ヘッダー {'charset': 'UTF-8'} データ属性
      エンティティ・ボディ <html>〜</html> サーバーからのデータ

  • このHTTPリクエスト/レスポンスをプログラム/スクリプトから扱うライブラリがあれば、HTTPサーバからhtmlデータを取得するCLIツールを簡単に作れるようになりますね。下記はHTTPリクエストを扱うPythonとPerlのライブラリです。

REST APIとは?
  • 先ほど、HTTPリクエストでhtmlデータや画像をHTTPサーバから取得しましたが、このhtmlデータ取得のように「よく見られるやり方(Representational)」でhtml以外のデータもやり取りできそうですよね。それがREST API(REpresentational State Transfer API)の考え方です。

  • html以外のデータについても、転送要求の受付URIをWebアプリケーションが用意すれば、クライアントはHTTPリクエストを利用してデータアクセスできることになります。

  • あとは、HTTPリクエストの代表的なメソッド(GET/POST/PUT/DELETE)とパラメータの組み合わせでデータ処理できるようになっていれば、Webアプリケーション側がREST APIを持っていると言えます。

  • 尚、REST APIでレスポンスによって戻る構造化データのデフォルトはJSONです。構造化データの元祖はXMLなので、両方サポートしているWebアプリケーションも多いですが、時代の流れに逆らう必要も無いかなと思います。

RedmineでREST APIを有効にする
  • 実際にRedmineでREST APIを使用する前に、まずRedmineのREST APIを有効化します。

  • 管理者権限を持つアカウントでRedmineにログインし
      管理→設定→API
    とメニューを移動します。

  • 下記のようにチェックを入れればREST APIが使用できる状態になります。

RedmineでREST APIを使ってみる
  • ではRedmineのチケット(issue)リストをREST APIで取得してみましょう。Redmine REST APIの
    を見ると、自分のPCで動作させているRedmineについては、HTTPリクエストに下記を設定すれば良いことがわかります。
    • リクエスト行: 'GET http://localhost:3000/issues.json'
    • ヘッダ: {'X-Redmine-API-Key': 'アカウントのAPI KEY'}

  • 尚APIキー値は、Redmine個人設定(右サイド)から取得できます(一部隠しています)。


  • レスポンスは、チケット(issue)のリストとしてJSONデータを取得します。Pythonならば下記コード例となります。
  • import requests
    import sys
    
    # URI to get issue list
    uri = 'http://localhost:3000/issues.json'
    
    # API key of Redmine account
    api_key = '8dc1f63ae...うんぬんかんぬん'
    
    # set API key to headers of HTTP request
    d_auth = {'X-Redmine-API-Key': api_key}
    
    # GET http://localhost:3000/issues.json with headers
    j_res = requests.get(uri, headers=d_auth)
    
    # check status code of response
    if j_res.status_code == 200:
        print(f"INF: HTTP request is successful for [{uri}]")
    else:
        print(f"ERR: status_code=[{j_res.status_code}] for [{uri}]")
        sys.exit(1)
    
    # converting response from json to python dict
    d_res = j_res.json()
    
    # show id, subject and status of each issue
    for o_issue in d_res['issues']:
        id = o_issue['id']
        subject = o_issue['subject']
        status = o_issue['status']['name']
        print(f"INF: id={id},\tsubject={subject},\tstatus={status}")
    
    print("INF: normally finished")
    
    >test.py
    INF: HTTP request is successful for [http://localhost:3000/issues.json]
    INF: id=30,     subject=Test 30,        status=新規
    INF: id=29,     subject=Test 29,        status=新規
    INF: id=28,     subject=Test 28,        status=新規
    INF: id=27,     subject=Test 27,        status=新規
    ...中略...
    INF: id=14,     subject=Test 14,        status=新規
    INF: id=13,     subject=Test 13,        status=新規
    INF: id=12,     subject=Test 12,        status=新規
    INF: id=11,     subject=Test 11,        status=新規
    INF: id=10,     subject=Test 10,        status=進行中
    INF: id=9,      subject=Test 09,        status=新規
    INF: id=8,      subject=Test 08,        status=新規
    INF: id=7,      subject=Test 07,        status=新規
    INF: id=6,      subject=Test 06,        status=新規
    INF: normally finished
    

次回はRedmine REST APIで追加や変更などしてみる
  • 今回はHTTPリクエストを使用してRedmine REST APIを触るところまでやってみました。Remineだけでなく他のWebアプリケーションもREST APIがあれば使えそうだと思えたでしょうか。

  • 次回はRedmine REST APIの続きで、チケット(Issue)の変更/追加/削除や、Wikiの編集などやってみたいと思います。
Notes
  1. あんなに頑張ったのに大変勿体ない。
  2. そう感じてしまうのがグループ間の文化差。個人の集合がグループだから気にしなくて良いんですけどね。
  3. このとき「それは...超えるべき壁だ(どやぁ)」な人が出ると分断発生で...残念な方向へ。
  4. Command Line Interface
  5. 2025/04/29現在の結果
  6. Uniform Resource Identifier で URL(Uniform Resource Locator)の上位相当
Copyright(C) 2025 Altmo
本HPについて