Skip to content

ci: fallback on gh when the php.net API is down#2233

Open
dunglas wants to merge 2 commits intomainfrom
ci/php-api-fallback
Open

ci: fallback on gh when the php.net API is down#2233
dunglas wants to merge 2 commits intomainfrom
ci/php-api-fallback

Conversation

@dunglas
Copy link
Member

@dunglas dunglas commented Mar 3, 2026

Unfortunately, GitHub Actions is often blocked by the php.net CDN. This patch adds a fallback to use GitHub to try to determine the PHP version to use. This is less ideal because PHP currently doesn't use GitHub extensively, and distribution archives aren't available in the GitHub releases, only on php.net.

Copilot AI review requested due to automatic review settings March 3, 2026 09:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves CI resilience when php.net’s releases API is unavailable (e.g., blocked by the php.net CDN) by adding a fallback mechanism to infer the latest PHP patch version via GitHub.

Changes:

  • Add php.net → GitHub (gh) fallback logic to determine the latest PHP version when PHP_VERSION isn’t set.
  • Update the sanitizers workflow to use the same fallback and to handle fetching either php.net .xz archives or GitHub .tar.gz archives.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
build-static.sh Adds php.net API lookup with a GitHub (gh) fallback to resolve the latest patch version for a given minor series.
.github/workflows/sanitizers.yaml Adds fallback logic for determining the PHP version and adjusts extraction to support GitHub tarballs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

build-static.sh Outdated
Comment on lines +66 to +77
json=$(curl -s "https://www.php.net/releases/index.php?json&version=$input")
latest=$(echo "$json" | jq -r '.version')
latest=$(echo "$json" | jq -r '.version' 2>/dev/null)

if [[ "$latest" == "$input"* ]]; then
echo "$latest"
else
echo "$input"
return
fi

# Fallback: use the latest GitHub release from php/php-src
if type "gh" >/dev/null 2>&1; then
latest=$(gh release list --repo php/php-src --exclude-drafts --exclude-pre-releases --json tagName --jq "[.[].tagName | select(startswith(\"php-${input}.\"))] | first | ltrimstr(\"php-\")")
fi
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this script runs with set -o errexit, failures in the command substitutions here (curl unreachable/blocked, jq parse error on non-JSON response, or gh failing due to auth/rate limit) will abort the whole script before the fallback logic can run. To make the fallback effective, wrap these calls in if ...; then ...; fi blocks (or append || true) and treat empty/"null" outputs as non-fatal so the function can continue to the GitHub/default path.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +71
if curl -fsSL 'https://www.php.net/releases/index.php?json&max=1&version=8.5' -o version.json 2>/dev/null; then
version="$(jq -r 'keys[0]' version.json)"
archive="$(jq -r '.[] .source[] | select(.filename |endswith(".xz")) | "https://www.php.net/distributions/" + .filename' version.json)"
if [ -n "$version" ] && [ "$version" != "null" ] && [ -n "$archive" ] && [ "$archive" != "null" ]; then
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "archive=$archive" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
# Fallback: use the latest GitHub release from php/php-src
version=$(gh release list --repo php/php-src --exclude-drafts --exclude-pre-releases --json tagName --jq '[.[].tagName | select(startswith("php-8.5."))] | first | ltrimstr("php-")')
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "archive=https://github.com/php/php-src/archive/refs/tags/php-${version}.tar.gz" >> "$GITHUB_OUTPUT"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub Actions runs bash steps with -e by default, so if php.net returns a 200 with HTML (CDN block page) jq will error and the step will fail before reaching the GitHub fallback. Consider making the jq reads non-fatal (e.g., redirect stderr and || true) and only using the parsed values when they’re non-empty/non-"null". Similarly, guard the gh release list call (and verify version is non-empty) so the workflow fails with a clear message if both sources are unavailable.

Copilot uses AI. Check for mistakes.
fi
# Fallback: use the latest GitHub release from php/php-src
version=$(gh release list --repo php/php-src --exclude-drafts --exclude-pre-releases --json tagName --jq '[.[].tagName | select(startswith("php-8.5."))] | first | ltrimstr("php-")')
Copy link
Member

@alexandre-daubois alexandre-daubois Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If gh fails as well, jq should return null. This will break without a verbose error. Should we extract the version fetch and check its value exists and is not null? This way we can print something like Failed to determine PHP version from both php.net and GitHub and exit early

Edit: well Copilot was faster than me at typing 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants