Skip to content

Instantly share code, notes, and snippets.

@cahna
Last active September 11, 2022 06:26
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cahna/45bb9eee92c5f1fce66f to your computer and use it in GitHub Desktop.
Save cahna/45bb9eee92c5f1fce66f to your computer and use it in GitHub Desktop.
download, build, and install aur packages with ansible

About

When using ArchLinux, I typically prefer to use an AUR helper like pacaur or yaourt to automate away the process of installing a community package.

Ansible's pacman module is great, but it doesn't support AUR packages or pacman's -U flag. Installing AUR packages with Ansible seemed to be left as an exercise to the user, and since AUR helpers do not come with a fresh Arch install, I created this set of tasks to be a reusable way of installing AUR packages on my Arch hosts.

I should take the time to PR an AUR module for Ansible sometime soon, but this is a nice, resusable submodule for any Arch-based Ansible role.

Example

---
- name: install yaourt on ArchLinux hosts
  hosts: my_archlinux_host_group
  gather_facts: yes
  vars:
    makepkg_nonroot_user: "{{ ansible_ssh_user }}"
  tasks:
    - name: install package-query (a yaourt dependency)
      include: aur/pkg.yml pkg_name=package-query
      
    - name: install yaourt
      include: aur/pkg.yml pkg_name=yaourt

Reccommended Usage

  1. Add this gist as a submodule to your Ansible role or playbook
# Example ./roles directory structure for an existing Ansible playbook with a 'foobar' role 
#   roles/
#     foobar/
#       tasks/
#         aur/          # Source repo added as a submodule (cloned into an `aur` directory)
#           pkg.yml     # Include this file with vars 'pkg_name' and 'makepkg_nonroot_user' to install an AUR package
$ cd ./roles/foobar/tasks
$ git submodule add https://gist.github.com/45bb9eee92c5f1fce66f.git aur
  1. Now aur/pkg.yml may be included from any task or handler within the foobar role. Given the variables pkg_name and makepkg_nonroot_user, the tasks will validate, download, compile (as the makepkg_nonroot_user user), and install (as root) the pkg_name package.

Tip: Set makepkg_nonroot_user in your group_vars/all file to avoid repeating yourself.

---
- name: AUR | get metadata from AurJson api
connection: local
sudo: no
uri: >
url=https://aur.archlinux.org/rpc.php?type=info&arg={{ pkg_name | mandatory }}
return_content=yes
timeout=6
register: api_info
- assert:
that:
- api_info.status == 200
- api_info.json is defined
- api_info.json.type == 'info'
- api_info.json.resultcount == 1
- api_info.json.results is defined
- name: AUR | {{ pkg_name }} | download tarball
sudo: no
connection: local
get_url: >
url='https://aur.archlinux.org{{ api_info.json.results.URLPath }}'
dest='/tmp/'
register: aur_tarball
- name: AUR | {{ pkg_name }} | upload tarball to host and extract it
sudo: yes
sudo_user: "{{ makepkg_nonroot_user }}"
unarchive: >
src={{ aur_tarball.dest }}
dest=/tmp/
register: extracted_pkg
# This will break if run as root. Set user to use with makepkg with 'makepkg_user' var
- name: AUR | {{ pkg_name }} | build package, including missing dependencies
when: extracted_pkg | changed
sudo: yes
sudo_user: "{{ makepkg_nonroot_user }}"
command: >
makepkg --noconfirm --noprogressbar -mfs
chdir=/tmp/{{ pkg_name }}
register: aur_makepkg_result
# Shameless variable declaration hack
- shell: ls -1 /tmp/{{ pkg_name | quote }} | grep pkg.tar
register: compiled_package_name
- name: AUR | {{ pkg_name }} | install newly-built aur package with pacman
when: aur_makepkg_result | changed
sudo: yes
shell: >
pacman --noconfirm --noprogressbar --needed -U {{ compiled_package_name.stdout | quote }}
chdir=/tmp/{{ pkg_name }}
register: pacman_install_result
changed_when: pacman_install_result.stdout is defined and pacman_install_result.stdout.find('there is nothing to do') == -1
@vonpupp
Copy link

vonpupp commented May 9, 2015

Hello,

I'm having an issue using your playbook. It seems that package-query builds successfully however the installation seems to fail on the last error handling "there is nothing to do", it seems so that the "&" symbol is causing those errors. Unfortunatelly I'm new to ansible and even I have researched about that error, I couldn't solve it. Here are the versions of pip libs I'm using:

[afu@vm ansible-playbooks]$ pip freeze
ansible==1.9.1
ecdsa==0.13
httplib2==0.9.1
Jinja2==2.7.3
MarkupSafe==0.23
notmuch==0.19
paramiko==1.15.2
pycrypto==2.6.1
PyYAML==3.11
urwid==1.3.0
wicd==1.7.3
zenmap==6.47

Do you know what might be wrong?

[afu@vm ansible-playbooks]$ ansible-playbook arch-yaourt2.yml -i "local," --extra-vars "makepkg_user=afu"

PLAY [install yaourt on ArchLinux hosts] ************************************** 

GATHERING FACTS *************************************************************** 
ok: [localhost]

TASK: [AUR | get metadata from AurJson api] *********************************** 
ok: [localhost]

TASK: [assert ] *************************************************************** 
ok: [localhost]

TASK: [AUR | package-query | download tarball] ******************************** 
ok: [localhost]

TASK: [AUR | package-query | upload tarball to host and extract it] *********** 
changed: [localhost]

TASK: [AUR | package-query | build package, including missing dependencies] *** 
changed: [localhost]

TASK: [shell ls -1 /tmp/package-query | grep pkg.tar] ************************* 
changed: [localhost]

TASK: [AUR | package-query | install newly-built aur package with pacman] ***** 
fatal: [localhost] => Failed to template {% if pacman_install_result.stdout is defined && pacman_install_result.stdout.find('there is nothing to do') == -1 %} True {% else %} False {% endif %}: template error while templating string: unexpected char u'&' at 46

FATAL: all hosts have already failed -- aborting

PLAY RECAP ******************************************************************** 
           to retry, use: --limit @/home/afu/arch-yaourt2.retry

localhost                  : ok=7    changed=3    unreachable=1    failed=0

Thank you very much!

@wrecker
Copy link

wrecker commented Jul 30, 2015

The problem is && is not a valid python operator. Replace && in changed_when: pacman_install_result.stdout is defined && pacman_install_result.stdout.find('there is nothing to do') == -1 with and

@wrecker
Copy link

wrecker commented Jul 30, 2015

Thanks for sharing this. I forked your gist and made some changes to skip the download & compile phase entirely if the package is already installed and is the same version as the AUR version.
https://gist.github.com/wrecker/39ecb1eb1ab8ee1d0ce1

@sinetoami
Copy link

Hey, @cahna! Hello. I have a question.
Can this approach find and make install all dependencies packages too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment