--- - name: Install basic development packages ansible.builtin.apt: name: "{{ development_packages }}" state: present become: true - name: Check if Node.js is installed ansible.builtin.command: node --version register: node_version_check failed_when: false changed_when: false - name: Check NodeSource repository file presence ansible.builtin.stat: path: /etc/apt/sources.list.d/nodesource.list register: nodesource_list_stat when: node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - name: Read NodeSource repository file ansible.builtin.slurp: src: /etc/apt/sources.list.d/nodesource.list register: nodesource_list_slurp when: - node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - nodesource_list_stat.stat.exists | default(false) - name: Set NodeSource repository state ansible.builtin.set_fact: nodesource_repo_state: >- {{ 'not_exists' if not (nodesource_list_stat.stat.exists | default(false)) else ( 'correct_config' if ( (nodesource_list_slurp.content | b64decode) is search('^deb \\[signed-by=/etc/apt/keyrings/nodesource\\.gpg\\] https://deb\\.nodesource\\.com/node_22\\.x nodistro main', multiline=True) ) else 'wrong_config' ) }} when: node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - name: Check NodeSource GPG key presence ansible.builtin.stat: path: /etc/apt/keyrings/nodesource.gpg register: nodesource_key_stat when: node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - name: Remove incorrect NodeSource repository ansible.builtin.file: path: /etc/apt/sources.list.d/nodesource.list state: absent become: true when: - node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - nodesource_repo_state == "wrong_config" - name: Create keyrings directory ansible.builtin.file: path: /etc/apt/keyrings state: directory mode: '0755' become: true when: - node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - not (nodesource_key_stat.stat.exists | default(false)) - name: Import NodeSource GPG key into apt keyring ansible.builtin.shell: | # Ensure keyrings directory exists mkdir -p /etc/apt/keyrings # Download and convert key to binary format for signed-by curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg chmod 644 /etc/apt/keyrings/nodesource.gpg # Verify the key file is valid if ! file /etc/apt/keyrings/nodesource.gpg | grep -q "PGP"; then echo "ERROR: Key file is not valid PGP format" exit 1 fi args: creates: /etc/apt/keyrings/nodesource.gpg become: true when: - node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - not (nodesource_key_stat.stat.exists | default(false)) - name: Add NodeSource repository only if needed ansible.builtin.apt_repository: repo: "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" state: present update_cache: false become: true when: - node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22') - nodesource_repo_state in ["not_exists", "wrong_config"] - name: Install Node.js 22 from NodeSource ansible.builtin.apt: name: nodejs state: present become: true when: - (node_version_check.rc != 0 or not node_version_check.stdout.startswith('v22')) - name: Verify Node.js installation ansible.builtin.command: node --version register: final_node_version changed_when: false - name: Display Node.js version ansible.builtin.debug: msg: "Node.js version installed: {{ final_node_version.stdout if final_node_version.stdout is defined else 'Not checked in dry-run mode' }}"