├── COPYRIGHT ├── .gitignore ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── release-please.yml │ └── ci.yml ├── assets ├── add.png ├── dock.png ├── logo.gh-dark-mode-only.png ├── logo.gh-light-mode-only.png ├── pr-full-color-on-black.jpeg └── pr-full-color-on-white.jpeg ├── molecule ├── defaults-restored-over-ssh │ ├── defaults │ │ └── main.yml │ └── molecule.yml ├── defaults-restored-on-localhost │ ├── defaults │ │ └── main.yml │ └── molecule.yml ├── _partials │ ├── ssh_config │ ├── playbooks │ │ └── defaults-restored │ │ │ ├── verify.yml │ │ │ └── converge.yml │ ├── tasks │ │ └── setup.yml │ └── defaults │ │ └── main.yml └── default │ ├── defaults │ └── main.yml │ └── molecule.yml ├── .gitmodules ├── package.json ├── requirements.yml ├── .editorconfig ├── templates ├── remove.j2 ├── move.j2 └── add.j2 ├── .ansible-lint ├── .later.yml ├── tasks ├── validate-all.yml ├── install.yml ├── move.yml ├── add.yml ├── main.yml ├── validate-pos.yml └── remove.yml ├── pyproject.toml ├── meta └── main.yml ├── vars └── main.yml ├── defaults └── main.yml ├── .yamllint ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── Makefile ├── README.md ├── LICENSE └── poetry.lock /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (C) 2022 lotyp 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | */__pycache__ 3 | *.pyc 4 | .cache 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | github: wayofdev 4 | 5 | ... 6 | -------------------------------------------------------------------------------- /assets/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayofdev/ansible-role-dock/HEAD/assets/add.png -------------------------------------------------------------------------------- /assets/dock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayofdev/ansible-role-dock/HEAD/assets/dock.png -------------------------------------------------------------------------------- /molecule/defaults-restored-over-ssh/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | homebrew_collect_analytics: false 4 | 5 | ... 6 | -------------------------------------------------------------------------------- /molecule/defaults-restored-on-localhost/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | homebrew_collect_analytics: false 4 | 5 | ... 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "contrib/poetry-bin"] 2 | path = contrib/poetry-bin 3 | url = https://github.com/gi0baro/poetry-bin 4 | -------------------------------------------------------------------------------- /assets/logo.gh-dark-mode-only.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayofdev/ansible-role-dock/HEAD/assets/logo.gh-dark-mode-only.png -------------------------------------------------------------------------------- /assets/logo.gh-light-mode-only.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayofdev/ansible-role-dock/HEAD/assets/logo.gh-light-mode-only.png -------------------------------------------------------------------------------- /assets/pr-full-color-on-black.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayofdev/ansible-role-dock/HEAD/assets/pr-full-color-on-black.jpeg -------------------------------------------------------------------------------- /assets/pr-full-color-on-white.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wayofdev/ansible-role-dock/HEAD/assets/pr-full-color-on-white.jpeg -------------------------------------------------------------------------------- /molecule/_partials/ssh_config: -------------------------------------------------------------------------------- 1 | Host macos-12-vm 2 | Hostname 10.211.55.3 3 | User tester 4 | IdentityFile ~/.ssh/id_rsa 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.3.0", 3 | "repository": { 4 | "url": "https://github.com/wayofdev/ansible-role-dock.git" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | roles: 4 | - name: elliotweiser.osx-command-line-tools 5 | - name: wayofdev.homebrew 6 | 7 | collections: 8 | - name: community.general 9 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | version: 2 4 | updates: 5 | # Maintain dependencies for GitHub Actions 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | interval: "daily" 10 | 11 | ... 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.{yml,yaml,toml,py}] 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /templates/remove.j2: -------------------------------------------------------------------------------- 1 | {{ dock_dockutil_path }} 2 | {% for item in dock_dockitems_to_remove | flatten(levels=1) %} 3 | --{{ item.item.action }} '{{ item.item.label }}' 4 | {% if item.item.allhomes is defined and item.item.allhomes %}--allhomes{% endif %} 5 | {% endfor %} 6 | -------------------------------------------------------------------------------- /molecule/_partials/playbooks/defaults-restored/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Verify 4 | hosts: all 5 | gather_facts: false 6 | tasks: 7 | - name: Molecule | Verify | Load scenario variables 8 | include_vars: "../../defaults/main.yml" 9 | tags: 10 | - always 11 | ... 12 | -------------------------------------------------------------------------------- /.ansible-lint: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # https://ansible-lint.readthedocs.io/en/latest/configuring/ 4 | 5 | skip_list: 6 | - no-handler 7 | - experimental 8 | - command-instead-of-shell 9 | - risky-shell-pipe 10 | - line-length 11 | 12 | exclude_paths: 13 | - ./contrib 14 | - ./.venv 15 | 16 | ... 17 | -------------------------------------------------------------------------------- /molecule/default/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | homebrew_collect_analytics: false 4 | 5 | dock_dockitems_erase_all: true 6 | dock_dockitems: 7 | - label: Launchpad 8 | action: add 9 | path: /System/Applications/Launchpad.app 10 | 11 | - label: Safari 12 | action: add 13 | path: /Applications/Safari.app 14 | 15 | ... 16 | -------------------------------------------------------------------------------- /.later.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | ansible: 4 | 5 | # List of allowed literal bools (ANSIBLE0014) 6 | literal-bools: 7 | - "true" 8 | - "false" 9 | - "yes" 10 | - "no" 11 | 12 | # Global settings for all defined rules 13 | rules: 14 | # List of files to exclude 15 | exclude_files: 16 | - ./contrib 17 | - ./.venv 18 | 19 | version: "1.0" 20 | 21 | ... 22 | -------------------------------------------------------------------------------- /molecule/_partials/playbooks/defaults-restored/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Molecule | Converge | Restore all default items in dock 4 | hosts: all 5 | 6 | environment: 7 | - PATH: "/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin:{{ ansible_env.PATH }}" 8 | 9 | tasks: 10 | - name: Molecule | Converge | Include setup tasks 11 | ansible.builtin.include_tasks: "../../tasks/setup.yml" 12 | tags: 13 | - always 14 | ... 15 | -------------------------------------------------------------------------------- /templates/move.j2: -------------------------------------------------------------------------------- 1 | {{ dock_dockutil_path }} 2 | {% for item in dock_dockitems_to_move.results | flatten(levels=1) %} 3 | --{{ item.item.action }} {% if item.item.label is defined %}'{{ item.item.label }}'{% elif item.item.path is defined %}'{{ item.item.path }}'{% endif %} 4 | {% if item.item.position is defined %}--position {{ item.item.position }}{% endif %} 5 | {% if item.item.allhomes is defined and item.item.allhomes %}--allhomes{% endif %} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /tasks/validate-all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil - Validation | Make sure that dockitems array contains valid "{{ item_to_validate }}" items 4 | ansible.builtin.fail: 5 | msg: >- 6 | "{{ item_to_validate }}" can only be one of: "{{ validation_lists[item_to_validate] | join(', ') }}" 7 | loop: "{{ dock_dockitems | flatten(levels=1) }}" 8 | when: 9 | - item[item_to_validate] is defined and not item[item_to_validate] in validation_lists[item_to_validate] 10 | run_once: true 11 | tags: 12 | - dock-manipulate 13 | - dock-validate 14 | 15 | ... 16 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # https://github.com/google-github-actions/release-please-action#release-types-supported 4 | 5 | on: # yamllint disable-line rule:truthy 6 | push: 7 | branches: 8 | - master 9 | 10 | name: release-please 11 | 12 | jobs: 13 | release-please: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: google-github-actions/release-please-action@v3 17 | id: release 18 | with: 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | release-type: node 21 | package-name: ansible-role-dock 22 | default-branch: master 23 | 24 | ... 25 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependency: 4 | name: galaxy 5 | options: 6 | role-file: requirements.yml 7 | requirements-file: requirements.yml 8 | 9 | # Run locally 10 | driver: 11 | name: delegated 12 | options: 13 | managed: false 14 | ansible_connection_options: 15 | connection: local 16 | ansible_connection: local 17 | ansible_sudo_pass: "${ANSIBLE_SUDO_PASSWORD}" 18 | become_method: sudo 19 | 20 | platforms: 21 | - name: macos-12-vm 22 | 23 | provisioner: 24 | name: ansible 25 | playbooks: 26 | converge: "../_partials/playbooks/defaults-restored/converge.yml" 27 | verify: "../_partials/playbooks/defaults-restored/verify.yml" 28 | 29 | verifier: 30 | name: ansible 31 | 32 | ... 33 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ansible-role-dock" 3 | version = "0.0.0" 4 | description = "Role is used to automate use of dockutil – command line tool for managing dock items. You can add, remove and re-arrange Dock items." 5 | authors = ["lotyp "] 6 | license = "GPL-3.0-only" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | ansible = "^6.0.0" 11 | jmespath = "^1.0.1" 12 | 13 | [tool.poetry.dev-dependencies] 14 | molecule = "^4.0.0" 15 | ansible-compat = "^2.1.0" 16 | ansible-lint = "^6.3.0" 17 | yamllint = "^1.26.3" 18 | pre-commit = "^2.19.0" 19 | ansible-later = {extras = ["ansible"], version = "^2.0.16"} 20 | 21 | [build-system] 22 | requires = ["poetry-core>=1.0.0"] 23 | build-backend = "poetry.core.masonry.api" 24 | -------------------------------------------------------------------------------- /tasks/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil | Check if app is already installed 4 | ansible.builtin.command: dockutil -V 5 | register: dockutil_version_output 6 | ignore_errors: true 7 | changed_when: false 8 | tags: 9 | - dock-install 10 | 11 | - name: Dockutil | Should we install 12 | ansible.builtin.set_fact: 13 | dockutil_not_found: "{{ dockutil_version_output.rc > 0 }}" 14 | tags: 15 | - dock-install 16 | 17 | - name: Dockutil | Install for macOS using brew 18 | community.general.homebrew: 19 | name: "{{ dock_dockutil_tap }}" 20 | state: present 21 | update_homebrew: true 22 | path: "/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin" 23 | when: dockutil_not_found 24 | tags: 25 | - dock-install 26 | 27 | ... 28 | -------------------------------------------------------------------------------- /molecule/defaults-restored-on-localhost/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependency: 4 | name: galaxy 5 | options: 6 | role-file: requirements.yml 7 | requirements-file: requirements.yml 8 | 9 | # Run locally 10 | driver: 11 | name: delegated 12 | options: 13 | managed: false 14 | ansible_connection_options: 15 | connection: local 16 | ansible_connection: local 17 | ansible_sudo_pass: "${ANSIBLE_SUDO_PASSWORD}" 18 | become_method: sudo 19 | 20 | platforms: 21 | - name: instance 22 | 23 | provisioner: 24 | name: ansible 25 | playbooks: 26 | converge: "../_partials/playbooks/defaults-restored/converge.yml" 27 | verify: "../_partials/playbooks/defaults-restored/verify.yml" 28 | 29 | verifier: 30 | name: ansible 31 | 32 | ... 33 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | galaxy_info: 4 | role_name: dock 5 | author: wayofdev 6 | description: Role is used to automate use of "dockutil" – command line tool for managing dock items. You can add, remove and re-arrange Dock items. 7 | company: wayofdev 8 | 9 | license: GPL-3.0-only 10 | 11 | min_ansible_version: "2.12" 12 | 13 | platforms: 14 | - name: macOS 15 | versions: 16 | - Monterey 17 | - Big-Sur 18 | 19 | galaxy_tags: 20 | - dock 21 | - dockutil 22 | - mac 23 | - osx 24 | - mdm 25 | - provisioning 26 | - automation 27 | 28 | dependencies: [] 29 | 30 | # Ensure that custom Ansible plugins and modules included in the main MacOps 31 | # collection are available to roles in other collections. 32 | collections: ["wayofdev.macops"] 33 | 34 | ... 35 | -------------------------------------------------------------------------------- /molecule/_partials/tasks/setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Molecule | Setup | Load default variables 4 | ansible.builtin.include_vars: "../defaults/main.yml" 5 | tags: 6 | - always 7 | 8 | # - name: Molecule | Setup | Load scenario variables 9 | # ansible.builtin.include_vars: defaults/main.yml 10 | 11 | - name: Molecule | Setup | Include elliotweiser.osx-command-line-tools 12 | ansible.builtin.include_role: 13 | name: elliotweiser.osx-command-line-tools 14 | tags: 15 | - always 16 | 17 | - name: Molecule | Setup | Include wayofdev.homebrew 18 | ansible.builtin.include_role: 19 | name: wayofdev.homebrew 20 | tags: 21 | - always 22 | 23 | - name: Molecule | Setup | Include wayofdev.dock 24 | ansible.builtin.include_role: 25 | name: ansible-role-dock 26 | tags: 27 | - always 28 | 29 | ... 30 | -------------------------------------------------------------------------------- /templates/add.j2: -------------------------------------------------------------------------------- 1 | {{ dock_dockutil_path }} 2 | {% for item in dock_dockitems_to_add %} 3 | --{{ item.item.action }} '{{ item.item.path }}' 4 | {% if item.item.position is defined %}--position {{ item.item.position }}{% endif %} 5 | {% if item.item.replacing is defined and item.item.replacing | length %}--replacing '{{ item.item.replacing }}'{% endif %} 6 | {% if item.item.before is defined and item.item.before | length %}--before '{{ item.item.before }}'{% endif %} 7 | {% if item.item.after is defined and item.item.after | length %}--after '{{ item.item.after }}'{% endif %} 8 | {% if item.item.allhomes is defined and item.item.allhomes %}--allhomes{% endif %} 9 | {% if item.item.view is defined %}--view {{ item.item.view }}{% endif %} 10 | {% if item.item.display is defined %}--display {{ item.item.display }}{% endif %} 11 | {% endfor %} 12 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dock_dockutil_path: dockutil 4 | 5 | items_to_validate: 6 | - action 7 | - display 8 | - sort 9 | - section 10 | - view 11 | - type 12 | 13 | validation_lists: 14 | action: 15 | - add 16 | - remove 17 | - move 18 | 19 | display: 20 | - folder 21 | - stack 22 | 23 | sort: 24 | - name 25 | - dateadded 26 | - datemodified 27 | - datecreated 28 | - kind 29 | 30 | section: 31 | - apps 32 | - others 33 | 34 | view: 35 | - grid 36 | - fan 37 | - list 38 | - auto 39 | 40 | type: 41 | - spacer 42 | - small-spacer 43 | - flex-spacer 44 | 45 | position: 46 | - beginning 47 | - middle 48 | - end 49 | 50 | dock_dockitems_to_add: [] 51 | dock_dockitems_to_remove: [] 52 | dock_dockitems_to_move: [] 53 | 54 | ... 55 | -------------------------------------------------------------------------------- /molecule/defaults-restored-over-ssh/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | dependency: 4 | name: galaxy 5 | options: 6 | role-file: requirements.yml 7 | requirements-file: requirements.yml 8 | 9 | # Run against remote machine over SSH 10 | driver: 11 | name: delegated 12 | options: 13 | managed: false 14 | login_cmd_template: 'ssh {instance} -F /tmp/ssh_config' 15 | ansible_connection_options: 16 | connection: ssh 17 | ansible_ssh_common_args: '-F /tmp/ssh_config' 18 | ansible_sudo_pass: "${ANSIBLE_SUDO_PASSWORD}" 19 | become_method: sudo 20 | 21 | platforms: 22 | - name: macos-12-vm 23 | 24 | provisioner: 25 | name: ansible 26 | playbooks: 27 | converge: "../_partials/playbooks/defaults-restored/converge.yml" 28 | verify: "../_partials/playbooks/defaults-restored/verify.yml" 29 | 30 | verifier: 31 | name: ansible 32 | 33 | ... 34 | -------------------------------------------------------------------------------- /tasks/move.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil | Get information on items to move 4 | ansible.builtin.shell: "{{ dock_dockutil_path }} -f '{{ item.label }}'" 5 | register: dock_dockitems_to_move 6 | loop: "{{ dock_dockitems | selectattr('action', 'equalto', 'move') }}" 7 | changed_when: false 8 | failed_when: > 9 | "No such file or directory" in dock_dockitems_to_move.stdout 10 | or "command not found" in dock_dockitems_to_move.stdout 11 | or "was not found in" in dock_dockitems_to_move.stdout 12 | tags: 13 | - dock-move 14 | 15 | - name: Dockutil | Moving items 16 | ansible.builtin.shell: "{{ lookup('template', './templates/move.j2') | replace('\n', '') | trim }}" 17 | loop_control: 18 | label: "{{ item.item }}" 19 | changed_when: false 20 | when: dock_dockitems_to_move.results is defined and (dock_dockitems_to_move.results | length > 0) 21 | tags: 22 | - dock-move 23 | 24 | ... 25 | -------------------------------------------------------------------------------- /tasks/add.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil | Get information on items to add 4 | ansible.builtin.shell: "{{ dock_dockutil_path }} -f '{{ item.label }}'" 5 | register: to_add 6 | loop: "{{ dock_dockitems | selectattr('action', 'equalto', 'add') }}" 7 | changed_when: false 8 | failed_when: > 9 | "No such file or directory" in to_add.stdout 10 | or "command not found" in to_add.stdout 11 | tags: 12 | - dock-add 13 | 14 | - name: Dockutil | Filter out already added items 15 | ansible.builtin.set_fact: 16 | dock_dockitems_to_add: "{{ dock_dockitems_to_add | default([]) + [item] }}" 17 | loop: "{{ to_add.results | rejectattr('stdout', 'search', 'was found in') }}" 18 | tags: 19 | - dock-add 20 | 21 | - name: Dockutil | Adding items 22 | ansible.builtin.shell: "{{ lookup('template', './templates/add.j2') | replace('\n', '') | trim }}" 23 | loop_control: 24 | label: "{{ item.item }}" 25 | changed_when: false 26 | when: dock_dockitems_to_add is defined and (dock_dockitems_to_add | length > 0) 27 | tags: 28 | - dock-add 29 | 30 | ... 31 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Should we try to install dockutil? 4 | dock_dockutil_install: true 5 | 6 | # Path to custom or official tap of dockutil 7 | dock_dockutil_tap: lotyp/formulae/dockutil 8 | 9 | # Removes all contents from dock including "others" section with Downloads folder. 10 | # Prefer this option on new installations together with configured "dockitems". 11 | dock_dockitems_erase_all: true 12 | 13 | # Array of dockitems to add, move, or remove inside Dock 14 | dock_dockitems: [] 15 | # - label: System Preferences 16 | # action: add 17 | # path: /System/Applications/System Preferences.app 18 | # 19 | # - label: TextEdit 20 | # action: add 21 | # path: /System/Applications/TextEdit.app 22 | # 23 | # - label: Messages 24 | # action: add 25 | # path: /System/Applications/Messages.app 26 | # 27 | # - label: com.apple.mail 28 | # action: add 29 | # path: /System/Applications/Mail.app 30 | # before: Messages 31 | # 32 | # - label: News 33 | # action: add 34 | # path: /Applications/News.app 35 | # 36 | # - label: Reminders 37 | # action: add 38 | # path: /System/Applications/Reminders.app 39 | # after: TextEdit 40 | # 41 | # - label: News 42 | # action: remove 43 | 44 | ... 45 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil | Include | General validation tasks 4 | ansible.builtin.include_tasks: validate-all.yml 5 | loop: "{{ items_to_validate | flatten(levels=1) }}" 6 | loop_control: 7 | loop_var: item_to_validate 8 | tags: 9 | - dock-manipulate 10 | - dock-validate 11 | - dock-add 12 | - dock-remove 13 | - dock-move 14 | 15 | - name: Dockutil | Include | Other validation tasks 16 | ansible.builtin.include_tasks: validate-pos.yml 17 | tags: 18 | - dock-manipulate 19 | - dock-validate 20 | - dock-add 21 | - dock-remove 22 | - dock-move 23 | 24 | - name: Dockutil | Include | Install dockutil 25 | ansible.builtin.include_tasks: install.yml 26 | when: dock_dockutil_install | bool 27 | tags: 28 | - dock-install 29 | 30 | - name: Dockutil | Include | Remove items 31 | ansible.builtin.include_tasks: remove.yml 32 | tags: 33 | - dock-manipulate 34 | - dock-remove 35 | 36 | - name: Dockutil | Include | Add items 37 | ansible.builtin.include_tasks: add.yml 38 | tags: 39 | - dock-manipulate 40 | - dock-add 41 | 42 | - name: Dockutil | Include | Move items 43 | ansible.builtin.include_tasks: move.yml 44 | tags: 45 | - dock-manipulate 46 | - dock-move 47 | 48 | ... 49 | -------------------------------------------------------------------------------- /tasks/validate-pos.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil - Validation | Make sure that dockitems array contains valid "position" items 4 | ansible.builtin.fail: 5 | msg: >- 6 | "position" can only be one of: "{{ validation_lists.position | join(', ') }}" or [+/-]index_number (int) 7 | loop: "{{ dock_dockitems }}" 8 | when: 9 | - item.position is defined 10 | - not item.position | regex_search('([0-9]+|beginning|middle|end)') 11 | run_once: true 12 | tags: 13 | - dock-manipulate 14 | - dock-validate 15 | 16 | - name: Dockutil - Validation | Make sure that dockitems array contains path if action is add 17 | ansible.builtin.fail: 18 | msg: >- 19 | "path" must be present when you are trying to add item. Specify full path to app. 20 | loop: "{{ dock_dockitems }}" 21 | when: 22 | - item.action == 'add' 23 | - item.path is not defined 24 | run_once: true 25 | tags: 26 | - dock-manipulate 27 | - dock-validate 28 | 29 | - name: Dockutil - Validation | Make sure that each item contains label 30 | ansible.builtin.fail: 31 | msg: >- 32 | "label" must be defined. Please check documentation for more info. 33 | loop: "{{ dock_dockitems }}" 34 | when: 35 | - item.label is not defined 36 | run_once: true 37 | tags: 38 | - dock-manipulate 39 | - dock-validate 40 | 41 | ... 42 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | extends: default 4 | 5 | ignore: | 6 | contrib 7 | .venv 8 | 9 | # Overwrite above default rules 10 | rules: 11 | braces: 12 | # Defaults 13 | # min-spaces-inside: 0 14 | # max-spaces-inside: 0 15 | 16 | # Keep 0 min-spaces to not error on empty {} collection definitions 17 | min-spaces-inside: 0 18 | 19 | # Allow one space inside braces to improve code readability 20 | max-spaces-inside: 1 21 | 22 | brackets: 23 | # Defaults 24 | # min-spaces-inside: 0 25 | # max-spaces-inside: 0 26 | 27 | # Keep 0 min-spaces to not error on empty [] collection definitions 28 | min-spaces-inside: 0 29 | 30 | # Allow one space inside braces to improve code readability 31 | max-spaces-inside: 1 32 | 33 | colons: 34 | # Defaults 35 | # min-spaces-before: 0 36 | # max-spaces-after: 1 37 | 38 | # Allow multiple spaces after a colon to allow indentation of YAML 39 | # dictionary values 40 | max-spaces-after: -1 41 | 42 | commas: 43 | # Defaults 44 | # max-spaces-after: 1 45 | 46 | # Allow multiple spaces after a comma to allow indentation of YAML 47 | # dictionary values 48 | max-spaces-after: -1 49 | 50 | comments: 51 | require-starting-space: true 52 | min-spaces-from-content: 1 53 | 54 | line-length: disable 55 | 56 | ... 57 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.3.0 6 | hooks: 7 | - id: trailing-whitespace 8 | - id: end-of-file-fixer 9 | - id: check-added-large-files 10 | - id: fix-encoding-pragma 11 | 12 | - repo: https://github.com/adrienverge/yamllint 13 | rev: v1.26.3 14 | hooks: 15 | - id: yamllint 16 | files: \.(yaml|yml)$ 17 | types: [file, yaml] 18 | entry: yamllint --strict 19 | 20 | - repo: https://github.com/commitizen-tools/commitizen 21 | rev: v2.27.1 22 | hooks: 23 | - id: commitizen 24 | stages: 25 | - commit-msg 26 | 27 | - repo: https://github.com/ansible/ansible-lint 28 | rev: v6.3.0 29 | hooks: 30 | - id: ansible-lint 31 | entry: ansible-lint . --force-color 32 | pass_filenames: false 33 | always_run: true 34 | additional_dependencies: 35 | - .[community] 36 | 37 | - repo: https://github.com/robertdebock/pre-commit 38 | rev: v1.5.1 39 | hooks: 40 | - id: ansible_role_find_unused_variable 41 | - id: ansible_role_find_empty_files 42 | - id: ansible_role_find_empty_directories 43 | - id: ansible_role_fix_readability 44 | - id: ansible_role_find_undefined_handlers 45 | - id: ansible_role_find_unquoted_values 46 | 47 | ... 48 | -------------------------------------------------------------------------------- /tasks/remove.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Dockutil | Remove all dock items 4 | ansible.builtin.shell: "{{ dock_dockutil_path }} --remove all" 5 | register: removed_items_task 6 | when: dock_dockitems_erase_all | bool 7 | changed_when: false 8 | tags: 9 | - dock-manipulate 10 | - dock-remove 11 | 12 | - name: Dockutil | Get information on items to remove 13 | ansible.builtin.shell: "{{ dock_dockutil_path }} -f '{{ item.label }}'" 14 | register: to_remove 15 | loop: "{{ dock_dockitems | selectattr('action', 'equalto', 'remove') }}" 16 | changed_when: false 17 | failed_when: > 18 | "No such file or directory" in to_remove.stdout 19 | or "command not found" in to_remove.stdout 20 | tags: 21 | - dock-remove 22 | 23 | - name: Dockutil | Filter out already removed items 24 | ansible.builtin.set_fact: 25 | dock_dockitems_to_remove: "{{ dock_dockitems_to_remove + [item] }}" 26 | loop: "{{ to_remove.results | rejectattr('stdout', 'search', 'was not found in') }}" 27 | tags: 28 | - dock-remove 29 | vars: 30 | dock_dockitems_to_remove: [] 31 | 32 | - name: Dockutil | Removing items 33 | ansible.builtin.shell: "{{ lookup('template', './templates/remove.j2') | replace('\n', '') | trim }}" 34 | loop_control: 35 | label: "{{ item.item }}" 36 | changed_when: false 37 | when: dock_dockitems_to_remove is defined and (dock_dockitems_to_remove | length > 0) 38 | tags: 39 | - dock-remove 40 | 41 | ... 42 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [2.3.0](https://github.com/wayofdev/ansible-role-dock/compare/v2.2.0...v2.3.0) (2022-07-03) 4 | 5 | 6 | ### Features 7 | 8 | * updating py dependencies ([51f8a30](https://github.com/wayofdev/ansible-role-dock/commit/51f8a3015d7b6408cef37bb6c732abbad8491193)) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * dockutil not installing when using tags ([a4c21ca](https://github.com/wayofdev/ansible-role-dock/commit/a4c21ca7049f5c44ec0bc7b15e21825e89046fd0)) 14 | 15 | ## [2.2.0](https://github.com/wayofdev/ansible-role-dock/compare/v2.1.0...v2.2.0) (2022-06-29) 16 | 17 | 18 | ### Features 19 | 20 | * updating template code ([cf409e5](https://github.com/wayofdev/ansible-role-dock/commit/cf409e585dde483cda8579f4b8163cc22d05f334)) 21 | 22 | 23 | ### Bug Fixes 24 | 25 | * missing lock file ([06730fa](https://github.com/wayofdev/ansible-role-dock/commit/06730fafc55eb402271c0f8230cfcdd0d751c5b2)) 26 | 27 | ## [2.1.0](https://github.com/wayofdev/ansible-role-dock/compare/v2.0.0...v2.1.0) (2022-06-21) 28 | 29 | 30 | ### Features 31 | 32 | * moving to molecule tests ([6f13d69](https://github.com/wayofdev/ansible-role-dock/commit/6f13d6926515dd537243a9385d008c2eaf0bf760)) 33 | 34 | ## [2.0.0](https://github.com/wayofdev/ansible-role-dock/compare/v1.1.0...v2.0.0) (2022-06-19) 35 | 36 | 37 | ### Features 38 | 39 | * molecule tests improved, updated README.md ([a084ec5](https://github.com/wayofdev/ansible-role-dock/commit/a084ec5a740406c3e3c6dfc23028b2c791e44b02)) 40 | * refactoring code ([b6d6052](https://github.com/wayofdev/ansible-role-dock/commit/b6d6052916038e13a426713ee12d8506a44d4102)) 41 | 42 | 43 | ### Miscellaneous Chores 44 | 45 | * release 2.0.0 ([a22fe01](https://github.com/wayofdev/ansible-role-dock/commit/a22fe01bf9074516a738b09afec7e516bdd55cca)) 46 | -------------------------------------------------------------------------------- /molecule/_partials/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | homebrew_collect_analytics: false 4 | 5 | dock_dockitems_erase_all: true 6 | dock_dockitems: 7 | - label: Launchpad 8 | action: add 9 | path: /System/Applications/Launchpad.app 10 | 11 | - label: Safari 12 | action: add 13 | path: /Applications/Safari.app 14 | 15 | - label: Messages 16 | action: add 17 | path: /System/Applications/Messages.app 18 | 19 | - label: Mail 20 | action: add 21 | path: /System/Applications/Mail.app 22 | 23 | - label: Maps 24 | action: add 25 | path: /System/Applications/Maps.app 26 | 27 | - label: Photos 28 | action: add 29 | path: /System/Applications/Photos.app 30 | 31 | - label: FaceTime 32 | action: add 33 | path: /System/Applications/FaceTime.app 34 | 35 | - label: Calendar 36 | action: add 37 | path: /System/Applications/Calendar.app 38 | 39 | - label: Contacts 40 | action: add 41 | path: /System/Applications/Contacts.app 42 | 43 | - label: Reminders 44 | action: add 45 | path: /System/Applications/Reminders.app 46 | 47 | - label: Notes 48 | action: add 49 | path: /System/Applications/Notes.app 50 | 51 | - label: TV 52 | action: add 53 | path: /System/Applications/TV.app 54 | 55 | - label: Music 56 | action: add 57 | path: /System/Applications/Music.app 58 | 59 | - label: Podcasts 60 | action: add 61 | path: /System/Applications/Podcasts.app 62 | 63 | - label: News 64 | action: add 65 | path: /System/Applications/News.app 66 | 67 | - label: App Store 68 | action: add 69 | path: /System/Applications/App Store.app 70 | 71 | - label: System Preferences 72 | action: add 73 | path: /System/Applications/System Preferences.app 74 | 75 | ... 76 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ### 2 | ### Variables 3 | ### 4 | 5 | export ANSIBLE_FORCE_COLOR = 1 6 | export PY_COLORS = 1 7 | export PYTHONIOENCODING = UTF-8 8 | export LC_CTYPE = en_US.UTF-8 9 | export LANG = en_US.UTF-8 10 | 11 | # https://serverfault.com/questions/1031491/display-ansible-playbook-output-properly-formatted 12 | # https://stackoverflow.com/questions/50009505/ansible-stdout-formatting 13 | export ANSIBLE_STDOUT_CALLBACK = unixy 14 | 15 | TASK_TAGS ?= "dock-validate,dock-install,dock-manipulate,dock-add,dock-remove,dock-move" 16 | REQS ?= requirements.yml 17 | INSTALL_POETRY ?= true 18 | POETRY_BIN ?= poetry 19 | POETRY_RUNNER ?= poetry run 20 | ANSIBLE_LATER_BIN = ansible-later 21 | 22 | # leave empty to disable 23 | # -v - verbose; 24 | # -vv - more details 25 | # -vvv - enable connection debugging 26 | DEBUG_VERBOSITY ?= -vvv 27 | 28 | ### Lint yaml files 29 | lint: later 30 | $(POETRY_RUNNER) yamllint . 31 | $(POETRY_RUNNER) ansible-lint . --force-color 32 | .PHONY: lint 33 | 34 | ### Run tests 35 | m-local: 36 | $(POETRY_RUNNER) molecule test --scenario-name defaults-restored-on-localhost -- $(DEBUG_VERBOSITY) --tags $(TASK_TAGS) 37 | .PHONY: m-local 38 | 39 | m-remote: 40 | $(POETRY_RUNNER) molecule test --scenario-name defaults-restored-over-ssh -- $(DEBUG_VERBOSITY) --tags $(TASK_TAGS) 41 | .PHONY: m-remote 42 | 43 | login-mac: 44 | $(POETRY_RUNNER) molecule login \ 45 | --host macos-12-vm \ 46 | --scenario-name defaults-restored-over-ssh 47 | .PHONY: login-mac 48 | 49 | debug-version: 50 | $(POETRY_RUNNER) ansible --version 51 | .PHONY: debug-version 52 | 53 | later: 54 | $(POETRY_RUNNER) $(ANSIBLE_LATER_BIN) **/*.yml 55 | .PHONY: later 56 | 57 | ### Install ansible dependencies 58 | install: install-poetry install-deps 59 | .PHONY: install 60 | 61 | install-deps: 62 | $(POETRY_BIN) install 63 | $(POETRY_RUNNER) ansible-galaxy install -r $(REQS) 64 | .PHONY: install-deps 65 | 66 | install-poetry: 67 | ifeq ($(INSTALL_POETRY),true) 68 | sudo sh contrib/poetry-bin/install.sh 69 | else 70 | @echo "Poetry installation disabled by global variable! Exiting..." 71 | @exit 0 72 | endif 73 | .PHONY: install-poetry 74 | 75 | ### Git 76 | hooks: 77 | $(POETRY_RUNNER) pre-commit install 78 | $(POETRY_RUNNER) pre-commit autoupdate 79 | .PHONY: hooks 80 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: ci 4 | 5 | on: # yamllint disable-line rule:truthy 6 | push: 7 | branches: 8 | - master 9 | pull_request: 10 | branches: 11 | - master 12 | workflow_dispatch: 13 | inputs: 14 | shouldPublish: 15 | description: 'Should publish role to Ansible Galaxy? (yes/no)' 16 | required: false 17 | default: 'no' 18 | 19 | jobs: 20 | lint: 21 | name: Lint 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Check out the codebase 25 | uses: actions/checkout@v3 26 | 27 | - name: Setup python 28 | uses: actions/setup-python@v4 29 | with: 30 | python-version: '3.9' 31 | 32 | - name: Install poetry into system 33 | uses: gi0baro/setup-poetry-bin@v1 34 | with: 35 | virtualenvs-in-project: true 36 | 37 | - name: Load cached .venv 38 | id: cached-poetry-dependencies 39 | uses: actions/cache@v3 40 | with: 41 | path: .venv 42 | key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}-${{ hashFiles('**/requirements.yml') }} 43 | 44 | - name: Install dependencies 45 | if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' 46 | run: make install-deps 47 | 48 | - name: Run linting tasks 49 | run: make lint 50 | 51 | integration-macos-molecule: 52 | name: Integration on macOS 53 | runs-on: ${{ matrix.os }} 54 | strategy: 55 | max-parallel: 4 56 | matrix: 57 | os: ["macos-12"] 58 | scenario: ["defaults-restored-on-localhost"] 59 | 60 | steps: 61 | - name: Check out the codebase 62 | uses: actions/checkout@v3 63 | with: 64 | submodules: true 65 | 66 | - name: Check out the actions/cache source 67 | uses: actions/checkout@v3 68 | with: 69 | repository: actions/cache 70 | ref: v3 71 | path: .tmp/actions/cache 72 | 73 | - name: Check out fix - make actions/cache@v3 run always, not only when job succeeds 74 | run: | 75 | sed -i -e '/ post-if: /d' .tmp/actions/cache/action.yml 76 | 77 | - name: Install poetry into system 78 | uses: gi0baro/setup-poetry-bin@v1 79 | with: 80 | virtualenvs-in-project: true 81 | 82 | - name: Load cached .venv 83 | id: cached-poetry-dependencies 84 | uses: ./.tmp/actions/cache 85 | with: 86 | path: .venv 87 | key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}-${{ hashFiles('**/requirements.yml') }} 88 | 89 | - name: Install dependencies 90 | if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' 91 | run: make install-deps 92 | 93 | - name: Test the playbook with molecule 94 | run: poetry run molecule test --scenario-name "${SCENARIO}" -- -v 95 | env: 96 | SCENARIO: ${{ matrix.scenario }} 97 | PY_COLORS: '1' 98 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 99 | 100 | publish: 101 | if: github.event.inputs.shouldPublish == 'yes' || github.ref == 'refs/heads/master' 102 | needs: 103 | - lint 104 | - integration-macos-molecule 105 | runs-on: ubuntu-latest 106 | steps: 107 | - name: Publish to Ansible Galaxy 108 | uses: robertdebock/galaxy-action@1.2.1 109 | with: 110 | galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} 111 | 112 | ... 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 |
7 | 8 |
9 | 10 |
11 | 12 |
13 | Build Status 14 | Ansible Role 15 | Latest Version 16 | Ansible Quality Score 17 | Ansible Role 18 | Software License 19 | Commits since latest release 20 |
21 | 22 |
23 | 24 | # Ansible Role: macOS Dock Automation 25 | 26 | Role is used to automate use of [dockutil](https://github.com/kcrawford/dockutil) – command line tool for managing Dock items. You can add, remove and re-arrange Dock items. 27 | 28 | If you **like/use** this role, please consider **starring** it. Thanks! 29 | 30 |
31 | 32 | ## 🗂 Table of contents 33 | 34 | * [Benefits of this role](#-benefits-of-this-role) 35 | * [Requirements](#-requirements) 36 | * [Role Variables](#-role-variables) 37 | * [Structure](#-structure) 38 | * [Adding](#-adding) 39 | * [Adding with Replace](#-adding-with-replace) 40 | * [Adding folders](#-adding-folders) 41 | * [Removing](#-removing) 42 | * [Moving](#-moving) 43 | * [Example Playbook](#-example-playbook) 44 | * [Development](#-development) 45 | * [Testing](#-testing) 46 | * [on localhost](#-on-localhost) 47 | * [over SSH](#-over-ssh) 48 | * [Dependencies](#-dependencies) 49 | * [Compatibility](#-compatibility) 50 | * [License](#-license) 51 | * [Author Information](#-author-information) 52 | * [Credits and Resources](#-credits-and-resources) 53 | * [Contributors](#-contributors) 54 | * [Sponsors](#-sponsors) 55 | 56 |
57 | 58 | ## ⭐️ Benefits of this role: 59 | 60 | * This version supports latest 3.x [dockutil](https://github.com/kcrawford/dockutil) 61 | * Items are added, positioned and removed in single command run instead of loops 62 | * Latest macOS Monterey support 63 | * Can erase all items contained in Dock with one setting 64 | * No need for ansible handlers and sudo rights to do `killall` to restart Dock, as it is handled by `dockutil` by itself! 65 | * Supports all `dockutil` options, like: 66 | `--add, --remove, --move, --replacing, --position, --after, --before, --section, --allhomes, --sort, --display, --view` 67 | 68 |
69 | 70 | ## 📑 Requirements 71 | 72 | - **Homebrew**: Requires `homebrew` already installed (you can use `wayofdev.homebrew` to install it on your macOS). 73 | - Up-to-date version of ansible. During maintenance/development, we stick to ansible versions and will use new features if they are available (and update `meta/main.yml` for the minimum version). 74 | - Compatible OS. See [compatibility](#-compatibility) table. 75 | - Role has dependencies on third-party roles on different operating systems. See `requirements.yml` and [dependencies](#-dependencies) section. 76 | 77 |
78 | 79 | ## 🔧 Role Variables 80 | 81 | Section shows all possible variants of adding, moving, replacing and removing of applications, spacers, folders. Available variables are listed below, along with example values (see `defaults/main.yml`): 82 | 83 |
84 | 85 | ### → Structure 86 | 87 | Group controls installation of dockutil, and allows to select custom tap: 88 | 89 | ```yaml 90 | # Should we try to install dockutil? 91 | dock_dockutil_install: # (default: true) Install dockutil using homebrew. 92 | 93 | # Path to custom or official tap of dockutil 94 | dock_dockutil_tap: lotyp/formulae/dockutil # By default, 3.x tap is used 95 | ``` 96 | 97 | Role allows to wipe macOS dock completely: 98 | 99 | ```yaml 100 | # Removes all contents from dock including "others" section with Downloads folder. 101 | # Prefer this option on new installations together with configured "dockitems". 102 | dock_dockitems_erase_all: # Whether to attempt to erase all items in Dock including Downloads folder! (default: false) 103 | ``` 104 | 105 | Variable structure to add, move, or remove items in Dock: 106 | 107 | ```yaml 108 | dock_dockitems: 109 | - label: