Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -688,14 +688,8 @@ using System;using System.Collections.Generic;using System.IO;using System.Net;u
$confirmMigrationParameters = Confirm-MigrationParameter -dataSource $dataSource -csvName $csvName -TempPassword $TempPassword -LeaveDomain $LeaveDomain -ForceReboot $ForceReboot -UpdateHomePath $UpdateHomePath -AutoBindJCUser $AutoBindJCUser -PrimaryUser $PrimaryUser -BindAsAdmin $BindAsAdmin -SetDefaultWindowsUser $SetDefaultWindowsUser -systemContextBinding $systemContextBinding -JumpCloudAPIKey $JumpCloudAPIKey -JumpCloudOrgID $JumpCloudOrgID -postMigrationBehavior $postMigrationBehavior -removeMDM $removeMDM -ReportStatus $ReportStatus -localEXEs $localEXEs -SetFullPermission $SetFullPermission -BlockAccountLogin $BlockAccountLogin -bypassExeValidation $bypassExeValidation
if ($confirmMigrationParameters) { Write-Host "[STATUS] Migration parameters validated successfully." }

try {
$localExeValidation = Test-RequiredLocalExeFiles -localEXEs $localEXEs
if ($localExeValidation) { Write-Host "[STATUS] Local executable pre-check completed successfully." }
} catch {
Write-Host "[ERROR] Local executable validation failed: $_"
exit 1
}
#endregion validation

#region dataImport
if ($dataSource -eq 'CSV') {
Write-Host "[status] Using CSV source..."
Expand All @@ -709,8 +703,20 @@ try {
Write-Host "[ERROR] Failed to retrieve migration users: $_"
exit 1
}
#endregion dataImport
if (-not $UsersToMigrate) { Write-Host "[status] No users to migrate, exiting..."; exit 1 }
#endregion dataImport

#region exeValidation
try {
$localExeValidation = Test-RequiredLocalExeFiles -localEXEs $localEXEs
if ($localExeValidation) { Write-Host "[STATUS] Local executable pre-check completed successfully." }
} catch {
Write-Host "[ERROR] Local executable validation failed: $_"
exit 1
}
$guiJcadmuPath = Get-LatestADMUGUIExe -useLocalEXEs $localEXEs -BypassValidation $bypassExeValidation
#endregion exeValidation

Comment on lines 706 to +719

@coderabbitai coderabbitai Bot Jul 1, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Early-exit uses failure exit code for a benign "no users" state.

The new early exit at Line 706 calls exit 1 when $UsersToMigrate is empty. For the Description data source, Get-MgUserFromDesc returns $null simply when there are no pending users to migrate (e.g., all users already migrated, or a routine check-in) — this is not necessarily an error condition. Exiting with code 1 will likely be recorded as a failed JumpCloud command run, which can generate false-positive failure alerts for otherwise-healthy systems.

This also appears to be genuinely new behavior (per the AI summary), which conflicts with the PR description's statement that no new behavior beyond reordering is expected.

Consider using exit 0 for this no-op case, or reserve exit 1 for genuine failures.

💡 Proposed fix
-if (-not $UsersToMigrate) { Write-Host "[status] No users to migrate, exiting..."; exit 1 }
+if (-not $UsersToMigrate) { Write-Host "[status] No users to migrate, exiting..."; exit 0 }
📝 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.

Suggested change
if (-not $UsersToMigrate) { Write-Host "[status] No users to migrate, exiting..."; exit 1 }
#endregion dataImport
#region exeValidation
try {
$localExeValidation = Test-RequiredLocalExeFiles -localEXEs $localEXEs
if ($localExeValidation) { Write-Host "[STATUS] Local executable pre-check completed successfully." }
} catch {
Write-Host "[ERROR] Local executable validation failed: $_"
exit 1
}
$guiJcadmuPath = Get-LatestADMUGUIExe -useLocalEXEs $localEXEs -BypassValidation $bypassExeValidation
#endregion exeValidation
if (-not $UsersToMigrate) { Write-Host "[status] No users to migrate, exiting..."; exit 0 }
`#endregion` dataImport
`#region` exeValidation
try {
$localExeValidation = Test-RequiredLocalExeFiles -localEXEs $localEXEs
if ($localExeValidation) { Write-Host "[STATUS] Local executable pre-check completed successfully." }
} catch {
Write-Host "[ERROR] Local executable validation failed: $_"
exit 1
}
$guiJcadmuPath = Get-LatestADMUGUIExe -useLocalEXEs $localEXEs -BypassValidation $bypassExeValidation
`#endregion` exeValidation
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jumpcloud-ADMU-Advanced-Deployment/InvokeFromJCAgent/3_ADMU_Invoke.ps1`
around lines 706 - 719, The early-exit in the $UsersToMigrate check currently
treats a benign “no users to migrate” state as a failure. Update the exit path
near the initial data import logic so the no-op case returns a success code
instead of failing the JumpCloud run, and keep exit 1 only for real errors in
the surrounding migration flow. Use the $UsersToMigrate check and the existing
exeValidation block as anchors when making the change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is correct, if there are no users to migrate, we do want to throw an exit 1 to indicate something happened that we didn't expect. In this context an exit code 1 is good enough to denote there was an error with data prep. If no users are able to migrated I want an exit code 1.

An alternative would be to define a table of new exit codes:
1 error
2 no users to migrate
3 data validation error etc

The team can take this back and work as a separate card but for this change it's fine to keep it as is.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@jworkmanjc, understood — thanks for the clarification. Keeping exit 1 for the "no users to migrate" case makes sense given the current convention of using exit 1 to denote any unexpected/error condition in this script. The idea of a structured exit code table (e.g., 1=error, 2=no users, 3=data validation) is a nice enhancement for more granular alerting/triage, but agreed that's reasonable to defer as a separate follow-up card rather than bundling it into this reorder-focused PR.

Let me know if you'd like me to open a follow-up issue to track the structured exit code idea.


✏️ Learnings added
Learnt from: jworkmanjc
Repo: TheJumpCloud/jumpcloud-ADMU PR: 270
File: jumpcloud-ADMU-Advanced-Deployment/InvokeFromJCAgent/3_ADMU_Invoke.ps1:706-719
Timestamp: 2026-07-01T17:19:18.338Z
Learning: In `jumpcloud-ADMU-Advanced-Deployment/InvokeFromJCAgent/3_ADMU_Invoke.ps1` (JumpCloud ADMU Invoke Script), when `$UsersToMigrate` is empty/null after the data import step, the script intentionally exits with `exit 1` (not `exit 0`), even though this can represent a benign "no pending users" state (e.g., via `Get-MgUserFromDesc`). This is a deliberate design choice by the team (per maintainer jworkmanjc): exit code 1 is used broadly to denote "something happened that we didn't expect" including data prep issues, not just hard failures. A future enhancement being considered (not yet planned) is a structured exit code table (e.g., 1=general error, 2=no users to migrate, 3=data validation error) to allow finer-grained alerting, but this exit-code granularity work is out of scope for reorder-focused PRs and would be tracked as a separate card.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

#region logoffUsers
$loggedInUsers = (quser) -replace '^>', ' ' | ForEach-Object -Process { $_ -replace '\s{2,}', ',' }
$processedUsers = @()
Expand All @@ -725,7 +731,6 @@ foreach ($user in $UsersList) {
logoff.exe $($user.ID)
}
}
#endregion logoffUsers
if ($LeaveDomain) {
$LeaveDomain = $false
Write-Host "[status] Domain will be un-joined for last user migrated"
Expand All @@ -736,9 +741,9 @@ if ($ForceReboot) {
Write-Host "[status] System will $postMigrationBehavior after last user is migrated"
$ForceRebootAfterMigration = $true
}
#endregion logoffUsers (implied)
#endregion logoffUsers

#region migration
$guiJcadmuPath = Get-LatestADMUGUIExe -useLocalEXEs $localEXEs -BypassValidation $bypassExeValidation
$migrationResults = Invoke-UserMigrationBatch -UsersToMigrate $UsersToMigrate -MigrationConfig @{
TempPassword = $TempPassword
UpdateHomePath = $UpdateHomePath
Expand Down