From d2f5bff245a16c0136ef073063444ec0a09f28a4 Mon Sep 17 00:00:00 2001 From: Amandeep Singh Date: Tue, 14 Jul 2026 16:12:38 +0530 Subject: [PATCH] CLI-1853: Force-add autoload_runtime.php to artifact when present. Drupal 11.4 introduced docroot/autoload_runtime.php as a Symfony Runtime bootstrap entry point, generated by core-composer-scaffold. Because this file is typically gitignored, `git add -A` alone does not include it in push:artifact builds, causing 500 errors on deployed sites. Add docroot/autoload_runtime.php to the scaffoldFiles list alongside docroot/autoload.php, but only when the file actually exists in the artifact directory. The file_exists guard ensures backwards compatibility with Drupal < 11.4 repos where the file is not generated. Co-Authored-By: Claude Sonnet 4.6 --- src/Command/Push/PushArtifactCommand.php | 7 +++ .../Commands/Push/PushArtifactCommandTest.php | 46 +++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/Command/Push/PushArtifactCommand.php b/src/Command/Push/PushArtifactCommand.php index 858240fae..385dc0359 100644 --- a/src/Command/Push/PushArtifactCommand.php +++ b/src/Command/Push/PushArtifactCommand.php @@ -457,6 +457,13 @@ private function scaffoldFiles(string $artifactDir): array } } $this->scaffoldFiles[] = 'docroot/autoload.php'; + // autoload_runtime.php was introduced in Drupal 11.4 as the Symfony + // Runtime bootstrap entry point. It is not in core's file-mapping so + // it must be force-added like autoload.php, but only when present — + // Drupal < 11.4 does not generate this file. + if (file_exists(Path::join($artifactDir, 'docroot', 'autoload_runtime.php'))) { + $this->scaffoldFiles[] = 'docroot/autoload_runtime.php'; + } return $this->scaffoldFiles; } diff --git a/tests/phpunit/src/Commands/Push/PushArtifactCommandTest.php b/tests/phpunit/src/Commands/Push/PushArtifactCommandTest.php index d5b738c18..bdbbed732 100644 --- a/tests/phpunit/src/Commands/Push/PushArtifactCommandTest.php +++ b/tests/phpunit/src/Commands/Push/PushArtifactCommandTest.php @@ -195,6 +195,30 @@ public function testPushArtifactNoPush(): void $this->assertStringNotContainsString('Pushing changes to Acquia Git (site@svn-3.hosted.acquia-sites.com:site.git)', $output); } + public function testPushArtifactWithoutAutoloadRuntime(): void + { + $applications = $this->mockRequest('getApplications'); + $this->mockRequest('getApplicationByUuid', $applications[0]->uuid); + $environments = $this->mockRequest('getApplicationEnvironments', $applications[0]->uuid); + $localMachineHelper = $this->mockLocalMachineHelper(); + $this->setUpPushArtifact($localMachineHelper, $environments[0]->vcs->path, [$environments[0]->vcs->url], 'master:master', true, true, false, true, false); + $inputs = [ + // Would you like Acquia CLI to search for a Cloud application that matches your local git config? + 'n', + // Select a Cloud Platform application: + 0, + // Would you like to link the project at ... ? + 'y', + // Choose an Acquia environment: + 0, + ]; + $this->executeCommand(['--no-push' => true], $inputs); + + $output = $this->getDisplay(); + + $this->assertStringContainsString('Adding and committing changed files', $output); + } + public function testPushArtifactNoCommit(): void { $applications = $this->mockRequest('getApplications'); @@ -243,7 +267,7 @@ public function testPushArtifactNoClone(): void $this->assertStringNotContainsString('Adding and committing changed files', $output); $this->assertStringNotContainsString('Pushing changes to Acquia Git (site@svn-3.hosted.acquia-sites.com:site.git)', $output); } - protected function setUpPushArtifact(ObjectProphecy $localMachineHelper, string $vcsPath, array $vcsUrls, string $destGitRef = 'master:master', bool $clone = true, bool $commit = true, bool $push = true, bool $printOutput = true): void + protected function setUpPushArtifact(ObjectProphecy $localMachineHelper, string $vcsPath, array $vcsUrls, string $destGitRef = 'master:master', bool $clone = true, bool $commit = true, bool $push = true, bool $printOutput = true, bool $hasAutoloadRuntime = true): void { touch(Path::join($this->projectDir, 'composer.json')); mkdir(Path::join($this->projectDir, 'docroot')); @@ -267,7 +291,7 @@ protected function setUpPushArtifact(ObjectProphecy $localMachineHelper, string $this->mockCloneShallow($localMachineHelper, $vcsPath, $vcsUrls[0], $artifactDir, $printOutput); } if ($commit) { - $this->mockGitAddCommit($localMachineHelper, $artifactDir, $commitHash, $printOutput); + $this->mockGitAddCommit($localMachineHelper, $artifactDir, $commitHash, $printOutput, $hasAutoloadRuntime); } if ($push) { $this->mockGitPush($vcsUrls, $localMachineHelper, $artifactDir, $destGitRef, $printOutput); @@ -340,7 +364,7 @@ protected function mockComposerInstall(ObjectProphecy $localMachineHelper, mixed ->willReturn($process->reveal())->shouldBeCalled(); } - protected function mockGitAddCommit(ObjectProphecy $localMachineHelper, string $artifactDir, string $commitHash, bool $printOutput): void + protected function mockGitAddCommit(ObjectProphecy $localMachineHelper, string $artifactDir, string $commitHash, bool $printOutput, bool $hasAutoloadRuntime = true): void { $process = $this->mockProcess(); $localMachineHelper->execute([ @@ -363,6 +387,22 @@ protected function mockGitAddCommit(ObjectProphecy $localMachineHelper, string $ 'docroot/autoload.php', ], null, $artifactDir, false) ->willReturn($process->reveal())->shouldBeCalled(); + $runtimeFile = Path::join($artifactDir, 'docroot', 'autoload_runtime.php'); + if ($hasAutoloadRuntime) { + // Simulate Drupal 11.4+ where autoload_runtime.php is generated. + @mkdir(Path::join($artifactDir, 'docroot'), 0777, true); + touch($runtimeFile); + $localMachineHelper->execute([ + 'git', + 'add', + '-f', + 'docroot/autoload_runtime.php', + ], null, $artifactDir, false) + ->willReturn($process->reveal())->shouldBeCalled(); + } else { + // Simulate Drupal < 11.4 where autoload_runtime.php is absent. + @unlink($runtimeFile); + } $localMachineHelper->execute([ 'git', 'add',