Repository navigation
build: pin PHP builds and checksums, and update them automatically #245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| # Opens or updates a pull request when there is a new build of the embedded PHP | ||
| # (from upsun/cli-php-builds) or a new CA bundle. See scripts/update-php.sh. | ||
| name: Update PHP | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: "30 6 * * *" | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: update-php | ||
|
|
||
| env: | ||
| BRANCH: automated/update-php | ||
|
|
||
| jobs: | ||
| update: | ||
| runs-on: ubuntu-latest | ||
| # Holds the credentials of the GitHub App that opens the pull request. | ||
| environment: php-updates | ||
|
|
||
| steps: | ||
| - name: Check out repository code | ||
| uses: actions/checkout@v7 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Check for updates | ||
| id: check | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| scripts/update-php.sh "$RUNNER_TEMP/title" "$RUNNER_TEMP/body" | ||
| if [[ -f "$RUNNER_TEMP/title" ]]; then | ||
| echo "title=$(cat "$RUNNER_TEMP/title")" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| # Skips pushing again (and re-running CI) if the branch already has this update. | ||
| - name: Check the existing branch | ||
| id: existing | ||
| if: steps.check.outputs.title | ||
| env: | ||
| TITLE: ${{ steps.check.outputs.title }} | ||
| run: | | ||
| if git fetch --depth=1 origin "$BRANCH" 2>/dev/null \ | ||
| && [[ "$(git log -1 --format=%s FETCH_HEAD)" == "$TITLE" ]]; then | ||
| echo "up_to_date=true" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| - name: Verify the downloads | ||
| if: steps.check.outputs.title && !steps.existing.outputs.up_to_date | ||
| run: | | ||
| make download-php | ||
| expected=$(sed -n 's/^PHP_VERSION = //p' Makefile) | ||
| actual=$(internal/legacy/archives/php_linux_amd64 -r 'echo PHP_VERSION;') | ||
| if [[ "$actual" != "$expected" ]]; then | ||
| echo "::error::Expected PHP $expected, got $actual" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Generate GitHub App token | ||
| id: app-token | ||
| if: steps.check.outputs.title && !steps.existing.outputs.up_to_date | ||
| uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 | ||
| with: | ||
| app-id: ${{ vars.APP_ID }} | ||
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | ||
| permission-contents: write | ||
| permission-pull-requests: write | ||
|
|
||
| # Pushes with the App token, so that CI runs on the pull request. | ||
| - name: Push and open or update the pull request | ||
| if: steps.check.outputs.title && !steps.existing.outputs.up_to_date | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| APP_SLUG: ${{ steps.app-token.outputs.app-slug }} | ||
| TITLE: ${{ steps.check.outputs.title }} | ||
| run: | | ||
| user_id=$(gh api "/users/${APP_SLUG}%5Bbot%5D" --jq .id) | ||
| git config user.name "${APP_SLUG}[bot]" | ||
| git config user.email "${user_id}+${APP_SLUG}[bot]@users.noreply.github.com" | ||
| git switch -c "$BRANCH" | ||
| printf '%s\n\n' "$TITLE" | cat - "$RUNNER_TEMP/body" | git commit -a -F - | ||
| git push --force "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "HEAD:refs/heads/$BRANCH" | ||
|
|
||
| pr=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number') | ||
| if [[ -n "$pr" ]]; then | ||
| gh pr edit "$pr" --title "$TITLE" --body-file "$RUNNER_TEMP/body" | ||
| else | ||
| gh pr create --base "$GITHUB_REF_NAME" --head "$BRANCH" --title "$TITLE" --body-file "$RUNNER_TEMP/body" | ||
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| 26af30fdde5cd3ea5032415ce5aea40e5a0c69d52c4cc0cc8d5c669592fd9c27 php-8.5.11-darwin-amd64 | ||
| 8899461b8796b03f807bc71661650790aaf2a98a4ac5d59fe1520cda5f4212d2 php-8.5.11-darwin-arm64 | ||
| a3806545776bbac282211346700f3467a7ccde8b44771095d61a11f265978a01 php-8.5.11-linux-amd64 | ||
| e0968165a094ed374e3d134f6a048e667dba92b5df40b1e5962a48b47ee9b63b php-8.5.11-linux-arm64 | ||
| d034a9a3a1fc6505723d5c879f82c414406615ea64c172afbb2b9de4ce098441 php-8.5.11-windows-amd64.exe | ||
| e6659656c6df2be75caef66f403ecf10b7933b65d87a81edd904db2b880fa55f sources.json |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| #!/usr/bin/env bash | ||
| # Updates the pinned PHP build (in the Makefile and the checksums file) to the latest cli-php-builds release for the | ||
| # current PHP minor version, and the pinned CA bundle to the latest from curl.se. | ||
| # Writes a pull request title and body to the files given as arguments, if anything changed. | ||
| # Requires: gh (authenticated), jq, curl, sha256sum. | ||
| set -euo pipefail | ||
|
|
||
| title_file=${1:?Usage: $0 TITLE_FILE BODY_FILE} | ||
| body_file=${2:?Usage: $0 TITLE_FILE BODY_FILE} | ||
|
|
||
| repo=upsun/cli-php-builds | ||
| sums_file=internal/legacy/php_sha256sums.txt | ||
|
|
||
| makefile_var() { | ||
| sed -n "s/^$1 = //p" Makefile | ||
| } | ||
|
|
||
| set_makefile_var() { | ||
| sed -i.bak "s/^$1 = .*/$1 = $2/" Makefile && rm Makefile.bak | ||
| } | ||
|
|
||
| tmp=$(mktemp -d) | ||
| trap 'rm -rf "$tmp"' EXIT | ||
|
|
||
| php_version=$(makefile_var PHP_VERSION) | ||
| php_build=$(makefile_var PHP_BUILD) | ||
| cacert_date=$(makefile_var CACERT_DATE) | ||
| # Builds are numbered from 1, so PHP_BUILD = 0 (for a new PHP version) always updates. | ||
| old_tag="php-$php_version-$php_build" | ||
| minor=$(cut -d. -f1,2 <<< "$php_version") | ||
|
|
||
| new_tag=$(gh release list --repo "$repo" --exclude-drafts --exclude-pre-releases --limit 100 \ | ||
| --json tagName --jq '.[].tagName' \ | ||
| | grep -E "^php-${minor//./\\.}\.[0-9]+-[0-9]+$" | sort -V | tail -n1 || true) | ||
| if [[ -z "$new_tag" ]]; then | ||
| echo "No release found for PHP $minor" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| new_cacert_date=$(curl -fsSL https://curl.se/docs/caextract.html \ | ||
| | grep -oE 'cacert-[0-9]{4}-[0-9]{2}-[0-9]{2}\.pem' | sed 's/^cacert-//; s/\.pem$//' | sort | tail -n1) | ||
| if [[ -z "$new_cacert_date" ]]; then | ||
| echo "No CA bundle found" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| titles=() | ||
| body="" | ||
|
|
||
| if [[ "$new_tag" != "$old_tag" ]]; then | ||
| if [[ "$(sort -V <<< "$old_tag"$'\n'"$new_tag" | tail -n1)" != "$new_tag" ]]; then | ||
| echo "The latest release $new_tag is older than $old_tag" >&2 | ||
| exit 1 | ||
| fi | ||
| new_version=$(sed -E 's/^php-(.*)-[0-9]+$/\1/' <<< "$new_tag") | ||
| new_build=${new_tag##*-} | ||
|
|
||
| gh release download "$new_tag" --repo "$repo" --dir "$tmp/new" --pattern SHA256SUMS.txt --pattern sources.json | ||
| if ! gh release download "$old_tag" --repo "$repo" --dir "$tmp/old" --pattern sources.json; then | ||
| mkdir -p "$tmp/old" && echo '{}' > "$tmp/old/sources.json" | ||
| fi | ||
|
|
||
| cp "$tmp/new/SHA256SUMS.txt" "$sums_file" | ||
| set_makefile_var PHP_VERSION "$new_version" | ||
| set_makefile_var PHP_BUILD "$new_build" | ||
|
|
||
| if [[ "$new_version" == "$php_version" ]]; then | ||
| titles+=("rebuild PHP $new_version (build $new_build)") | ||
| else | ||
| titles+=("upgrade PHP to $new_version (build $new_build)") | ||
| fi | ||
|
|
||
| # Lists changed source archives, one row per change, with the platforms it applies to. | ||
| changes=$(jq -rn --slurpfile old "$tmp/old/sources.json" --slurpfile new "$tmp/new/sources.json" ' | ||
| $old[0] as $o | $new[0] as $n | ||
| | [($o + $n | keys[]) as $p | (($o[$p] // {}) + ($n[$p] // {}) | keys[]) as $lib | ||
| | {p: $p, lib: $lib, old: ($o[$p][$lib] // "-"), new: ($n[$p][$lib] // "-")} | ||
| | select(.old != .new)] | ||
| | group_by([.lib, .old, .new]) | ||
| | map("| \(.[0].lib) | \(.[0].old) | \(.[0].new) | \(map(.p) | join(", ")) |") | ||
| | .[]') | ||
| body+="Updates the embedded PHP binaries from [$old_tag](https://github.com/$repo/releases/tag/$old_tag)" | ||
| body+=" to [$new_tag](https://github.com/$repo/releases/tag/$new_tag)."$'\n\n' | ||
| if [[ -n "$changes" ]]; then | ||
| body+="| Source | Old | New | Platforms |"$'\n'"|---|---|---|---|"$'\n'"$changes"$'\n\n' | ||
| else | ||
| body+="No source archives changed."$'\n\n' | ||
| fi | ||
| fi | ||
|
|
||
| if [[ "$new_cacert_date" > "$cacert_date" ]]; then | ||
| file="cacert-$new_cacert_date.pem" | ||
| curl -fsSL "https://curl.se/ca/$file" -o "$tmp/$file" | ||
| curl -fsSL "https://curl.se/ca/$file.sha256" -o "$tmp/$file.sha256" | ||
| (cd "$tmp" && sha256sum -c "$file.sha256") | ||
| set_makefile_var CACERT_DATE "$new_cacert_date" | ||
| set_makefile_var CACERT_SHA256 "$(cut -d' ' -f1 "$tmp/$file.sha256")" | ||
| titles+=("update the CA bundle to $new_cacert_date") | ||
| body+="Updates the CA bundle (embedded for PHP on Windows) from $cacert_date to $new_cacert_date." | ||
| body+=" See: https://curl.se/docs/caextract.html"$'\n\n' | ||
| fi | ||
|
|
||
| if [[ ${#titles[@]} -eq 0 ]]; then | ||
| echo "Up to date: $old_tag, CA bundle $cacert_date" | ||
| exit 0 | ||
| fi | ||
|
|
||
| title="build: ${titles[0]}" | ||
| if [[ ${#titles[@]} -gt 1 ]]; then | ||
| title+=" and ${titles[1]}" | ||
| fi | ||
| echo "$title" > "$title_file" | ||
| printf '%s' "$body" > "$body_file" | ||
| echo "$title" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.