You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iggy.apache.org by "hubcio (via GitHub)" <gi...@apache.org> on 2026/07/01 23:47:27 UTC
Re: [PR] feat(php): wire release pipeline [iggy]
hubcio commented on code in PR #3500:
URL: https://github.com/apache/iggy/pull/3500#discussion_r3509632999
##########
.github/workflows/publish.yml:
##########
@@ -1314,6 +1340,101 @@ jobs:
# above ensure the tag is never pushed before the registry is serving
# the artifact (Go is exempt: the tag IS the release).
- name: Tag SDK release (${{ matrix.key }})
+ if: |
+ success() &&
+ inputs.dry_run == false &&
+ matrix.type != 'php' &&
+ inputs.skip_tag_creation == false &&
+ steps.ver.outputs.should_tag == 'true'
+ uses: ./.github/actions/utils/create-git-tag
+ with:
+ tag: ${{ steps.ver.outputs.tag }}
+ commit: ${{ needs.validate.outputs.commit }}
+ message: |
+ Release ${{ matrix.key }} ${{ steps.ver.outputs.version }}
+
+ Component: ${{ matrix.key }}
+ Tag: ${{ steps.ver.outputs.tag }}
+ Commit: ${{ needs.validate.outputs.commit }}
+ Released by: GitHub Actions (workflow ${{ github.run_id }})
+
+ - name: Set status output
+ id: status
+ if: always()
+ run: echo "status=${{ job.status }}" >> "$GITHUB_OUTPUT"
+
+ publish-php:
+ name: PHP SDK
+ needs: [validate, plan, check-tags, build-php-extensions]
+ if: |
+ !cancelled() &&
+ needs.validate.outputs.has_targets == 'true' &&
+ needs.plan.outputs.has_php == 'true' &&
+ fromJson(needs.plan.outputs.php_targets).include[0].key != 'noop' &&
+ (needs.build-php-extensions.result == 'success' || needs.build-php-extensions.result == 'skipped')
Review Comment:
when php is selected (`has_php == 'true'`, so validate and plan must have succeeded), `build-php-extensions` can only end up `skipped` here if check-tags failed - and in that case this job still runs (`!cancelled()`), pushes the tag (the tag step runs before the publish step) and then fails downloading the `php-extensions-all` artifact that was never built. result: tag without release, and post-merge auto-publish permanently skips that version because the tag exists. dropping the `!cancelled()` + result checks and relying on plain needs semantics with the `has_php` condition gives exactly the right behavior.
##########
scripts/extract-version.sh:
##########
@@ -406,12 +422,11 @@ fi
# version would be auto-published to PyPI but never git-tagged).
#
# Matches (any of):
-# -edge[.N] (rust crates, docker, node SDK)
-# -rc[.N] (all SDKs)
+# -<semver pre-release> (rust crates, docker, node/PHP SDKs)
# .devN (Python SDK PEP 440 development markers)
# rcN$ (legacy bare rcN, retained for compatibility)
if [[ "$RETURN_IS_PRE_RELEASE" == "true" ]]; then
- if [[ "$VERSION" =~ -(edge|rc) ]] \
+ if [[ "$VERSION" =~ -[0-9A-Za-z] ]] \
Review Comment:
`-[0-9A-Za-z]` also matches a hyphen inside semver build metadata, so `1.2.3+linux-x64` would classify as pre-release. latent today (no component uses build metadata), but anchoring on the patch part is cheap: `^[0-9]+\.[0-9]+\.[0-9]+-`.
##########
.github/workflows/publish.yml:
##########
@@ -982,13 +1008,13 @@ jobs:
fi
else
# Manual publish: always push the versioned manifest, plus :latest
- # for stable (non edge/rc) releases.
+ # for stable releases.
docker buildx imagetools create \
-t "${IMAGE}:${VERSION}" \
$(printf "${IMAGE}@sha256:%s " *)
echo "✅ Pushed manifest: ${IMAGE}:${VERSION}"
- if [[ ! "$VERSION" =~ -(edge|rc) ]]; then
+ if [ "$(scripts/extract-version.sh "${{ matrix.key }}" --is-pre-release)" != "true" ]; then
Review Comment:
if `extract-version.sh` fails here, the command substitution comes back empty, `!= "true"` passes and `:latest` gets pushed for a possibly-prerelease version. the check-tags variant at line 554 guards this with `|| echo false` (fails safe by skipping); this one should fail safe too - `|| echo true`.
##########
.github/workflows/_build_php_extensions.yml:
##########
@@ -0,0 +1,469 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: _build_php_extensions
+on:
+ workflow_call:
+ inputs:
+ version:
+ type: string
+ required: false
+ default: ""
+ upload_artifacts:
+ type: boolean
+ required: false
+ default: true
+ use_latest_ci:
+ type: boolean
+ required: false
+ default: true
+ description: "Use latest CI configuration and scripts from master branch"
+ commit:
+ type: string
+ required: false
+ default: ""
+ description: "Specific commit to checkout for building PHP extensions"
+ outputs:
+ artifact_name:
+ description: "Name of the uploaded artifact containing PHP extension archives"
+ value: ${{ jobs.collect.outputs.artifact_name }}
+
+permissions:
+ contents: read
+
+jobs:
+ license-manifest:
+ name: Generate PHP binary license manifest
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download latest copy script from master
+ if: inputs.use_latest_ci
+ run: |
+ curl -sSL "https://raw.githubusercontent.com/${{ github.repository }}/master/scripts/copy-latest-from-master.sh" \
+ -o /tmp/copy-latest-from-master.sh
+ chmod +x /tmp/copy-latest-from-master.sh
+
+ - uses: actions/checkout@v6.0.2
+ with:
+ ref: ${{ inputs.commit }}
+
+ - name: Save and apply latest CI from master
+ if: inputs.use_latest_ci
+ run: |
+ /tmp/copy-latest-from-master.sh save .github scripts
+ /tmp/copy-latest-from-master.sh apply
+
+ - name: Install cargo-about
+ run: |
+ mkdir -p "$HOME/.cargo/bin"
+ TARGET="$(uname -m)-unknown-linux-musl"
+ curl -sSfL "https://github.com/EmbarkStudios/cargo-about/releases/download/0.9.0/cargo-about-0.9.0-${TARGET}.tar.gz" \
+ | tar -xz -C "$HOME/.cargo/bin" --strip-components=1 "cargo-about-0.9.0-${TARGET}/cargo-about"
+
+ - name: Generate third-party license manifest
+ run: ./scripts/ci/third-party-licenses.sh --generate --manifest foreign/php/Cargo.toml --output foreign/php/LICENSE-binary
+
+ - name: Upload license manifest
+ uses: actions/upload-artifact@v7
+ with:
+ name: php-license-binary
+ path: foreign/php/LICENSE-binary
+ retention-days: 7
+
+ linux:
+ name: PHP ${{ matrix.php }} ${{ matrix.arch }} linux-${{ matrix.libc }}
+ needs: license-manifest
+ runs-on: ${{ matrix.runner }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - php: "8.3"
+ arch: x86_64
+ libc: glibc
+ runner: ubuntu-latest
+ image: php:8.3-cli-bookworm
+ - php: "8.4"
+ arch: x86_64
+ libc: glibc
+ runner: ubuntu-latest
+ image: php:8.4-cli-bookworm
+ - php: "8.3"
+ arch: arm64
+ libc: glibc
+ runner: ubuntu-24.04-arm
+ image: php:8.3-cli-bookworm
+ - php: "8.4"
+ arch: arm64
+ libc: glibc
+ runner: ubuntu-24.04-arm
+ image: php:8.4-cli-bookworm
+ - php: "8.3"
+ arch: x86_64
+ libc: musl
+ runner: ubuntu-latest
+ image: php:8.3-cli-alpine
+ - php: "8.4"
+ arch: x86_64
+ libc: musl
+ runner: ubuntu-latest
+ image: php:8.4-cli-alpine
+ - php: "8.3"
+ arch: arm64
+ libc: musl
+ runner: ubuntu-24.04-arm
+ image: php:8.3-cli-alpine
+ - php: "8.4"
+ arch: arm64
+ libc: musl
+ runner: ubuntu-24.04-arm
+ image: php:8.4-cli-alpine
+ steps:
+ - name: Download latest copy script from master
+ if: inputs.use_latest_ci
+ run: |
+ curl -sSL "https://raw.githubusercontent.com/${{ github.repository }}/master/scripts/copy-latest-from-master.sh" \
+ -o /tmp/copy-latest-from-master.sh
+ chmod +x /tmp/copy-latest-from-master.sh
+
+ - uses: actions/checkout@v6.0.2
+ with:
+ ref: ${{ inputs.commit }}
+
+ - name: Save and apply latest CI from master
+ if: inputs.use_latest_ci
+ run: |
+ /tmp/copy-latest-from-master.sh save .github scripts
+ /tmp/copy-latest-from-master.sh apply
+
+ - name: Download license manifest
+ uses: actions/download-artifact@v8
+ with:
+ name: php-license-binary
+ path: foreign/php
+
+ - name: Setup PHP release tools
+ id: release
+ uses: ./.github/actions/php/setup-release-tools
+ with:
+ version: ${{ inputs.version }}
+
+ - name: Cache Linux PHP cargo state
+ uses: actions/cache@v5
+ with:
+ path: |
+ target/php-cargo-home/registry
+ target/php-cargo-home/git
+ target/php-rustup-home
+ key: php-release-linux-${{ matrix.arch }}-${{ matrix.libc }}-php${{ matrix.php }}-${{ hashFiles('Cargo.lock', 'foreign/php/Cargo.toml') }}
+ restore-keys: |
+ php-release-linux-${{ matrix.arch }}-${{ matrix.libc }}-php${{ matrix.php }}-
+ php-release-linux-${{ matrix.arch }}-${{ matrix.libc }}-
+ php-release-linux-${{ matrix.arch }}-
+
+ - name: Build and package PHP extension
+ env:
+ VERSION: ${{ steps.release.outputs.version }}
+ PHP_VERSION: ${{ matrix.php }}
+ PHP_ARCH: ${{ matrix.arch }}
+ PHP_LIBC: ${{ matrix.libc }}
+ PHP_IMAGE: ${{ matrix.image }}
+ run: |
+ set -euo pipefail
+
+ mkdir -p foreign/php/dist
+
+ docker run --rm \
+ -e CARGO_TERM_COLOR=always \
+ -e CARGO_HOME=/workspace/target/php-cargo-home \
+ -e RUSTUP_HOME=/workspace/target/php-rustup-home \
+ -e "CARGO_TARGET_DIR=/workspace/target/php-release-${PHP_VERSION}-${PHP_ARCH}-${PHP_LIBC}" \
+ -e VERSION="${VERSION}" \
+ -e PHP_VERSION="${PHP_VERSION}" \
+ -e PHP_ARCH="${PHP_ARCH}" \
+ -e PHP_LIBC="${PHP_LIBC}" \
+ -v "$PWD:/workspace" \
+ -w /workspace \
+ "${PHP_IMAGE}" \
+ sh -lc '
+ set -eu
+
+ if command -v apt-get >/dev/null 2>&1; then
+ apt-get update
+ apt-get install -y --no-install-recommends \
+ build-essential \
+ ca-certificates \
+ clang \
+ curl \
+ git \
+ libclang-dev \
+ libhwloc-dev \
+ libssl-dev \
+ libudev-dev \
+ pkg-config \
+ zip
+ rm -rf /var/lib/apt/lists/*
+ else
+ apk add --no-cache \
+ build-base \
+ ca-certificates \
+ clang \
+ clang-dev \
+ curl \
+ eudev-dev \
+ git \
+ hwloc-dev \
+ linux-headers \
+ openssl-dev \
+ pkgconf \
+ zip
+ fi
+
+ mkdir -p "$CARGO_HOME" "$RUSTUP_HOME"
+ if [ ! -x "$CARGO_HOME/bin/rustup" ]; then
+ curl -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh
+ sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain none
+ fi
+ . "$CARGO_HOME/env"
+ rustup show
+
+ php --version
+ php-config --version
+ cargo build --release --manifest-path foreign/php/Cargo.toml
Review Comment:
rustup toolchains on alpine default to `+crt-static`, and a cdylib on musl needs `RUSTFLAGS="-C target-feature=-crt-static"` to link - ext-php-rs itself sets exactly this in its own crate-local `.cargo/config.toml` for `cfg(target_env = "musl")`, but that doesn't propagate to dependents and nothing sets it here. expect the 4 musl legs to fail at link time. adding a musl target section to `foreign/php/.cargo/config.toml` works, but only combined with fixing the cwd so that config actually loads (see the macos comment).
##########
.github/workflows/_build_php_extensions.yml:
##########
@@ -0,0 +1,469 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: _build_php_extensions
+on:
+ workflow_call:
+ inputs:
+ version:
+ type: string
+ required: false
+ default: ""
+ upload_artifacts:
+ type: boolean
+ required: false
+ default: true
+ use_latest_ci:
+ type: boolean
+ required: false
+ default: true
+ description: "Use latest CI configuration and scripts from master branch"
+ commit:
+ type: string
+ required: false
+ default: ""
+ description: "Specific commit to checkout for building PHP extensions"
+ outputs:
+ artifact_name:
+ description: "Name of the uploaded artifact containing PHP extension archives"
+ value: ${{ jobs.collect.outputs.artifact_name }}
+
+permissions:
+ contents: read
+
+jobs:
+ license-manifest:
+ name: Generate PHP binary license manifest
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download latest copy script from master
+ if: inputs.use_latest_ci
+ run: |
+ curl -sSL "https://raw.githubusercontent.com/${{ github.repository }}/master/scripts/copy-latest-from-master.sh" \
+ -o /tmp/copy-latest-from-master.sh
+ chmod +x /tmp/copy-latest-from-master.sh
+
+ - uses: actions/checkout@v6.0.2
+ with:
+ ref: ${{ inputs.commit }}
+
+ - name: Save and apply latest CI from master
+ if: inputs.use_latest_ci
+ run: |
+ /tmp/copy-latest-from-master.sh save .github scripts
+ /tmp/copy-latest-from-master.sh apply
+
+ - name: Install cargo-about
+ run: |
+ mkdir -p "$HOME/.cargo/bin"
+ TARGET="$(uname -m)-unknown-linux-musl"
+ curl -sSfL "https://github.com/EmbarkStudios/cargo-about/releases/download/0.9.0/cargo-about-0.9.0-${TARGET}.tar.gz" \
+ | tar -xz -C "$HOME/.cargo/bin" --strip-components=1 "cargo-about-0.9.0-${TARGET}/cargo-about"
+
+ - name: Generate third-party license manifest
+ run: ./scripts/ci/third-party-licenses.sh --generate --manifest foreign/php/Cargo.toml --output foreign/php/LICENSE-binary
+
+ - name: Upload license manifest
+ uses: actions/upload-artifact@v7
+ with:
+ name: php-license-binary
+ path: foreign/php/LICENSE-binary
+ retention-days: 7
+
+ linux:
+ name: PHP ${{ matrix.php }} ${{ matrix.arch }} linux-${{ matrix.libc }}
+ needs: license-manifest
+ runs-on: ${{ matrix.runner }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - php: "8.3"
+ arch: x86_64
+ libc: glibc
+ runner: ubuntu-latest
+ image: php:8.3-cli-bookworm
+ - php: "8.4"
+ arch: x86_64
+ libc: glibc
+ runner: ubuntu-latest
+ image: php:8.4-cli-bookworm
+ - php: "8.3"
+ arch: arm64
+ libc: glibc
+ runner: ubuntu-24.04-arm
+ image: php:8.3-cli-bookworm
+ - php: "8.4"
+ arch: arm64
+ libc: glibc
+ runner: ubuntu-24.04-arm
+ image: php:8.4-cli-bookworm
+ - php: "8.3"
+ arch: x86_64
+ libc: musl
+ runner: ubuntu-latest
+ image: php:8.3-cli-alpine
+ - php: "8.4"
+ arch: x86_64
+ libc: musl
+ runner: ubuntu-latest
+ image: php:8.4-cli-alpine
+ - php: "8.3"
+ arch: arm64
+ libc: musl
+ runner: ubuntu-24.04-arm
+ image: php:8.3-cli-alpine
+ - php: "8.4"
+ arch: arm64
+ libc: musl
+ runner: ubuntu-24.04-arm
+ image: php:8.4-cli-alpine
+ steps:
+ - name: Download latest copy script from master
+ if: inputs.use_latest_ci
+ run: |
+ curl -sSL "https://raw.githubusercontent.com/${{ github.repository }}/master/scripts/copy-latest-from-master.sh" \
+ -o /tmp/copy-latest-from-master.sh
+ chmod +x /tmp/copy-latest-from-master.sh
+
+ - uses: actions/checkout@v6.0.2
+ with:
+ ref: ${{ inputs.commit }}
+
+ - name: Save and apply latest CI from master
+ if: inputs.use_latest_ci
+ run: |
+ /tmp/copy-latest-from-master.sh save .github scripts
+ /tmp/copy-latest-from-master.sh apply
+
+ - name: Download license manifest
+ uses: actions/download-artifact@v8
+ with:
+ name: php-license-binary
+ path: foreign/php
+
+ - name: Setup PHP release tools
+ id: release
+ uses: ./.github/actions/php/setup-release-tools
+ with:
+ version: ${{ inputs.version }}
+
+ - name: Cache Linux PHP cargo state
+ uses: actions/cache@v5
+ with:
+ path: |
+ target/php-cargo-home/registry
+ target/php-cargo-home/git
+ target/php-rustup-home
+ key: php-release-linux-${{ matrix.arch }}-${{ matrix.libc }}-php${{ matrix.php }}-${{ hashFiles('Cargo.lock', 'foreign/php/Cargo.toml') }}
+ restore-keys: |
+ php-release-linux-${{ matrix.arch }}-${{ matrix.libc }}-php${{ matrix.php }}-
+ php-release-linux-${{ matrix.arch }}-${{ matrix.libc }}-
+ php-release-linux-${{ matrix.arch }}-
+
+ - name: Build and package PHP extension
+ env:
+ VERSION: ${{ steps.release.outputs.version }}
+ PHP_VERSION: ${{ matrix.php }}
+ PHP_ARCH: ${{ matrix.arch }}
+ PHP_LIBC: ${{ matrix.libc }}
+ PHP_IMAGE: ${{ matrix.image }}
+ run: |
+ set -euo pipefail
+
+ mkdir -p foreign/php/dist
+
+ docker run --rm \
+ -e CARGO_TERM_COLOR=always \
+ -e CARGO_HOME=/workspace/target/php-cargo-home \
+ -e RUSTUP_HOME=/workspace/target/php-rustup-home \
+ -e "CARGO_TARGET_DIR=/workspace/target/php-release-${PHP_VERSION}-${PHP_ARCH}-${PHP_LIBC}" \
+ -e VERSION="${VERSION}" \
+ -e PHP_VERSION="${PHP_VERSION}" \
+ -e PHP_ARCH="${PHP_ARCH}" \
+ -e PHP_LIBC="${PHP_LIBC}" \
+ -v "$PWD:/workspace" \
+ -w /workspace \
+ "${PHP_IMAGE}" \
+ sh -lc '
+ set -eu
+
+ if command -v apt-get >/dev/null 2>&1; then
+ apt-get update
+ apt-get install -y --no-install-recommends \
+ build-essential \
+ ca-certificates \
+ clang \
+ curl \
+ git \
+ libclang-dev \
+ libhwloc-dev \
+ libssl-dev \
+ libudev-dev \
+ pkg-config \
+ zip
+ rm -rf /var/lib/apt/lists/*
+ else
+ apk add --no-cache \
+ build-base \
+ ca-certificates \
+ clang \
+ clang-dev \
+ curl \
+ eudev-dev \
+ git \
+ hwloc-dev \
+ linux-headers \
+ openssl-dev \
+ pkgconf \
+ zip
+ fi
+
+ mkdir -p "$CARGO_HOME" "$RUSTUP_HOME"
+ if [ ! -x "$CARGO_HOME/bin/rustup" ]; then
+ curl -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh
+ sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain none
+ fi
+ . "$CARGO_HOME/env"
+ rustup show
+
+ php --version
+ php-config --version
+ cargo build --release --manifest-path foreign/php/Cargo.toml
+
+ extension="$(find "${CARGO_TARGET_DIR}/release" -maxdepth 1 -name "libiggy_php.so" -print -quit)"
+ if [ -z "$extension" ]; then
+ echo "PHP extension was not produced"
+ exit 1
+ fi
+
+ package_dir="$(mktemp -d)"
+ cp "$extension" "$package_dir/iggy_php.so"
+ cp foreign/php/LICENSE "$package_dir/LICENSE"
+ cp foreign/php/NOTICE "$package_dir/NOTICE"
+ cp foreign/php/LICENSE-binary "$package_dir/LICENSE-binary"
+
+ archive="php_iggy_php-${VERSION}_php${PHP_VERSION}-${PHP_ARCH}-linux-${PHP_LIBC}-nts.zip"
+ (cd "$package_dir" && zip -9 "/workspace/foreign/php/dist/${archive}" iggy_php.so LICENSE NOTICE LICENSE-binary)
+ rm -rf "$package_dir"
+ '
+
+ ls -lh foreign/php/dist
+
+ - name: Upload PHP extension archive
+ if: inputs.upload_artifacts
+ uses: actions/upload-artifact@v7
+ with:
+ name: php-package-linux-${{ matrix.arch }}-${{ matrix.libc }}-php${{ matrix.php }}
+ path: foreign/php/dist/*.zip
+ retention-days: 7
+
+ macos:
+ name: PHP ${{ matrix.php }} ${{ matrix.arch }} macos
+ needs: license-manifest
+ runs-on: ${{ matrix.runner }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - php: "8.3"
+ arch: x86_64
+ runner: macos-15-intel
+ - php: "8.4"
+ arch: x86_64
+ runner: macos-15-intel
+ - php: "8.3"
+ arch: arm64
+ runner: macos-15
+ - php: "8.4"
+ arch: arm64
+ runner: macos-15
+ steps:
+ - name: Download latest copy script from master
+ if: inputs.use_latest_ci
+ run: |
+ curl -sSL "https://raw.githubusercontent.com/${{ github.repository }}/master/scripts/copy-latest-from-master.sh" \
+ -o /tmp/copy-latest-from-master.sh
+ chmod +x /tmp/copy-latest-from-master.sh
+
+ - uses: actions/checkout@v6.0.2
+ with:
+ ref: ${{ inputs.commit }}
+
+ - name: Save and apply latest CI from master
+ if: inputs.use_latest_ci
+ run: |
+ /tmp/copy-latest-from-master.sh save .github scripts
+ /tmp/copy-latest-from-master.sh apply
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: none
+
+ - name: Setup Rust with cache
+ uses: ./.github/actions/utils/setup-rust-with-cache
+ with:
+ shared-key: php-release
+ save-cache: "false"
+
+ - name: Download license manifest
+ uses: actions/download-artifact@v8
+ with:
+ name: php-license-binary
+ path: foreign/php
+
+ - name: Setup PHP release tools
+ id: release
+ uses: ./.github/actions/php/setup-release-tools
+ with:
+ version: ${{ inputs.version }}
+
+ - name: Build and package PHP extension
+ env:
+ VERSION: ${{ steps.release.outputs.version }}
+ PHP_VERSION: ${{ matrix.php }}
+ PHP_ARCH: ${{ matrix.arch }}
+ CARGO_TARGET_DIR: ${{ github.workspace }}/target/php-release-${{ matrix.php }}-${{ matrix.arch }}-macos
+ run: |
+ set -euo pipefail
+
+ php --version
+ php-config --version
+ cargo build --release --manifest-path foreign/php/Cargo.toml
Review Comment:
this builds from the repo root with `--manifest-path`, but cargo config discovery is cwd-based - `foreign/php/.cargo/config.toml` (the `-Wl,-undefined,dynamic_lookup` link args) never loads. ext-php-rs 0.15.14 doesn't emit those link args from its build script (it only ships them in its own crate-local `.cargo/config.toml`, which doesn't propagate to dependents), so all 4 macos legs will fail linking with undefined zend symbols. fix: `cd foreign/php && cargo build --release` and adjust `CARGO_TARGET_DIR`/`find` paths.
##########
scripts/ci/php-sdk-version-sync.sh:
##########
@@ -0,0 +1,172 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+set -euo pipefail
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+MODE=""
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --check)
+ MODE="check"
+ shift
+ ;;
+ --fix)
+ MODE="fix"
+ shift
+ ;;
+ --help|-h)
+ echo "Usage: $0 [--check|--fix]"
+ echo ""
+ echo "Validate PHP SDK Cargo, Rust SDK dependency, and Composer metadata"
+ echo ""
+ echo "Options:"
+ echo " --check Check Cargo dependency and Composer version metadata"
+ echo " --fix Sync the Rust SDK dependency and remove a manual Composer version field"
+ echo " --help Show this help message"
+ exit 0
+ ;;
+ *)
+ echo -e "${RED}Error: Unknown option $1${NC}"
+ echo "Use --help for usage information"
+ exit 1
+ ;;
+ esac
+done
+
+if [ -z "$MODE" ]; then
+ echo -e "${RED}Error: Please specify either --check or --fix${NC}"
+ echo "Use --help for usage information"
+ exit 1
+fi
+
+REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
+cd "$REPO_ROOT"
+
+RUST_SDK_CARGO_TOML="core/sdk/Cargo.toml"
+PHP_CARGO_TOML="foreign/php/Cargo.toml"
+COMPOSER_JSON="foreign/php/composer.json"
+
+PHP_CARGO_VERSION=$(grep '^version = ' "$PHP_CARGO_TOML" | head -1 | sed 's/version = "\(.*\)"/\1/')
+RUST_SDK_VERSION=$(grep '^version = ' "$RUST_SDK_CARGO_TOML" | head -1 | sed 's/version = "\(.*\)"/\1/')
+PHP_IGGY_DEP_LINE=$(grep '^iggy = ' "$PHP_CARGO_TOML" | head -1 || true)
+PHP_IGGY_DEP_VERSION=""
+if [[ "$PHP_IGGY_DEP_LINE" == *'version = "'* ]]; then
+ PHP_IGGY_DEP_VERSION=$(printf '%s\n' "$PHP_IGGY_DEP_LINE" | sed 's/.*version = "\([^"]*\)".*/\1/')
+fi
+COMPOSER_VERSION_LINE=$(grep '"version"' "$COMPOSER_JSON" | head -1 || true)
+COMPOSER_VERSION=""
+if [ -n "$COMPOSER_VERSION_LINE" ]; then
+ COMPOSER_VERSION=$(printf '%s\n' "$COMPOSER_VERSION_LINE" | sed 's/.*"version": *"\([^"]*\)".*/\1/')
+fi
+
+if [ -z "$PHP_CARGO_VERSION" ]; then
+ echo -e "${RED}Error: Could not extract version from $PHP_CARGO_TOML${NC}"
+ exit 1
+fi
+
+if [ -z "$RUST_SDK_VERSION" ]; then
+ echo -e "${RED}Error: Could not extract version from $RUST_SDK_CARGO_TOML${NC}"
+ exit 1
+fi
+
+echo "PHP SDK version check:"
+echo " PHP Cargo.toml: $PHP_CARGO_VERSION"
+echo " core/sdk Cargo.toml: $RUST_SDK_VERSION"
+if [ -n "$PHP_IGGY_DEP_VERSION" ]; then
+ echo " PHP iggy dependency: $PHP_IGGY_DEP_VERSION"
+else
+ echo " PHP iggy dependency: missing version"
+fi
+if [ -n "$COMPOSER_VERSION" ]; then
+ echo " composer.json: $COMPOSER_VERSION (must be removed)"
+else
+ echo " composer.json: no manual version"
+fi
+echo ""
+
+if [ "$MODE" = "check" ]; then
+ if [ "$PHP_IGGY_DEP_VERSION" = "$RUST_SDK_VERSION" ] && [ -z "$COMPOSER_VERSION" ]; then
+ echo -e "${GREEN}✓ PHP SDK metadata is synchronized${NC}"
+ exit 0
+ fi
+
+ echo -e "${RED}✗ PHP SDK metadata is NOT synchronized${NC}"
+ echo ""
+ if [ "$PHP_IGGY_DEP_VERSION" != "$RUST_SDK_VERSION" ]; then
+ echo "The PHP iggy dependency must match $RUST_SDK_CARGO_TOML."
+ fi
+ if [ -n "$COMPOSER_VERSION" ]; then
+ echo "Packagist/Composer derive VCS package versions from tags."
+ echo "Remove the version field from $COMPOSER_JSON."
+ fi
+ echo ""
+ echo -e "${YELLOW}Run '$0 --fix' to sync PHP SDK metadata${NC}"
+ exit 1
+fi
+
+changed=0
+
+sedi() {
+ if sed --version 2>/dev/null | grep -q 'GNU'; then
+ sed -i "$@"
+ else
+ sed -i '' "$@"
+ fi
+}
+
+if [ "$PHP_IGGY_DEP_VERSION" != "$RUST_SDK_VERSION" ]; then
+ if grep -q '^iggy = .*version = ' "$PHP_CARGO_TOML"; then
+ sedi "s/^\(iggy = .*version = \"\)[^\"]*/\1${RUST_SDK_VERSION}/" "$PHP_CARGO_TOML"
+ else
+ sedi "s/^\(iggy = {[^}]*\) }/\1, version = \"${RUST_SDK_VERSION}\" }/" "$PHP_CARGO_TOML"
+ fi
+ changed=1
+fi
+
+if [ -n "$COMPOSER_VERSION" ]; then
+ sedi '/^[[:space:]]*"version"[[:space:]]*:/d' "$COMPOSER_JSON"
Review Comment:
deleting the `"version"` line with sed breaks composer.json when the field happens to be the last key in the object - the previous line keeps its trailing comma and the file is no longer valid json. the re-grep at line 157 only proves the line is gone, not that the json still parses. cheap guard: `python3 -c 'import json,sys;json.load(open(sys.argv[1]))' foreign/php/composer.json` after the edit.
##########
scripts/bump-version.sh:
##########
@@ -319,6 +324,10 @@ read_current_version() {
grep '^version = ' "$abs_file" | head -1 | sed 's/version = "\(.*\)"/\1/' ;;
pyproject)
grep '^version = ' "$abs_file" | head -1 | sed 's/version = "\(.*\)"/\1/' ;;
+ php-cargo)
+ grep '^version = ' "$abs_file" | head -1 | sed 's/version = "\(.*\)"/\1/' ;;
+ composer)
Review Comment:
also at line 377. the `composer` format cases are unreachable - no component maps to `composer` (sdk-php uses `php-cargo`), and the version field is banned from composer.json by design (php-sdk-version-sync.sh enforces its absence). dead code, delete both.
##########
.github/actions/php/post-merge/action.yml:
##########
@@ -0,0 +1,193 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: php-post-merge
+description: PHP post-merge GitHub release publishing with pre-built PIE extension archives
+
+inputs:
+ version:
+ description: "Version for publishing"
+ required: true
+ tag:
+ description: "Git tag that identifies this PHP SDK release"
+ required: true
+ commit:
+ description: "Commit SHA being published"
+ required: true
+ dry_run:
+ description: "Dry run mode"
+ required: false
+ default: "false"
+ packages_artifact:
+ description: "Name of the artifact containing PHP extension archives"
+ required: false
+ default: "php-extensions-all"
+ packages_path:
+ description: "Path where PHP packages should be downloaded"
+ required: false
+ default: "dist"
+
+runs:
+ using: "composite"
+ steps:
+ - name: Validate version format
+ run: |
+ VERSION="${{ inputs.version }}"
+
+ if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
+ echo "Invalid PHP SDK version format: $VERSION"
+ echo "Expected Composer/Cargo-compatible SemVer: X.Y.Z[-prerelease][+build]"
+ exit 1
+ fi
+
+ echo "Version format valid: $VERSION"
+ shell: bash
+
+ - name: Download pre-built PHP packages
+ uses: actions/download-artifact@v8
+ with:
+ name: ${{ inputs.packages_artifact }}
+ path: ${{ inputs.packages_path }}
+
+ - name: Validate downloaded PHP packages
+ run: |
+ set -euo pipefail
+
+ PACKAGES_PATH="${{ inputs.packages_path }}"
+ VERSION="${{ inputs.version }}"
+
+ if [ ! -d "$PACKAGES_PATH" ]; then
+ echo "PHP packages directory not found: $PACKAGES_PATH"
+ exit 1
+ fi
+
+ expected=(
Review Comment:
these 13 filenames duplicate the build matrix by hand - a platform added to `_build_php_extensions.yml` later won't be validated here (removal fails hard, which is the safe direction). fine as-is, just flagging the coupling in case a generated manifest is worth it later.
##########
.github/workflows/publish.yml:
##########
@@ -1314,6 +1340,101 @@ jobs:
# above ensure the tag is never pushed before the registry is serving
# the artifact (Go is exempt: the tag IS the release).
- name: Tag SDK release (${{ matrix.key }})
+ if: |
+ success() &&
+ inputs.dry_run == false &&
+ matrix.type != 'php' &&
Review Comment:
`matrix.type != 'php'` is dead - the plan step already filters php out of `non_docker_targets`, so this matrix never contains a php entry. delete it or leave a comment saying it's defensive.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@iggy.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org