Skip to content

Commit 8d779ab

Browse files
committed
chore: wip
1 parent 16726e0 commit 8d779ab

File tree

5 files changed

+420
-61
lines changed

5 files changed

+420
-61
lines changed

.github/workflows/precompile-php.yml

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,14 @@ jobs:
975975
run: |
976976
cd binaries/
977977
978+
# Debug: Show what we have
979+
echo "🔍 Current directory structure:"
980+
ls -la
981+
echo ""
982+
echo "🔍 Looking for tar.gz files:"
983+
find . -name "*.tar.gz" -type f
984+
echo ""
985+
978986
# Create a manifest of all built binaries
979987
cat > manifest.json << EOF
980988
{
@@ -985,31 +993,61 @@ jobs:
985993
EOF
986994
987995
first=true
988-
for dir in */; do
989-
if [[ -f "$dir"*.tar.gz ]]; then
990-
if [[ $first == "false" ]]; then
991-
echo "," >> manifest.json
992-
fi
993-
tarball=$(ls "$dir"*.tar.gz | head -1)
994-
filename=$(basename "$tarball")
995-
size=$(stat -c%s "$tarball" 2>/dev/null || stat -f%z "$tarball")
996-
997-
# Extract metadata from tarball if available
998-
tar -xzOf "$tarball" "*/metadata.json" > temp_metadata.json 2>/dev/null || echo '{}' > temp_metadata.json
999-
1000-
echo " {" >> manifest.json
1001-
echo " \"filename\": \"$filename\"," >> manifest.json
1002-
echo " \"size\": $size," >> manifest.json
1003-
cat temp_metadata.json | sed 's/^/ /' | sed '1s/^ {//' | sed '$s/$//' >> manifest.json
1004-
echo " }" >> manifest.json
1005-
first=false
996+
# Find all tar.gz files recursively
997+
for tarball in $(find . -name "*.tar.gz" -type f); do
998+
if [[ $first == "false" ]]; then
999+
echo "," >> manifest.json
1000+
fi
1001+
1002+
filename=$(basename "$tarball")
1003+
size=$(stat -c%s "$tarball" 2>/dev/null || stat -f%z "$tarball")
1004+
1005+
echo "Processing: $filename (size: $size bytes)"
1006+
1007+
# Extract metadata from tarball if available
1008+
tar -xzOf "$tarball" "*/metadata.json" > temp_metadata.json 2>/dev/null || echo '{}' > temp_metadata.json
1009+
1010+
# Parse the binary name to extract components
1011+
# Expected format: php-8.4.11-darwin-arm64-laravel-mysql.tar.gz
1012+
binary_name=$(echo "$filename" | sed 's/\.tar\.gz$//')
1013+
1014+
# Extract components from binary name
1015+
if [[ "$binary_name" =~ ^php-([^-]+)-([^-]+)-([^-]+)-(.+)$ ]]; then
1016+
php_version="${BASH_REMATCH[1]}"
1017+
platform="${BASH_REMATCH[2]}"
1018+
architecture="${BASH_REMATCH[3]}"
1019+
configuration="${BASH_REMATCH[4]}"
1020+
else
1021+
# Fallback if pattern doesn't match
1022+
php_version="unknown"
1023+
platform="unknown"
1024+
architecture="unknown"
1025+
configuration="unknown"
10061026
fi
1027+
1028+
echo " {" >> manifest.json
1029+
echo " \"filename\": \"$filename\"," >> manifest.json
1030+
echo " \"size\": $size," >> manifest.json
1031+
echo " \"php_version\": \"$php_version\"," >> manifest.json
1032+
echo " \"platform\": \"$platform\"," >> manifest.json
1033+
echo " \"architecture\": \"$architecture\"," >> manifest.json
1034+
echo " \"configuration\": \"$configuration\"," >> manifest.json
1035+
echo " \"built_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> manifest.json
1036+
echo " \"extensions\": \"$(cat temp_metadata.json | jq -r '.extensions // ""' 2>/dev/null || echo '')\"" >> manifest.json
1037+
echo " }" >> manifest.json
1038+
first=false
10071039
done
10081040
10091041
echo " ]" >> manifest.json
10101042
echo " }" >> manifest.json
10111043
1044+
echo ""
1045+
echo "📋 Generated manifest.json:"
10121046
cat manifest.json
1047+
echo ""
1048+
echo "📊 Summary:"
1049+
echo " - Total binaries found: $(find . -name "*.tar.gz" -type f | wc -l)"
1050+
echo " - Manifest file size: $(stat -c%s manifest.json 2>/dev/null || stat -f%z manifest.json) bytes"
10131051
10141052
- name: Create GitHub Release
10151053
uses: softprops/action-gh-release@v1

packages/launchpad/src/binary-downloader.ts

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -248,26 +248,47 @@ export class PrecompiledBinaryDownloader {
248248
private async downloadManifest(): Promise<BinaryManifest> {
249249
console.log('📋 Downloading precompiled binary manifest...')
250250

251-
const manifestUrl = `${this.GITHUB_API}/repos/${this.GITHUB_REPO}/releases/latest`
251+
// First, get all releases to find the latest binaries release
252+
const releasesUrl = `${this.GITHUB_API}/repos/${this.GITHUB_REPO}/releases`
252253

253254
try {
254-
const response = await fetch(manifestUrl, {
255+
const releasesResponse = await fetch(releasesUrl, {
255256
headers: {
256257
'User-Agent': 'Launchpad Binary Downloader',
257258
'Accept': 'application/vnd.github.v3+json',
258259
},
259260
})
260261

261-
if (!response.ok) {
262-
throw new Error(`GitHub API error: ${response.status} ${response.statusText}`)
262+
if (!releasesResponse.ok) {
263+
if (releasesResponse.status === 403) {
264+
throw new Error('GitHub API rate limit exceeded. Please try again later.')
265+
}
266+
throw new Error(`GitHub API error: ${releasesResponse.status} ${releasesResponse.statusText}`)
263267
}
264268

265-
const release = await response.json() as GitHubRelease
269+
const releases = await releasesResponse.json() as GitHubRelease[]
270+
271+
// Find the latest release with binaries- prefix
272+
const binariesReleases = releases.filter(release =>
273+
release.tag_name.startsWith('binaries-'),
274+
).sort((a, b) => {
275+
// Sort by release number (binaries-1234)
276+
const aNum = Number.parseInt(a.tag_name.replace('binaries-', ''), 10)
277+
const bNum = Number.parseInt(b.tag_name.replace('binaries-', ''), 10)
278+
return bNum - aNum // Latest first
279+
})
280+
281+
if (binariesReleases.length === 0) {
282+
throw new Error('No binaries releases found. The precompile workflow may not have run yet.')
283+
}
284+
285+
const binariesRelease = binariesReleases[0]
286+
console.log(`📦 Found binaries release: ${binariesRelease.tag_name}`)
266287

267288
// Find manifest.json in release assets
268-
const manifestAsset = release.assets?.find(asset => asset.name === 'manifest.json')
289+
const manifestAsset = binariesRelease.assets?.find(asset => asset.name === 'manifest.json')
269290
if (!manifestAsset) {
270-
throw new Error('No manifest.json found in latest release')
291+
throw new Error('No manifest.json found in binaries release')
271292
}
272293

273294
// Download manifest content
@@ -280,12 +301,21 @@ export class PrecompiledBinaryDownloader {
280301

281302
// Add download URLs to binaries
282303
manifest.binaries = manifest.binaries.map((binary) => {
283-
const asset = release.assets?.find(asset => asset.name === binary.filename)
304+
const asset = binariesRelease.assets?.find(asset => asset.name === binary.filename)
305+
if (!asset) {
306+
console.warn(`⚠️ No asset found for binary: ${binary.filename}`)
307+
}
284308
return {
285309
...binary,
286310
download_url: asset?.browser_download_url || '',
287311
}
288-
})
312+
}).filter(binary => binary.download_url) // Remove binaries without download URLs
313+
314+
console.log(`📋 Manifest loaded: ${manifest.binaries.length} binaries available`)
315+
316+
if (manifest.binaries.length === 0) {
317+
throw new Error('No valid binaries found in manifest. The release may be incomplete.')
318+
}
289319

290320
return manifest
291321
}
@@ -391,7 +421,7 @@ export class PrecompiledBinaryDownloader {
391421
*/
392422
private generateDiscordErrorMessage(detectedConfig: string, platform: string, architecture: string): string {
393423
return `
394-
🚨 **Unsupported PHP Configuration Detected**
424+
🚨 **PHP Binary Not Available**
395425
396426
We don't have a precompiled binary for your setup yet. Please help us improve!
397427
@@ -405,9 +435,19 @@ We don't have a precompiled binary for your setup yet. Please help us improve!
405435
2. Share this error in the #launchpad channel
406436
3. Tell us about your project setup so we can add support
407437
408-
**Workaround:**
409-
- Launchpad will automatically fall back to source compilation
410-
- This will take longer but will work for your configuration
438+
**Available Configurations:**
439+
- laravel-mysql: Laravel with MySQL/MariaDB
440+
- laravel-postgres: Laravel with PostgreSQL
441+
- laravel-sqlite: Laravel with SQLite
442+
- api-only: Minimal API applications
443+
- enterprise: Full-featured enterprise build
444+
- wordpress: WordPress-optimized
445+
- full-stack: Complete PHP with all major extensions
446+
447+
**Next Steps:**
448+
- Try a different PHP version if available
449+
- Check if your platform/architecture is supported
450+
- Request support for your specific configuration
411451
412452
Thanks for helping us make Launchpad better! 🙏
413453
`.trim()
@@ -549,16 +589,31 @@ Thanks for helping us make Launchpad better! 🙏
549589
if (!binary) {
550590
const platform = this.getPlatform()
551591
const arch = this.getArchitecture()
552-
const detectedConfig = this.detectFrameworkAndDatabase()
592+
const detectedConfig = await this.detectFrameworkAndDatabase()
593+
594+
// Show available binaries for debugging
595+
const availableBinaries = manifest.binaries.filter(b =>
596+
b.platform === platform && b.architecture === arch,
597+
)
598+
599+
console.log(`\n🔍 Available binaries for ${platform}-${arch}:`)
600+
if (availableBinaries.length > 0) {
601+
availableBinaries.forEach((b) => {
602+
console.log(` - PHP ${b.php_version} (${b.configuration})`)
603+
})
604+
}
605+
else {
606+
console.log(` ❌ No binaries available for ${platform}-${arch}`)
607+
}
553608

554609
// Generate helpful Discord error message
555-
const discordMessage = this.generateDiscordErrorMessage(await detectedConfig, platform, arch)
610+
const discordMessage = this.generateDiscordErrorMessage(detectedConfig, platform, arch)
556611
console.log(`\n${discordMessage}\n`)
557612

558613
throw new Error(
559614
`No precompiled binary found for ${platform}-${arch} with ${detectedConfig} configuration${
560615
requestedVersion ? ` and PHP ${requestedVersion}` : ''
561-
}. See Discord message above for help.`,
616+
}. See available binaries above and Discord message for help.`,
562617
)
563618
}
564619

packages/launchpad/src/install-core.ts

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -223,41 +223,30 @@ export async function installPackage(packageName: string, packageSpec: string, i
223223
return await installMeilisearch(installPath, requestedVersion)
224224
}
225225

226-
// Special handling for PHP - use precompiled binaries for speed
226+
// Special handling for PHP - use precompiled binaries from GitHub
227227
if (name === 'php' || domain === 'php.net') {
228-
try {
229-
if (config.verbose) {
230-
console.warn(`Installing PHP from precompiled binaries for ${name}`)
231-
}
228+
console.log('🐘 Installing PHP using precompiled binaries from GitHub...')
232229

230+
try {
233231
// Import the binary downloader
234-
const { downloadPhpBinary, PrecompiledBinaryDownloader } = await import('./binary-downloader')
232+
const { downloadPhpBinary } = await import('./binary-downloader')
235233

236-
// Check if precompiled binaries are available
237-
const downloader = new PrecompiledBinaryDownloader(installPath)
238-
const isSupported = await downloader.isSupported()
239-
240-
if (isSupported) {
241-
console.log('🚀 Using precompiled PHP binaries...')
242-
return await downloadPhpBinary(installPath, requestedVersion)
243-
}
244-
else {
245-
console.warn('🔧 Custom extensions detected: falling back to source build. Nudge us or open an issue if you need this!')
246-
throw new Error('Source builds are no longer supported. Use precompiled binaries instead. If you need this, nudge us or open an issue!')
247-
}
234+
// Always use precompiled binaries for PHP
235+
return await downloadPhpBinary(installPath, requestedVersion)
248236
}
249237
catch (error) {
250-
if (config.verbose) {
251-
console.log(`⚠️ Binary download failed: ${error instanceof Error ? error.message : String(error)}`)
252-
}
253-
}
238+
const errorMessage = error instanceof Error ? error.message : String(error)
239+
console.error(`❌ Failed to install PHP from precompiled binaries: ${errorMessage}`)
254240

255-
// CRITICAL: Install ALL PHP dependencies FIRST before building
256-
if (config.verbose) {
257-
console.log('🔧 Setting up build environment for PHP...')
258-
}
241+
// Provide helpful error message
242+
console.log('\n💡 Troubleshooting:')
243+
console.log('1. Check your internet connection')
244+
console.log('2. Verify that the precompile workflow has run recently')
245+
console.log('3. Try a different PHP version if available')
246+
console.log('4. Join our Discord for help: https://discord.gg/stacksjs')
259247

260-
throw new Error('Source builds are no longer supported. Use precompiled binaries instead.')
248+
throw new Error(`PHP installation failed: ${errorMessage}`)
249+
}
261250
}
262251

263252
if (config.verbose) {

0 commit comments

Comments
 (0)