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
17 changes: 12 additions & 5 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,18 @@ jobs:
set -e
echo "status=${status}" >> "${GITHUB_OUTPUT}"

- name: Finalize Zsh Syntax Result
- name: Run Zsh Regression Tests
id: zsh_tests
if: steps.zsh_syntax.outputs.status == '0'
run: zsh tests/installomator-label-parser.zsh

Comment on lines +272 to +276
- name: Finalize Zsh Validation Result
if: success() || failure()
shell: bash
run: |
target_count="${{ steps.collect_targets.outputs.count }}"
syntax_status="${{ steps.zsh_syntax.outputs.status }}"
tests_outcome="${{ steps.zsh_tests.outcome }}"

if [[ "${target_count}" == "0" ]]; then
{
Expand All @@ -286,19 +292,20 @@ jobs:
fi

{
echo "### Zsh Syntax"
echo "### Zsh Validation"
echo
echo "- Files scanned: ${target_count}"
echo "- Regression tests: ${tests_outcome}"
} >> "${GITHUB_STEP_SUMMARY}"

if [[ "${syntax_status}" == "0" ]]; then
if [[ "${syntax_status}" == "0" && "${tests_outcome}" == "success" ]]; then
echo "" >> "${GITHUB_STEP_SUMMARY}"
echo "✅ All zsh files passed \`zsh -n\`" >> "${GITHUB_STEP_SUMMARY}"
echo "✅ Zsh syntax and regression tests passed" >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi

echo "" >> "${GITHUB_STEP_SUMMARY}"
echo "❌ zsh syntax errors found" >> "${GITHUB_STEP_SUMMARY}"
echo "❌ Zsh validation failed" >> "${GITHUB_STEP_SUMMARY}"
exit 1

shellcheck:
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

All notable changes to this project are documented in this file.

## 1.2.0b2 - 18-Aug-2026
## 1.2.0b3 - 18-Aug-2026
- Fixed validation of Installomator labels declared in multiline alias arms (Bug Report #16)
- Added `selectionDialogDefaultChecked` to configure default selection for interactive-mode items (while keeping already-installed items disabled and unchecked; thanks for FR #14, @jeffmw777!)
- Updated `codex` Validation Path

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
![GitHub release (latest by date)](https://img.shields.io/github/v/release/Setup-Your-Mac/SYM-Lite?display_name=tag) ![GitHub issues](https://img.shields.io/github/issues-raw/Setup-Your-Mac/SYM-Lite) ![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/Setup-Your-Mac/SYM-Lite) ![GitHub pull requests](https://img.shields.io/github/issues-pr-raw/Setup-Your-Mac/SYM-Lite) ![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed-raw/Setup-Your-Mac/SYM-Lite) [![swiftDialog](https://img.shields.io/badge/swiftDialog-Enabled-blue)](https://swiftdialog.app) [![Semgrep Security Scan](https://img.shields.io/badge/security%20scanned%20by-Semgrep-00C7B7?style=flat&logo=semgrep&logoColor=white)](https://semgrep.dev)

# SYM-Lite (1.2.0b2)
# SYM-Lite (1.2.0b3)

> **SYM-Lite** is a lean, purpose-built script for executing MDM-agnostic [Installomator labels](https://github.com/Installomator/Installomator/tree/main/fragments/labels) and [Homebrew](https://brew.sh) casks / formulas, as well as Jamf Pro-specific [policy triggers](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Triggers_for_Policies), all through a unified [swiftDialog](https://swiftdialog.app) selection and reporting interface.

Expand Down Expand Up @@ -71,7 +71,7 @@ installomatorLabels=(
)
```

At runtime, SYM-Lite validates each configured label against `organizationInstallomatorFile` before building the picker or accepting silent-mode CSV input. If a label is missing from that Installomator file, or if the Installomator file is unavailable or unreadable, SYM-Lite logs a warning or error and removes Installomator labels from the current run while leaving other item types available.
At runtime, SYM-Lite validates each configured label against single-line and continued top-level alias arms in `organizationInstallomatorFile` before building the picker or accepting silent-mode CSV input. If a label is missing from that Installomator file, or if the Installomator file is unavailable, unreadable, or cannot be parsed, SYM-Lite logs a warning or error and removes Installomator labels from the current run while leaving other item types available.

### Adding Homebrew Items

Expand Down Expand Up @@ -341,6 +341,6 @@ swiftDialog's [Inspect Mode](https://swiftdialog.app/advanced/inspect-mode/) use

(The rest of the document — Logging, Troubleshooting, Testing Checklist, Next Steps, and Support — remains unchanged as the reordering was already applied where relevant.)

**Version:** 1.2.0b2
**Version:** 1.2.0b3
**Date:** 18-Aug-2026
**Author:** Dan K. Snelson (@dan-snelson)
44 changes: 42 additions & 2 deletions SYM-Lite.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
#
# HISTORY
#
# Version 1.2.0b2, 18-Aug-2026, Dan K. Snelson (@dan-snelson)
# Version 1.2.0b3, 18-Aug-2026, Dan K. Snelson (@dan-snelson)
# - Fixed validation of Installomator labels declared in multiline alias arms (Bug Report #16)
# - Added `selectionDialogDefaultChecked` to configure default selection for interactive-mode items (while keeping already-installed items disabled and unchecked; thanks for FR #14, @jeffmw777!)
# - Updated `codex` Validation Path
#
Expand All @@ -35,7 +36,7 @@ setopt NONOMATCH
setopt TYPESET_SILENT

# Script Version
scriptVersion="1.2.0b2"
scriptVersion="1.2.0b3"

# Script Human-readable Name
humanReadableScriptName="Setup Your Mac Lite: Developer Edition"
Expand Down Expand Up @@ -516,6 +517,7 @@ function getAvailableInstallomatorLabels() {
BEGIN {
inLabelCase = 0
caseDepth = 0
continuedArm = ""
}

/^[[:space:]]*case[[:space:]]+\$label[[:space:]]+in[[:space:]]*$/ {
Expand All @@ -525,6 +527,31 @@ function getAvailableInstallomatorLabels() {
}

inLabelCase {
if (continuedArm != "") {
if (caseDepth != 1) {
exit 2
}

if ($0 ~ /^[[:space:]]*[A-Za-z0-9_*][A-Za-z0-9_|-]*\|\\[[:space:]]*$/) {
labelFragment = $0
sub(/^[[:space:]]*/, "", labelFragment)
sub(/\\[[:space:]]*$/, "", labelFragment)
continuedArm = continuedArm labelFragment
next
}

if ($0 ~ /^[[:space:]]*[A-Za-z0-9_*][A-Za-z0-9_|-]*\)[[:space:]]*$/) {
labelFragment = $0
sub(/^[[:space:]]*/, "", labelFragment)
sub(/\)[[:space:]]*$/, "", labelFragment)
print continuedArm labelFragment
continuedArm = ""
next
}

exit 2
}

if ($0 ~ /^[[:space:]]*case[[:space:]].*[[:space:]]+in[[:space:]]*$/) {
caseDepth++
next
Expand All @@ -538,13 +565,26 @@ function getAvailableInstallomatorLabels() {
next
}

if (caseDepth == 1 && $0 ~ /^[[:space:]]*[A-Za-z0-9_*][A-Za-z0-9_|-]*\|\\[[:space:]]*$/) {
continuedArm = $0
sub(/^[[:space:]]*/, "", continuedArm)
sub(/\\[[:space:]]*$/, "", continuedArm)
next
}

if (caseDepth == 1 && $0 ~ /^[[:space:]]*[A-Za-z0-9_*][A-Za-z0-9_|-]*\)[[:space:]]*$/) {
labelArm = $0
sub(/^[[:space:]]*/, "", labelArm)
sub(/\)[[:space:]]*$/, "", labelArm)
print labelArm
}
}

END {
if (continuedArm != "") {
exit 2
}
}
' "${organizationInstallomatorFile}"); then
return 1
fi
Expand Down
Loading