--- - name: Ensure workstation user directories exist tags: [dotfiles, dotfiles:workstation] ansible.builtin.file: path: "{{ item.path }}" state: directory owner: "{{ username }}" group: "{{ user_group }}" mode: "{{ item.mode }}" loop: "{{ workstation_user_directories | default([]) }}" loop_control: label: "{{ item.path }}" - name: Copy workstation dotfiles tags: [dotfiles, dotfiles:workstation] ansible.builtin.copy: src: "{{ playbook_dir }}/../dotfiles/workstation/{{ item.src }}" dest: "{{ user_home }}/{{ item.dest }}" owner: "{{ username }}" group: "{{ user_group }}" mode: "{{ item.mode }}" loop: "{{ workstation_dotfiles | default([]) }}" loop_control: label: "{{ item.dest }}" - name: Render workstation templates tags: [dotfiles, dotfiles:workstation] ansible.builtin.template: src: "{{ item.src }}" dest: "{{ user_home }}/{{ item.dest }}" owner: "{{ username }}" group: "{{ user_group }}" mode: "{{ item.mode }}" loop: "{{ workstation_templates | default([]) }}" loop_control: label: "{{ item.dest }}" - name: Set workstation external tool release metadata tags: [packages] ansible.builtin.set_fact: workstation_tools_tmp_dir: /tmp/workstation-tools opencode_asset_name: >- {{ 'opencode-linux-x64-baseline.tar.gz' if ansible_facts['architecture'] == 'x86_64' else 'opencode-linux-arm64.tar.gz' if ansible_facts['architecture'] in ['aarch64', 'arm64'] else '' }} - name: Ensure architecture is supported for OpenCode binary tags: [packages] ansible.builtin.fail: msg: "Unsupported architecture {{ ansible_facts['architecture'] }} for OpenCode release binary" when: opencode_asset_name == '' - name: Ensure temporary directory exists for workstation external tools tags: [packages] ansible.builtin.file: path: "{{ workstation_tools_tmp_dir }}" state: directory mode: "0755" - name: Fetch latest OpenCode release metadata tags: [packages] ansible.builtin.uri: url: https://api.github.com/repos/anomalyco/opencode/releases/latest headers: Accept: application/vnd.github+json return_content: true register: opencode_latest_release changed_when: false - name: Set OpenCode release asset metadata tags: [packages] ansible.builtin.set_fact: opencode_version: "{{ opencode_latest_release.json.tag_name }}" opencode_asset: >- {{ opencode_latest_release.json.assets | selectattr('name', 'equalto', opencode_asset_name) | first | default({}) }} - name: Ensure latest OpenCode asset metadata is available tags: [packages] ansible.builtin.fail: msg: "Could not find OpenCode asset {{ opencode_asset_name }} in release {{ opencode_version }}" when: opencode_asset == {} - name: Download OpenCode release archive tags: [packages] ansible.builtin.get_url: url: "{{ opencode_asset.browser_download_url }}" dest: "{{ workstation_tools_tmp_dir }}/{{ opencode_asset.name }}" checksum: "{{ opencode_asset.digest | default(omit) }}" mode: "0644" - name: Extract OpenCode release archive tags: [packages] ansible.builtin.unarchive: src: "{{ workstation_tools_tmp_dir }}/{{ opencode_asset.name }}" dest: "{{ workstation_tools_tmp_dir }}" remote_src: true - name: Install OpenCode binary tags: [packages] ansible.builtin.copy: src: "{{ workstation_tools_tmp_dir }}/opencode" dest: /usr/local/bin/opencode remote_src: true owner: root group: root mode: "0755" - name: Ensure GNOME extension directories exist tags: [packages, gnome] ansible.builtin.file: path: "{{ item }}" state: directory owner: "{{ username }}" group: "{{ user_group }}" mode: "0755" loop: - "{{ user_home }}/.cache/gnome-shell/extensions" - "{{ user_home }}/.local/share/gnome-shell/extensions" - name: Gather workstation user account data tags: [packages, gnome] ansible.builtin.getent: database: passwd key: "{{ username }}" - name: Set workstation GNOME session environment tags: [packages, gnome] ansible.builtin.set_fact: workstation_user_uid: "{{ ansible_facts.getent_passwd[username][1] }}" workstation_gnome_extension_dir: "{{ user_home }}/.cache/gnome-shell/extensions" workstation_gnome_environment: HOME: "{{ user_home }}" XDG_RUNTIME_DIR: "/run/user/{{ ansible_facts.getent_passwd[username][1] }}" DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ ansible_facts.getent_passwd[username][1] }}/bus" - name: Download workstation GNOME extension archives tags: [packages, gnome] ansible.builtin.get_url: url: >- https://extensions.gnome.org/download-extension/{{ item.uuid }}.shell-extension.zip?version_tag={{ item.version_tag }} dest: "{{ workstation_gnome_extension_dir }}/{{ item.uuid }}.zip" owner: "{{ username }}" group: "{{ user_group }}" mode: "0644" loop: "{{ workstation_gnome_extensions | default([]) }}" loop_control: label: "{{ item.uuid }}" - name: Check installed workstation GNOME extensions tags: [packages, gnome] ansible.builtin.stat: path: "{{ user_home }}/.local/share/gnome-shell/extensions/{{ item.uuid }}/metadata.json" loop: "{{ workstation_gnome_extensions | default([]) }}" loop_control: label: "{{ item.uuid }}" register: workstation_gnome_extension_install_state - name: Install workstation GNOME extensions from downloaded archives tags: [packages, gnome] ansible.builtin.command: cmd: "gnome-extensions install --force {{ workstation_gnome_extension_dir }}/{{ item.uuid }}.zip" become_user: "{{ username }}" environment: "{{ workstation_gnome_environment }}" loop: "{{ workstation_gnome_extensions | default([]) }}" loop_control: label: "{{ item.uuid }}" when: >- not ( workstation_gnome_extension_install_state.results | selectattr('item.uuid', 'equalto', item.uuid) | map(attribute='stat.exists') | first | default(false) ) - name: Read current workstation GNOME enabled extensions tags: [gnome] ansible.builtin.command: cmd: gsettings get org.gnome.shell enabled-extensions become_user: "{{ username }}" environment: "{{ workstation_gnome_environment }}" register: workstation_enabled_gnome_extensions_current changed_when: false - name: Compute desired workstation GNOME enabled extensions tags: [gnome] ansible.builtin.set_fact: workstation_enabled_gnome_extensions_current_list: >- {{ ( workstation_enabled_gnome_extensions_current.stdout | default('') | regex_search('\[.*\]') | default('[]', true) ) | from_yaml }} - name: Build desired workstation GNOME enabled extensions list tags: [gnome] ansible.builtin.set_fact: workstation_enabled_gnome_extensions_desired: >- {{ ( workstation_enabled_gnome_extensions_current_list + ( workstation_gnome_extensions | default([]) | selectattr('enabled', 'defined') | selectattr('enabled') | map(attribute='uuid') | list ) ) | difference(workstation_disabled_gnome_extensions | default([])) | unique | sort }} - name: Build workstation GNOME extensions gsettings payload tags: [gnome] ansible.builtin.set_fact: workstation_enabled_gnome_extensions_desired_gsettings: >- [{% for extension_uuid in workstation_enabled_gnome_extensions_desired -%} '{{ extension_uuid | replace("'", "\\'") }}'{% if not loop.last %}, {% endif %} {%- endfor %}] - name: Determine whether workstation GNOME enabled extensions must change tags: [gnome] ansible.builtin.set_fact: workstation_gnome_extensions_state_changed: >- {{ (workstation_enabled_gnome_extensions_current_list | sort) != workstation_enabled_gnome_extensions_desired }} - name: Apply workstation GNOME enabled extensions list tags: [gnome] ansible.builtin.command: argv: - gsettings - set - org.gnome.shell - enabled-extensions - "{{ workstation_enabled_gnome_extensions_desired_gsettings }}" become_user: "{{ username }}" environment: "{{ workstation_gnome_environment }}" changed_when: workstation_gnome_extensions_state_changed when: workstation_gnome_extensions_state_changed - name: Enable UFW firewall on workstation tags: [services, packages] community.general.ufw: state: enabled