-
Notifications
You must be signed in to change notification settings - Fork 1
improved GPO & intune templates #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds Enforced/Defaults policy branches and many new policies and localizations; implements managed-setting detection in the Settings UI; renames Intune keys to Graph-*, adds secure secret handling and keyring migration; implements policy-driven script signing via certificate thumbprint with path and auto-detect fallbacks; updates CI workflows and docs. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant SettingsView as SettingsView GUI
participant Config as SwitchCraftConfig
participant Registry as Windows Registry
participant Widget as UI Widget
User->>SettingsView: open / raise Settings view
SettingsView->>SettingsView: schedule _check_managed_settings (500ms)
rect `#EBF5FF`
Note over SettingsView,Config: Managed settings resolution
SettingsView->>Config: is_managed(key) for each mapped widget
Config->>Registry: query HKLM/HKCU Policy paths
Registry-->>Config: policy value present / not present
Config-->>SettingsView: True / False
alt managed == True
SettingsView->>Widget: disable widget and set displayed value from registry
else
SettingsView->>Widget: leave enabled (use preference/keyring)
end
end
sequenceDiagram
participant Caller as Signing Caller
participant Service as SigningService
participant Config as SwitchCraftConfig
participant PowerShell as PowerShell Executor
participant Registry as Windows Registry
Caller->>Service: request sign(script)
Service->>Config: get_value("SignScripts")
Config->>Registry: check policy/preference precedence
Registry-->>Config: value
Config-->>Service: signing enabled?
alt SignScripts == True
Service->>Config: get_value("CodeSigningCertThumbprint")
Config->>Registry: read thumbprint (policy/preference)
Registry-->>Config: thumbprint / none
alt thumbprint present
Service->>PowerShell: locate cert in Cert:\CurrentUser\My by thumbprint
PowerShell-->>Service: cert found / not found
alt cert found
Service->>PowerShell: Sign-File with found cert
PowerShell-->>Service: success
else
Service-->>Caller: error (certificate not found)
end
else if cert_path provided
Service->>PowerShell: Sign using provided .pfx path (may require password)
PowerShell-->>Service: success / failure
else
Service->>PowerShell: auto-detect code-signing cert in stores and sign
PowerShell-->>Service: success / failure
end
else
Service-->>Caller: skip signing
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
README.md (1)
16-17: Duplicate heading detected.Line 16 and 17 both contain
## 📚 Documentation. Remove the duplicate on line 17.🔎 Proposed fix
## 📚 Documentation -## 📚 Documentation - [**✨ Features & Analysis**](docs/FEATURES.md): Detailed breakdown of supported installers and analysis capabilities.docs/PolicyDefinitions/README.md (1)
82-85: Precedence documentation inconsistency.The precedence order here (lines 82-85) shows HKLM Preference before HKCU Preference, but the updated
config.pynow checks HKCU Preference (User) before HKLM Preference (Machine). Update to match the code:🔎 Proposed fix
1. **Machine Policy** (`HKLM\Software\Policies\FaserF\SwitchCraft`) - *Highest Priority (Intune/GPO)* 2. **User Policy** (`HKCU\Software\Policies\FaserF\SwitchCraft`) - *High Priority (Intune/GPO)* -3. **Machine Preference** (`HKLM\Software\FaserF\SwitchCraft`) -4. **User Preference** (`HKCU\Software\FaserF\SwitchCraft`) - *Default User Settings* +3. **User Preference** (`HKCU\Software\FaserF\SwitchCraft`) - *User Settings* +4. **Machine Preference** (`HKLM\Software\FaserF\SwitchCraft`) - *Admin Default*
🧹 Nitpick comments (2)
src/switchcraft/services/signing_service.py (1)
85-103: Consider capturing both stdout and stderr for debugging.When signing fails, line 98 logs stdout as a warning, but stderr (line 97) is only logged if non-empty. The condition
completed.returncode == 0 and "Signed Successfully"is good, but failed signing may have useful info in stdout even when stderr is empty.🔎 Suggested improvement
if completed.returncode == 0 and "Signed Successfully" in completed.stdout: logger.info(f"Successfully signed {script_path_obj.name}") return True else: - if completed.stderr: - logger.error(f"Signing Error: {completed.stderr.strip()}") - logger.warning(f"Signing Output: {completed.stdout.strip()}") + logger.error(f"Signing failed for {script_path_obj.name}") + if completed.stdout.strip(): + logger.warning(f"Signing stdout: {completed.stdout.strip()}") + if completed.stderr.strip(): + logger.error(f"Signing stderr: {completed.stderr.strip()}") return Falsedocs/PolicyDefinitions/de-DE/SwitchCraft.adml (1)
1-137: Consider native speaker review for translation quality.While the German translations appear technically accurate and the overall structure is excellent, consider having a native German speaker review the localization to ensure the terminology and phrasing align with German IT/enterprise conventions.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
README.mddocs/PolicyDefinitions/README.mddocs/PolicyDefinitions/SwitchCraft.admxdocs/PolicyDefinitions/de-DE/SwitchCraft.admldocs/PolicyDefinitions/en-US/SwitchCraft.admlsrc/switchcraft/gui/views/intune_view.pysrc/switchcraft/gui/views/settings_view.pysrc/switchcraft/services/signing_service.pysrc/switchcraft/utils/config.py
🧰 Additional context used
🧬 Code graph analysis (3)
src/switchcraft/services/signing_service.py (1)
src/switchcraft/utils/config.py (1)
get_value(23-60)
src/switchcraft/gui/views/settings_view.py (1)
src/switchcraft/utils/config.py (2)
is_managed(63-82)get_value(23-60)
src/switchcraft/gui/views/intune_view.py (1)
src/switchcraft/utils/config.py (1)
get_value(23-60)
🪛 GitHub Actions: CI Orchestrator
src/switchcraft/gui/views/settings_view.py
[error] 1046-1046: E701: Multiple statements on one line (colon).
🪛 markdownlint-cli2 (0.18.1)
docs/PolicyDefinitions/README.md
17-17: Multiple headings with the same content
(MD024, no-duplicate-heading)
🔇 Additional comments (14)
README.md (1)
123-124: New feature documentation looks good.The Cloud Sync and Script Signing features are documented concisely and align with the implementation changes in this PR.
src/switchcraft/utils/config.py (1)
71-82:is_managedimplementation is sound.The method correctly checks only the Policy paths (not Preference paths) to determine if a setting is enforced. The broad exception handler on line 79 silently ignores errors, which is acceptable here since the method returns a safe default (
False).docs/PolicyDefinitions/SwitchCraft.admx (2)
15-63: Category hierarchy is well-structured.The Enforced/Defaults branching with subcategories (Updates, General, AI, Security, Intune) provides clear organization for both mandatory policies and default settings.
158-164: Security consideration: Client Secret stored in registry.
GraphClientSecretis stored as plain text in the registry. While the ADML includes a warning, consider:
- Documenting that the secret should have minimal permissions (read-only app registration)
- Recommending certificate-based authentication for production environments
This is noted in the help text, so no action required, but worth highlighting for enterprise deployments.
src/switchcraft/gui/views/settings_view.py (1)
1067-1069:tkraiseoverride is a good pattern for refreshing managed state.Re-checking managed settings when the view is raised ensures the UI reflects policy changes if they occurred while another tab was active.
src/switchcraft/services/signing_service.py (1)
33-44: Thumbprint-based signing implementation is solid.The logic correctly:
- Prioritizes policy-configured thumbprint
- Searches CurrentUser store first, then LocalMachine
- Provides clear error messaging if certificate not found
docs/PolicyDefinitions/en-US/SwitchCraft.adml (2)
92-95: Good security warning for GraphClientSecret.The help text appropriately warns about registry storage security considerations.
99-133: Presentation elements are correctly defined.All presentation IDs match the corresponding ADMX policy references, and the UI element bindings (dropdowns, textboxes) are properly configured.
src/switchcraft/gui/views/intune_view.py (1)
113-117: Credential key renaming is consistent.The keys now match the policy definitions (
GraphTenantId,GraphClientId,GraphClientSecret) and are used consistently in both_show_intune_form(lines 113-115) and_run_upload(lines 256-258).Consider documenting the migration path for users who had previously configured
IntuneTenantID/IntuneClientId/IntuneClientSecret. Existing configurations will silently stop working.#!/bin/bash # Check if old key names are still referenced anywhere rg -n "IntuneTenantID|IntuneClientId|IntuneClientSecret" --type pydocs/PolicyDefinitions/de-DE/SwitchCraft.adml (5)
14-15: LGTM: Well-organized category structure.The new category hierarchy (Enforced/Defaults/General/AI/Security/Intune) provides clear organization for policy management. The German translations are appropriate, and special characters are properly escaped.
Also applies to: 31-34
52-63: LGTM: General settings are well-defined.The Winget integration, language selection, and Git repository path configurations are clearly documented with appropriate help text. The German translations are technically accurate.
66-74: LGTM: AI provider configuration is well-documented.The AI provider options are clearly explained with privacy and API key requirements noted. The distinction between local (private) and cloud-based providers is appropriate.
77-83: LGTM: Script signing configuration is secure and well-documented.The certificate thumbprint approach is appropriate for code signing, and the help text correctly references the certificate store location. The override behavior is clearly explained.
103-133: LGTM: Presentation bindings are complete and correct.All new policy strings have corresponding presentation entries with appropriate control types (dropdowns for selections, text boxes for input). The German labels are contextually appropriate, and the bindings maintain consistency with the string table.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/switchcraft/gui/views/settings_view.py (2)
1032-1043: Widget attribute names still don't match actual widget references.This is the same issue flagged in the previous review. The
managed_widgetsdictionary references attributes that don't exist:
chk_winget→ actual widget iswinget_var(BooleanVar at line 62); the CTkSwitch at line 69 has no stored referencecombo_lang→ no stored reference; OptionMenu created inline at line 83combo_theme→ no stored reference; OptionMenu created inline at line 95combo_ai_provider→ should beai_provider(correct name at line 549)combo_channel→ should bechannel_opt(correct name at line 394)Since
getattr(..., None)returnsNonefor missing attributes, policy enforcement silently fails for most settings.Based on learnings from past reviews, this issue must be addressed to enable policy enforcement.
1045-1046: Fix E701 style violation: multiple statements on one line.This is the same formatting issue flagged in the previous review.
🔎 Proposed fix
for key, widget in managed_widgets.items(): - if not widget: continue + if not widget: + continue
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/switchcraft/gui/views/settings_view.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/switchcraft/gui/views/settings_view.py (1)
src/switchcraft/utils/config.py (3)
SwitchCraftConfig(9-239)is_managed(63-82)get_value(23-60)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build / Build Installer (windows-latest)
🔇 Additional comments (2)
src/switchcraft/gui/views/settings_view.py (2)
48-49: LGTM!The initial scheduled check for managed settings is appropriately placed after UI setup, allowing widgets to initialize before enforcement.
1068-1070: LGTM!The
tkraiseoverride correctly preserves base behavior and re-checks managed settings when the view is brought to the foreground, ensuring policy enforcement stays current.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
tests/test_config_secure.py (1)
10-13: Test silently skips if SwitchCraftConfig import fails.The bare
except ImportError: passmeans that if the module fails to import, the test class will be defined but all test methods will silently pass without actually testing anything. This can mask real import/dependency issues.🔎 Recommended fix
try: from switchcraft.utils.config import SwitchCraftConfig except ImportError: - pass + import unittest + raise unittest.SkipTest("SwitchCraftConfig not available")Or use
unittest.skipIfdecorator on the test class:try: from switchcraft.utils.config import SwitchCraftConfig SWITCHCRAFT_AVAILABLE = True except ImportError: SWITCHCRAFT_AVAILABLE = False @unittest.skipIf(not SWITCHCRAFT_AVAILABLE, "SwitchCraftConfig not available") class TestSecureConfig(unittest.TestCase): ...src/switchcraft/gui/views/settings_view.py (1)
1055-1077: Consider narrowing exception handling for better error visibility.The broad
except Exception: passat line 1076 will silently catch all errors when configuring managed widgets, including AttributeErrors if widget APIs change or TypeErrors from unexpected values. This can make debugging difficult.🔎 Suggested refinement
if SwitchCraftConfig.is_managed(key): try: widget.configure(state="disabled") if isinstance(widget, ctk.CTkEntry): val = SwitchCraftConfig.get_value(key, "") widget.delete(0, "end") widget.insert(0, str(val)) elif isinstance(widget, ctk.CTkSwitch): val = SwitchCraftConfig.get_value(key, 0) # Ensure integer/bool if str(val).lower() in ("true", "1", "yes"): widget.select() else: widget.deselect() elif isinstance(widget, (ctk.CTkOptionMenu, ctk.CTkComboBox, ctk.CTkSegmentedButton)): val = SwitchCraftConfig.get_value(key, "") widget.set(str(val)) - except Exception: - pass + except (AttributeError, TypeError) as e: + logger.warning(f"Failed to configure managed widget for '{key}': {e}")This logs issues while preventing crashes, making it easier to diagnose widget API changes or configuration problems.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
docs/PolicyDefinitions/README.mddocs/PolicyDefinitions/en-US/SwitchCraft.admlsrc/switchcraft/gui/views/intune_view.pysrc/switchcraft/gui/views/settings_view.pysrc/switchcraft/services/signing_service.pysrc/switchcraft/utils/config.pytests/test_config_secure.py
🧰 Additional context used
🧬 Code graph analysis (4)
src/switchcraft/services/signing_service.py (1)
src/switchcraft/utils/config.py (1)
get_value(24-61)
src/switchcraft/gui/views/intune_view.py (1)
src/switchcraft/utils/config.py (2)
get_value(24-61)get_secure_value(173-227)
tests/test_config_secure.py (1)
src/switchcraft/utils/config.py (1)
get_secure_value(173-227)
src/switchcraft/gui/views/settings_view.py (1)
src/switchcraft/utils/config.py (4)
get_secure_value(173-227)get_value(24-61)set_secret(240-254)is_managed(64-83)
🔇 Additional comments (7)
src/switchcraft/gui/views/intune_view.py (1)
113-115: LGTM! Credential handling updated correctly.The migration from
IntuneTenantID/IntuneClientId/IntuneClientSecrettoGraphTenantId/GraphClientId/GraphClientSecretis consistent with the broader policy changes. Usingget_secure_valuefor the client secret properly implements secure credential retrieval with policy precedence and keyring fallback.docs/PolicyDefinitions/README.md (1)
46-61: Comprehensive OMA-URI configuration documentation.The consolidated base URI approach with the detailed settings table makes Intune configuration much clearer. The inclusion of
GraphClientSecretin the table addresses the previous gap, and the example XML for bulk import is helpful for administrators.src/switchcraft/gui/views/settings_view.py (1)
789-796: Secure credential loading implemented correctly.The conditional handling for
GraphClientSecretusingget_secure_valueversus standardget_valuefor other fields properly implements the secure credential retrieval pattern. This ensures secrets are loaded from the keyring (or policy) with appropriate precedence.src/switchcraft/services/signing_service.py (1)
36-47: Thumbprint-based signing provides robust certificate management.The policy-driven thumbprint approach properly searches both
CurrentUser\MyandLocalMachine\Mystores, providing clear fallback behavior. The explicit error message when the certificate isn't found (line 46) helps administrators diagnose deployment issues quickly.src/switchcraft/utils/config.py (1)
208-220: Migration logic safely transitions secrets to keyring.The migration path (lines 210-220) properly:
- Logs the migration event
- Stores the secret in the keyring
- Attempts to delete the legacy registry entry
- Gracefully handles deletion failures with a warning
- Returns the migrated value
This ensures secrets are moved to more secure storage while maintaining availability during the transition.
docs/PolicyDefinitions/en-US/SwitchCraft.adml (2)
86-95: Important security warning for GraphClientSecret deployment.The help text appropriately warns administrators that
GraphClientSecretis stored in the registry when deployed via policy. This is crucial information since registry values are less secure than keyring storage. Consider also documenting recommended ACL restrictions in the main README.
103-133: UI presentation bindings are complete and well-structured.All new policies have corresponding presentation definitions with appropriate control types (dropdownList for selections, textBox for free-form input). The refId attributes correctly map to their policy definitions, ensuring proper rendering in the Group Policy Editor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (2)
.github/workflows/review-auto-merge.yml (2)
41-51: Same bot check pattern issue as ci-orchestrator.yml.The
*[bot]pattern matching has the same issue here. See the comment on ci-orchestrator.yml for the fix.
55-56: Same overly broad skip detection issue.The
test("skip"; "i")regex is too permissive. See the comment on ci-orchestrator.yml for the recommended fix.
🧹 Nitpick comments (3)
.github/workflows/ci-orchestrator.yml (1)
64-120: Consider extracting shared auto-merge logic.The auto-merge logic here duplicates nearly identical code in
review-auto-merge.yml. Consider extracting this into a reusable composite action or shared script to maintain DRY principles..github/workflows/review-auto-merge.yml (1)
3-5: Workflow triggers on all review types.This workflow runs on any review submission, including "REQUEST_CHANGES" and "COMMENT" reviews which will never lead to a merge. Consider filtering to only run on approving reviews to save CI minutes.
🔎 Proposed fix
on: pull_request_review: types: [submitted] + +jobs: + auto-merge-review: + runs-on: ubuntu-latest + if: github.event.review.state == 'approved'docs/PolicyDefinitions/README.md (1)
19-19: Security warning for GraphClientSecret could be stronger.While "(Use with caution)" is noted, consider adding explicit guidance that secrets in GPO/registry are stored in plaintext and recommending secure alternatives (like Azure Key Vault, Managed Identity, or the application's keyring storage) for production environments.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
.github/workflows/auto-merge.yml.github/workflows/ci-orchestrator.yml.github/workflows/lint.yml.github/workflows/review-auto-merge.ymlREADME.mddocs/PolicyDefinitions/README.mddocs/upgrade.mdsrc/switchcraft/gui/views/settings_view.pysrc/switchcraft/utils/config.pytests/test_config_secure.py
💤 Files with no reviewable changes (1)
- .github/workflows/auto-merge.yml
✅ Files skipped from review due to trivial changes (1)
- docs/upgrade.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/switchcraft/utils/config.py
🧰 Additional context used
🧬 Code graph analysis (2)
src/switchcraft/gui/views/settings_view.py (1)
src/switchcraft/utils/config.py (4)
get_secure_value(173-227)get_value(24-61)set_secret(240-254)is_managed(64-83)
tests/test_config_secure.py (1)
src/switchcraft/utils/config.py (1)
get_secure_value(173-227)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build / Build Installer (windows-latest)
🔇 Additional comments (7)
README.md (1)
123-124: LGTM!New feature documentation for Cloud Sync and Script Signing accurately reflects the functionality added in this PR.
tests/test_config_secure.py (2)
14-46: Test setup is well-structured.Good use of patching for keyring and winreg to enable cross-platform testing of Windows-specific functionality. The setUp/tearDown pattern ensures proper cleanup.
83-101: The winreg mocking is correct and the test passes.The mock setup via
sys.modulespatching correctly intercepts thewinregimport insideget_secure_value(), and theHKEY_CURRENT_USERconstant (value 2) is properly defined insetUp()and used consistently in theside_effectcomparison. The test successfully validates that the migration logic works as expected. No changes needed.docs/PolicyDefinitions/README.md (1)
7-19: Documentation updates look good.The policy table is comprehensive, OMA-URI paths are correctly documented, and the
GraphClientSecretentry (line 60) addresses the previous review comment. The masked value example (*****) is appropriate for secrets.Also applies to: 48-61
src/switchcraft/gui/views/settings_view.py (3)
789-796: Good implementation of secure credential handling.The differentiation between
GraphClientSecret(usingget_secure_value) and other fields (usingget_value) correctly implements the secure value precedence fromconfig.py.
1042-1053: Widget mapping addresses previous review feedback.The
managed_widgetsdictionary now correctly references the stored widget attributes (winget_switch,lang_menu,theme_menu,ai_provider,channel_opt) instead of the non-existent names flagged in the previous review.
1079-1081: Good approach for re-checking managed settings on view raise.Calling
_check_managed_settingswhen the view is raised ensures policy enforcement is re-evaluated when navigating back to settings, which handles cases where policies might change during app runtime.
| if [[ "$PR_AUTHOR" == *"[bot]" ]]; then | ||
| echo "PR Author is a Bot. Allowed." | ||
| else | ||
| PERM=$(gh api "repos/$REPO/collaborators/$PR_AUTHOR/permission" --jq '.permission') | ||
| echo "Author Permission: $PERM" | ||
| if [[ "$PERM" == "admin" || "$PERM" == "maintain" || "$PERM" == "write" ]]; then | ||
| echo "Author has trusted permission ($PERM). Allowed." | ||
| else | ||
| echo "::notice::PR Author ($PR_AUTHOR) does not have sufficient permissions ($PERM) for auto-merge. Skipping." | ||
| exit 0 | ||
| fi | ||
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bot check pattern matching is incorrect.
The pattern *[bot] in bash [[ ]] is a glob pattern, but it's case-sensitive and might not match all bot formats (e.g., dependabot[bot]). The * before [bot] should work, but consider using a suffix check for clarity.
🔎 Proposed fix
- if [[ "$PR_AUTHOR" == *"[bot]" ]]; then
+ if [[ "$PR_AUTHOR" == *\[bot\] ]]; thenOr for more robust matching:
- if [[ "$PR_AUTHOR" == *"[bot]" ]]; then
+ if [[ "$PR_AUTHOR" =~ \[bot\]$ ]]; then📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if [[ "$PR_AUTHOR" == *"[bot]" ]]; then | |
| echo "PR Author is a Bot. Allowed." | |
| else | |
| PERM=$(gh api "repos/$REPO/collaborators/$PR_AUTHOR/permission" --jq '.permission') | |
| echo "Author Permission: $PERM" | |
| if [[ "$PERM" == "admin" || "$PERM" == "maintain" || "$PERM" == "write" ]]; then | |
| echo "Author has trusted permission ($PERM). Allowed." | |
| else | |
| echo "::notice::PR Author ($PR_AUTHOR) does not have sufficient permissions ($PERM) for auto-merge. Skipping." | |
| exit 0 | |
| fi | |
| fi | |
| if [[ "$PR_AUTHOR" == *\[bot\] ]]; then | |
| echo "PR Author is a Bot. Allowed." | |
| else | |
| PERM=$(gh api "repos/$REPO/collaborators/$PR_AUTHOR/permission" --jq '.permission') | |
| echo "Author Permission: $PERM" | |
| if [[ "$PERM" == "admin" || "$PERM" == "maintain" || "$PERM" == "write" ]]; then | |
| echo "Author has trusted permission ($PERM). Allowed." | |
| else | |
| echo "::notice::PR Author ($PR_AUTHOR) does not have sufficient permissions ($PERM) for auto-merge. Skipping." | |
| exit 0 | |
| fi | |
| fi |
🤖 Prompt for AI Agents
.github/workflows/ci-orchestrator.yml around lines 92 to 103: the bot author
check uses a case-sensitive glob `*"[bot]"` which can miss variants; convert
PR_AUTHOR to lowercase and perform a suffix match against "[bot]" (e.g., use
bash parameter expansion `${PR_AUTHOR,,}` then `[[ "${PR_AUTHOR,,}" == *"[bot]"
]]`) so matching is robust and clear; ensure the variable is quoted to avoid
word-splitting and preserve existing logic for bot authors.
| IS_APPROVED=$(gh api "repos/$REPO/pulls/$PR_NUMBER/reviews" --jq '.[] | select(.user.login == "coderabbitai[bot]" and .state == "APPROVED") | .state' | head -n 1) | ||
| HAS_SKIP_COMMENT=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "coderabbitai[bot]" and (.body | test("skip"; "i"))) | .id' | head -n 1) | ||
| if [[ -n "$IS_APPROVED" ]]; then | ||
| echo "Coderabbit APPROVED." | ||
| elif [[ -n "$HAS_SKIP_COMMENT" ]]; then | ||
| echo "Coderabbit SKIPPED review." | ||
| else | ||
| echo "::notice::Coderabbit has not approved or skipped yet. Waiting." | ||
| exit 0 | ||
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overly broad "skip" detection.
The regex test("skip"; "i") matches any comment containing "skip" anywhere (e.g., "I'll skip this review", "Please don't skip tests"). This could cause unintended auto-merges.
🔎 Proposed fix
Consider matching a specific pattern like @coderabbitai skip or a dedicated label:
- HAS_SKIP_COMMENT=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "coderabbitai[bot]" and (.body | test("skip"; "i"))) | .id' | head -n 1)
+ HAS_SKIP_COMMENT=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "coderabbitai[bot]" and (.body | test("<!-- skip_review -->|\\[skip\\]"; "i"))) | .id' | head -n 1)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| IS_APPROVED=$(gh api "repos/$REPO/pulls/$PR_NUMBER/reviews" --jq '.[] | select(.user.login == "coderabbitai[bot]" and .state == "APPROVED") | .state' | head -n 1) | |
| HAS_SKIP_COMMENT=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "coderabbitai[bot]" and (.body | test("skip"; "i"))) | .id' | head -n 1) | |
| if [[ -n "$IS_APPROVED" ]]; then | |
| echo "Coderabbit APPROVED." | |
| elif [[ -n "$HAS_SKIP_COMMENT" ]]; then | |
| echo "Coderabbit SKIPPED review." | |
| else | |
| echo "::notice::Coderabbit has not approved or skipped yet. Waiting." | |
| exit 0 | |
| fi | |
| IS_APPROVED=$(gh api "repos/$REPO/pulls/$PR_NUMBER/reviews" --jq '.[] | select(.user.login == "coderabbitai[bot]" and .state == "APPROVED") | .state' | head -n 1) | |
| HAS_SKIP_COMMENT=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.user.login == "coderabbitai[bot]" and (.body | test("<!-- skip_review -->|\\[skip\\]"; "i"))) | .id' | head -n 1) | |
| if [[ -n "$IS_APPROVED" ]]; then | |
| echo "Coderabbit APPROVED." | |
| elif [[ -n "$HAS_SKIP_COMMENT" ]]; then | |
| echo "Coderabbit SKIPPED review." | |
| else | |
| echo "::notice::Coderabbit has not approved or skipped yet. Waiting." | |
| exit 0 | |
| fi |
🤖 Prompt for AI Agents
.github/workflows/ci-orchestrator.yml lines 107-117: the current skip detection
uses a broad regex that matches any occurrence of "skip"; change it to detect a
specific, unambiguous signal such as the exact phrase "@coderabbitai skip"
(case-insensitive) or a dedicated PR label instead of any "skip" substring.
Update the GH comments query to only consider comments where the body matches
that exact mention/phrase (or alternatively call the labels endpoint and check
for a specific label name) so accidental uses of the word "skip" don't trigger
auto-merge.
| - name: Commit and Push Fixes | ||
| if: always() | ||
| run: | | ||
| git config --global user.name "github-actions[bot]" | ||
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add src/ | ||
| if ! git diff --cached --quiet; then | ||
| git commit -m "style: auto-fix ruff linting issues" | ||
| git push |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto-commit step has potential issues.
-
if: always()runs even when prior steps fail (e.g., Python setup fails), which would cause the git commands to fail or behave unexpectedly. -
Risk of infinite commit loop: pushing a commit triggers a new workflow run, which could auto-fix and push again. Consider adding
[skip ci]to the commit message or checkinggithub.actorto skip bot commits. -
For PRs from forks, this step will fail since
GITHUB_TOKENlacks write access to the fork's branch.
🔎 Proposed fix
- name: Commit and Push Fixes
- if: always()
+ if: success() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add src/
if ! git diff --cached --quiet; then
- git commit -m "style: auto-fix ruff linting issues"
+ git commit -m "style: auto-fix ruff linting issues [skip ci]"
git push
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Commit and Push Fixes | |
| if: always() | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git add src/ | |
| if ! git diff --cached --quiet; then | |
| git commit -m "style: auto-fix ruff linting issues" | |
| git push | |
| - name: Commit and Push Fixes | |
| if: success() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git add src/ | |
| if ! git diff --cached --quiet; then | |
| git commit -m "style: auto-fix ruff linting issues [skip ci]" | |
| git push |
| if SwitchCraftConfig.is_managed(key): | ||
| try: | ||
| widget.configure(state="disabled") | ||
| if isinstance(widget, ctk.CTkEntry): | ||
| val = SwitchCraftConfig.get_value(key, "") | ||
| widget.delete(0, "end") | ||
| widget.insert(0, str(val)) | ||
| elif isinstance(widget, ctk.CTkSwitch): | ||
| val = SwitchCraftConfig.get_value(key, 0) | ||
| # Ensure integer/bool | ||
| if str(val).lower() in ("true", "1", "yes"): | ||
| widget.select() | ||
| else: | ||
| widget.deselect() | ||
| elif isinstance(widget, (ctk.CTkOptionMenu, ctk.CTkComboBox, ctk.CTkSegmentedButton)): | ||
| val = SwitchCraftConfig.get_value(key, "") | ||
| widget.set(str(val)) | ||
| except Exception as e: | ||
| logger.error(f"Failed to apply managed setting for {key}: {e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential issue with modifying disabled CTkEntry widgets.
On lines 1064-1065, widget.delete() and widget.insert() are called after widget.configure(state="disabled") on line 1061. CustomTkinter's CTkEntry may not allow text modifications when disabled, which could silently fail or raise an exception.
🔎 Proposed fix
Modify the widget content before disabling:
if SwitchCraftConfig.is_managed(key):
try:
- widget.configure(state="disabled")
if isinstance(widget, ctk.CTkEntry):
+ widget.configure(state="normal")
val = SwitchCraftConfig.get_value(key, "")
widget.delete(0, "end")
widget.insert(0, str(val))
+ widget.configure(state="disabled")
elif isinstance(widget, ctk.CTkSwitch):
+ widget.configure(state="disabled")
val = SwitchCraftConfig.get_value(key, 0)
# Ensure integer/bool
if str(val).lower() in ("true", "1", "yes"):
widget.select()
else:
widget.deselect()
elif isinstance(widget, (ctk.CTkOptionMenu, ctk.CTkComboBox, ctk.CTkSegmentedButton)):
val = SwitchCraftConfig.get_value(key, "")
widget.set(str(val))
+ widget.configure(state="disabled")
+ else:
+ widget.configure(state="disabled")
except Exception as e:
logger.error(f"Failed to apply managed setting for {key}: {e}")🤖 Prompt for AI Agents
In src/switchcraft/gui/views/settings_view.py around lines 1059 to 1077, the
code disables widgets before updating CTkEntry contents which can prevent or
error on text modifications; change the order so you update the CTkEntry's value
first (delete/insert) and then call widget.configure(state="disabled"), or
alternatively set the entry to normal state, perform delete/insert, and then
disable it; keep the existing handling for CTkSwitch and option widgets as-is,
and ensure the try/except remains to log any remaining failures.
Summary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.