diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 91642f81..77bdb5db 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -60,6 +60,12 @@ jobs: INTERVAL=30 ELAPSED=0 + # RC tags: publish with whatever assets are available (minimum: Linux >= 4 OR macOS >= 4) + # Stable tags: require all platforms (Linux >= 8, macOS >= 4, Windows >= 8) + # jane: RC releases exist for downstream testing — a partial release + # (e.g. Windows fails with 504) is still useful for testing Linux/macOS. + IS_RC=$(echo "$TAG" | grep -qiE '(rc|beta|alpha|dev)\.' && echo "true" || echo "false") + while [ $ELAPSED -lt $MAX_WAIT ]; do ASSETS_JSON=$(gh release view "$TAG" --repo "${{ github.repository }}" --json assets 2>/dev/null || echo '{"assets":[]}') @@ -67,11 +73,20 @@ jobs: MACOS=$(echo "$ASSETS_JSON" | jq '[.assets[].name | select(endswith(".tar.gz") and contains("macos"))] | length' 2>/dev/null || echo 0) WIN=$(echo "$ASSETS_JSON" | jq '[.assets[].name | select(endswith(".zip") and contains("x86_64"))] | length' 2>/dev/null || echo 0) - echo "Assets: Linux=$LINUX, macOS=$MACOS, Windows=$WIN (${ELAPSED}s / ${MAX_WAIT}s)" + echo "Assets: Linux=$LINUX, macOS=$MACOS, Windows=$WIN (${ELAPSED}s / ${MAX_WAIT}s) RC=$IS_RC" - if [ "$LINUX" -ge 8 ] && [ "$MACOS" -ge 4 ] && [ "$WIN" -ge 8 ]; then - echo "All platform assets present" - exit 0 + if [ "$IS_RC" = "true" ]; then + # RC: sufficient if Linux OR macOS assets are present + if [ "$LINUX" -ge 4 ] || [ "$MACOS" -ge 4 ]; then + echo "RC: sufficient assets for pre-release (Linux=$LINUX, macOS=$MACOS, Windows=$WIN)" + exit 0 + fi + else + # Stable: require all platforms + if [ "$LINUX" -ge 8 ] && [ "$MACOS" -ge 4 ] && [ "$WIN" -ge 8 ]; then + echo "All platform assets present" + exit 0 + fi fi sleep $INTERVAL @@ -96,6 +111,14 @@ jobs: echo "Asset counts: Linux=${LINUX_COUNT}, macOS=${MACOS_COUNT}, Windows=${WINDOWS_COUNT}, Total=${TOTAL_COUNT}" + # RC tags: skip strict validation (partial releases are OK for testing) + if echo "$TAG" | grep -qiE '(rc|beta|alpha|dev)\.'; then + echo "RC tag detected — skipping strict asset validation" + [ "$TOTAL_COUNT" -ge 4 ] || { echo "ERROR: RC needs at least 4 assets, got $TOTAL_COUNT"; exit 1; } + echo "RC: $TOTAL_COUNT assets (sufficient for pre-release)" + exit 0 + fi + fail=0 [ "$LINUX_COUNT" -lt 8 ] && { echo "ERROR: Linux has only $LINUX_COUNT bundles (expected >= 8)"; fail=1; } [ "$MACOS_COUNT" -lt 4 ] && { echo "ERROR: macOS has only $MACOS_COUNT bundles (expected >= 4)"; fail=1; } diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 2f6f8713..6ccf6b48 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -188,6 +188,7 @@ jobs: fi - name: Install Firebird SDK + if: steps.cache-fb-sdk.outputs.cache-hit != 'true' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -294,7 +295,21 @@ jobs: uses: ./.github/actions/determine-php-version with: php-minor: ${{ matrix.php }} - + + - name: Cache PHP source + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 + id: cache-php-src + with: + path: /tmp/php-src-cached + key: php-src-${{ steps.php-version.outputs.full_version }} + + - name: Cache Firebird SDK + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 + id: cache-fb-sdk + with: + path: /opt/firebird + key: firebird-sdk-${{ env.FB_VERSION }}-${{ env.FB_BUILD }}-${{ matrix.fb_arch }} + - name: Install PHP ${{ matrix.php }} (${{ matrix.variant }}) shell: bash run: | @@ -304,14 +319,36 @@ jobs: echo "Building PHP ${FULL_VERSION} (${VARIANT})..." - # Download PHP source - curl -fsSL "https://www.php.net/distributions/php-${FULL_VERSION}.tar.xz" \ - -o /tmp/php.tar.xz - - mkdir -p /tmp/php-src - tar -xJf /tmp/php.tar.xz -C /tmp/php-src --strip-components=1 + # Use cached PHP source if available (avoids 504 from php.net) + if [ -d /tmp/php-src-cached/php-src ]; then + echo "Using cached PHP source" + cp -a /tmp/php-src-cached/php-src /tmp/php-src + else + # Download PHP source with retry (php.net sometimes returns 504) + DELAY=10 + for attempt in 1 2 3 4 5; do + echo "Downloading PHP source (attempt ${attempt}/5)..." + if curl -fsSL --retry 3 --retry-delay 5 \ + "https://www.php.net/distributions/php-${FULL_VERSION}.tar.xz" \ + -o /tmp/php.tar.xz; then + FSIZE=$(stat -c%s /tmp/php.tar.xz 2>/dev/null || echo "0") + if [ "${FSIZE}" -gt 5000000 ]; then + echo "Download succeeded (${FSIZE} bytes)" + break + fi + echo "File too small (${FSIZE} bytes), discarding" + rm -f /tmp/php.tar.xz + fi + [ "${attempt}" -lt 5 ] && echo "Sleeping ${DELAY}s..." && sleep "${DELAY}" && DELAY=$((DELAY * 2)) + done + [ -f /tmp/php.tar.xz ] || { echo "ERROR: PHP source download failed after 5 attempts" >&2; exit 1; } + + mkdir -p /tmp/php-src /tmp/php-src-cached + tar -xJf /tmp/php.tar.xz -C /tmp/php-src --strip-components=1 + cp -a /tmp/php-src /tmp/php-src-cached/ + fi cd /tmp/php-src - + # Configure options CONFIGURE_OPTS=( "--prefix=${INSTALL_DIR}" diff --git a/.github/workflows/release-windows.yml b/.github/workflows/release-windows.yml index 0a88b8bb..1b64246c 100644 --- a/.github/workflows/release-windows.yml +++ b/.github/workflows/release-windows.yml @@ -100,6 +100,27 @@ jobs: echo "FIREBIRD_HOME=$sdkPath" >> $env:GITHUB_ENV echo "$sdkPath\bin" >> $env:GITHUB_PATH + - name: Check PHP SDK availability + shell: pwsh + run: | + # Check if downloads.php.net is reachable before attempting the build. + # jane: php-windows-builder downloads PHP SDK deps from downloads.php.net + # which intermittently returns 504 Gateway Timeout. This check gives early + # visibility and a retry window before the build step fails. + $vs = if ('${{ matrix.php-version }}' -ge '8.4') { 'vs17' } else { 'vs16' } + $url = "https://downloads.php.net/~windows/php-sdk/deps/$vs/x64/" + for ($i = 1; $i -le 5; $i++) { + try { + $resp = Invoke-WebRequest -Uri $url -Method Head -TimeoutSec 10 + Write-Host "PHP SDK available (HTTP $($resp.StatusCode))" + exit 0 + } catch { + Write-Host "Attempt $i/5: PHP SDK not available ($($_.Exception.Message))" + if ($i -lt 5) { Start-Sleep -Seconds 30 } + } + } + Write-Host "::warning::PHP SDK deps unavailable, build may fail with 504" + - name: Resolve release tag id: reltag shell: bash diff --git a/CHANGELOG.md b/CHANGELOG.md index 9848697e..06f36dd0 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [13.0.1-rc.1] - 2026-07-21 + +### CI/CD Pipeline Fixes + +- **build-extension action**: `phpize-clean` default changed from `false` to `true` + + stale `.so` removal before `phpize --clean` to prevent header/library version + mismatches when the source tree is shared between Docker containers with different + Firebird client versions (#558) +- **ci.yml**: Added stale `.so` removal + `phpize --clean` to `pdo_fbird` standalone + build step +- **.deb packaging**: Fixed Docker image naming for Ubuntu distros — `php:*-cli-jammy` + and `php:*-cli-noble` don't exist on Docker Hub. Now uses `ubuntu:22.04`/`ubuntu:24.04` + base images + Sury PPA for PHP installation +- **release-linux.yml**: Added PHP source caching + Firebird SDK caching + retry logic + (5 attempts with exponential backoff) for `php.net` 504 errors +- **release-windows.yml**: Added PHP SDK availability check before build (early + visibility + retry for `downloads.php.net` 504 errors) +- **publish-release.yml**: Relaxed asset requirements for RC tags — publishes as + pre-release if Linux >= 4 OR macOS >= 4 assets are present (instead of requiring + all platforms). Stable releases still require all platforms. +- **.gitignore**: Added `/debian/` and `/dist/` build output directories + +### SIGSEGV Fix (PHP 8.5/FB3) + +- **Root cause**: Stale `.so` compiled against FB 5.0 headers (`FB_API_VER=50`), + loaded with FB 3.0 client library. `IResultSet::close()` dispatched through a + vtable slot (`deprecatedClose`) that doesn't exist in FB 3.0's `libfbclient` + → NULL function pointer → SIGSEGV during shutdown. +- **Fix**: `phpize --clean` + `rm -f stale .so` before every build (PR #558) +- **Validation**: 12/12 containers pass (4,321 tests, 0 failures) + ## [13.0.1] - 2026-07-20 ### v13.0.1 — Post-Release Bugfixes diff --git a/VERSION.txt b/VERSION.txt index 5cb7d856..452d34d4 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -13.0.1 +13.0.1-rc.1 diff --git a/packaging/debian/build-matrix.sh b/packaging/debian/build-matrix.sh index c9e29a5a..a8d2bc3a 100755 --- a/packaging/debian/build-matrix.sh +++ b/packaging/debian/build-matrix.sh @@ -117,14 +117,28 @@ get_docker_image() { esac case "$distro" in + # Debian: official PHP Docker images exist with Debian codenames bookworm) echo "php:${php_ver}-cli-bookworm" ;; trixie) echo "php:${php_ver}-cli-trixie" ;; - jammy) echo "php:${php_ver}-cli-jammy" ;; - noble) echo "php:${php_ver}-cli-noble" ;; + # Ubuntu: no official PHP Docker images (only Debian codenames exist). + # Use Ubuntu base image + install PHP from packages.sury.org PPA. + # jane: PHP Docker images only use Debian codenames (bookworm, trixie), + # never Ubuntu codenames (jammy, noble). The Sury PPA provides PHP for + # both Debian AND Ubuntu suites. + jammy) echo "ubuntu:22.04" ;; + noble) echo "ubuntu:24.04" ;; *) echo ""; return 1 ;; esac } +# Check if a distro is Ubuntu (needs Sury PPA for PHP) +is_ubuntu() { + case "$1" in + jammy|noble) echo "true" ;; + *) echo "false" ;; + esac +} + # Map arch name to Docker platform get_docker_platform() { local arch="$1" @@ -205,11 +219,25 @@ build_package() { -e FB_ROOT="${fb_mount}" \ "$docker_image" \ bash -c "export DEBIAN_FRONTEND=noninteractive && \ - apt-get update -qq && \ - apt-get install -y -qq --no-install-recommends \ - autoconf build-essential gcc g++ make libtool bison re2c \ - libicu-dev libxml2-dev libtommath1 patchelf dpkg-dev debhelper \ - jq curl wget git ca-certificates && \ + $(if [ "$(is_ubuntu "$distro")" = "true" ]; then + echo "apt-get update -qq && \ + apt-get install -y -qq lsb-release ca-certificates curl && \ + curl -sSLo /tmp/keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb && \ + dpkg -i /tmp/keyring.deb && \ + printf 'Types: deb\nURIs: https://packages.sury.org/php/\nSuites: \$(lsb_release -sc)\nComponents: main\nSigned-By: /usr/share/keyrings/debsuryorg-archive-keyring.gpg\n' > /etc/apt/sources.list.d/php.sources && \ + apt-get update -qq && \ + apt-get install -y -qq --no-install-recommends \ + php${php_ver}-cli php${php_ver}-dev \ + autoconf build-essential gcc g++ make libtool bison re2c \ + libicu-dev libxml2-dev libtommath1 patchelf dpkg-dev debhelper \ + jq curl wget git ca-certificates &&" + else + echo "apt-get update -qq && \ + apt-get install -y -qq --no-install-recommends \ + autoconf build-essential gcc g++ make libtool bison re2c \ + libicu-dev libxml2-dev libtommath1 patchelf dpkg-dev debhelper \ + jq curl wget git ca-certificates &&" + fi) \ cd /ext && bash packaging/debian/build.sh --php-version $php_ver --distro $distro --arch $arch --output-dir /output" \ > "$result_log" 2>&1 || exit_code=$? diff --git a/stubs/firebird-classes.php b/stubs/firebird-classes.php index 8a366069..ca96729d 100644 --- a/stubs/firebird-classes.php +++ b/stubs/firebird-classes.php @@ -7,7 +7,7 @@ * C extension. These are used by static analysis tools and IDEs. * * @package php-firebird-stubs - * @version 13.0.1 + * @version 13.0.1-rc.1 * @author satware AG * @copyright 2025 satware AG * @license PHP-3.01 https://www.php.net/license/3_01.txt diff --git a/stubs/firebird-stubs.php b/stubs/firebird-stubs.php index 3fc674fe..4d7fcf43 100644 --- a/stubs/firebird-stubs.php +++ b/stubs/firebird-stubs.php @@ -10,7 +10,7 @@ * This stub file does not contain any implementation. * * @package php-firebird-stubs - * @version 13.0.1 + * @version 13.0.1-rc.1 * @author satware AG * @copyright 2025-2026 satware AG * @license PHP-3.01 https://www.php.net/license/3_01.txt diff --git a/stubs/pdo-fbird-stubs.php b/stubs/pdo-fbird-stubs.php index 20c395ad..646e0eea 100644 --- a/stubs/pdo-fbird-stubs.php +++ b/stubs/pdo-fbird-stubs.php @@ -15,7 +15,7 @@ * 'SYSDBA', 'masterkey'); * * @package php-firebird-stubs - * @version 13.0.1 + * @version 13.0.1-rc.1 * @author satware AG * @copyright 2025-2026 satware AG * @license PHP-3.01 https://www.php.net/license/3_01.txt