GitHub の private リポジトリで開発を進めている Golang プロジェクトがあります。CiecleCI 上でビルドを行ってバイナリファイルを GitHub Releases にアップロードしているものがあります。
これまでは「手動で最新版ファイルをダウンロードして ansible でデプロイする」といった方法を取っていました。都度行うには手間なので ansible の playbook 1発で実行させたくなりました。
実行したい処理
- 特定の GitHub Releases から最新版のファイルをダウンロード
- ansible 実行対象サーバのファイルと差し替え
- GitHub Releases の各バージョンには 1 ファイルのみ アップロードされている状態
準備
GitHub の API にアクセスする必要があるため Personal Access Token を取得します。管理画面 から新しいトークンの作成ができます。権限は 1 番上の repo にチェックを入れるだけです。
取得したトークンを環境変数に設定します。(実際には direnv を使っています)
$ export GITHUB_TOKEN=YOUR-GITHUB-TOKEN
参考 playbook
- name: private な github releases からファイルをダウンロードする
hosts: all
vars:
github:
user: 'USER-NAME' # 対象リポジトリのユーザ名
repos: 'REPOSITORY-NAME' # 対象リポジトリ名
token: "{{ lookup('env', 'GITHUB_TOKEN') }}" # 環境変数 GITHUB_TOKEN をロード
dest: '/path/to/savepath' # DL したファイルの保存先パス
tasks:
- name: '{{ github.user }}/{{ github.repos }} 最新版情報取得'
uri:
url: 'https://api.github.com/repos/{{ github.user }}/{{ github.repos }}/releases/latest'
HEADER_Authorization: 'token {{ github.token }}'
return_content: yes
body_format: json
register: response # 最新版の情報を取得
- name: GitHub API からダウンロード用 URL 取得
uri:
url: '{{ response.json.assets[0].url }}'
HEADER_Authorization: 'token {{ github.token }}'
HEADER_Accept: 'application/octet-stream'
follow_redirects: no
return_content: yes
body_format: json
status_code: 302
register: response # DL 対象ファイルの URL を取得
- name: '{{ github.user }}/{{ github.repos }} からファイルをダウンロード'
get_url:
url: '{{ response.location }}'
dest: '{{ github.dest }}'
force: yes
owner: root
group: root
mode: 0500
become: True
処理手順
- uri モジュールを使って最新版リリース情報を取得
- レスポンス: Get the latest release
- 取得したいファイルは 1 つだけなので, assets の 0 番の URL が処理対象
- uri モジュールで 1 で取得した JSON を使って DL 対象の URL にアクセス
- レスポンス: Get a single release asset
- status: 302 が返り, レスポンスヘッダの Location に DL 用 URL が書かれている
- 2 のレスポンスヘッダ Location に記載されている URL にアクセスしファイル取得
本来なら 1 のデータ取得後に get_url
モジュールで 2 へアクセスすればファイルが落とせそうな気がします。しかし get_url
が HTTP Status: 302 Found のリダイレクトにエラーを吐くので, 直接レスポンスの Location を見て DL しています。
curl であれば 1 で取得した response.json.assets[0].url
に対して次のコマンドでファイルを DL できます。
$ curl -L -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/octet-stream" https://api.github.com/repos/USER-NAME/REPOSITORY-NAME/releases/assets/:asset_id
command
モジュールで curl を使ったほうが早い気もしますが, 折角 ansible を使ているので playbook で頑張りました。
get_url モジュールの取扱間違いの可能性
もしかすると get_url
の扱いを間違えている結果, 余計な処理を間に挟まなければならないのかもしれません。一応ドキュメントは読んでいますが, お気づきの点がある方はひっそり Twitter あたりで教えて欲しいください。