44 schedule :
55 - cron : ' 0 0 * * *'
66 workflow_dispatch :
7+ inputs :
8+ force_full :
9+ description : " Force a full rebuild of all PHP versions regardless of detected changes"
10+ type : boolean
11+ required : false
12+ default : false
713
814permissions :
915 contents : read
@@ -18,18 +24,11 @@ jobs:
1824 env :
1925 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
2026 FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 : true
27+ PHP_MINORS : " 8.2 8.3 8.4 8.5"
2128 steps :
22- - name : Set architecture variables
29+ - name : Install PHP and composer
2330 run : |
24- if [[ "${{ matrix.arch }}" == "arm64" ]]; then
25- echo "RPM_ARCH=aarch64" >> $GITHUB_ENV
26- else
27- echo "RPM_ARCH=x86_64" >> $GITHUB_ENV
28- fi
29-
30- - name : Install composer
31- run : |
32- sudo curl -L https://files.henderkes.com/${RPM_ARCH}-linux/php -o /usr/local/bin/php
31+ sudo curl -L https://files.henderkes.com/x86_64-linux/php -o /usr/local/bin/php
3332 sudo chmod +x /usr/local/bin/php
3433 sudo curl -sS https://raw.githubusercontent.com/composer/getcomposer.org/f3108f64b4e1c1ce6eb462b159956461592b3e3e/web/installer | php -- --quiet
3534 sudo mv composer.phar /usr/local/bin/composer
@@ -42,41 +41,176 @@ jobs:
4241 - name : Composer install
4342 run : composer install
4443
44+ - name : Restore previous state
45+ uses : actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
46+ with :
47+ path : .download-state
48+ key : spc-downloads-lock
49+
50+ - name : Seed empty state if missing
51+ run : |
52+ set -euo pipefail
53+ mkdir -p .download-state
54+ [[ -f .download-state/lock.prev.json ]] || echo '{}' > .download-state/lock.prev.json
55+ [[ -f .download-state/meta.prev.json ]] || echo '{}' > .download-state/meta.prev.json
56+
4557 - name : Download extensions
4658 run : |
4759 php vendor/bin/spc download --shallow-clone -e amqp,apcu,ast,bcmath,brotli,bz2,calendar,ctype,curl,dba,decimal,deepclone,dio,dom,ds,ev,event,excimer,exif,ffi,fileinfo,filter,ftp,gd,gettext,gmp,gmssl,grpc,iconv,igbinary,imagick,inotify,intl,ldap,libxml,lz4,maxminddb,mbregex,mbstring,memcache,memcached,mongodb,msgpack,mysqli,mysqlnd,mysqlnd_parsec,mysqlnd_ed25519,odbc,opcache,openssl,opentelemetry,parallel,password-argon2,pcov,pcntl,pdo,pdo_mysql,pdo_odbc,pdo_pgsql,pdo_sqlite,pdo_sqlsrv,pgsql,phar,posix,protobuf,rar,rdkafka,readline,redis,session,shmop,simdjson,simplexml,snappy,soap,sockets,sodium,spx,sqlite3,sqlsrv,ssh2,swoole,sysvmsg,sysvsem,sysvshm,tidy,tokenizer,trader,uuid,uv,xdebug,xhprof,xlswriter,xml,xmlreader,xmlwriter,xsl,xz,yac,yaml,zip,zlib,zstd
4860
61+ - name : Probe latest PHP versions
62+ id : probe-php
63+ run : |
64+ set -euo pipefail
65+ new='{}'
66+ for v in $PHP_MINORS; do
67+ latest=$(curl -fsSL "https://www.php.net/releases/index.php?json=&max=1&version=${v}" \
68+ | jq -r 'keys[0] // empty')
69+ if [[ -z "$latest" ]]; then
70+ echo "::error::Failed to fetch latest PHP version for ${v}"
71+ exit 1
72+ fi
73+ echo "PHP ${v} latest: ${latest}"
74+ new=$(jq --arg v "$v" --arg l "$latest" '. + {($v): $l}' <<< "$new")
75+ done
76+ mkdir -p downloads
77+ jq --argjson v "$new" -n '{php_versions: $v}' > downloads/.spc-meta.json
78+
79+ - name : Diff state and compute triggers
80+ id : diff
81+ env :
82+ FORCE_FULL : ${{ inputs.force_full }}
83+ run : |
84+ set -euo pipefail
85+
86+ EXT_JSON=vendor/crazywhalecc/static-php-cli/config/ext.json
87+ src_to_ext=$(jq -c '
88+ to_entries
89+ | map(select(.value.source != null))
90+ | map({(.value.source): .key})
91+ | add // {}
92+ ' "$EXT_JSON")
93+ echo "Source->ext map size: $(jq 'length' <<< "$src_to_ext")"
94+
95+ changed_sources=$(jq -nc \
96+ --slurpfile prev .download-state/lock.prev.json \
97+ --slurpfile cur downloads/.lock.json '
98+ ($prev[0] // {}) as $p | ($cur[0] // {}) as $c |
99+ [ ($c | keys[]) as $k
100+ | select(($p[$k].hash // "") != ($c[$k].hash // "")) ]
101+ ')
102+ echo "Changed source keys: $(jq -c . <<< "$changed_sources")"
103+
104+ changed_exts=$(jq -nc --argjson s "$changed_sources" --argjson m "$src_to_ext" '
105+ $s | map($m[.]) | map(select(. != null)) | unique
106+ ')
107+ pkgs=$(jq -r 'join(",")' <<< "$changed_exts")
108+ echo "Changed packages: ${pkgs:-<none>}"
109+
110+ full_versions=$(jq -nrc \
111+ --slurpfile prev .download-state/meta.prev.json \
112+ --slurpfile cur downloads/.spc-meta.json '
113+ (($prev[0].php_versions) // {}) as $p |
114+ (($cur[0].php_versions) // {}) as $c |
115+ [ ($c | keys[]) as $k | select($c[$k] != ($p[$k] // "")) ]
116+ ')
117+ echo "PHP minors with bumped php-src: $(jq -c . <<< "$full_versions")"
118+
119+ all_minors=$(jq -nc --arg s "$PHP_MINORS" '$s | split(" ")')
120+ if [[ "$FORCE_FULL" == "true" ]]; then
121+ echo "force_full input set -> rebuilding all PHP versions"
122+ full_versions="$all_minors"
123+ fi
124+
125+ full_csv=$(jq -r 'join(",")' <<< "$full_versions")
126+
127+ partial_csv=""
128+ if [[ -n "$pkgs" ]]; then
129+ partial_csv=$(jq -nrc \
130+ --argjson all "$all_minors" \
131+ --argjson full "$full_versions" '
132+ $all - $full | join(",")
133+ ')
134+ fi
135+
136+ any="false"
137+ if [[ -n "$pkgs" || -n "$full_csv" ]]; then
138+ any="true"
139+ fi
140+
141+ echo "full_php=$full_csv" | tee -a $GITHUB_OUTPUT
142+ echo "partial_php=$partial_csv" | tee -a $GITHUB_OUTPUT
143+ echo "changed_packages=$pkgs" | tee -a $GITHUB_OUTPUT
144+ echo "any_change=$any" | tee -a $GITHUB_OUTPUT
145+
146+ {
147+ echo "## spc-download summary"
148+ echo "- Full rebuild PHP versions: ${full_csv:-<none>}"
149+ echo "- Partial rebuild PHP versions: ${partial_csv:-<none>}"
150+ echo "- Changed packages: ${pkgs:-<none>}"
151+ echo "- Any change: $any"
152+ } >> "$GITHUB_STEP_SUMMARY"
153+
154+ - name : Persist current state for next run
155+ if : hashFiles('downloads/.lock.json') != ''
156+ run : |
157+ set -euo pipefail
158+ cp downloads/.lock.json .download-state/lock.prev.json
159+ cp downloads/.spc-meta.json .download-state/meta.prev.json
160+
161+ - name : Delete previous state cache
162+ if : hashFiles('downloads/.lock.json') != ''
163+ continue-on-error : true
164+ env :
165+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
166+ run : |
167+ gh api -X DELETE \
168+ "/repos/$GITHUB_REPOSITORY/actions/caches?key=spc-downloads-lock" \
169+ 2>/dev/null || true
170+
171+ - name : Save state cache
172+ if : hashFiles('downloads/.lock.json') != ''
173+ uses : actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
174+ with :
175+ path : .download-state
176+ key : spc-downloads-lock
177+
49178 - name : Create tarball (keep permissions)
179+ if : steps.diff.outputs.any_change == 'true'
50180 run : |
51181 tar -czf downloads.tar.gz -C downloads .
52182
53183 - name : Upload downloads directory
184+ if : steps.diff.outputs.any_change == 'true'
54185 uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
55186 with :
56187 name : downloads-tarball
57188 path : downloads.tar.gz
58- retention-days : 2
189+ retention-days : 14
59190
60- - name : Trigger build-rpm-modular-packages workflow
61- if : success()
62- run : gh workflow run build-rpm-modular-packages.yml
191+ - name : Trigger downstream workflows
192+ if : steps.diff.outputs.any_change == 'true'
63193 env :
64- GH_TOKEN : ${{ secrets.GH_PAT }} # use our own user as the triggering user
65-
66- # - name: Trigger build-gcc-deb-packages workflow
67- # if: success()
68- # run: gh workflow run build-gcc-deb-packages.yml
69- # env:
70- # GH_TOKEN: ${{ secrets.GH_PAT }} # use our own user as the triggering user
71-
72- - name : Trigger build-deb-forgejo workflow
73- if : success()
74- run : gh workflow run build-deb-forgejo.yml
75- env :
76- GH_TOKEN : ${{ secrets.GH_PAT }} # use our own user as the triggering user
77-
78- - name : Trigger build-apk-forgejo workflow
79- if : success()
80- run : gh workflow run build-apk-forgejo.yml
81- env :
82- GH_TOKEN : ${{ secrets.GH_PAT }} # use our own user as the triggering user
194+ GH_TOKEN : ${{ secrets.GH_PAT }}
195+ FULL_PHP : ${{ steps.diff.outputs.full_php }}
196+ PARTIAL_PHP : ${{ steps.diff.outputs.partial_php }}
197+ CHANGED_PACKAGES : ${{ steps.diff.outputs.changed_packages }}
198+ run : |
199+ set -euo pipefail
200+ workflows=(
201+ build-rpm-modular-packages.yml
202+ build-deb-forgejo.yml
203+ build-apk-forgejo.yml
204+ )
205+ for wf in "${workflows[@]}"; do
206+ if [[ -n "$FULL_PHP" ]]; then
207+ echo ">> $wf : full rebuild for $FULL_PHP"
208+ gh workflow run "$wf" -f php_versions="$FULL_PHP"
209+ fi
210+ if [[ -n "$CHANGED_PACKAGES" && -n "$PARTIAL_PHP" ]]; then
211+ echo ">> $wf : partial rebuild for $PARTIAL_PHP, packages=$CHANGED_PACKAGES"
212+ gh workflow run "$wf" \
213+ -f php_versions="$PARTIAL_PHP" \
214+ -f packages="$CHANGED_PACKAGES"
215+ fi
216+ done
0 commit comments