Skip to content
Open
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
3 changes: 1 addition & 2 deletions .github/workflows/docs_preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,14 @@ jobs:
run: npm run docs:build
working-directory: docs
env:
BASE_URL: /SwitchCraft/pr-preview/pr-${{ github.event.pull_request.number }}/
BASE_URL: /pr-preview/pr-${{ github.event.pull_request.number }}/

- name: Deploy Preview
uses: rossjrw/pr-preview-action@v1
with:
source-dir: docs/.vitepress/dist
preview-branch: gh-pages
umbrella-dir: pr-preview
pages-base-path: /SwitchCraft
action: auto

cleanup-preview:
Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ jobs:
# Beta/Stable: remove commit ID if present (e.g., "2026.1.2b1" or "2026.1.2")
APP_VERSION=$(echo "$VERSION" | sed -E 's/\+[a-zA-Z0-9.-]+$//')
fi
sed -i "s/#define MyAppVersion \".*\"/#define MyAppVersion \"$APP_VERSION\"/" switchcraft_modern.iss
sed -i "s/#define MyAppVersionNumeric \".*\"/#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_modern.iss
sed -i "s/#define MyAppVersionInfo \".*\"/#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_modern.iss
sed -i "s/#define MyAppVersion \".*\"/#define MyAppVersion \"$APP_VERSION\"/" switchcraft_legacy.iss
sed -i "s/#define MyAppVersionNumeric \".*\"/#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_legacy.iss
sed -i "s/#define MyAppVersionInfo \".*\"/#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_legacy.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersion \".*\"/\1#define MyAppVersion \"$APP_VERSION\"/" switchcraft_modern.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionNumeric \".*\"/\1#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_modern.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionInfo \".*\"/\1#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_modern.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersion \".*\"/\1#define MyAppVersion \"$APP_VERSION\"/" switchcraft_legacy.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionNumeric \".*\"/\1#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_legacy.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionInfo \".*\"/\1#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_legacy.iss

- name: Generate Changelog
id: changelog
Expand Down Expand Up @@ -192,12 +192,12 @@ jobs:
VERSION_INFO="${BASE_VERSION}.0"
# For dev releases: MyAppVersion should include commit ID (full DEV_VERSION)
# MyAppVersionNumeric should be numeric only (BASE_VERSION)
sed -i "s/#define MyAppVersion \".*\"/#define MyAppVersion \"$DEV_VERSION\"/" switchcraft_modern.iss
sed -i "s/#define MyAppVersionNumeric \".*\"/#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_modern.iss
sed -i "s/#define MyAppVersionInfo \".*\"/#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_modern.iss
sed -i "s/#define MyAppVersion \".*\"/#define MyAppVersion \"$DEV_VERSION\"/" switchcraft_legacy.iss
sed -i "s/#define MyAppVersionNumeric \".*\"/#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_legacy.iss
sed -i "s/#define MyAppVersionInfo \".*\"/#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_legacy.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersion \".*\"/\1#define MyAppVersion \"$DEV_VERSION\"/" switchcraft_modern.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionNumeric \".*\"/\1#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_modern.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionInfo \".*\"/\1#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_modern.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersion \".*\"/\1#define MyAppVersion \"$DEV_VERSION\"/" switchcraft_legacy.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionNumeric \".*\"/\1#define MyAppVersionNumeric \"$BASE_VERSION\"/" switchcraft_legacy.iss
sed -i "s/^\([[:space:]]*\)#define MyAppVersionInfo \".*\"/\1#define MyAppVersionInfo \"$VERSION_INFO\"/" switchcraft_legacy.iss

# Update fallback versions in build scripts and version generator
# Update build_release.ps1 fallback
Expand Down
55 changes: 53 additions & 2 deletions .github/workflows/review-auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,57 @@ jobs:
fi
fi

# 3. Check Coderabbit Status
# 3. Check for Review Comments (especially CodeRabbit feedback)
echo "Checking for review comments in code..."

# Get all review comments on code (inline comments with position/diff_hunk)
# These are comments that reviewers leave on specific lines of code
INLINE_REVIEW_COMMENTS=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments" --paginate --jq '[.[] | select(.position != null or .original_position != null) | select(.user.login != "github-actions[bot]")] | length')

# Check for CodeRabbit review comments specifically (both inline and general)
CODERABBIT_INLINE=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments" --paginate --jq '[.[] | select(.user.login == "coderabbitai[bot]" and (.position != null or .original_position != null))] | length')

# Also check for CodeRabbit review comments in PR comments (not just inline)
CODERABBIT_PR_COMMENTS=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --paginate --jq '[.[] | select(.user.login == "coderabbitai[bot]" and (.body | test("suggestion|review|feedback|issue|problem|error|warning"; "i")))] | length')

TOTAL_CODERABBIT_COMMENTS=$((CODERABBIT_INLINE + CODERABBIT_PR_COMMENTS))

# If there are any inline review comments (from any reviewer, especially CodeRabbit), skip auto-merge
if [[ "$INLINE_REVIEW_COMMENTS" -gt 0 ]] || [[ "$CODERABBIT_PR_COMMENTS" -gt 0 ]]; then
echo "::notice::Review comments found ($INLINE_REVIEW_COMMENTS inline, $CODERABBIT_INLINE from CodeRabbit inline, $CODERABBIT_PR_COMMENTS from CodeRabbit PR comments). Auto-merge skipped."

# Check if comment already exists to avoid duplicates
COMMENT_EXISTS=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.body | contains("Auto-Merge Skipped") and contains("review comments")) | .id' | head -n 1)
if [[ -z "$COMMENT_EXISTS" ]]; then
# Post a comment explaining why auto-merge was skipped
BODY=$'🚫 **Auto-Merge Skipped**\n\nAuto-merge was not executed because review comments were found in the code.\n\n'
if [[ "$CODERABBIT_INLINE" -gt 0 ]] || [[ "$CODERABBIT_PR_COMMENTS" -gt 0 ]]; then
BODY+="CodeRabbit has left "
if [[ "$CODERABBIT_INLINE" -gt 0 ]] && [[ "$CODERABBIT_PR_COMMENTS" -gt 0 ]]; then
BODY+="$CODERABBIT_INLINE inline comment(s) and $CODERABBIT_PR_COMMENTS PR comment(s)"
elif [[ "$CODERABBIT_INLINE" -gt 0 ]]; then
BODY+="$CODERABBIT_INLINE inline comment(s)"
else
BODY+="$CODERABBIT_PR_COMMENTS PR comment(s)"
fi
BODY+=" that need to be addressed.\n\n"
fi
if [[ "$INLINE_REVIEW_COMMENTS" -gt 0 ]]; then
BODY+="There are $INLINE_REVIEW_COMMENTS inline review comment(s) in the code that need attention"
if [[ "$CODERABBIT_INLINE" -gt 0 ]]; then
BODY+=" ($CODERABBIT_INLINE from CodeRabbit)"
fi
BODY+=".\n\n"
fi
BODY+="Please review and address the feedback before merging.\n\n"
BODY+="Once all review comments are resolved and CI workflows pass, auto-merge will proceed."
gh pr comment "$PR_NUMBER" --body "$BODY"
fi
exit 0
fi
echo "No review comments found. Proceeding..."

# 4. Check Coderabbit Status (approval or skip)
echo "Checking Coderabbit status..."
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)
Expand All @@ -87,5 +137,6 @@ jobs:
exit 0
fi

# 4. Attempt Merge
# 5. Attempt Merge
echo "All checks passed. Attempting auto-merge..."
gh pr merge "$PR_NUMBER" --merge --auto --delete-branch
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,5 @@ mock_script.ps1
test_output.ps1
/docs/node_modules
/docs/.vitepress
verification_output*.txt
debug_output.txt
4 changes: 2 additions & 2 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default defineConfig({
items: [
{ text: 'Intune Integration', link: '/INTUNE' },
{ text: 'Intune Setup Guide', link: '/INTUNE_SETUP' },
{ text: 'OMA-URI Reference', link: '/IntuneConfig' },
{ text: 'OMA-URI Reference', link: '/Intune_Configuration_Guide' },
{ text: 'GPO / ADMX Policies', link: '/PolicyDefinitions/README' },
{ text: 'Registry Settings', link: '/Registry' },
{ text: 'Security Guide', link: '/SECURITY' }
Expand Down Expand Up @@ -80,7 +80,7 @@ export default defineConfig({
items: [
{ text: 'Intune Integration', link: '/INTUNE' },
{ text: 'Intune Setup Guide', link: '/INTUNE_SETUP' },
{ text: 'OMA-URI Reference', link: '/IntuneConfig' },
{ text: 'OMA-URI Reference', link: '/Intune_Configuration_Guide' },
{ text: 'GPO / ADMX Policies', link: '/PolicyDefinitions/README' },
{ text: 'Registry Settings', link: '/Registry' },
{ text: 'Security Guide', link: '/SECURITY' }
Expand Down
159 changes: 159 additions & 0 deletions docs/GPO_TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# GPO/Intune Troubleshooting Guide

> [!TIP]
> **Quick Help**: If you see a list of failed policies (like `SignScripts_Enf`, `UpdateChannel_Enf`, etc. all with error -2016281112), read the [detailed troubleshooting guide](./INTUNE_ERROR_FIX.md) first.

## Error Code -2016281112 (Remediation Failed)

If you see error code **-2016281112** for your SwitchCraft policies in Intune, this means "Remediation failed" - the policy could not be applied to the device.

### Common Causes

1. **Incorrect Data Type**
- **Problem**: Using "Integer" or "Boolean" instead of "String"
- **Solution**: All ADMX-backed policies MUST use **String** (or "String (XML)") as the Data Type
- **Example Error**: `DebugMode_Enf Integer` - The "Integer" suffix indicates wrong data type

2. **ADMX Not Installed**
- **Problem**: The ADMX file was not ingested before configuring policies
- **Solution**: Ensure the ADMX ingestion policy shows "Succeeded" status:
- OMA-URI: `./Device/Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/switchcraft/Policy/SwitchCraftPolicy`
- Data Type: **String**
- Value: Full content of `SwitchCraft.admx` file

3. **Incorrect OMA-URI Path**
- **Problem**: Wrong path structure or typos in the OMA-URI
- **Solution**: Verify the exact path matches the documentation:
- Base: `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced`
- Category suffix: `~[Category]_Enf/[PolicyName]_Enf`
- Example: `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~General_Enf/CompanyName_Enf`

4. **Malformed XML Value**
- **Problem**: Invalid XML structure in the Value field
- **Solution**: Ensure the XML follows the correct format:
- For enabled/disabled policies: `<enabled/>` or `<disabled/>`
- For policies with data: `<enabled/><data id="[ElementId]" value="[Value]"/>`
- **Common Mistakes**:
- Missing closing tags
- Wrong element IDs (must match ADMX file)
- Special characters not properly escaped

5. **Windows Version Compatibility**
- **Problem**: Policy not supported on the target Windows version
- **Solution**: Ensure devices are running Windows 10/11 (policies require Windows 10+)

6. **Registry Permissions**
- **Problem**: Insufficient permissions to write to `HKCU\Software\Policies\FaserF\SwitchCraft`
- **Solution**: Verify the user has write access to their own HKCU registry hive

### Step-by-Step Troubleshooting

#### Step 1: Verify ADMX Installation

Check if the ADMX ingestion policy is successful:
- Go to Intune Portal → Devices → Configuration Profiles
- Find the profile containing the ADMX ingestion policy
- Verify status is "Succeeded" (not "Error")

If it shows "Error":
1. Re-upload the ADMX file content
2. Ensure the entire file is copied (including XML header)
3. Verify no special characters were corrupted during copy-paste

#### Step 2: Check Data Types

For each policy showing error -2016281112:
1. Open the policy configuration in Intune
2. Verify **Data Type** is set to **"String"** (NOT "Integer" or "Boolean")
3. If wrong, delete and recreate the policy with correct Data Type

#### Step 3: Validate OMA-URI Paths

Compare your OMA-URI paths with the reference table:

| Policy | Correct OMA-URI |
|--------|----------------|
| Debug Mode | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced/DebugMode_Enf` |
| Update Channel | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~Updates_Enf/UpdateChannel_Enf` |
| Company Name | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~General_Enf/CompanyName_Enf` |
| Enable Winget | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~General_Enf/EnableWinget_Enf` |
| Graph Tenant ID | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~Intune_Enf/GraphTenantId_Enf` |
| Graph Client ID | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~Intune_Enf/GraphClientId_Enf` |
| Graph Client Secret | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~Intune_Enf/GraphClientSecret_Enf` |
| Intune Test Groups | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~Intune_Enf/IntuneTestGroups_Enf` |
| Sign Scripts | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~Security_Enf/SignScripts_Enf` |
| AI Provider | `./User/Vendor/MSFT/Policy/Config/switchcraft~Policy~FaserF~SwitchCraft~Enforced~AI_Enf/AIProvider_Enf` |

**Important Notes:**
- Use `~` (tilde) to separate namespace parts, NOT `/` (slash)
- Category names end with `_Enf` (e.g., `General_Enf`, `Intune_Enf`)
- Policy names end with `_Enf` (e.g., `DebugMode_Enf`, `CompanyName_Enf`)

#### Step 4: Validate XML Values

Verify the XML structure matches the expected format:

**For Boolean Policies (Enable/Disable):**
```xml
<enabled/>
```
or
```xml
<disabled/>
```

**For Policies with Data:**
```xml
<enabled/>
<data id="CompanyNameBox" value="Your Company Name"/>
```

**Element IDs must match the ADMX file:**
- `CompanyNameBox` (not `CompanyName` or `CompanyName_Enf`)
- `GraphTenantIdBox` (not `GraphTenantId` or `TenantId`)
- `UpdateChannelDropdown` (not `UpdateChannel` or `Channel`)
- `LanguageDropdown` (not `Language` or `Lang`)

#### Step 5: Test on Device

1. **Sync Policy**: On the target device, run:
```powershell
gpupdate /force
```
Or trigger a sync from Intune Portal → Devices → [Device] → Sync

2. **Check Registry**: Verify the policy was applied:
```powershell
Get-ItemProperty -Path "HKCU:\Software\Policies\FaserF\SwitchCraft" -ErrorAction SilentlyContinue
```

3. **Check Event Logs**: Look for Group Policy errors:
```powershell
Get-WinEvent -LogName "Microsoft-Windows-User Device Registration/Admin" | Where-Object {$_.LevelDisplayName -eq "Error"}
```

### Quick Fix Checklist

- [ ] ADMX ingestion policy shows "Succeeded"
- [ ] All policy Data Types are set to "String"
- [ ] OMA-URI paths match documentation exactly (including tildes)
- [ ] XML values use correct format (`<enabled/>` or `<enabled/><data id="..." value="..."/>`)
- [ ] Element IDs match ADMX file (e.g., `CompanyNameBox`, not `CompanyName`)
- [ ] Device has synced policies (`gpupdate /force`)
- [ ] Registry key exists: `HKCU\Software\Policies\FaserF\SwitchCraft`

### Still Not Working?

If policies still fail after following all steps:

1. **Delete and Recreate**: Remove all failing policies and recreate them from scratch
2. **Re-upload ADMX**: Delete and recreate the ADMX ingestion policy
3. **Check Intune Logs**: Review device compliance logs in Intune Portal
4. **Test with Single Policy**: Create a test profile with only one policy to isolate the issue
5. **Verify Windows Version**: Ensure target devices are Windows 10 1809+ or Windows 11

### Additional Resources

- [Intune Configuration Guide](./Intune_Configuration_Guide.md)
- [Policy Definitions README](./PolicyDefinitions/README.md)
- [Microsoft Docs: ADMX Ingestion](https://learn.microsoft.com/en-us/mem/intune/configuration/administrative-templates-windows)
Loading
Loading