概要
Ansibleを使って、GitHubリリースにアップロードされているWheelファイルをダウンロードしインストールします。
事前準備と前提
community.generalコレクションを使用するので、インストールされていなければ下記のコマンドでインストールして下さい。
ansible-galaxy collection install community.general
また、AnsibleでインストールするPythonパッケージは、下記Jupyter Notebookの例のようにGitHubのリリースに.whl
ファイルとしてアップロードされているとします。
最新リリースの取得
community.generalコレクションにgithub_releaseというモジュールはあるのですが、v4.8.0時点ではアセットの取得ができません。
代わりにansible.builtin.get_urlモジュールを使って直接Get the latest release APIにアクセスします。
- name: Find the latest version
ansible.builtin.uri:
url: "https://api.github.com/repos/{{ org }}/{{ repo }}/releases/latest"
headers:
Authorization: "Bearer {{ github_token }}"
Accept: application/vnd.github.v3+json
register: info
no_log: true
変数org
にレポジトリのOrganization名(個人アカウントの場合はユーザ名)、repo
にリポジトリ名が格納されているとします。
リポジトリがプライベートの場合はAuthorizationヘッダを使った認証が必要です。
変数github_token
にはrepo
権限のあるアクセストークンを格納されているとします。
パブリックレポジトリの場合、Authorizationヘッダは不要です。
APIのレスポンスはJSON形式で返ってくるので、戻り値を格納した変数info
のjson
属性からアクセスできます。
Wheelファイルのダウンロードとインストール
GitHubリリースにアップロードされたファイルは、Get the latest release APIレスポンスのassets属性にリストとして記録されています。
その中から、.whl
ファイルだけを取得するためにJSONクエリフィルターを使います。
クエリassets[?ends_with(name, `.whl`)].{name: name, url: url}
は、assets
の中からname
が.whl
で終わるものだけを抜き出し、name
とurl
からなるオブジェクトを作成します。
このname
とurl
は、get_urlモジュールのdest
とurl
で使用しています。
- name: Download the latest package
ansible.builtin.get_url:
url: "{{ item.url }}"
headers:
Authorization: "Bearer {{ github_token }}"
Accept: application/octet-stream
dest: "/tmp/{{ item.name }}"
mode: "0644"
loop: "{{ info.json | community.general.json_query(query) }}"
vars:
query: "assets[?ends_with(name, `.whl`)].{name: name, url: url}"
register: download
no_log: true
今回もパブリックリポジトリの場合、Authorizationヘッダは不要です。
Accept: application/octet-stream
の指定を忘れると、.whl
ファイルではなくメタデータがJSON形式で返ってきてしまうので注意が必要です。
最後に、ダウンロードしてきた.whl
ファイルをpip
を使ってインストールします。
- name: Install the package
ansible.builtin.pip:
name: "file://{{ item.dest }}"
state: present
loop: "{{ download.results }}"
assetsがリストのため、このタスクもループ処理になります。
プレイブック
以上をまとめたプレイブックは次の通りです。vars
以下の変数を適切に設定してください。
github_token
はvaultで暗号化しておくと良いでしょう。
- hosts: all
become: true
gather_facts: false
vars:
org: org_name
repo: repo_name
github_token: personal_access_token
tasks:
- name: Find the latest version
ansible.builtin.uri:
url: "https://api.github.com/repos/{{ org }}/{{ repo }}/releases/latest"
headers:
Authorization: "Bearer {{ github_token }}"
Accept: application/vnd.github.v3+json
register: info
no_log: true
- name: Download the latest package
ansible.builtin.get_url:
url: "{{ item.url }}"
headers:
Authorization: "Bearer {{ github_token }}"
Accept: application/octet-stream
dest: "/tmp/{{ item.name }}"
mode: "0644"
loop: "{{ info.json | community.general.json_query(query) }}"
vars:
query: "assets[?ends_with(name, `.whl`)].{name: name, url: url}"
register: download
no_log: true
- name: Install the package
ansible.builtin.pip:
name: "file://{{ item.dest }}"
state: present
loop: "{{ download.results }}"