Skip to content

Fix localhive CLI publish copy#17670

Merged
sebastienros merged 3 commits into
mainfrom
sebastienros/fix-localhive-recursive-copy
May 29, 2026
Merged

Fix localhive CLI publish copy#17670
sebastienros merged 3 commits into
mainfrom
sebastienros/fix-localhive-recursive-copy

Conversation

@sebastienros
Copy link
Copy Markdown
Contributor

Description

Fixes localhive.sh CLI installation when the publish output contains subdirectories, such as culture-specific resource folders.

The failing path was using:

cp -f "$CLI_PUBLISH_DIR"/* "$CLI_BIN_DIR"/

That wildcard expands both files and directories. On macOS/BSD cp, a publish resource directory such as fr/ causes an error like cp: .../fr is a directory (not copied); on Linux/GNU cp, the equivalent is cp: -r not specified; omitting directory '...'. Because the script runs with set -e and checks the cp result, it then aborted with the localhive error path: Failed to copy CLI files from $CLI_PUBLISH_DIR to $CLI_BIN_DIR.

This changes the install copy to recursively copy the publish directory contents:

cp -Rf "$CLI_PUBLISH_DIR"/. "$CLI_BIN_DIR"/

Using /. preserves the intended contents-copy behavior while allowing both files and directories to be installed.

Validation:

bash -n localhive.sh
dotnet test --project tests/Aspire.Acquisition.Tests/Aspire.Acquisition.Tests.csproj --no-launch-profile -- --filter-class "*.LocalHiveScriptFunctionTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"

Also manually validated the copy command against a temporary publish directory containing a nested culture/resource folder.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Copy publish directory contents recursively so localized resource folders and other subdirectories are installed with the Aspire CLI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 17:08
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17670

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17670"

Copy link
Copy Markdown
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 fixes localhive.sh CLI installation when the dotnet publish output contains subdirectories (e.g., culture/resource folders). It replaces a glob-based cp that fails on directories with a recursive contents copy that works across BSD/macOS and GNU/Linux cp.

Changes:

  • Switch CLI publish output copy from cp "$dir"/* to cp -R "$dir"/. to correctly copy both files and subdirectories.
  • Update the in-script comment to reflect directory-copy behavior.

@github-actions
Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 108 passed, 0 failed, 2 unknown (commit 41ae60b)

View all recordings
Status Test Recording Job Artifacts
AddPackageInteractiveWhileAppHostRunningDetached Recording #78552052659 Logs
AddPackageWhileAppHostRunningDetached Recording #78552052659 Logs
AgentCommands_AllHelpOutputs_AreCorrect Recording #78552052528 Logs
AgentInitCommand_DefaultSelection_InstallsDefaultSkills Recording #78552052528 Logs
AgentInitCommand_MigratesDeprecatedConfig Recording #78552052528 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp Recording #78552053142 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_DevLocalhost Recording #78552053142 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_Isolated Recording #78552053142 Logs
AllPublishMethodsBuildDockerImages Recording #78552052281 Logs
AspireAddAndStartWorkAgainstLegacyAppHostTs Recording #78552052364 Logs
AspireAddPackageVersionToDirectoryPackagesProps Recording #78552053349 Logs
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost Recording #78552052459 Logs
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles Recording #78552053113 Logs
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive Recording #78552053113 Logs
AspireStartUpdatesStaleTypeScriptAppHostPath Recording #78552053287 Logs
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps Recording #78552053349 Logs
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent Recording #78552053349 Logs
Banner_DisplayedOnFirstRun Recording #78552052803 Logs
Banner_DisplayedWithExplicitFlag Recording #78552052803 Logs
Banner_NotDisplayedWithNoLogoFlag Recording #78552052803 Logs
CertificatesClean_RemovesCertificates Recording #78552052379 Logs
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate Recording #78552052379 Logs
CertificatesTrust_WithUntrustedCert_TrustsCertificate Recording #78552052379 Logs
ConfigSetGet_CreatesNestedJsonFormat Recording #78552052375 Logs
CreateAndRunAspireStarterProject Recording #78552053354 Logs
CreateAndRunAspireStarterProjectWithBundle Recording #78552052531 Logs
CreateAndRunEmptyAppHostProject Recording #78552053014 Logs
CreateAndRunJavaEmptyAppHostProject Recording #78552053181 Logs
CreateAndRunJsReactProject Recording #78552052311 Logs
CreateAndRunPolyglotAppHostWithDevLocalhostUrls Recording #78552053354 Logs
CreateAndRunPythonReactProject Recording #78552053242 Logs
CreateAndRunTypeScriptEmptyAppHostProject Recording #78552053115 Logs
CreateAndRunTypeScriptStarterProject Recording #78552052389 Logs
CreateJavaAppHostWithViteApp Recording #78552052964 Logs
CreateTypeScriptAppHostWithViteApp_AllowsGuestAppPackageManagerToDiffer Recording #78552052544 Logs
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain Recording #78552052544 Logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces Recording #78552052388 Logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces_DevLocalhost Recording #78552052388 Logs
DashboardRunWithOtelTracesReturnsNoTraces Recording #78552052388 Logs
DashboardRunWithOtelTracesReturnsNoTraces_DevLocalhost Recording #78552052388 Logs
DeployK8sBasicApiService Recording #78552052316 Logs
DeployK8sWithExternalHelmChart Recording #78552053157 Logs
DeployK8sWithGarnet Recording #78552052740 Logs
DeployK8sWithMongoDB Recording #78552053285 Logs
DeployK8sWithMySql Recording #78552052372 Logs
DeployK8sWithPostgres Recording #78552052263 Logs
DeployK8sWithRabbitMQ Recording #78552053338 Logs
DeployK8sWithRedis Recording #78552053535 Logs
DeployK8sWithSqlServer Recording #78552053216 Logs
DeployK8sWithValkey Recording #78552052756 Logs
DeployTypeScriptAppToKubernetes Recording #78552052666 Logs
DescribeCommandResolvesReplicaNames Recording #78552053019 Logs
DescribeCommandShowsRunningResources Recording #78552053019 Logs
DetachFormatJsonProducesValidJson Recording #78552052691 Logs
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance Recording #78552052691 Logs
DoPublishAndDeployListStepsWork Recording #78552053335 Logs
DocsCommand_RendersInteractiveMarkdownFromLocalSource Recording #78552053012 Logs
DoctorCommand_DetectsDeprecatedAgentConfig Recording #78552052528 Logs
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain Recording #78552053104 Logs
DoctorCommand_WithSslCertDir_ShowsTrusted Recording #78552053104 Logs
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted Recording #78552053104 Logs
GatewayWithoutExternalEndpoint_FailsPublishWithGuidance Recording #78552053308 Logs
GeneratedAspireDevScript_StartsWatchMode_WithConfiguredToolchain Recording #78552052544 Logs
GlobalMigration_HandlesCommentsAndTrailingCommas Recording #78552052375 Logs
GlobalMigration_HandlesMalformedLegacyJson Recording #78552052375 Logs
GlobalMigration_PreservesAllValueTypes Recording #78552052375 Logs
GlobalMigration_SkipsWhenNewConfigExists Recording #78552052375 Logs
GlobalSettings_MigratedFromLegacyFormat Recording #78552052375 Logs
IngressWithoutExternalEndpoint_FailsPublishWithGuidance Recording #78552053308 Logs
InitTypeScriptAppHost_AugmentsExistingViteRepoInWorkspaceSubdirectory Recording #78552052544 Logs
InteractiveCSharpInitCreatesExpectedFiles Recording #78552053272 Logs
InvalidAppHostPathWithComments_IsHealedOnRun Recording #78552052367 Logs
JavaScriptHostingApisRunFromTypeScriptAppHost Recording #78552052281 Logs
LatestCliCanStartStableChannelAppHost Recording #78552053354 Logs
LatestCliCanStartStableChannelTypeScriptAppHost Recording #78552053354 Logs
LegacySettingsMigration_AdjustsRelativeAppHostPath Recording #78552053287 Logs
LogsCommandShowsResourceLogs Recording #78552053390 Logs
OtelLogsReturnsStructuredLogsFromStarterApp Recording #78552052348 Logs
OtelLogsReturnsStructuredLogsFromStarterAppIsolated Recording #78552052348 Logs
PsCommandListsRunningAppHost Recording #78552052454 Logs
PsFormatJsonOutputsOnlyJsonToStdout Recording #78552052454 Logs
PublishJavaScriptPatternsGeneratesExpectedDockerComposeArtifacts Recording #78552052441 Logs
PublishWithConfigureEnvFileUpdatesEnvOutput Recording #78552052441 Logs
PublishWithDockerComposeServiceCallbackSucceeds Recording #78552052441 Logs
PublishWithoutOutputPathUsesAppHostDirectoryDefault Recording #78552052441 Logs
ResourceCommand_FailedExecution_DisplaysAppHostLogPathAndLogContainsEntries Recording #78552053385 Logs
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput Recording #78552053385 Logs
RestoreGeneratesSdkFiles Recording #78552053152 Logs
RestoreGeneratesSdkFiles_WithConfiguredToolchain Recording #78552052592 Logs
RestoreRefreshesGeneratedSdkAfterAddingIntegration Recording #78552052592 Logs
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes Recording #78552053315 Logs
RunFromParentDirectory_UsesExistingConfigNearAppHost Recording #78552052825 Logs
RunReportsSyntaxErrorsForDotNetAppHost Recording #78552052845 Logs
RunReportsSyntaxErrorsForTypeScriptAppHost Recording #78552052845 Logs
SecretCrudOnDotNetAppHost Recording #78552052381 Logs
SecretCrudOnTypeScriptAppHost Recording #78552052312 Logs
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels Recording #78552052548 Logs
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets Recording #78552052628 Logs
StartReportsSyntaxErrorsForDotNetAppHost Recording #78552052845 Logs
StartReportsSyntaxErrorsForTypeScriptAppHost Recording #78552052845 Logs
StopAllAppHostsFromAppHostDirectory Recording #78552052352 Logs
StopJavaPolyglotAppHostUsingApphostDirectory Recording #78552052318 Logs
StopNonInteractiveSingleAppHost Recording #78552052352 Logs
StopTypeScriptPolyglotAppHostUsingApphostDirectory Recording #78552053205 Logs
StopWithNoRunningAppHostExitsSuccessfully Recording #78552052659 Logs
UnAwaitedChainsCompileWithAutoResolvePromises Recording #78552052592 Logs
UpdateProjectChannelToStable_CSharpEmptyAppHost_PreservesAspireConfigChannel Recording #78552052945 Logs
UpdateProjectChannelToStable_CSharpSingleFileInit_PreservesAspireConfigChannel Recording #78552052945 Logs
UpdateProjectChannelToStable_TypeScriptSingleFileInit_PreservesAspireConfigChannel Recording #78552052945 Logs
UpdateProjectChannelToStable_TypeScript_PreviewsStablePackagesAndPreservesChannel Recording #78552052945 Logs

📹 Recordings uploaded automatically from CI run #26651125653

@radical radical closed this May 29, 2026
@radical radical deleted the sebastienros/fix-localhive-recursive-copy branch May 29, 2026 19:09
@microsoft-github-policy-service microsoft-github-policy-service Bot added this to the 13.5 milestone May 29, 2026
@sebastienros sebastienros restored the sebastienros/fix-localhive-recursive-copy branch May 29, 2026 19:11
@sebastienros sebastienros reopened this May 29, 2026
@sebastienros sebastienros enabled auto-merge (squash) May 29, 2026 19:11
@sebastienros sebastienros merged commit 2cd49bd into main May 29, 2026
21 checks passed
@sebastienros sebastienros deleted the sebastienros/fix-localhive-recursive-copy branch May 29, 2026 19:13
aspire-repo-bot Bot added a commit to microsoft/aspire.dev that referenced this pull request May 29, 2026
…acOS/Linux

Documents the 'Failed to copy CLI files' error that occurs when using
localhive.sh with a publish output containing culture-specific
subdirectories (e.g., fr/, de/). The fix is to use cp -Rf with the
/.  suffix instead of a glob.

Relates to microsoft/aspire#17670

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@aspire-repo-bot
Copy link
Copy Markdown
Contributor

Pull request created: #1128

Generated by PR Documentation Check

@aspire-repo-bot
Copy link
Copy Markdown
Contributor

📝 Documentation has been drafted in microsoft/aspire.dev#1128 targeting release/13.4.

Added a "Building from source" troubleshooting section to src/frontend/src/content/docs/get-started/troubleshooting.mdx documenting the Failed to copy CLI files error that affects localhive.sh users on macOS/Linux when the publish output contains culture-specific resource subdirectories.

Note: The docs_required signal was triggered by pr_body_has_cli_flag_mention firing on dotnet test MTP filter flags in the PR's validation block — not on Aspire CLI user-facing flags. This is likely a false positive; the reviewer may close this PR if no documentation update is warranted.

Note

This draft PR needs human review before merging.

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.

3 participants