Skip to content

Commit bbbfdb3

Browse files
henderkesdunglasAlliBalliBaba
authored
ci: build .rpm and .deb packages (#1497)
* add ./create-rpm.sh file to build a "frankenphp" rpm package * also build a deb package * renamed to build-packages * linter... * add depends * linter again? * linter number 3 * linter number 4 * set default locations for ini file, conf files and extensions * set unified path for modules that should be ok on all dists * add default content into "package" folder * make file executable * worker is in public folder * what on earth did I do x) * use same FRANKENPHP_VERSION and make sure to let pr's run the rpm generation too (version 0.0.0) to see issues * install ruby, fpm and rpm-build * move to after changing base urls because it would fail with packages not found * ruby 3 build needs gcc 10 * rpm-build is necessary too... * and I forgot to link the package folder * create directories if they don't exist * copy out all frankenphp* files? * lint fix * only copy frankenphp-* files * only copy frankenphp-* files * the .deb file is name frankenphp_1.5.0... - create output folder instead and upload all things inside that will simplify things when later adding xdebug.so and ffi.so * update the last two steps to use the gh-output directory * add post install script to set frankenphp able to bind to port 80 for non-root users * dnf over yum, I think the yum alias was removed in RH 9.5 * newlines * newlines * add text what missing libcap means * copy php.ini-production from php-src, linter, update ruby version * move Caddyfile to /etc/frankenphp/Caddyfile * linter * fix a copy and paste error * better describe fallback to 0.0.0 * linter * copy installation scripts from official caddy packages, change user to frankenphp too * bombombom * make files executable * tabs * linter * linter again * use empty directory for three different destinations instead of keeping three empty local directories * caddy says the file is incorrectly formatted without these spaces * remove wildcard matcher from root directive * Apply suggestions from code review commit suggested changes to preinstall/postinstall scripts Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update dev.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * remove misleading comment * update documentation for paths * update documentation for paths some more * fix musl opcache-jit issue * markdown linter * the damn tab * Apply suggestions from code review Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * drop dev.Dockerfile php location from config.md * add php config note to CONTRIBUTING.md * dashes instead of asterisks in chinese docs * fix package building * create frankenphp user in case it doesn't exist for deb packages * create users if they don't exist, delete them again if they didn't exist * satisfy linter * create the user with the same commands as the postinst/preinstall scripts * Removes toolchain requirements. * trigger * Removes explicit calls to go get * trigger * setcap by default * simplify example project * bring page more in line with the caddy / apache / nginx default page * update to html 5 * oopsies * revert style to original * remove https:// (caddy uses http:// on RHEL, :80 on Debian) --------- Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> Co-authored-by: Alliballibaba <alliballibaba@gmail.com>
1 parent 0b83602 commit bbbfdb3

34 files changed

+717
-77
lines changed

.github/workflows/static.yaml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ jobs:
218218
targets: static-builder-gnu
219219
set: |
220220
${{ (github.event_name == 'pull_request' || matrix.platform == 'linux/arm64') && 'static-builder-gnu.args.NO_COMPRESS=1' || '' }}
221+
static-builder-gnu.args.BUILD_PACKAGES=1
221222
*.tags=
222223
*.platform=${{ matrix.platform }}
223224
*.cache-from=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder-gnu
@@ -247,30 +248,36 @@ jobs:
247248
path: /tmp/metadata-gnu/*
248249
if-no-files-found: error
249250
retention-days: 1
250-
- name: Copy binary
251+
- name: Copy all frankenphp* files
251252
run: |
252253
# shellcheck disable=SC2034
253254
digest=$(jq -r '."static-builder-gnu"."${{ fromJson(needs.prepare.outputs.push) && 'containerimage.digest' || 'containerimage.config.digest' }}"' <<< "${METADATA}")
254-
docker create --platform=${{ matrix.platform }} --name static-builder-gnu "${{ fromJson(needs.prepare.outputs.push) && '${IMAGE_NAME}@${digest}' || '${digest}' }}"
255-
docker cp "static-builder-gnu:/go/src/app/dist/${BINARY}" "${BINARY}-gnu"
255+
container_id=$(docker create --platform=${{ matrix.platform }} "${{ fromJson(needs.prepare.outputs.push) && '${IMAGE_NAME}@${digest}' || '${digest}' }}")
256+
mkdir -p gh-output
257+
cd gh-output
258+
for file in $(docker run --rm "${{ fromJson(needs.prepare.outputs.push) && '${IMAGE_NAME}@${digest}' || '${digest}' }}" sh -c "ls /go/src/app/dist | grep '^frankenphp'"); do
259+
docker cp "${container_id}:/go/src/app/dist/${file}" "./${file}"
260+
done
261+
docker rm "${container_id}"
262+
mv "${BINARY}" "${BINARY}-gnu"
256263
env:
257264
METADATA: ${{ steps.build.outputs.metadata }}
258265
BINARY: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
259266
- name: Upload artifact
260267
if: ${{ !fromJson(needs.prepare.outputs.push) }}
261268
uses: actions/upload-artifact@v4
262269
with:
263-
name: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}-gnu
264-
path: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}-gnu
270+
name: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}-gnu-files
271+
path: gh-output/*
265272
- name: Upload assets
266273
if: fromJson(needs.prepare.outputs.push) && (needs.prepare.outputs.ref || github.ref_type == 'tag')
267-
run: gh release upload "${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref }}" frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}-gnu --repo dunglas/frankenphp --clobber
274+
run: gh release upload "${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref }}" gh-output/* --repo dunglas/frankenphp --clobber
268275
env:
269276
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
270277
- if: fromJson(needs.prepare.outputs.push) && (needs.prepare.outputs.ref || github.ref_type == 'tag')
271278
uses: actions/attest-build-provenance@v2
272279
with:
273-
subject-path: ${{ github.workspace }}/frankenphp-linux-*-gnu
280+
subject-path: ${{ github.workspace }}/gh-output/frankenphp-linux-*-gnu
274281
- name: Run sanity checks
275282
run: |
276283
"${BINARY}" version
@@ -281,7 +288,7 @@ jobs:
281288
"${BINARY}" list-modules | grep http.handlers.vulcain
282289
"${BINARY}" php-cli -r "echo 'Sanity check passed';"
283290
env:
284-
BINARY: ./frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}-gnu
291+
BINARY: ./gh-output/frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}-gnu
285292

286293
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
287294
push:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
__debug_bin
99
frankenphp.test
1010
caddy/frankenphp/Build
11+
package/etc/php.ini
1112
*.log

CONTRIBUTING.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ docker build -t frankenphp-dev -f dev.Dockerfile .
1111
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -p 443:443/udp -v $PWD:/go/src/app -it frankenphp-dev
1212
```
1313

14-
The image contains the usual development tools (Go, GDB, Valgrind, Neovim...).
14+
The image contains the usual development tools (Go, GDB, Valgrind, Neovim...) and uses the following php setting locations
1515

16-
If docker version is lower than 23.0, build is failed by dockerignore [pattern issue](https://github.com/moby/moby/pull/42676). Add directories to `.dockerignore`.
16+
- php.ini: `/etc/frankenphp/php.ini` A php.ini file with development presets is provided by default.
17+
- additional configuration files: `/etc/frankenphp/php.d/*.ini`
18+
- php extensions: `/usr/lib/frankenphp/modules/`
19+
20+
If your docker version is lower than 23.0, the build will fail due to dockerignore [pattern issue](https://github.com/moby/moby/pull/42676). Add directories to `.dockerignore`.
1721

1822
```patch
1923
!testdata/*.php

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ RUN set -eux; \
1919
/app/public \
2020
/config/caddy \
2121
/data/caddy \
22-
/etc/caddy; \
22+
/etc/frankenphp; \
2323
sed -i 's/php/frankenphp run/g' /usr/local/bin/docker-php-entrypoint; \
2424
echo '<?php phpinfo();' > /app/public/index.php
2525

26-
COPY --link caddy/frankenphp/Caddyfile /etc/caddy/Caddyfile
26+
COPY --link caddy/frankenphp/Caddyfile /etc/frankenphp/Caddyfile
2727
RUN curl -sSLf \
2828
-o /usr/local/bin/install-php-extensions \
2929
https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \
3030
chmod +x /usr/local/bin/install-php-extensions
3131

32-
CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
32+
CMD ["--config", "/etc/frankenphp/Caddyfile", "--adapter", "caddyfile"]
3333
HEALTHCHECK CMD curl -f http://localhost:2019/metrics || exit 1
3434

3535
# See https://caddyserver.com/docs/conventions#file-locations for details
@@ -113,7 +113,7 @@ RUN echo $CGO_LDFLAGS
113113
WORKDIR /go/src/app/caddy/frankenphp
114114
RUN GOBIN=/usr/local/bin go install -tags 'nobadger,nomysql,nopgx' -ldflags "-w -s -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" -buildvcs=true && \
115115
setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
116-
cp Caddyfile /etc/caddy/Caddyfile && \
116+
cp Caddyfile /etc/frankenphp/Caddyfile && \
117117
frankenphp version && \
118118
frankenphp build-info
119119

alpine.Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ RUN set -eux; \
1818
/app/public \
1919
/config/caddy \
2020
/data/caddy \
21-
/etc/caddy; \
21+
/etc/frankenphp; \
2222
sed -i 's/php/frankenphp run/g' /usr/local/bin/docker-php-entrypoint; \
2323
echo '<?php phpinfo();' > /app/public/index.php
2424

25-
COPY --link caddy/frankenphp/Caddyfile /etc/caddy/Caddyfile
25+
COPY --link caddy/frankenphp/Caddyfile /etc/frankenphp/Caddyfile
2626
RUN curl -sSLf \
2727
-o /usr/local/bin/install-php-extensions \
2828
https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \
2929
chmod +x /usr/local/bin/install-php-extensions
3030

31-
CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
31+
CMD ["--config", "/etc/frankenphp/Caddyfile", "--adapter", "caddyfile"]
3232
HEALTHCHECK CMD curl -f http://localhost:2019/metrics || exit 1
3333

3434
# See https://caddyserver.com/docs/conventions#file-locations for details

build-packages.sh

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -x
5+
6+
# Ensure required tools are installed
7+
if ! command -v rpmbuild &>/dev/null; then
8+
echo "Error: rpm-build is required to create RPM packages."
9+
echo "Install it with: sudo dnf install rpm-build"
10+
exit 1
11+
fi
12+
13+
if ! command -v ruby &>/dev/null; then
14+
echo "Error: Ruby is required by FPM."
15+
echo "Install it with: sudo dnf install ruby"
16+
exit 1
17+
fi
18+
19+
if ! command -v fpm &>/dev/null; then
20+
echo "Error: FPM (rubygem-fpm) is required to create RPM packages."
21+
echo "Install it with: sudo gem install fpm"
22+
exit 1
23+
fi
24+
25+
arch="$(uname -m)"
26+
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
27+
bin="frankenphp-${os}-${arch}"
28+
29+
if [ ! -f "dist/$bin" ]; then
30+
echo "Error: dist/$bin not found. Run './build-static.sh' first"
31+
exit 1
32+
fi
33+
34+
if [ -z "${FRANKENPHP_VERSION}" ]; then
35+
FRANKENPHP_VERSION="$(git rev-parse --verify HEAD)"
36+
export FRANKENPHP_VERSION
37+
elif [ -d ".git/" ]; then
38+
CURRENT_REF="$(git rev-parse --abbrev-ref HEAD)"
39+
export CURRENT_REF
40+
41+
if echo "${FRANKENPHP_VERSION}" | grep -F -q "."; then
42+
# Tag
43+
44+
# Trim "v" prefix if any
45+
FRANKENPHP_VERSION=${FRANKENPHP_VERSION#v}
46+
export FRANKENPHP_VERSION
47+
48+
git checkout "v${FRANKENPHP_VERSION}"
49+
else
50+
git checkout "${FRANKENPHP_VERSION}"
51+
fi
52+
fi
53+
54+
if [[ ! "${FRANKENPHP_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
55+
echo "Warning: FRANKENPHP_VERSION must be set to X.Y.Z (e.g. 1.5.1), got '${FRANKENPHP_VERSION}'"
56+
echo "Falling back to non-release version 0.0.0"
57+
FRANKENPHP_VERSION=0.0.0
58+
fi
59+
60+
group_preexists=0
61+
user_preexists=0
62+
63+
if getent group frankenphp >/dev/null; then
64+
group_preexists=1
65+
else
66+
groupadd --system frankenphp
67+
fi
68+
69+
if getent passwd frankenphp >/dev/null; then
70+
user_preexists=1
71+
else
72+
useradd --system \
73+
--gid frankenphp \
74+
--create-home \
75+
--home-dir /var/lib/frankenphp \
76+
--shell /usr/sbin/nologin \
77+
--comment "FrankenPHP web server" \
78+
frankenphp
79+
fi
80+
81+
mkdir -p package/empty
82+
mkdir -p package/etc
83+
[ -f ./dist/static-php-cli/source/php-src/php.ini-production ] && cp -f ./dist/static-php-cli/source/php-src/php.ini-production ./package/etc/php.ini
84+
85+
cd dist
86+
iteration=1
87+
glibc_version=$(ldd -v "$bin" | awk '/GLIBC_/ {gsub(/[()]/, "", $2); print $2}' | grep -v GLIBC_PRIVATE | sort -V | tail -n1)
88+
cxxabi_version=$(strings "$bin" | grep -oP 'CXXABI_\d+\.\d+(\.\d+)?' | sort -V | tail -n1)
89+
90+
fpm -s dir -t rpm -n frankenphp -v "${FRANKENPHP_VERSION}" \
91+
--config-files /etc/frankenphp/Caddyfile \
92+
--config-files /etc/frankenphp/php.ini \
93+
--depends "libc.so.6(${glibc_version})(64bit)" \
94+
--depends "libstdc++.so.6(${cxxabi_version})(64bit)" \
95+
--before-install ../package/rhel/preinstall.sh \
96+
--after-install ../package/rhel/postinstall.sh \
97+
--before-remove ../package/rhel/preuninstall.sh \
98+
--after-remove ../package/rhel/postuninstall.sh \
99+
--iteration "${iteration}" \
100+
--rpm-user frankenphp --rpm-group frankenphp \
101+
"${bin}=/usr/bin/frankenphp" \
102+
"../package/rhel/frankenphp.service=/usr/lib/systemd/system/frankenphp.service" \
103+
"../package/Caddyfile=/etc/frankenphp/Caddyfile" \
104+
"../package/content/=/usr/share/frankenphp" \
105+
"../package/etc/php.ini=/etc/frankenphp/php.ini" \
106+
"../package/empty/=/etc/frankenphp/php.d" \
107+
"../package/empty/=/usr/lib/frankenphp/modules" \
108+
"../package/empty/=/var/lib/frankenphp"
109+
110+
glibc_version=$(ldd -v "$bin" | awk '/GLIBC_/ {gsub(/[()]/, "", $2); print $2}' | grep -v GLIBC_PRIVATE | sed 's/GLIBC_//' | sort -V | tail -n1)
111+
cxxabi_version=$(strings "$bin" | grep -oP 'CXXABI_\d+\.\d+(\.\d+)?' | sed 's/CXXABI_//' | sort -V | tail -n1)
112+
113+
fpm -s dir -t deb -n frankenphp -v "${FRANKENPHP_VERSION}" \
114+
--config-files /etc/frankenphp/Caddyfile \
115+
--config-files /etc/frankenphp/php.ini \
116+
--depends "libc6 (>= ${glibc_version})" \
117+
--depends "libstdc++6 (>= ${cxxabi_version})" \
118+
--after-install ../package/debian/postinst.sh \
119+
--before-remove ../package/debian/prerm.sh \
120+
--after-remove ../package/debian/postrm.sh \
121+
--iteration "${iteration}" \
122+
--deb-user frankenphp --deb-group frankenphp \
123+
"${bin}=/usr/bin/frankenphp" \
124+
"../package/debian/frankenphp.service=/usr/lib/systemd/system/frankenphp.service" \
125+
"../package/Caddyfile=/etc/frankenphp/Caddyfile" \
126+
"../package/content/=/usr/share/frankenphp" \
127+
"../package/etc/php.ini=/etc/frankenphp/php.ini" \
128+
"../package/empty/=/etc/frankenphp/php.d" \
129+
"../package/empty/=/usr/lib/frankenphp/modules" \
130+
"../package/empty/=/var/lib/frankenphp"
131+
132+
[ "$user_preexists" -eq 0 ] && userdel frankenphp
133+
[ "$group_preexists" -eq 0 ] && groupdel frankenphp
134+
135+
cd ..

build-static.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ fi
4040
# init spc build additional args
4141
if [ -z "${SPC_OPT_BUILD_ARGS}" ]; then
4242
SPC_OPT_BUILD_ARGS=""
43-
if [ "${SPC_LIBC}" = "musl" ]; then
44-
SPC_OPT_BUILD_ARGS="${SPC_OPT_BUILD_ARGS} --disable-opcache-jit"
45-
fi
43+
fi
44+
if [ "${SPC_LIBC}" = "musl" ] && [[ "${SPC_OPT_BUILD_ARGS}" != *"--disable-opcache-jit"* ]]; then
45+
SPC_OPT_BUILD_ARGS="${SPC_OPT_BUILD_ARGS} --disable-opcache-jit"
4646
fi
4747
# init spc download additional args
4848
if [ -z "${SPC_OPT_DOWNLOAD_ARGS}" ]; then

caddy/frankenphp/Caddyfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# The Caddyfile is an easy way to configure FrankenPHP and the Caddy web server.
2+
#
3+
# https://frankenphp.dev/docs/config
4+
# https://caddyserver.com/docs/caddyfile
5+
16
{
27
{$CADDY_GLOBAL_OPTIONS}
38

@@ -43,3 +48,9 @@
4348

4449
php_server
4550
}
51+
52+
# As an alternative to editing the above site block, you can add your own site
53+
# block files in the Caddyfile.d directory, and they will be included as long
54+
# as they use the .caddyfile extension.
55+
56+
import Caddyfile.d/*.caddyfile

dev-alpine.Dockerfile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,21 @@ WORKDIR /usr/local/src/php
5151
RUN git clone --branch=PHP-8.4 https://github.com/php/php-src.git . && \
5252
# --enable-embed is only necessary to generate libphp.so, we don't use this SAPI directly
5353
./buildconf --force && \
54-
./configure \
54+
EXTENSION_DIR=/usr/lib/frankenphp/modules ./configure \
5555
--enable-embed \
5656
--enable-zts \
5757
--disable-zend-signals \
5858
--enable-zend-max-execution-timers \
59+
--with-config-file-path=/etc/frankenphp/php.ini \
60+
--with-config-file-scan-dir=/etc/frankenphp/php.d \
5961
--enable-debug && \
6062
make -j"$(nproc)" && \
6163
make install && \
6264
ldconfig /etc/ld.so.conf.d && \
63-
cp php.ini-development /usr/local/lib/php.ini && \
64-
echo "zend_extension=opcache.so" >> /usr/local/lib/php.ini && \
65-
echo "opcache.enable=1" >> /usr/local/lib/php.ini && \
65+
mkdir -p /etc/frankenphp/php.d && \
66+
cp php.ini-development /etc/frankenphp/php.ini && \
67+
echo "zend_extension=opcache.so" >> /etc/frankenphp/php.ini && \
68+
echo "opcache.enable=1" >> /etcfrankenphp/php.ini && \
6669
php --version
6770

6871
# Install e-dant/watcher (necessary for file watching)

dev.Dockerfile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,21 @@ WORKDIR /usr/local/src/php
5353
RUN git clone --branch=PHP-8.4 https://github.com/php/php-src.git . && \
5454
# --enable-embed is only necessary to generate libphp.so, we don't use this SAPI directly
5555
./buildconf --force && \
56-
./configure \
56+
EXTENSION_DIR=/usr/lib/frankenphp/modules ./configure \
5757
--enable-embed \
5858
--enable-zts \
5959
--disable-zend-signals \
6060
--enable-zend-max-execution-timers \
61+
--with-config-file-path=/etc/frankenphp/php.ini \
62+
--with-config-file-scan-dir=/etc/frankenphp/php.d \
6163
--enable-debug && \
6264
make -j"$(nproc)" && \
6365
make install && \
6466
ldconfig && \
65-
cp php.ini-development /usr/local/lib/php.ini && \
66-
echo "zend_extension=opcache.so" >> /usr/local/lib/php.ini && \
67-
echo "opcache.enable=1" >> /usr/local/lib/php.ini && \
67+
mkdir -p /etc/frankenphp/php.d && \
68+
cp php.ini-development /etc/frankenphp/php.ini && \
69+
echo "zend_extension=opcache.so" >> /etc/frankenphp/php.ini && \
70+
echo "opcache.enable=1" >> /etcfrankenphp/php.ini && \
6871
php --version
6972

7073
# Install e-dant/watcher (necessary for file watching)

0 commit comments

Comments
 (0)