fix: harden nested package build against collisions and missing assets
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Platform: mokocli CI / Gate 1: Code Quality (pull_request) Failing after 53s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 15s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 2m32s
Platform: mokocli CI / Gate 2: Unit Tests (8.1) (pull_request) Has been cancelled
Platform: mokocli CI / Gate 2: Unit Tests (8.2) (pull_request) Has been cancelled
Platform: mokocli CI / Gate 2: Unit Tests (8.3) (pull_request) Has been cancelled
Platform: mokocli CI / Gate 3: Self-Health Check (pull_request) Has been cancelled
Platform: mokocli CI / Gate 4: Governance (pull_request) Has been cancelled
Platform: mokocli CI / Gate 5: Template Integrity (pull_request) Has been cancelled
Platform: mokocli CI / CI Summary (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled

- Write nested sub-extension ZIPs to subdirectory to prevent filename
  collisions with outer package ZIPs (deferred ZipArchive::addFile reads)
- Apply exclude patterns to nested top-level files (parity with outer)
- Patch nested manifest with folder="packages" so Joomla finds sub-ZIPs
- Include all top-level directories (not just language/) in nested packages

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
This commit is contained in:
2026-06-26 21:11:46 -05:00
parent 8e30fa54b3
commit 3c420284e3
+31 -7
View File
@@ -285,7 +285,6 @@ class ReleasePackageCli extends CliFramework
echo " Building nested package: {$subName}\n";
$nestedPkgDirs = glob("{$subSourceDir}/packages/*", GLOB_ONLYDIR) ?: [];
// Read nested manifest to filter only listed sub-extensions
$nestedManifested = [];
foreach ($nestedPkgManifests as $npmf) {
$npmXml = @simplexml_load_file($npmf);
@@ -299,12 +298,16 @@ class ReleasePackageCli extends CliFramework
}
}
// Use a subdirectory to avoid filename collisions with outer ZIPs
$nestedOutputDir = "{$outputDir}/nested_{$subName}";
@mkdir($nestedOutputDir, 0755, true);
foreach ($nestedPkgDirs as $npd) {
$nestedSubName = basename($npd);
if (!empty($nestedManifested) && !isset($nestedManifested[$nestedSubName])) {
continue;
}
$nestedSubZipPath = "{$outputDir}/{$nestedSubName}.zip";
$nestedSubZipPath = "{$nestedOutputDir}/{$nestedSubName}.zip";
$nsZip = new \ZipArchive();
if ($nsZip->open($nestedSubZipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
continue;
@@ -315,17 +318,38 @@ class ReleasePackageCli extends CliFramework
echo " Nested sub: {$nestedSubName}.zip\n";
}
// Add top-level files (manifest, script, language)
// Patch nested manifest: ensure folder="packages" so Joomla finds sub-ZIPs
foreach ($nestedPkgManifests as $npmf) {
$npmContent = file_get_contents($npmf);
if ($npmContent !== false
&& strpos($npmContent, '<files>') !== false
&& strpos($npmContent, 'folder="packages"') === false
) {
$npmContent = str_replace('<files>', '<files folder="packages">', $npmContent);
file_put_contents($npmf, $npmContent);
echo " Fixed: added folder=\"packages\" to " . basename($npmf) . "\n";
}
}
// Add top-level files (manifest, script, etc.) with exclude filter
$nestedTopFiles = array_merge(
glob("{$subSourceDir}/*.xml") ?: [],
glob("{$subSourceDir}/*.php") ?: []
);
foreach ($nestedTopFiles as $ntf) {
$subZip->addFile($ntf, basename($ntf));
if (!$this->isExcluded(basename($ntf), $this->excludePatterns)) {
$subZip->addFile($ntf, basename($ntf));
}
}
$nestedLangDir = "{$subSourceDir}/language";
if (is_dir($nestedLangDir)) {
$this->addDirToZip($subZip, $nestedLangDir, 'language', $this->excludePatterns);
// Add all top-level directories except packages/
$nestedTopDirs = glob("{$subSourceDir}/*", GLOB_ONLYDIR) ?: [];
foreach ($nestedTopDirs as $ntd) {
$ndName = basename($ntd);
if ($ndName === 'packages') {
continue;
}
$this->addDirToZip($subZip, $ntd, $ndName, $this->excludePatterns);
}
} else {
$this->addDirToZip($subZip, $subSourceDir, '', $this->excludePatterns);