Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ digest. Read that before changing a role or adding a tool.
- Docker (Engine on Linux, CLI-only via Homebrew on macOS, no Docker Desktop, bring your own daemon)
- Git, GitHub CLI, Git LFS
- CLI utilities: jq, bat, fzf, ripgrep, fd, gron, sd, git-delta, lazygit, moreutils, miller, tmux, htop, age, ...
- Playwright (`--tags playwright`): the CLI as a uv tool, plus Chromium, Firefox and WebKit in `~/.cache/ms-playwright`. On Ubuntu its own `install-deps` adds the system libraries. Fedora gets the CLI, libavif and libmanette only, since Playwright does not support it

**Opt-in, via tags:**

Expand Down
8 changes: 8 additions & 0 deletions ansible/roles/developer/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@
tags: ['developer', 'utilities']
tags: ['developer', 'utilities']

- name: Install Playwright
ansible.builtin.include_tasks:
file: playwright.yml
apply:
tags: ['developer', 'playwright']
tags: ['developer', 'playwright']
when: ansible_facts['distribution'] in ['Fedora', 'Ubuntu']

- name: Install Git and version control tools
ansible.builtin.include_tasks:
file: git.yml
Expand Down
114 changes: 114 additions & 0 deletions ansible/roles/developer/tasks/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
# Playwright CLI, its system libraries and its browsers.
#
# Playwright owns its dependency list per release, so nothing here names a
# package. The Python distribution bundles its own driver, which means no node
# is needed to run it.

# Playwright does not support Fedora: no install-deps, no browsers. WebKit still
# wants these two libraries wherever Playwright is used.
- name: Install browser runtime libraries (Fedora)
ansible.builtin.dnf:
name:
- libavif
- libmanette
state: present
when: ansible_facts['distribution'] == 'Fedora'

- name: Install Playwright and its browsers
block:
# --upgrade, no pin: uv installs it if missing and pulls the latest release
# if present. uv prints "Installed 1 executable" on every run, so only the
# package lines count as a change.
- name: Install or upgrade the Playwright CLI
ansible.builtin.command:
cmd: uv tool install --upgrade playwright
environment:
PATH: "{{ user_home }}/.local/bin:{{ ansible_facts['env'].PATH }}"
become: true
become_user: "{{ actual_user }}"
register: developer_playwright_cli
changed_when: >-
(developer_playwright_cli.stdout ~ developer_playwright_cli.stderr)
is search('(Installed|Updated|Uninstalled) [0-9]+ packages?')

# --dry-run simulates the apt-get install and exits non-zero when any
# library is missing, which is what makes the real run idempotent.
- name: Check Playwright's system libraries (apt)
ansible.builtin.command:
argv: ["{{ user_home }}/.local/bin/playwright", install-deps, --dry-run, chromium, firefox, webkit]
become: true
register: developer_playwright_deps_probe
changed_when: false
failed_when: false
check_mode: false
when:
- ansible_facts['os_family'] == 'Debian'
- not ansible_check_mode

- name: Install Playwright's system libraries (apt)
ansible.builtin.command:
argv: ["{{ user_home }}/.local/bin/playwright", install-deps, chromium, firefox, webkit]
environment:
DEBIAN_FRONTEND: noninteractive
become: true
changed_when: true
when:
- ansible_facts['os_family'] == 'Debian'
- not ansible_check_mode
- developer_playwright_deps_probe.rc != 0

- name: Mark Playwright's system libraries as handled
ansible.builtin.set_fact:
developer_playwright_deps_ok: true
when:
- ansible_facts['os_family'] == 'Debian'
- not ansible_check_mode

# Browsers land in the user's ~/.cache/ms-playwright. A converged host
# prints nothing, so a download line is the only sign of change.
- name: Install the Playwright browsers
ansible.builtin.command:
cmd: playwright install chromium firefox webkit
environment:
PATH: "{{ user_home }}/.local/bin:{{ ansible_facts['env'].PATH }}"
become: true
become_user: "{{ actual_user }}"
register: developer_playwright_browsers
changed_when: >-
(developer_playwright_browsers.stdout ~ developer_playwright_browsers.stderr)
is search('Downloading')
when:
- ansible_facts['distribution'] != 'Fedora'
- not ansible_check_mode

rescue:
- name: Record that Playwright did not install
# noqa: var-naming[no-role-prefix] -- deploy_warnings is the shared
# accumulator playbooks/main.yml reports from. See docs/resilient-deploy.md.
ansible.builtin.set_fact:
deploy_warnings: >-
{{ deploy_warnings | default([])
+ ['playwright: ' ~ (ansible_failed_task.name | default('unknown task'))
~ ' -- ' ~ (ansible_failed_result.msg | default('no message'))] }}

# WebKit loads both. If a Playwright release drops either from its list, the
# converge fails here rather than leaving a browser that breaks at runtime.
- name: Read the installed libavif and libmanette packages
ansible.builtin.command:
argv: [dpkg-query, -W, -f, '${db:Status-Abbrev} ${Package}\n', 'libavif*', 'libmanette-*']
register: developer_playwright_libs
changed_when: false
failed_when: false
check_mode: false
when: developer_playwright_deps_ok | default(false)

- name: Assert libavif and libmanette are installed
ansible.builtin.assert:
that:
- developer_playwright_libs.stdout_lines | select('match', '^ii +libavif[0-9]') | list | length > 0
- developer_playwright_libs.stdout_lines | select('match', '^ii +libmanette-') | list | length > 0
fail_msg: >-
Playwright's install-deps left libavif or libmanette out. Both must be
installed: libavif[0-9]* and libmanette-*.
when: developer_playwright_deps_ok | default(false)
Loading