Skip to content

Commit 1d75824

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix/opcache-safe-reset
2 parents 3e7cdd0 + bd8f0c2 commit 1d75824

File tree

205 files changed

+14017
-2630
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

205 files changed

+14017
-2630
lines changed

.codespellrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[codespell]
2+
check-hidden =
3+
skip = .git,docs/*/*,docs,*/go.mod,*/go.sum,./internal/phpheaders/phpheaders.go

.editorconfig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ root = true
44
end_of_line = lf
55
insert_final_newline = true
66

7-
[*.sh]
7+
[*.{sh,Dockerfile}]
88
indent_style = tab
99
tab_width = 4
1010

11-
[*.Dockerfile]
12-
indent_style = tab
13-
tab_width = 4
11+
[*.{yaml,yml}]
12+
indent_style = space
13+
tab_width = 2

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ body:
77
attributes:
88
value: |
99
Thanks for taking the time to fill out this bug report!
10-
Before submitting a bug, please double-check that your problem [is not
11-
a known issue](https://frankenphp.dev/docs/known-issues/)
12-
(especially if you use XDebug or Tideways), and that is has not
13-
[already been reported](https://github.com/php/frankenphp/issues).
10+
11+
Before submitting, please ensure that your issue:
12+
13+
* Is not [a known issue](https://frankenphp.dev/docs/known-issues/).
14+
* Has not [already been reported](https://github.com/php/frankenphp/issues).
15+
* Is not caused by a dependency (like Caddy or PHP itself). If the issue is with a dependency, please report it to the upstream project directly.
1416
- type: textarea
1517
id: what-happened
1618
attributes:
1719
label: What happened?
1820
description: |
19-
Tell us what you do, what you get and what you expected.
21+
Tell us what you do, what you get, and what you expected.
2022
Provide us with some step-by-step instructions to reproduce the issue.
2123
validations:
2224
required: true
@@ -29,8 +31,9 @@ body:
2931
- Docker (Debian Trixie)
3032
- Docker (Debian Bookworm)
3133
- Docker (Alpine)
34+
- apk packages
3235
- deb packages
33-
- rpm packages
36+
- RPM packages
3437
- Static binary
3538
- Custom (tell us more in the description)
3639
default: 0
@@ -55,6 +58,8 @@ body:
5558
options:
5659
- GNU/Linux
5760
- macOS
61+
- Windows
62+
- FreeBSD
5863
- Other (tell us more in the description)
5964
default: 0
6065
validations:
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
write_output() {
5+
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
6+
echo "$1" >>"${GITHUB_OUTPUT}"
7+
else
8+
echo "$1"
9+
fi
10+
}
11+
12+
get_php_version() {
13+
local version="$1"
14+
skopeo inspect "docker://docker.io/library/php:${version}" \
15+
--override-os linux \
16+
--override-arch amd64 |
17+
jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")'
18+
}
19+
20+
PHP_82_LATEST="$(get_php_version 8.2)"
21+
PHP_83_LATEST="$(get_php_version 8.3)"
22+
PHP_84_LATEST="$(get_php_version 8.4)"
23+
PHP_85_LATEST="$(get_php_version 8.5)"
24+
25+
PHP_VERSION="${PHP_82_LATEST},${PHP_83_LATEST},${PHP_84_LATEST},${PHP_85_LATEST}"
26+
write_output "php_version=${PHP_VERSION}"
27+
write_output "php82_version=${PHP_82_LATEST//./-}"
28+
write_output "php83_version=${PHP_83_LATEST//./-}"
29+
write_output "php84_version=${PHP_84_LATEST//./-}"
30+
write_output "php85_version=${PHP_85_LATEST//./-}"
31+
32+
if [[ "${GITHUB_EVENT_NAME:-}" == "schedule" ]]; then
33+
FRANKENPHP_LATEST_TAG="$(gh release view --repo php/frankenphp --json tagName --jq '.tagName')"
34+
git checkout "${FRANKENPHP_LATEST_TAG}"
35+
fi
36+
37+
METADATA="$(PHP_VERSION="${PHP_VERSION}" docker buildx bake --print | jq -c)"
38+
39+
BASE_IMAGES=()
40+
while IFS= read -r image; do
41+
BASE_IMAGES+=("${image}")
42+
done < <(jq -r '
43+
.target[]?.contexts? | to_entries[]?
44+
| select(.value | startswith("docker-image://"))
45+
| .value
46+
| sub("^docker-image://"; "")
47+
' <<<"${METADATA}" | sort -u)
48+
49+
BASE_IMAGE_DIGESTS=()
50+
for image in "${BASE_IMAGES[@]}"; do
51+
if [[ "${image}" == */* ]]; then
52+
ref="docker://docker.io/${image}"
53+
else
54+
ref="docker://docker.io/library/${image}"
55+
fi
56+
digest="$(skopeo inspect "${ref}" \
57+
--override-os linux \
58+
--override-arch amd64 \
59+
--format '{{.Digest}}')"
60+
BASE_IMAGE_DIGESTS+=("${image}@${digest}")
61+
done
62+
63+
BASE_FINGERPRINT="$(printf '%s\n' "${BASE_IMAGE_DIGESTS[@]}" | sort | sha256sum | awk '{print $1}')"
64+
write_output "base_fingerprint=${BASE_FINGERPRINT}"
65+
66+
if [[ "${GITHUB_EVENT_NAME:-}" != "schedule" ]]; then
67+
write_output "skip=false"
68+
exit 0
69+
fi
70+
71+
FRANKENPHP_LATEST_TAG_NO_PREFIX="${FRANKENPHP_LATEST_TAG#v}"
72+
EXISTING_FINGERPRINT=$(
73+
skopeo inspect "docker://docker.io/dunglas/frankenphp:${FRANKENPHP_LATEST_TAG_NO_PREFIX}" \
74+
--override-os linux \
75+
--override-arch amd64 |
76+
jq -r '.Labels["dev.frankenphp.base.fingerprint"] // empty'
77+
)
78+
79+
if [[ -n "${EXISTING_FINGERPRINT}" ]] && [[ "${EXISTING_FINGERPRINT}" == "${BASE_FINGERPRINT}" ]]; then
80+
write_output "skip=true"
81+
exit 0
82+
fi
83+
84+
write_output "ref=${FRANKENPHP_LATEST_TAG}"
85+
write_output "skip=false"
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
PHP_VERSION="${PHP_VERSION:-}"
5+
GO_VERSION="${GO_VERSION:-}"
6+
USE_LATEST_PHP="${USE_LATEST_PHP:-0}"
7+
8+
if [[ -z "${GO_VERSION}" ]]; then
9+
GO_VERSION="$(awk -F'"' '/variable "GO_VERSION"/ {f=1} f && /default/ {print $2; exit}' docker-bake.hcl)"
10+
GO_VERSION="${GO_VERSION:-1.26}"
11+
fi
12+
13+
if [[ -z "${PHP_VERSION}" ]]; then
14+
PHP_VERSION="$(awk -F'"' '/variable "PHP_VERSION"/ {f=1} f && /default/ {print $2; exit}' docker-bake.hcl)"
15+
PHP_VERSION="${PHP_VERSION:-8.2,8.3,8.4,8.5}"
16+
fi
17+
18+
if [[ "${USE_LATEST_PHP}" == "1" ]]; then
19+
PHP_82_LATEST=$(skopeo inspect docker://docker.io/library/php:8.2 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
20+
PHP_83_LATEST=$(skopeo inspect docker://docker.io/library/php:8.3 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
21+
PHP_84_LATEST=$(skopeo inspect docker://docker.io/library/php:8.4 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
22+
PHP_85_LATEST=$(skopeo inspect docker://docker.io/library/php:8.5 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
23+
PHP_VERSION="${PHP_82_LATEST},${PHP_83_LATEST},${PHP_84_LATEST},${PHP_85_LATEST}"
24+
fi
25+
26+
OS_LIST=()
27+
while IFS= read -r os; do
28+
OS_LIST+=("${os}")
29+
done < <(
30+
python3 - <<'PY'
31+
import re
32+
33+
with open("docker-bake.hcl", "r", encoding="utf-8") as f:
34+
data = f.read()
35+
36+
# Find the first "os = [ ... ]" block and extract quoted values
37+
m = re.search(r'os\s*=\s*\[(.*?)\]', data, re.S)
38+
if not m:
39+
raise SystemExit(1)
40+
41+
vals = re.findall(r'"([^"]+)"', m.group(1))
42+
for v in vals:
43+
print(v)
44+
PY
45+
)
46+
47+
IFS=',' read -r -a PHP_VERSIONS <<<"${PHP_VERSION}"
48+
49+
BASE_IMAGES=()
50+
for os in "${OS_LIST[@]}"; do
51+
BASE_IMAGES+=("golang:${GO_VERSION}-${os}")
52+
for pv in "${PHP_VERSIONS[@]}"; do
53+
BASE_IMAGES+=("php:${pv}-zts-${os}")
54+
done
55+
done
56+
57+
mapfile -t BASE_IMAGES < <(printf '%s\n' "${BASE_IMAGES[@]}" | sort -u)
58+
59+
BASE_IMAGE_DIGESTS=()
60+
for image in "${BASE_IMAGES[@]}"; do
61+
if [[ "${image}" == */* ]]; then
62+
ref="docker://docker.io/${image}"
63+
else
64+
ref="docker://docker.io/library/${image}"
65+
fi
66+
digest="$(skopeo inspect "${ref}" --override-os linux --override-arch amd64 --format '{{.Digest}}')"
67+
BASE_IMAGE_DIGESTS+=("${image}@${digest}")
68+
done
69+
70+
hash_cmd="sha256sum"
71+
if ! command -v "${hash_cmd}" >/dev/null 2>&1; then
72+
hash_cmd="shasum -a 256"
73+
fi
74+
75+
fingerprint="$(printf '%s\n' "${BASE_IMAGE_DIGESTS[@]}" | sort | ${hash_cmd} | awk '{print $1}')"
76+
77+
echo "PHP_VERSION=${PHP_VERSION}"
78+
echo "GO_VERSION=${GO_VERSION}"
79+
echo "OS_LIST=${OS_LIST[*]}"
80+
echo "Base images:"
81+
printf ' %s\n' "${BASE_IMAGES[@]}"
82+
echo "Fingerprint: ${fingerprint}"

.github/workflows/docker.yaml

Lines changed: 21 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
name: Build Docker images
2+
name: Build Docker Images
33
concurrency:
44
cancel-in-progress: true
55
group: ${{ github.workflow }}-${{ github.ref }}
@@ -50,54 +50,19 @@ jobs:
5050
php85_version: ${{ steps.check.outputs.php85_version }}
5151
skip: ${{ steps.check.outputs.skip }}
5252
ref: ${{ steps.check.outputs.ref || (github.event_name == 'workflow_dispatch' && inputs.version) || '' }}
53+
base_fingerprint: ${{ steps.check.outputs.base_fingerprint }}
5354
steps:
54-
- name: Check PHP versions
55-
id: check
56-
env:
57-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58-
run: |
59-
PHP_82_LATEST=$(skopeo inspect docker://docker.io/library/php:8.2 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
60-
PHP_83_LATEST=$(skopeo inspect docker://docker.io/library/php:8.3 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
61-
PHP_84_LATEST=$(skopeo inspect docker://docker.io/library/php:8.4 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
62-
PHP_85_LATEST=$(skopeo inspect docker://docker.io/library/php:8.5 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
63-
{
64-
echo php_version="${PHP_82_LATEST},${PHP_83_LATEST},${PHP_84_LATEST},${PHP_85_LATEST}"
65-
echo php82_version="${PHP_82_LATEST//./-}"
66-
echo php83_version="${PHP_83_LATEST//./-}"
67-
echo php84_version="${PHP_84_LATEST//./-}"
68-
echo php85_version="${PHP_85_LATEST//./-}"
69-
} >> "${GITHUB_OUTPUT}"
70-
71-
# Check if the Docker images must be rebuilt
72-
if [[ "${GITHUB_EVENT_NAME}" != "schedule" ]]; then
73-
echo skip=false >> "${GITHUB_OUTPUT}"
74-
exit 0
75-
fi
76-
77-
FRANKENPHP_LATEST_TAG=$(gh release view --repo php/frankenphp --json tagName --jq '.tagName')
78-
FRANKENPHP_LATEST_TAG_NO_PREFIX="${FRANKENPHP_LATEST_TAG#v}"
79-
FRANKENPHP_82_LATEST=$(skopeo inspect docker://docker.io/dunglas/frankenphp:"${FRANKENPHP_LATEST_TAG_NO_PREFIX}"-php8.2 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
80-
FRANKENPHP_83_LATEST=$(skopeo inspect docker://docker.io/dunglas/frankenphp:"${FRANKENPHP_LATEST_TAG_NO_PREFIX}"-php8.3 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
81-
FRANKENPHP_84_LATEST=$(skopeo inspect docker://docker.io/dunglas/frankenphp:"${FRANKENPHP_LATEST_TAG_NO_PREFIX}"-php8.4 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
82-
FRANKENPHP_85_LATEST=$(skopeo inspect docker://docker.io/dunglas/frankenphp:"${FRANKENPHP_LATEST_TAG_NO_PREFIX}"-php8.5 --override-os linux --override-arch amd64 | jq -r '.Env[] | select(test("^PHP_VERSION=")) | sub("^PHP_VERSION="; "")')
83-
84-
if [[ "${FRANKENPHP_82_LATEST}" == "${PHP_82_LATEST}" ]] && [[ "${FRANKENPHP_83_LATEST}" == "${PHP_83_LATEST}" ]] && [[ "${FRANKENPHP_84_LATEST}" == "${PHP_84_LATEST}" ]] && [[ "${FRANKENPHP_85_LATEST}" == "${PHP_85_LATEST}" ]]; then
85-
echo skip=true >> "${GITHUB_OUTPUT}"
86-
exit 0
87-
fi
88-
89-
{
90-
echo ref="${FRANKENPHP_LATEST_TAG}"
91-
echo skip=false
92-
} >> "${GITHUB_OUTPUT}"
9355
- uses: actions/checkout@v6
94-
if: ${{ !fromJson(steps.check.outputs.skip) }}
9556
with:
96-
ref: ${{ steps.check.outputs.ref }}
57+
fetch-depth: 0
9758
persist-credentials: false
9859
- name: Set up Docker Buildx
99-
if: ${{ !fromJson(steps.check.outputs.skip) }}
10060
uses: docker/setup-buildx-action@v3
61+
- name: Check PHP versions and base image fingerprint
62+
id: check
63+
env:
64+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65+
run: ./.github/scripts/docker-compute-fingerprints.sh
10166
- name: Create variants matrix
10267
if: ${{ !fromJson(steps.check.outputs.skip) }}
10368
id: matrix
@@ -181,17 +146,18 @@ jobs:
181146
${{ (github.event_name == 'pull_request') && '*.args.NO_COMPRESS=1' || '' }}
182147
*.tags=
183148
*.platform=${{ matrix.platform }}
184-
builder-${{ matrix.variant }}.cache-from=type=gha,scope=builder-${{ matrix.variant }}-${{ needs.prepare.outputs.ref || github.ref }}-${{ matrix.platform }}
185-
builder-${{ matrix.variant }}.cache-from=type=gha,scope=refs/heads/main-builder-${{ matrix.variant }}-${{ matrix.platform }}
186-
builder-${{ matrix.variant }}.cache-to=type=gha,scope=builder-${{ matrix.variant }}-${{ needs.prepare.outputs.ref || github.ref }}-${{ matrix.platform }},ignore-error=true
187-
runner-${{ matrix.variant }}.cache-from=type=gha,scope=runner-${{ matrix.variant }}-${{ needs.prepare.outputs.ref || github.ref }}-${{ matrix.platform }}
188-
runner-${{ matrix.variant }}.cache-from=type=gha,scope=refs/heads/main-runner-${{ matrix.variant }}-${{ matrix.platform }}
189-
runner-${{ matrix.variant }}.cache-to=type=gha,scope=runner-${{ matrix.variant }}-${{ needs.prepare.outputs.ref || github.ref }}-${{ matrix.platform }},ignore-error=true
149+
${{ fromJson(needs.prepare.outputs.push) && '' || format('builder-{0}.cache-from=type=gha,scope=builder-{0}-{1}-{2}', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }}
150+
${{ fromJson(needs.prepare.outputs.push) && '' || format('builder-{0}.cache-from=type=gha,scope=refs/heads/main-builder-{0}-{1}', matrix.variant, matrix.platform) }}
151+
${{ fromJson(needs.prepare.outputs.push) && '' || format('builder-{0}.cache-to=type=gha,scope=builder-{0}-{1}-{2},ignore-error=true', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }}
152+
${{ fromJson(needs.prepare.outputs.push) && '' || format('runner-{0}.cache-from=type=gha,scope=runner-{0}-{1}-{2}', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }}
153+
${{ fromJson(needs.prepare.outputs.push) && '' || format('runner-{0}.cache-from=type=gha,scope=refs/heads/main-runner-{0}-{1}', matrix.variant, matrix.platform) }}
154+
${{ fromJson(needs.prepare.outputs.push) && '' || format('runner-{0}.cache-to=type=gha,scope=runner-{0}-{1}-{2},ignore-error=true', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }}
190155
${{ fromJson(needs.prepare.outputs.push) && format('*.output=type=image,name={0},push-by-digest=true,name-canonical=true,push=true', env.IMAGE_NAME) || '' }}
191156
env:
192157
SHA: ${{ github.sha }}
193158
VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref || 'dev' }}
194159
PHP_VERSION: ${{ needs.prepare.outputs.php_version }}
160+
BASE_FINGERPRINT: ${{ needs.prepare.outputs.base_fingerprint }}
195161
- # Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600
196162
name: Export metadata
197163
if: fromJson(needs.prepare.outputs.push)
@@ -208,15 +174,15 @@ jobs:
208174
VARIANT: ${{ matrix.variant }}
209175
- name: Upload builder metadata
210176
if: fromJson(needs.prepare.outputs.push)
211-
uses: actions/upload-artifact@v5
177+
uses: actions/upload-artifact@v7
212178
with:
213179
name: metadata-builder-${{ matrix.variant }}-${{ steps.prepare.outputs.sanitized_platform }}
214180
path: /tmp/metadata/builder/*
215181
if-no-files-found: error
216182
retention-days: 1
217183
- name: Upload runner metadata
218184
if: fromJson(needs.prepare.outputs.push)
219-
uses: actions/upload-artifact@v5
185+
uses: actions/upload-artifact@v7
220186
with:
221187
name: metadata-runner-${{ matrix.variant }}-${{ steps.prepare.outputs.sanitized_platform }}
222188
path: /tmp/metadata/runner/*
@@ -225,8 +191,10 @@ jobs:
225191
- name: Run tests
226192
if: ${{ !fromJson(needs.prepare.outputs.push) }}
227193
run: |
194+
# TODO: remove "containerimage.config.digest" fallback once all runners use buildx v0.18+
195+
# which replaced it with "containerimage.digest" and "containerimage.descriptor"
228196
docker run --platform="${PLATFORM}" --rm \
229-
"$(jq -r ".\"builder-${VARIANT}\".\"containerimage.config.digest\"" <<< "${METADATA}")" \
197+
"$(jq -r ".\"builder-${VARIANT}\" | .\"containerimage.config.digest\" // .\"containerimage.digest\"" <<< "${METADATA}")" \
230198
sh -c "./go.sh test ${RACE} -v $(./go.sh list ./... | grep -v github.com/dunglas/frankenphp/internal/testext | grep -v github.com/dunglas/frankenphp/internal/extgen | tr '\n' ' ') && cd caddy && ../go.sh test ${RACE} -v ./..."
231199
env:
232200
METADATA: ${{ steps.build.outputs.metadata }}
@@ -248,7 +216,7 @@ jobs:
248216
target: ["builder", "runner"]
249217
steps:
250218
- name: Download metadata
251-
uses: actions/download-artifact@v6
219+
uses: actions/download-artifact@v8
252220
with:
253221
pattern: metadata-${{ matrix.target }}-${{ matrix.variant }}-*
254222
path: /tmp/metadata

.github/workflows/docs.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
name: Deploy Docs
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "docs/**"
9+
- "README.md"
10+
- "CONTRIBUTING.md"
11+
- "install.ps1"
12+
- "install.sh"
13+
permissions: {}
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.ref }}
16+
cancel-in-progress: true
17+
jobs:
18+
deploy:
19+
runs-on: ubuntu-slim
20+
steps:
21+
- name: Trigger website deployment
22+
env:
23+
GH_TOKEN: ${{ secrets.WEBSITE_DEPLOY_TOKEN }}
24+
run: gh api repos/dunglas/frankenphp-website/actions/workflows/hugo.yaml/dispatches -f ref=main

0 commit comments

Comments
 (0)