Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

@vonpupp 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

This comment has been minimized.

Copy link

@wrecker 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

This comment has been minimized.

Copy link

@wrecker 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

This comment has been minimized.

Copy link

@sinetoami sinetoami commented Aug 3, 2018

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
You can’t perform that action at this time.