Ansible - Download latest release binary from Github repo
I got inspired and extended the play. After downloading I add the version number to the binary and link to the program. so I can check on the next run if the version is still up to date. Otherwise it is downloaded and linked again.
- hosts: localhost
become: false
vars:
org: watchexec
repo: watchexec
filename: x86_64-unknown-linux-gnu.tar.xz
version: latest
project_url: https://api.github.com/repos/{{ org }}/{{ repo }}/releases
tasks:
- name: check {{ repo }} version
uri:
url: "{{ project_url }}/{{ version }}"
return_content: true
register: latest_version
- name: check if {{ repo }}-{{ version }} already there
stat:
path: "{{ ansible_env.HOME }}/.local/bin/{{ repo }}-{{ latest_version.json.tag_name }}"
register: newestbinary
- name: download and link to version {{ version }}
block:
- name: create tempfile
tempfile:
state: directory
suffix: dwnld
register: tempfolder_1
- name: "installing {{ repo }} {{ latest_version.json.tag_name }}"
# idea from: https://stackoverflow.com/a/62672308/886659
loop: "{{ latest_version.json.assets }}"
when: "filename|string in item.name"
unarchive:
remote_src: yes
src: "{{ item.browser_download_url }}"
dest: "{{ tempfolder_1.path }}"
keep_newer: yes
extra_opts:
- --strip=1
- --no-anchored
- "{{ repo }}"
- name: command because no mv available
command: mv "{{ tempfolder_1.path }}/{{ repo }}" "{{ ansible_env.HOME }}/.local/bin/{{ repo }}-{{ latest_version.json.tag_name }}"
args:
creates: "{{ ansible_env.HOME }}/.local/bin/{{ repo }}-{{ latest_version.json.tag_name }}"
- name: "link {{ repo }}-{{ latest_version.json.tag_name }} -> {{ repo }} "
file:
src: "{{ ansible_env.HOME }}/.local/bin/{{ repo }}-{{ latest_version.json.tag_name }}"
dest: "{{ ansible_env.HOME }}/.local/bin/{{ repo }}"
state: link
force: yes
when: not newestbinary.stat.exists
always:
- name: delete {{ tempfolder_1.path|default("tempfolder") }}
file:
path: "{{ tempfolder_1.path }}"
state: absent
when: tempfolder_1.path is defined
ignore_errors: true
# vim:ft=yaml.ansible:
here is the file on github
I am using the following recipe to download and extract latest watchexec
binary for Linux from GitHub releases.
- hosts: localhost
tasks:
- name: check latest watchexec
uri:
url: https://api.github.com/repos/watchexec/watchexec/releases/latest
return_content: true
register: watchexec_latest
- name: "installing watchexec {{ watchexec_latest.json.tag_name }}"
loop: "{{ watchexec_latest.json.assets }}"
when: "'x86_64-unknown-linux-musl.tar.xz' in item.name"
unarchive:
remote_src: yes
src: "{{ item.browser_download_url }}"
dest: "{{ ansible_env.HOME }}/bin/"
keep_newer: yes
extra_opts:
- --strip=1
- --no-anchored
- watchexec
tar
extra_opts
explained here.
This still downloads the binary every time a playbook is called. As an improvement, it might be possible to use set_fact
for caching node_id
attribute that corresponds to the unpacked file.
Github has an API to manipulate the release which is documented.
so imagine you want to get the latest release of ansible (which belong to the project ansible) you would
- call the url
https://api.github.com/repos/ansible/ansible/releases/latest
- get an json structure like this
{ "url": "https://api.github.com/repos/ansible/ansible/releases/5120666", "assets_url": "https://api.github.com/repos/ansible/ansible/releases/5120666/assets", "upload_url": "https://uploads.github.com/repos/ansible/ansible/releases/5120666/assets{?name,label}", "html_url": "https://github.com/ansible/ansible/releases/tag/v2.2.1.0-0.3.rc3", "id": 5120666, "node_id": "MDc6UmVsZWFzZTUxMjA2NjY=", "tag_name": "v2.2.1.0-0.3.rc3", "target_commitish": "devel", "name": "THESE ARE NOT OUR OFFICIAL RELEASES", ... }, "prerelease": false, "created_at": "2017-01-09T16:49:01Z", "published_at": "2017-01-10T20:09:37Z", "assets": [ ], "tarball_url": "https://api.github.com/repos/ansible/ansible/tarball/v2.2.1.0-0.3.rc3", "zipball_url": "https://api.github.com/repos/ansible/ansible/zipball/v2.2.1.0-0.3.rc3", "body": "For official tarballs go to https://releases.ansible.com\n" }
- get the value of the key
tarball_url
- download the value of the key retrieved just above
In ansible code that would do
- hosts: localhost
tasks:
- uri:
url: https://api.github.com/repos/ansible/ansible/releases/latest
return_content: true
register: json_reponse
- get_url:
url: "{{ json_reponse.json.tarball_url }}"
dest: ./ansible-latest.tar.gz
I let you adapt the proper parameters to answer your question :)
Another approach is to use ansible github_release module to get the latest tag
example
- name: Get gogs latest tag
github_release:
user: gogs
repo: gogs
action: latest_release
register: gogs_latest
- name: Grab gogs latest binaries
unarchive:
src: "https://github.com/gogs/gogs/releases/download/{{ gogs_latest['tag'] }}/gogs_{{ gogs_latest['tag'] | regex_replace('^v','') }}_linux_amd64.zip"
dest: /usr/local/bin
remote_src: true
- The regex part at the end is for replacing the v at the beginning of the tag since the format now on GitHub for gogs is gogs_0.12.3_linux_armv7.zip and latest tag includes a v