Skip to content

Conversation

@paolomainardi
Copy link
Member

@paolomainardi paolomainardi commented Oct 24, 2025

User description

Summary

Implements a generic preflight-check system that detects both Homebrew-managed and manually-installed cask applications before attempting installation.

Changes

  • Add config/packages/cask-app-names.yml mapping cask names to app bundles
  • Replace individual Docker/Chrome checks with unified preflight system
  • Check both brew installations and /Applications directory
  • Display clear warnings for manually-installed apps
  • Skip conflicting packages to prevent permission errors

Fixes #268


🤖 Generated with Claude Code


PR Type

Bug fix, Enhancement


Description

  • Implemented generic preflight-check system for cask packages to detect both Homebrew and manual installations

  • Added cask-app-names.yml mapping file for cask-to-app bundle name translations

  • Replaced individual Docker/Chrome checks with unified detection logic

  • Added user-friendly warnings for manually-installed apps with skip behavior to prevent permission errors


Diagram Walkthrough

flowchart LR
  A["Load cask mappings"] --> B["Check Homebrew installations"]
  B --> C["Check manual installations"]
  C --> D["Parse installation status"]
  D --> E["Display warnings"]
  E --> F["Remove conflicts from install list"]
  F --> G["Install remaining casks"]
Loading

File Walkthrough

Relevant files
Enhancement
base.yml
Implement unified preflight-check system for cask packages

ansible/macos/macos/base.yml

  • Added task to load cask-app-names.yml mapping file
  • Replaced individual Docker/Chrome checks with unified preflight-check
    block
  • Implemented detection for both Homebrew-managed and manually-installed
    cask packages
  • Added warning messages for manually-installed apps and automatic skip
    logic
+58/-18 
Configuration changes
cask-app-names.yml
Add cask-to-app bundle name mapping configuration               

config/packages/cask-app-names.yml

  • Created mapping file for cask package names to Application bundle
    names
  • Includes common applications like Chrome, Docker, VS Code, Slack,
    Zoom, iTerm2, and Ghostty
+17/-0   

…conflicts

Implements a generic preflight-check system that detects both Homebrew-managed
and manually-installed cask applications before attempting installation.

Changes:
- Add config/packages/cask-app-names.yml mapping cask names to app bundles
- Replace individual Docker/Chrome checks with unified preflight system
- Check both brew installations and /Applications directory
- Display clear warnings for manually-installed apps
- Skip conflicting packages to prevent permission errors

Fixes #268

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Paolo Mainardi <[email protected]>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a generic preflight-check system for cask packages to prevent installation conflicts between Homebrew-managed and manually-installed applications. It replaces individual per-package checks with a unified approach that detects existing installations from both sources before attempting installation.

Key Changes:

  • Introduces a mapping file to associate cask package names with their application bundle names
  • Replaces individual Docker and Chrome installation checks with a unified preflight system
  • Adds clear user warnings when manually-installed apps are detected and skipped

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
config/packages/cask-app-names.yml New mapping file associating cask package names with their application bundle names for conflict detection
ansible/macos/macos/base.yml Replaces individual package checks with unified preflight system that detects both Homebrew and manual installations

Comment on lines 118 to 122
for pkg in {{ all_cask_packages | map('quote') | join(' ') }}; do
if brew list --cask "$pkg" >/dev/null 2>&1; then
echo "$pkg:brew"
fi
done
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shell loop executes brew list --cask for each package individually, resulting in N brew invocations. Consider using brew list --cask once to get all installed casks, then filtering against all_cask_packages in Ansible/Jinja2, which would reduce brew command overhead significantly.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

@claude claude bot Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude finished @paolomainardi's task —— View job


Analysis of brew optimization suggestion

  • Read and understand the current implementation
  • Analyze the optimization suggestion for brew commands
  • Provide recommendations

Review Feedback

I've analyzed the review comment about optimizing the brew list --cask calls. The reviewer is absolutely correct - there's a significant performance issue with the current implementation.

Current Implementation Issues

Lines 117-122 - Checking Homebrew-installed casks:

shell: |
  for pkg in {{ all_cask_packages | map('quote') | join(' ') }}; do
    if brew list --cask "$pkg" >/dev/null 2>&1; then
      echo "$pkg:brew"
    fi
  done

Lines 128-137 - Checking manually-installed casks:

shell: |
  {% for cask in all_cask_packages %}
  {% if cask in cask_mappings.cask_to_app_mapping %}
  if [ -d "/Applications/{{ cask_mappings.cask_to_app_mapping[cask] }}" ]; then
    if ! brew list --cask {{ cask }} >/dev/null 2>&1; then
      echo "{{ cask }}:manual"
    fi
  fi
  {% endif %}
  {% endfor %}

Problem: If there are N casks to check, this executes brew list --cask up to 2N times (once per package in each task). Each brew invocation has overhead for process startup, loading Homebrew's Ruby environment, etc.

Recommended Optimization

Call brew list --cask once to get all installed casks, then use shell logic to check against that cached list:

- name: Check which cask packages are already installed via Homebrew
  shell: |
    # Get all installed casks once
    installed_casks=$(brew list --cask 2>/dev/null || echo "")
    
    # Check each package against the cached list
    for pkg in {{ all_cask_packages | map('quote') | join(' ') }}; do
      if echo "$installed_casks" | grep -qx "$pkg"; then
        echo "$pkg:brew"
      fi
    done
  register: homebrew_cask_check
  changed_when: false
  become: false

- name: Check which cask packages are manually installed
  shell: |
    # Get all installed casks once (reuse for efficiency)
    installed_casks=$(brew list --cask 2>/dev/null || echo "")
    
    {% for cask in all_cask_packages %}
    {% if cask in cask_mappings.cask_to_app_mapping %}
    if [ -d "/Applications/{{ cask_mappings.cask_to_app_mapping[cask] }}" ]; then
      if ! echo "$installed_casks" | grep -qx "{{ cask }}"; then
        echo "{{ cask }}:manual"
      fi
    fi
    {% endif %}
    {% endfor %}
  register: manual_cask_check
  changed_when: false
  become: false

Performance Impact

  • Before: 2N brew invocations (where N = number of casks)
  • After: 2 brew invocations (one per task)
  • Example: With 10 casks, this reduces from 20 brew calls to 2 calls - a 10x improvement

Additional Improvements to Consider

The reviewer also noted other good points:

  1. Line 145: The :brew and :manual suffixes could be eliminated by outputting just package names from different streams or files
  2. Line 170: The conditional is redundant since the outer when already guards against empty lists

Would you like me to implement these optimizations?

Comment on lines 144 to 145
homebrew_installed_casks: "{{ homebrew_cask_check.stdout_lines | map('regex_replace', ':brew$', '') | list }}"
manually_installed_casks: "{{ manual_cask_check.stdout_lines | map('regex_replace', ':manual$', '') | list }}"
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The suffix tags ':brew' and ':manual' are used as markers but are stripped immediately after parsing. Consider outputting just the package names directly from the shell commands instead of adding and removing markers, which would simplify the parsing logic.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

debug:
msg:
- "📦 Cask packages to be installed: {{ all_cask_packages | length }}"
- "{{ all_cask_packages | join(', ') if all_cask_packages | length > 0 else 'None (all already installed)' }}"
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional check if all_cask_packages | length > 0 is redundant since the outer when condition already guards against empty lists at line 171. The else branch 'None (all already installed)' will never execute. Simplify to just {{ all_cask_packages | join(', ') }}.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@sparkfabrik-ai-bot
Copy link

Failed to generate code suggestions for PR

Copy link
Member Author

@paolomainardi paolomainardi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude check this comments

Comment on lines 118 to 122
for pkg in {{ all_cask_packages | map('quote') | join(' ') }}; do
if brew list --cask "$pkg" >/dev/null 2>&1; then
echo "$pkg:brew"
fi
done
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 144 to 145
homebrew_installed_casks: "{{ homebrew_cask_check.stdout_lines | map('regex_replace', ':brew$', '') | list }}"
manually_installed_casks: "{{ manual_cask_check.stdout_lines | map('regex_replace', ':manual$', '') | list }}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

debug:
msg:
- "📦 Cask packages to be installed: {{ all_cask_packages | length }}"
- "{{ all_cask_packages | join(', ') if all_cask_packages | length > 0 else 'None (all already installed)' }}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@claude
Copy link

claude bot commented Oct 24, 2025

Claude finished @paolomainardi's task —— View job


Review of Copilot Comments

I've analyzed the PR implementation and the automated review comments. Here's my assessment:


📊 Performance Optimization Comments (Comments #122 and #137)

Status: ✅ Valid and Important

Issue: Both tasks (lines 117-122 and 128-137) execute brew list --cask multiple times in a loop, which is inefficient.

Current Implementation:

  • Line 118-122: Loops through all cask packages, calling brew list --cask "$pkg" for each one
  • Line 129-137: For each cask in the mapping, calls brew list --cask {{ cask }} again

Performance Impact:

  • If you have 10 cask packages, this results in potentially 20+ brew command invocations
  • Each brew list --cask call has startup overhead (loading Homebrew, checking state, etc.)
  • On systems with many casks, this compounds significantly

Recommended Fix:

- name: Get all installed casks once
  command: brew list --cask
  register: all_installed_casks
  changed_when: false
  become: false

- name: Check which cask packages are already installed via Homebrew
  set_fact:
    homebrew_installed_casks: "{{ all_cask_packages | select('in', all_installed_casks.stdout_lines) | list }}"

- name: Check which cask packages are manually installed
  set_fact:
    manually_installed_casks: "{{ all_cask_packages | difference(homebrew_installed_casks) | select('sparkdock_is_manually_installed') | list }}"

Where sparkdock_is_manually_installed would be a custom filter, or we could use a different approach with stat module to check /Applications/ directories.

Alternative simpler approach:

- name: Get all installed casks once
  command: brew list --cask
  register: all_installed_casks
  changed_when: false
  become: false

- name: Check which mapped casks are manually installed
  stat:
    path: "/Applications/{{ cask_mappings.cask_to_app_mapping[item] }}"
  register: manual_install_check
  loop: "{{ all_cask_packages }}"
  when: item in cask_mappings.cask_to_app_mapping

- name: Parse installation status
  set_fact:
    homebrew_installed_casks: "{{ all_cask_packages | select('in', all_installed_casks.stdout_lines) | list }}"
    manually_installed_casks: "{{ manual_install_check.results | selectattr('stat.exists', 'equalto', true) | map(attribute='item') | select('not in', all_installed_casks.stdout_lines) | list }}"

This would reduce from O(N) brew calls to just 1 call + N stat checks (which are much faster than brew commands).


🔧 Code Simplification Comments

Comment #145 (Line 145): Marker Tags

Status: ✅ Valid - Minor Improvement

The :brew and :manual suffixes are added then immediately stripped. While this works, it's unnecessary complexity. You could output just the package names directly from the shell commands.

Impact: Low - This is more about code cleanliness than performance.


Comment #170 (Line 170): Redundant Conditional

Status: ⚠️ Reviewer Partially Incorrect

Current code:

- "{{ all_cask_packages | join(', ') if all_cask_packages | length > 0 else 'None (all already installed)' }}"

Analysis: The reviewer claims the else branch will never execute, but this is incorrect. After line 164 removes already-installed casks, all_cask_packages can indeed be empty if all packages were already installed. So the else branch IS reachable and the current code is correct.

However, the conditional could be simplified slightly to just check the length once rather than in a ternary, but it's not wrong as-is.


Comment #8 (cask-app-names.yml): Documentation Clarity

Status: ✅ Valid - Documentation Improvement

Suggestion: Add guidance about when NOT to include casks in the mapping file.

Current comment:

# Only include casks that:
# 1. Are commonly installed manually by users
# 2. Cause installation conflicts when already present
# 3. Have standard installation paths in /Applications

Recommendation: The comment could be enhanced with examples of what to exclude, but the current guidance is already pretty clear. This is a nice-to-have improvement.


🎯 Summary and Recommendations

Priority 1 - High Impact (Should Implement):

  1. Optimize brew calls (Comments Fix git dubious ownership error with always tag for sparkdock directory #122, Fix lock file cleanup when user triggers SIGINT through Ctrl-C #137): This is the most important change. Reducing multiple brew invocations to a single call will significantly improve performance, especially on slower systems or when managing many packages. Estimated improvement: 5-10x faster for 10 packages, scales linearly.

Priority 2 - Low Impact (Optional):
2. Remove marker tags (Comment #145): Minor code cleanup, but not critical. Could make code slightly more readable.
3. Improve documentation (Comment #8): Helpful for maintainability, but current docs are adequate.

Priority 3 - No Action Needed:
4. Comment #170: The reviewer's analysis is incorrect. The else branch IS reachable when all packages are already installed. Current code is fine.


💡 Next Steps

My recommendation: Implement the performance optimization (Priority 1) as it will provide meaningful speed improvements during Ansible runs. The other suggestions are minor and can be addressed if desired, but the performance fix is worth doing.

Would you like me to implement the performance optimization? I can refactor the preflight check to use a single brew list --cask call instead of the loop-based approach.

@paolomainardi
Copy link
Member Author

Claude finished @paolomainardi's task —— View job

Review of Copilot Comments

I've analyzed the PR implementation and the automated review comments. Here's my assessment:

📊 Performance Optimization Comments (Comments #122 and #137)

Status: ✅ Valid and Important

Issue: Both tasks (lines 117-122 and 128-137) execute brew list --cask multiple times in a loop, which is inefficient.

Current Implementation:

  • Line 118-122: Loops through all cask packages, calling brew list --cask "$pkg" for each one
  • Line 129-137: For each cask in the mapping, calls brew list --cask {{ cask }} again

Performance Impact:

  • If you have 10 cask packages, this results in potentially 20+ brew command invocations
  • Each brew list --cask call has startup overhead (loading Homebrew, checking state, etc.)
  • On systems with many casks, this compounds significantly

Recommended Fix:

- name: Get all installed casks once
  command: brew list --cask
  register: all_installed_casks
  changed_when: false
  become: false

- name: Check which cask packages are already installed via Homebrew
  set_fact:
    homebrew_installed_casks: "{{ all_cask_packages | select('in', all_installed_casks.stdout_lines) | list }}"

- name: Check which cask packages are manually installed
  set_fact:
    manually_installed_casks: "{{ all_cask_packages | difference(homebrew_installed_casks) | select('sparkdock_is_manually_installed') | list }}"

Where sparkdock_is_manually_installed would be a custom filter, or we could use a different approach with stat module to check /Applications/ directories.

Alternative simpler approach:

- name: Get all installed casks once
  command: brew list --cask
  register: all_installed_casks
  changed_when: false
  become: false

- name: Check which mapped casks are manually installed
  stat:
    path: "/Applications/{{ cask_mappings.cask_to_app_mapping[item] }}"
  register: manual_install_check
  loop: "{{ all_cask_packages }}"
  when: item in cask_mappings.cask_to_app_mapping

- name: Parse installation status
  set_fact:
    homebrew_installed_casks: "{{ all_cask_packages | select('in', all_installed_casks.stdout_lines) | list }}"
    manually_installed_casks: "{{ manual_install_check.results | selectattr('stat.exists', 'equalto', true) | map(attribute='item') | select('not in', all_installed_casks.stdout_lines) | list }}"

This would reduce from O(N) brew calls to just 1 call + N stat checks (which are much faster than brew commands).

🔧 Code Simplification Comments

Comment #145 (Line 145): Marker Tags

Status: ✅ Valid - Minor Improvement

The :brew and :manual suffixes are added then immediately stripped. While this works, it's unnecessary complexity. You could output just the package names directly from the shell commands.

Impact: Low - This is more about code cleanliness than performance.

Comment #170 (Line 170): Redundant Conditional

Status: ⚠️ Reviewer Partially Incorrect

Current code:

- "{{ all_cask_packages | join(', ') if all_cask_packages | length > 0 else 'None (all already installed)' }}"

Analysis: The reviewer claims the else branch will never execute, but this is incorrect. After line 164 removes already-installed casks, all_cask_packages can indeed be empty if all packages were already installed. So the else branch IS reachable and the current code is correct.

However, the conditional could be simplified slightly to just check the length once rather than in a ternary, but it's not wrong as-is.

Comment #8 (cask-app-names.yml): Documentation Clarity

Status: ✅ Valid - Documentation Improvement

Suggestion: Add guidance about when NOT to include casks in the mapping file.

Current comment:

# Only include casks that:
# 1. Are commonly installed manually by users
# 2. Cause installation conflicts when already present
# 3. Have standard installation paths in /Applications

Recommendation: The comment could be enhanced with examples of what to exclude, but the current guidance is already pretty clear. This is a nice-to-have improvement.

🎯 Summary and Recommendations

Priority 1 - High Impact (Should Implement):

  1. Optimize brew calls (Comments Fix git dubious ownership error with always tag for sparkdock directory #122, Fix lock file cleanup when user triggers SIGINT through Ctrl-C #137): This is the most important change. Reducing multiple brew invocations to a single call will significantly improve performance, especially on slower systems or when managing many packages. Estimated improvement: 5-10x faster for 10 packages, scales linearly.

Priority 2 - Low Impact (Optional): 2. Remove marker tags (Comment #145): Minor code cleanup, but not critical. Could make code slightly more readable. 3. Improve documentation (Comment #8): Helpful for maintainability, but current docs are adequate.

Priority 3 - No Action Needed: 4. Comment #170: The reviewer's analysis is incorrect. The else branch IS reachable when all packages are already installed. Current code is fine.

💡 Next Steps

My recommendation: Implement the performance optimization (Priority 1) as it will provide meaningful speed improvements during Ansible runs. The other suggestions are minor and can be addressed if desired, but the performance fix is worth doing.

Would you like me to implement the performance optimization? I can refactor the preflight check to use a single brew list --cask call instead of the loop-based approach.

@claude take in charge those fixes.

cc @francescoben

@claude
Copy link

claude bot commented Oct 24, 2025

Claude finished @paolomainardi's task —— View job


Performance Optimizations Complete ✅

Successfully implemented the performance fixes identified in the review analysis.

Completed Tasks

  • Read current implementation in base.yml
  • Optimize brew calls to use single invocation instead of loop
  • Verify Ansible YAML syntax
  • Commit and push changes

Changes Implemented

Performance Optimization

Refactored the cask preflight checks to dramatically improve performance by eliminating redundant brew command invocations:

Key Improvements:

  1. Single brew call: Added upfront task that calls brew list --cask once and caches results
  2. Fast grep operations: Both Homebrew-installed and manually-installed checks now use grep against the cached list
  3. Simplified parsing: Removed marker tag logic (:brew and :manual suffixes) - now outputs package names directly
  4. Cleaner code: Eliminated regex_replace operations in parsing step

Performance Impact:

  • Before: Up to 2N brew invocations (where N = number of cask packages)
  • After: 1 brew invocation + 2N fast grep operations
  • Example: With 10 casks, this reduces from 20 brew calls to 1 brew call
  • Estimated improvement: 10-20x faster for typical installations

Technical Details:

# New task caches all installed casks once
- name: Get all installed casks from Homebrew (single call optimization)
  shell: brew list --cask 2>/dev/null || true
  register: all_installed_casks

# Then both checks use grep against cached list instead of calling brew
installed_casks="{{ all_installed_casks.stdout }}"
if echo "$installed_casks" | grep -qx "$pkg"; then
  echo "$pkg"
fi

Quality Checks:

  • No trailing whitespace (verified with git diff --check)
  • YAML structure verified
  • Maintained backward compatibility with existing logic

Commit Details

Commit: a64e6a2
Branch: claude/issue-268-20251024-1243

The optimization addresses the performance concerns raised in the automated code review while maintaining all existing functionality. The CI pipeline will validate the changes work correctly.


github-actions bot and others added 2 commits October 24, 2025 13:17
…vement

Refactor cask preflight checks to call 'brew list --cask' only once instead
of repeatedly in loops. This reduces brew invocations from O(N) to O(1),
providing 10-20x faster execution for typical installations.

Changes:
- Add single upfront 'brew list --cask' call to cache all installed casks
- Replace individual brew calls with grep against cached list
- Remove marker tag suffixes (:brew, :manual) - output package names directly
- Simplify parsing logic by eliminating regex_replace operations

Performance impact with 10 casks:
- Before: 20 brew invocations (2 per package)
- After: 1 brew invocation + fast grep operations

Addresses code review feedback from copilot-pull-request-reviewer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Paolo Mainardi <[email protected]>
@paolomainardi paolomainardi requested a review from Copilot October 24, 2025 13:23
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment on lines +123 to +131
shell: |
# Use cached list of installed casks
installed_casks="{{ all_installed_casks.stdout }}"
for pkg in {{ all_cask_packages | map('quote') | join(' ') }}; do
if echo "$installed_casks" | grep -qx "$pkg"; then
echo "$pkg"
fi
done
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Homebrew cask check is redundant. The script checks if packages are in all_installed_casks.stdout, which was already obtained by running brew list --cask. Since we have this data, we could filter all_cask_packages directly in Ansible using intersect instead of executing another shell command. This would eliminate the need for shell execution and improve maintainability.

Copilot uses AI. Check for mistakes.
Comment on lines +136 to +153
- name: Check which cask packages are manually installed
shell: |
# Use cached list of installed casks
installed_casks="{{ all_installed_casks.stdout }}"
{% for cask in all_cask_packages %}
{% if cask in cask_mappings.cask_to_app_mapping %}
if [ -d "/Applications/{{ cask_mappings.cask_to_app_mapping[cask] }}" ]; then
if ! echo "$installed_casks" | grep -qx "{{ cask }}"; then
echo "{{ cask }}"
fi
fi
{% endif %}
{% endfor %}
register: manual_cask_check
changed_when: false
become: false

Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manual cask check generates a shell script with Jinja2 templating that iterates through all cask packages. This creates a large shell script when many casks are configured. Consider using Ansible's native stat module with a loop to check for application existence, which would be more maintainable and easier to debug.

Suggested change
- name: Check which cask packages are manually installed
shell: |
# Use cached list of installed casks
installed_casks="{{ all_installed_casks.stdout }}"
{% for cask in all_cask_packages %}
{% if cask in cask_mappings.cask_to_app_mapping %}
if [ -d "/Applications/{{ cask_mappings.cask_to_app_mapping[cask] }}" ]; then
if ! echo "$installed_casks" | grep -qx "{{ cask }}"; then
echo "{{ cask }}"
fi
fi
{% endif %}
{% endfor %}
register: manual_cask_check
changed_when: false
become: false
- name: Check which cask packages are manually installed (stat loop)
stat:
path: "/Applications/{{ cask_mappings.cask_to_app_mapping[item] | default('') }}"
loop: "{{ all_cask_packages }}"
loop_control:
label: "{{ item }}"
register: manual_cask_stat_results
when: item in cask_mappings.cask_to_app_mapping
changed_when: false
become: false
- name: Set manually_installed_casks fact
set_fact:
manually_installed_casks: >-
{{
manual_cask_stat_results.results
| selectattr('stat.exists', 'defined')
| selectattr('stat.exists')
| map(attribute='item')
| select('match', '^(?!.*(' ~ (all_installed_casks.stdout | regex_replace('\n', '|')) ~ ')).*$')
| list
}}

Copilot uses AI. Check for mistakes.
msg:
- "📦 Cask packages to be installed: {{ all_cask_packages | length }}"
- "{{ all_cask_packages | join(', ') if all_cask_packages | length > 0 else 'None (all already installed)' }}"
when: ansible_verbosity >= 0
Copy link

Copilot AI Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition ansible_verbosity >= 0 will always be true since Ansible verbosity starts at 0 by default. This effectively means the debug message will always display. If the intent is to always show this message, remove the when condition. If conditional display is needed, use a higher verbosity threshold (e.g., >= 1).

Suggested change
when: ansible_verbosity >= 0

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ansible fails installing Google Chrome when it's already installed manually

2 participants