ci(security): no ${{ }} in run:, validate resolved versions, LiteSpeed index over HTTPS
Security review of #30: step outputs derived from the LiteSpeed apt index (fetched over plain HTTP) were spliced into shell via ${{ }} in jobs that hold registry push secrets — a MITM'd "version" would be shell injection. - every run: block in build-push.yaml and lsphp-source-emergency.yaml now receives matrix values, step outputs, inputs and run_id via env: only (incl. the pre-existing php.net / LiteSpeed resolve steps from #24/#29) - resolved versions are regex-checked before GITHUB_OUTPUT: PHP ^[0-9]+\.[0-9]+\.[0-9]+$, deb ^[0-9][0-9A-Za-z.+~:-]*$ - LiteSpeed Packages index fetched over HTTPS (--proto =https); measured rpms.litespeedtech.com serves it (HTTP/2 200) - lsphp-src-build.sh / lsphp-src-overlay.sh validate PHPVER too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
83c2ee9c2a
commit
42993f42bd
4 files changed
+82
-32
No files matched your search
@@ -97,19 +97,26 @@ jobs:
|
|||||||
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
||||||
- name: Cache-bust value
|
- name: Cache-bust value
|
||||||
id: bust
|
id: bust
|
||||||
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${{ gitea.run_id }}" >> "$GITHUB_OUTPUT"
|
env:
|
||||||
|
RUN_ID: ${{ gitea.run_id }}
|
||||||
|
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# The minimum PHP version this build must ship: php.net's current release for
|
# The minimum PHP version this build must ship: php.net's current release for
|
||||||
# the branch (over HTTPS). The Dockerfile fails if Remi gave us anything older,
|
# the branch (over HTTPS). The Dockerfile fails if Remi gave us anything older,
|
||||||
# so lagging mirrors or replayed repo metadata can't ship a vulnerable PHP.
|
# so lagging mirrors or replayed repo metadata can't ship a vulnerable PHP.
|
||||||
- name: Resolve current PHP release from php.net
|
- name: Resolve current PHP release from php.net
|
||||||
id: phpmin
|
id: phpmin
|
||||||
|
# Values reach the script via env, never via ${{ }} inside run: (a
|
||||||
|
# crafted string would otherwise be shell); outputs are regex-checked.
|
||||||
|
env:
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
v="${{ matrix.phpver }}"; branch="${v:0:1}.${v:1}"
|
v="$PHPVER"; branch="${v:0:1}.${v:1}"
|
||||||
json=$(curl -fsS --retry 5 --max-time 60 "https://www.php.net/releases/index.php?json&max=1&version=${branch}")
|
json=$(curl -fsS --retry 5 --max-time 60 "https://www.php.net/releases/index.php?json&max=1&version=${branch}")
|
||||||
min=$(printf '%s' "$json" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(next(iter(d)) if isinstance(d,dict) and d else "")')
|
min=$(printf '%s' "$json" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(next(iter(d)) if isinstance(d,dict) and d else "")')
|
||||||
if [ -z "$min" ]; then echo "::error::no php.net release found for ${branch}"; exit 1; fi
|
if [ -z "$min" ]; then echo "::error::no php.net release found for ${branch}"; exit 1; fi
|
||||||
|
[[ "$min" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::php.net returned a malformed version for ${branch}"; exit 1; }
|
||||||
echo "php.net current ${branch}: ${min}"
|
echo "php.net current ${branch}: ${min}"
|
||||||
echo "min=${min}" >> "$GITHUB_OUTPUT"
|
echo "min=${min}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
@@ -157,19 +164,26 @@ jobs:
|
|||||||
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
||||||
- name: Cache-bust value
|
- name: Cache-bust value
|
||||||
id: bust
|
id: bust
|
||||||
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${{ gitea.run_id }}" >> "$GITHUB_OUTPUT"
|
env:
|
||||||
|
RUN_ID: ${{ gitea.run_id }}
|
||||||
|
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# The minimum PHP version this build must ship: php.net's current release for
|
# The minimum PHP version this build must ship: php.net's current release for
|
||||||
# the branch (over HTTPS). The Dockerfile fails if Remi gave us anything older,
|
# the branch (over HTTPS). The Dockerfile fails if Remi gave us anything older,
|
||||||
# so lagging mirrors or replayed repo metadata can't ship a vulnerable PHP.
|
# so lagging mirrors or replayed repo metadata can't ship a vulnerable PHP.
|
||||||
- name: Resolve current PHP release from php.net
|
- name: Resolve current PHP release from php.net
|
||||||
id: phpmin
|
id: phpmin
|
||||||
|
# Values reach the script via env, never via ${{ }} inside run: (a
|
||||||
|
# crafted string would otherwise be shell); outputs are regex-checked.
|
||||||
|
env:
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
v="${{ matrix.phpver }}"; branch="${v:0:1}.${v:1}"
|
v="$PHPVER"; branch="${v:0:1}.${v:1}"
|
||||||
json=$(curl -fsS --retry 5 --max-time 60 "https://www.php.net/releases/index.php?json&max=1&version=${branch}")
|
json=$(curl -fsS --retry 5 --max-time 60 "https://www.php.net/releases/index.php?json&max=1&version=${branch}")
|
||||||
min=$(printf '%s' "$json" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(next(iter(d)) if isinstance(d,dict) and d else "")')
|
min=$(printf '%s' "$json" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(next(iter(d)) if isinstance(d,dict) and d else "")')
|
||||||
if [ -z "$min" ]; then echo "::error::no php.net release found for ${branch}"; exit 1; fi
|
if [ -z "$min" ]; then echo "::error::no php.net release found for ${branch}"; exit 1; fi
|
||||||
|
[[ "$min" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::php.net returned a malformed version for ${branch}"; exit 1; }
|
||||||
echo "php.net current ${branch}: ${min}"
|
echo "php.net current ${branch}: ${min}"
|
||||||
echo "min=${min}" >> "$GITHUB_OUTPUT"
|
echo "min=${min}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
@@ -222,7 +236,9 @@ jobs:
|
|||||||
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
||||||
- name: Cache-bust value
|
- name: Cache-bust value
|
||||||
id: bust
|
id: bust
|
||||||
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${{ gitea.run_id }}" >> "$GITHUB_OUTPUT"
|
env:
|
||||||
|
RUN_ID: ${{ gitea.run_id }}
|
||||||
|
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# Ask the LiteSpeed apt repo (the same one the base image's apt uses) for the
|
# Ask the LiteSpeed apt repo (the same one the base image's apt uses) for the
|
||||||
# CURRENT lsphp version. The Dockerfile asserts the installed package equals
|
# CURRENT lsphp version. The Dockerfile asserts the installed package equals
|
||||||
@@ -230,14 +246,21 @@ jobs:
|
|||||||
# it into the image labels org.whp.php-version / org.whp.lsphp-package-version.
|
# it into the image labels org.whp.php-version / org.whp.lsphp-package-version.
|
||||||
- name: Resolve current lsphp${{ matrix.phpver }} from the LiteSpeed repo
|
- name: Resolve current lsphp${{ matrix.phpver }} from the LiteSpeed repo
|
||||||
id: lsphp
|
id: lsphp
|
||||||
|
# HTTPS (rpms.litespeedtech.com serves it; measured 2026-10-21), values via
|
||||||
|
# env, and both outputs regex-checked before they reach GITHUB_OUTPUT.
|
||||||
|
env:
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
idx=$(curl -fsS --retry 3 --max-time 60 http://rpms.litespeedtech.com/debian/dists/noble/main/binary-amd64/Packages)
|
idx=$(curl -fsS --proto '=https' --retry 3 --max-time 60 https://rpms.litespeedtech.com/debian/dists/noble/main/binary-amd64/Packages)
|
||||||
pkg=$(printf '%s\n' "$idx" | awk -v p="lsphp${{ matrix.phpver }}" '/^Package: /{n=$2} /^Version: / && n==p {print $2}' | sort -V | tail -n1)
|
pkg=$(printf '%s\n' "$idx" | awk -v p="lsphp${PHPVER}" '/^Package: /{n=$2} /^Version: / && n==p {print $2}' | sort -V | tail -n1)
|
||||||
if [ -z "$pkg" ]; then echo "::error::lsphp${{ matrix.phpver }} not found in the LiteSpeed repo index"; exit 1; fi
|
if [ -z "$pkg" ]; then echo "::error::lsphp${PHPVER} not found in the LiteSpeed repo index"; exit 1; fi
|
||||||
echo "lsphp${{ matrix.phpver }} in repo: $pkg (PHP ${pkg%%-*})"
|
php="${pkg%%-*}"
|
||||||
|
[[ "$pkg" =~ ^[0-9][0-9A-Za-z.+~:-]*$ ]] || { echo "::error::malformed lsphp${PHPVER} package version in the repo index"; exit 1; }
|
||||||
|
[[ "$php" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::malformed PHP version '${php}' derived from lsphp${PHPVER} ${pkg}"; exit 1; }
|
||||||
|
echo "lsphp${PHPVER} in repo: $pkg (PHP ${php})"
|
||||||
echo "pkg=$pkg" >> "$GITHUB_OUTPUT"
|
echo "pkg=$pkg" >> "$GITHUB_OUTPUT"
|
||||||
echo "php=${pkg%%-*}" >> "$GITHUB_OUTPUT"
|
echo "php=${php}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Login to Gitea
|
- name: Login to Gitea
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
@@ -252,12 +275,15 @@ jobs:
|
|||||||
# the job goes green again by itself once the LiteSpeed repo catches up.
|
# the job goes green again by itself once the LiteSpeed repo catches up.
|
||||||
# Fail-open if the tag cannot be inspected (first build, registry blip).
|
# Fail-open if the tag cannot be inspected (first build, registry blip).
|
||||||
- name: Do not roll back a newer php.net emergency image
|
- name: Do not roll back a newer php.net emergency image
|
||||||
|
env:
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
|
NEW_PHP: ${{ steps.lsphp.outputs.php }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
ref=repo.anhonesthost.net/cloud-hosting-platform/cac-litespeed:php${{ matrix.phpver }}
|
ref="repo.anhonesthost.net/cloud-hosting-platform/cac-litespeed:php${PHPVER}"
|
||||||
src=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.lsphp-source" }}' 2>/dev/null || true)
|
src=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.lsphp-source" }}' 2>/dev/null || true)
|
||||||
cur=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.php-version" }}' 2>/dev/null || true)
|
cur=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.php-version" }}' 2>/dev/null || true)
|
||||||
new='${{ steps.lsphp.outputs.php }}'
|
new="$NEW_PHP"
|
||||||
echo "published $ref: source=${src:-?} php=${cur:-?}; this build: packaged $new"
|
echo "published $ref: source=${src:-?} php=${cur:-?}; this build: packaged $new"
|
||||||
if [ "$src" = "php.net" ] && [ "$cur" != "$new" ] && [ "$(printf '%s\n%s\n' "$cur" "$new" | sort -V | tail -n1)" = "$cur" ]; then
|
if [ "$src" = "php.net" ] && [ "$cur" != "$new" ] && [ "$(printf '%s\n%s\n' "$cur" "$new" | sort -V | tail -n1)" = "$cur" ]; then
|
||||||
echo "::error::$ref is a php.net emergency build of PHP $cur; LiteSpeed still ships $new. Not overwriting it with an older PHP. Re-run lsphp-source-emergency.yaml for a newer fix, or wait for LiteSpeed."
|
echo "::error::$ref is a php.net emergency build of PHP $cur; LiteSpeed still ships $new. Not overwriting it with an older PHP. Re-run lsphp-source-emergency.yaml for a newer fix, or wait for LiteSpeed."
|
||||||
@@ -313,7 +339,9 @@ jobs:
|
|||||||
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
# the package-upgrade layers consume CACHE_BUST and can never be reused.
|
||||||
- name: Cache-bust value
|
- name: Cache-bust value
|
||||||
id: bust
|
id: bust
|
||||||
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${{ gitea.run_id }}" >> "$GITHUB_OUTPUT"
|
env:
|
||||||
|
RUN_ID: ${{ gitea.run_id }}
|
||||||
|
run: echo "value=$(date -u +%Y%m%dT%H%M%SZ)-${RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# Ask the LiteSpeed apt repo (the same one the base image's apt uses) for the
|
# Ask the LiteSpeed apt repo (the same one the base image's apt uses) for the
|
||||||
# CURRENT lsphp version. The Dockerfile asserts the installed package equals
|
# CURRENT lsphp version. The Dockerfile asserts the installed package equals
|
||||||
@@ -321,14 +349,21 @@ jobs:
|
|||||||
# it into the image labels org.whp.php-version / org.whp.lsphp-package-version.
|
# it into the image labels org.whp.php-version / org.whp.lsphp-package-version.
|
||||||
- name: Resolve current lsphp${{ matrix.phpver }} from the LiteSpeed repo
|
- name: Resolve current lsphp${{ matrix.phpver }} from the LiteSpeed repo
|
||||||
id: lsphp
|
id: lsphp
|
||||||
|
# HTTPS (rpms.litespeedtech.com serves it; measured 2026-10-21), values via
|
||||||
|
# env, and both outputs regex-checked before they reach GITHUB_OUTPUT.
|
||||||
|
env:
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
idx=$(curl -fsS --retry 3 --max-time 60 http://rpms.litespeedtech.com/debian/dists/noble/main/binary-amd64/Packages)
|
idx=$(curl -fsS --proto '=https' --retry 3 --max-time 60 https://rpms.litespeedtech.com/debian/dists/noble/main/binary-amd64/Packages)
|
||||||
pkg=$(printf '%s\n' "$idx" | awk -v p="lsphp${{ matrix.phpver }}" '/^Package: /{n=$2} /^Version: / && n==p {print $2}' | sort -V | tail -n1)
|
pkg=$(printf '%s\n' "$idx" | awk -v p="lsphp${PHPVER}" '/^Package: /{n=$2} /^Version: / && n==p {print $2}' | sort -V | tail -n1)
|
||||||
if [ -z "$pkg" ]; then echo "::error::lsphp${{ matrix.phpver }} not found in the LiteSpeed repo index"; exit 1; fi
|
if [ -z "$pkg" ]; then echo "::error::lsphp${PHPVER} not found in the LiteSpeed repo index"; exit 1; fi
|
||||||
echo "lsphp${{ matrix.phpver }} in repo: $pkg (PHP ${pkg%%-*})"
|
php="${pkg%%-*}"
|
||||||
|
[[ "$pkg" =~ ^[0-9][0-9A-Za-z.+~:-]*$ ]] || { echo "::error::malformed lsphp${PHPVER} package version in the repo index"; exit 1; }
|
||||||
|
[[ "$php" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::malformed PHP version '${php}' derived from lsphp${PHPVER} ${pkg}"; exit 1; }
|
||||||
|
echo "lsphp${PHPVER} in repo: $pkg (PHP ${php})"
|
||||||
echo "pkg=$pkg" >> "$GITHUB_OUTPUT"
|
echo "pkg=$pkg" >> "$GITHUB_OUTPUT"
|
||||||
echo "php=${pkg%%-*}" >> "$GITHUB_OUTPUT"
|
echo "php=${php}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Login to Gitea
|
- name: Login to Gitea
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
@@ -343,12 +378,15 @@ jobs:
|
|||||||
# the job goes green again by itself once the LiteSpeed repo catches up.
|
# the job goes green again by itself once the LiteSpeed repo catches up.
|
||||||
# Fail-open if the tag cannot be inspected (first build, registry blip).
|
# Fail-open if the tag cannot be inspected (first build, registry blip).
|
||||||
- name: Do not roll back a newer php.net emergency image
|
- name: Do not roll back a newer php.net emergency image
|
||||||
|
env:
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
|
NEW_PHP: ${{ steps.lsphp.outputs.php }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
ref=repo.anhonesthost.net/cloud-hosting-platform/cac-lsphp:php${{ matrix.phpver }}
|
ref="repo.anhonesthost.net/cloud-hosting-platform/cac-lsphp:php${PHPVER}"
|
||||||
src=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.lsphp-source" }}' 2>/dev/null || true)
|
src=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.lsphp-source" }}' 2>/dev/null || true)
|
||||||
cur=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.php-version" }}' 2>/dev/null || true)
|
cur=$(docker buildx imagetools inspect "$ref" --format '{{ index .Image.Config.Labels "org.whp.php-version" }}' 2>/dev/null || true)
|
||||||
new='${{ steps.lsphp.outputs.php }}'
|
new="$NEW_PHP"
|
||||||
echo "published $ref: source=${src:-?} php=${cur:-?}; this build: packaged $new"
|
echo "published $ref: source=${src:-?} php=${cur:-?}; this build: packaged $new"
|
||||||
if [ "$src" = "php.net" ] && [ "$cur" != "$new" ] && [ "$(printf '%s\n%s\n' "$cur" "$new" | sort -V | tail -n1)" = "$cur" ]; then
|
if [ "$src" = "php.net" ] && [ "$cur" != "$new" ] && [ "$(printf '%s\n%s\n' "$cur" "$new" | sort -V | tail -n1)" = "$cur" ]; then
|
||||||
echo "::error::$ref is a php.net emergency build of PHP $cur; LiteSpeed still ships $new. Not overwriting it with an older PHP. Re-run lsphp-source-emergency.yaml for a newer fix, or wait for LiteSpeed."
|
echo "::error::$ref is a php.net emergency build of PHP $cur; LiteSpeed still ships $new. Not overwriting it with an older PHP. Re-run lsphp-source-emergency.yaml for a newer fix, or wait for LiteSpeed."
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ jobs:
|
|||||||
IN_VERSIONS: ${{ inputs.php_versions }}
|
IN_VERSIONS: ${{ inputs.php_versions }}
|
||||||
IN_IMAGES: ${{ inputs.images }}
|
IN_IMAGES: ${{ inputs.images }}
|
||||||
IN_PROD: ${{ format('{0}', inputs.push_production_tags) }}
|
IN_PROD: ${{ format('{0}', inputs.push_production_tags) }}
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
|
IMG: ${{ matrix.image }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
case "$IN_IMAGES" in both|lsphp|litespeed) ;; *) echo "::error::images must be both|lsphp|litespeed, got '$IN_IMAGES'"; exit 1 ;; esac
|
case "$IN_IMAGES" in both|lsphp|litespeed) ;; *) echo "::error::images must be both|lsphp|litespeed, got '$IN_IMAGES'"; exit 1 ;; esac
|
||||||
@@ -56,16 +58,17 @@ jobs:
|
|||||||
v=""
|
v=""
|
||||||
for pair in $IN_VERSIONS; do
|
for pair in $IN_VERSIONS; do
|
||||||
[[ "$pair" =~ ^(8[1-5])=([0-9]+\.[0-9]+\.[0-9]+)$ ]] || { echo "::error::bad php_versions entry '$pair' (want NN=X.Y.Z, NN in 81..85)"; exit 1; }
|
[[ "$pair" =~ ^(8[1-5])=([0-9]+\.[0-9]+\.[0-9]+)$ ]] || { echo "::error::bad php_versions entry '$pair' (want NN=X.Y.Z, NN in 81..85)"; exit 1; }
|
||||||
[ "${BASH_REMATCH[1]}" = '${{ matrix.phpver }}' ] && v="${BASH_REMATCH[2]}"
|
[ "${BASH_REMATCH[1]}" = "$PHPVER" ] && v="${BASH_REMATCH[2]}"
|
||||||
done
|
done
|
||||||
echo "prod=$IN_PROD" >> "$GITHUB_OUTPUT"
|
echo "prod=$IN_PROD" >> "$GITHUB_OUTPUT"
|
||||||
if [ -z "$v" ] || { [ "$IN_IMAGES" != both ] && [ "$IN_IMAGES" != '${{ matrix.image }}' ]; }; then
|
if [ -z "$v" ] || { [ "$IN_IMAGES" != both ] && [ "$IN_IMAGES" != "$IMG" ]; }; then
|
||||||
echo "not requested: php${{ matrix.phpver }} / ${{ matrix.image }}"; echo "skip=1" >> "$GITHUB_OUTPUT"; exit 0
|
echo "not requested: php${PHPVER} / ${IMG}"; echo "skip=1" >> "$GITHUB_OUTPUT"; exit 0
|
||||||
fi
|
fi
|
||||||
echo "skip=0" >> "$GITHUB_OUTPUT"
|
echo "skip=0" >> "$GITHUB_OUTPUT"
|
||||||
echo "version=$v" >> "$GITHUB_OUTPUT"
|
echo "version=$v" >> "$GITHUB_OUTPUT"
|
||||||
echo "image_name=cac-${{ matrix.image }}" >> "$GITHUB_OUTPUT"
|
case "$IMG" in lsphp|litespeed) ;; *) echo "::error::unexpected matrix image '$IMG'"; exit 1 ;; esac
|
||||||
echo "dockerfile=./Dockerfile.${{ matrix.image }}" >> "$GITHUB_OUTPUT"
|
echo "image_name=cac-${IMG}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "dockerfile=./Dockerfile.${IMG}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
if: steps.t.outputs.skip == '0'
|
if: steps.t.outputs.skip == '0'
|
||||||
@@ -77,26 +80,33 @@ jobs:
|
|||||||
- name: Resolve php.net release + packaged lsphp
|
- name: Resolve php.net release + packaged lsphp
|
||||||
if: steps.t.outputs.skip == '0'
|
if: steps.t.outputs.skip == '0'
|
||||||
id: v
|
id: v
|
||||||
|
env:
|
||||||
|
V: ${{ steps.t.outputs.version }}
|
||||||
|
PHPVER: ${{ matrix.phpver }}
|
||||||
|
RUN_ID: ${{ gitea.run_id }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
v='${{ steps.t.outputs.version }}'
|
v="$V"
|
||||||
|
[[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::malformed version '$v'"; exit 1; }
|
||||||
json=$(curl -fsS --retry 3 --max-time 60 "https://www.php.net/releases/index.php?json&version=$v")
|
json=$(curl -fsS --retry 3 --max-time 60 "https://www.php.net/releases/index.php?json&version=$v")
|
||||||
sha=$(printf '%s' "$json" | python3 -c 'import json,sys; d=json.load(sys.stdin); v=sys.argv[1]; print(next((s["sha256"] for s in d.get("source", []) if s.get("filename")=="php-%s.tar.xz"%v), ""))' "$v")
|
sha=$(printf '%s' "$json" | python3 -c 'import json,sys; d=json.load(sys.stdin); v=sys.argv[1]; print(next((s["sha256"] for s in d.get("source", []) if s.get("filename")=="php-%s.tar.xz"%v), ""))' "$v")
|
||||||
[ -n "$sha" ] || { echo "::error::php.net has no release php-$v.tar.xz (EOL branch? typo?): $json"; exit 1; }
|
[ -n "$sha" ] || { echo "::error::php.net has no release php-$v.tar.xz (EOL branch? typo?): $json"; exit 1; }
|
||||||
[[ "$sha" =~ ^[0-9a-f]{64}$ ]] || { echo "::error::no sha256 for php-$v.tar.xz in the php.net releases JSON"; exit 1; }
|
[[ "$sha" =~ ^[0-9a-f]{64}$ ]] || { echo "::error::no sha256 for php-$v.tar.xz in the php.net releases JSON"; exit 1; }
|
||||||
idx=$(curl -fsS --retry 3 --max-time 60 http://rpms.litespeedtech.com/debian/dists/noble/main/binary-amd64/Packages)
|
idx=$(curl -fsS --proto '=https' --retry 3 --max-time 60 https://rpms.litespeedtech.com/debian/dists/noble/main/binary-amd64/Packages)
|
||||||
pkg=$(printf '%s\n' "$idx" | awk -v p="lsphp${{ matrix.phpver }}" '/^Package: /{n=$2} /^Version: / && n==p {print $2}' | sort -V | tail -n1)
|
pkg=$(printf '%s\n' "$idx" | awk -v p="lsphp${PHPVER}" '/^Package: /{n=$2} /^Version: / && n==p {print $2}' | sort -V | tail -n1)
|
||||||
[ -n "$pkg" ] || { echo "::error::lsphp${{ matrix.phpver }} not in the LiteSpeed repo index"; exit 1; }
|
[ -n "$pkg" ] || { echo "::error::lsphp${PHPVER} not in the LiteSpeed repo index"; exit 1; }
|
||||||
|
[[ "$pkg" =~ ^[0-9][0-9A-Za-z.+~:-]*$ ]] || { echo "::error::malformed lsphp${PHPVER} package version in the repo index"; exit 1; }
|
||||||
pphp=${pkg%%-*}
|
pphp=${pkg%%-*}
|
||||||
|
[[ "$pphp" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::malformed PHP version '$pphp' from lsphp${PHPVER} $pkg"; exit 1; }
|
||||||
if [ "$(printf '%s\n%s\n' "$pphp" "$v" | sort -V | tail -n1)" != "$v" ] || [ "$pphp" = "$v" ]; then
|
if [ "$(printf '%s\n%s\n' "$pphp" "$v" | sort -V | tail -n1)" != "$v" ] || [ "$pphp" = "$v" ]; then
|
||||||
echo "::error::LiteSpeed already ships lsphp${{ matrix.phpver }} $pkg (PHP $pphp) >= $v — use the normal build (push to trunk / dispatch build-push.yaml)."
|
echo "::error::LiteSpeed already ships lsphp${PHPVER} $pkg (PHP $pphp) >= $v — use the normal build (push to trunk / dispatch build-push.yaml)."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "php.net $v sha256=$sha ; LiteSpeed lsphp${{ matrix.phpver }}=$pkg"
|
echo "php.net $v sha256=$sha ; LiteSpeed lsphp${PHPVER}=$pkg"
|
||||||
echo "sha=$sha" >> "$GITHUB_OUTPUT"
|
echo "sha=$sha" >> "$GITHUB_OUTPUT"
|
||||||
echo "pkg=$pkg" >> "$GITHUB_OUTPUT"
|
echo "pkg=$pkg" >> "$GITHUB_OUTPUT"
|
||||||
echo "pkgphp=$pphp" >> "$GITHUB_OUTPUT"
|
echo "pkgphp=$pphp" >> "$GITHUB_OUTPUT"
|
||||||
echo "bust=$(date -u +%Y%m%dT%H%M%SZ)-${{ gitea.run_id }}" >> "$GITHUB_OUTPUT"
|
echo "bust=$(date -u +%Y%m%dT%H%M%SZ)-${RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
if: steps.t.outputs.skip == '0'
|
if: steps.t.outputs.skip == '0'
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ die() { echo "FATAL(lsphp-src-build): $*" >&2; exit 1; }
|
|||||||
log() { echo "lsphp-src-build: $*"; }
|
log() { echo "lsphp-src-build: $*"; }
|
||||||
|
|
||||||
PHPVER="${PHPVER:?PHPVER required}"
|
PHPVER="${PHPVER:?PHPVER required}"
|
||||||
|
[[ "$PHPVER" =~ ^[0-9]{2}$ ]] || die "PHPVER='$PHPVER' is not NN."
|
||||||
if [ -z "${PHP_SRC_VERSION:-}" ]; then
|
if [ -z "${PHP_SRC_VERSION:-}" ]; then
|
||||||
[ -z "${PHP_SRC_SHA256:-}" ] || die "PHP_SRC_SHA256 given without PHP_SRC_VERSION."
|
[ -z "${PHP_SRC_SHA256:-}" ] || die "PHP_SRC_SHA256 given without PHP_SRC_VERSION."
|
||||||
log "PHP_SRC_VERSION empty — packaged lsphp build, nothing to do."
|
log "PHP_SRC_VERSION empty — packaged lsphp build, nothing to do."
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ MODE="${1:?usage: lsphp-src-overlay.sh runtime|dev PHPVER}"
|
|||||||
PHPVER="${2:?usage: lsphp-src-overlay.sh runtime|dev PHPVER}"
|
PHPVER="${2:?usage: lsphp-src-overlay.sh runtime|dev PHPVER}"
|
||||||
OUT="${3:-/lsphp-src-out}"
|
OUT="${3:-/lsphp-src-out}"
|
||||||
case "$MODE" in runtime|dev) ;; *) echo "FATAL(lsphp-src-overlay): mode must be runtime|dev" >&2; exit 1 ;; esac
|
case "$MODE" in runtime|dev) ;; *) echo "FATAL(lsphp-src-overlay): mode must be runtime|dev" >&2; exit 1 ;; esac
|
||||||
|
[[ "$PHPVER" =~ ^[0-9]{2}$ ]] || { echo "FATAL(lsphp-src-overlay): PHPVER='$PHPVER' is not NN" >&2; exit 1; }
|
||||||
|
|
||||||
die() { echo "FATAL(lsphp-src-overlay): $*" >&2; exit 1; }
|
die() { echo "FATAL(lsphp-src-overlay): $*" >&2; exit 1; }
|
||||||
log() { echo "lsphp-src-overlay[$MODE]: $*"; }
|
log() { echo "lsphp-src-overlay[$MODE]: $*"; }
|
||||||
|
|||||||
Reference in new issue
Block a user