Skip to content
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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds basic file watcher #1013

Merged
merged 168 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 142 commits
Commits
Show all changes
168 commits
Select commit Hold shift + click to select a range
2e15123
Adds filesystem watcher with tests.
Sep 1, 2024
19f4024
Refactoring.
Sep 2, 2024
008ff89
Merge branch 'main' into file-watchers
Sep 2, 2024
9451ade
Formatting.
Sep 2, 2024
bf4e72f
Formatting.
Sep 2, 2024
4920767
Switches to absolute path in tests.
Sep 2, 2024
c834a02
Fixes race condition from merge conflict.
Sep 2, 2024
4273035
Fixes race condition.
Sep 2, 2024
d5d86d5
Fixes tests.
Sep 2, 2024
236a782
Fixes markdown lint errors.
Sep 2, 2024
ad3c7fc
Switches back to absolute paths.
Sep 2, 2024
9b40362
Reverts back to relative file paths.
Sep 2, 2024
97b4688
Fixes golangci-lint issues.
Sep 2, 2024
b528c23
Uses github.com/dunglas/go-fswatch instead.
Sep 2, 2024
8cac13b
Stops watcher before stopping workers.
Sep 3, 2024
8a66165
Updates docs.
Sep 3, 2024
d8de3ee
Avoids segfault in tests.
Sep 3, 2024
3d7d849
Fixes watcher segmentation violations on shutdown.
Sep 3, 2024
08a4c8e
Adjusts watcher latencies and tests.
Sep 3, 2024
41d337b
Adds fswatch to dockerfiles
Sep 3, 2024
639c072
Fixes fswatch in alpine.
Sep 4, 2024
f6ba8d7
Fixes segfault (this time for real).
Sep 4, 2024
f6f4a9c
Allows queueing new reload if file changes while workers are reloading.
Sep 5, 2024
5e345f1
Makes tests more consistent.
Sep 5, 2024
0423bb9
Prevents the watcher from getting stuck if there is an error in the w…
Sep 5, 2024
1db309b
Reverts changing the image.
Sep 5, 2024
c6591f0
Puts fswatch version into docker-bake.hcl.
Sep 5, 2024
c946de9
Asserts instead of panicking.
Sep 5, 2024
0d4327d
Adds notice
AlliBalliBaba Sep 5, 2024
497627a
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 5, 2024
70461de
Update dev.Dockerfile
AlliBalliBaba Sep 5, 2024
6fcedfb
Update Dockerfile
AlliBalliBaba Sep 5, 2024
d8e0a2c
Update Dockerfile
AlliBalliBaba Sep 5, 2024
9df79f3
Update alpine.Dockerfile
AlliBalliBaba Sep 5, 2024
d8fb28c
Update alpine.Dockerfile
AlliBalliBaba Sep 5, 2024
d66588d
Update dev-alpine.Dockerfile
AlliBalliBaba Sep 5, 2024
53456f7
Update dev-alpine.Dockerfile
AlliBalliBaba Sep 5, 2024
fc27030
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 5, 2024
c61e42c
Update dev.Dockerfile
AlliBalliBaba Sep 5, 2024
c0836b9
Update docs/config.md
AlliBalliBaba Sep 5, 2024
71613fb
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 5, 2024
d87f3ff
Runs fswatch version.
Sep 5, 2024
0254b33
Removes .json.
Sep 5, 2024
1fb4bf2
Replaces ms with s.
Sep 5, 2024
665fa28
Resets the channel after closing it.
Sep 5, 2024
255c1c5
Update watcher_options.go
AlliBalliBaba Sep 5, 2024
f02c30b
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 5, 2024
9ec89dc
Update watcher_test.go
AlliBalliBaba Sep 5, 2024
420b125
Asserts no error instead.
Sep 5, 2024
138a3fe
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 5, 2024
e0e4bea
Fixes a race condition where events are fired after frankenphp has st…
Sep 5, 2024
77013f5
Updates docs.
Sep 5, 2024
a03bd81
Update watcher_options_test.go
AlliBalliBaba Sep 5, 2024
fce2e97
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 5, 2024
054dd1f
Allows queuing events while watchers are reloading.
Sep 5, 2024
36cab24
go fmt
Sep 5, 2024
94b2723
Refactors stopping and draining logic.
Sep 5, 2024
8044848
Allows extended watcher configuration with dirs, recursion, symlinks,…
Sep 6, 2024
96c2a11
Updates docs.
Sep 6, 2024
3de70de
Adds TODOS.
Sep 6, 2024
45a73ae
go fmt.
Sep 6, 2024
bc73a16
Fixes linting errors.
Sep 6, 2024
63975e7
Also allows wildcards in the longform and adjusts docs.
Sep 6, 2024
971e75a
Adds debug log.
Sep 6, 2024
f2b7bda
Fixes the watcher short form.
Sep 6, 2024
5de7a3d
Refactors sessions and options into a struct.
Sep 7, 2024
816b157
Fixes an overflow in the 'workersReadyWG' on unexpected terminations.
Sep 7, 2024
c90eeb1
Properly logs errors coming from session.Start().
Sep 7, 2024
f4b7c52
go fmt.
Sep 7, 2024
4a73228
Adds --nocache.
Sep 7, 2024
043801d
Fixes lint issue.
Sep 7, 2024
269a920
Refactors and resolves race condition on worker reload.
Sep 7, 2024
8af1874
Implements debouncing with a timer as suggested by @withinboredom.
Sep 7, 2024
a16b59e
Starts watcher even if no workers are defined.
Sep 7, 2024
2cc0d15
Updates docs with file limit warning.
Sep 7, 2024
94159d3
Adds watch config unit tests.
Sep 7, 2024
eea350b
Adjusts debounce timings.
Sep 7, 2024
64d1fa0
go fmt.
Sep 7, 2024
c60fbf6
Adds fswatch to static builder (test).
Sep 7, 2024
584a702
Adds a short grace period between stopping and destroying the watcher…
Sep 7, 2024
fe26542
Adds caddy test.
Sep 7, 2024
686ec68
Adjusts sleep time.
Sep 7, 2024
5edc067
Swap to edant/watcher.
Sep 10, 2024
1edd441
Fixes watch options and tests.
Sep 11, 2024
ba26532
go fmt.
Sep 11, 2024
e4377e9
Adds TODO.
Sep 11, 2024
08b8f42
Installs edant/watcher in the bookworm image.
Sep 11, 2024
c775523
Fixes linting.
Sep 11, 2024
c2b7d50
Refactors the watcher into its own module.
Sep 12, 2024
66c2e9a
Adjusts naming.
Sep 12, 2024
b294954
ADocker image adjustments and refactoring.
Sep 13, 2024
ebdbd48
Merge branch 'main' into file-watchers
Sep 13, 2024
d72d189
Testing installation methods.
Sep 14, 2024
8f3ee2b
Installs via gcc instead.
Sep 14, 2024
1acecf3
Fixes pointer formats.
Sep 14, 2024
2f28c19
Fixes lint issues.
Sep 14, 2024
3f16a0f
Fixes arm alpine and updates docs.
Sep 14, 2024
a7670df
Clang format.
Sep 14, 2024
438e4e2
Fixes dirs.
Sep 14, 2024
66b9c30
Adds watcher version arg.
Sep 14, 2024
1efc486
Merge branch 'refs/heads/main' into file-watchers
Sep 16, 2024
cd342c3
Uses static lib version.
Sep 16, 2024
db62988
Adds watcher to tests and sanitizers.
Sep 16, 2024
771c695
Uses sudo for copying the shared lib.
Sep 16, 2024
8bf02ca
Removes unnused func.
Sep 16, 2024
0893923
Refactoring.
Sep 16, 2024
e855f84
Update .github/workflows/sanitizers.yaml
AlliBalliBaba Sep 16, 2024
3d2de4a
Merge branch 'file-watchers' of https://github.com/AlliBalliBaba/fran…
Sep 16, 2024
5713209
Adds fpic.
Sep 16, 2024
fe978c0
Fixes linting.
Sep 16, 2024
a5fb0d2
Skips tests in msan.
Sep 17, 2024
41796bd
Resets op_cache in every worker thread after termination
Sep 17, 2024
5071e7e
Review fixes part 1.
Sep 19, 2024
f199b11
Test: installing libstc++ instead of gcc.
Sep 19, 2024
76d4ba0
Test: using msan ignorelist.
Sep 19, 2024
55b3589
Test: using msan ignorelist.
Sep 19, 2024
0bf555b
Test: using msan ignorelist.
Sep 19, 2024
266829b
Allows '/**/' for global recursion and '**/' for relative recursion.
Sep 19, 2024
0d0fa51
Reverts using the ignorelist.
Sep 19, 2024
f025e62
Calls opcache directly.
Sep 19, 2024
03123c4
Adds --watch to php-server command
Sep 19, 2024
8034f80
Merge branch 'main' into file-watchers
Sep 24, 2024
4c8a9c1
Properly free CStrings.
Sep 24, 2024
5f37d25
Sorts alphabetically and uses curl instead of git.
Sep 24, 2024
f925f54
Labeling and formatting.
Sep 24, 2024
1193de8
Update .github/workflows/sanitizers.yaml
AlliBalliBaba Sep 24, 2024
ef21c77
Update .github/workflows/sanitizers.yaml
AlliBalliBaba Sep 24, 2024
009c0b4
Update .github/workflows/tests.yaml
AlliBalliBaba Sep 24, 2024
6be5f99
Update .github/workflows/tests.yaml
AlliBalliBaba Sep 24, 2024
be2c344
Update caddy/caddy.go
AlliBalliBaba Sep 24, 2024
4e22dcd
Update docs/config.md
AlliBalliBaba Sep 24, 2024
6bad089
Update frankenphp_with_watcher_test.go
AlliBalliBaba Sep 24, 2024
01e320e
Update watcher/watcher.h
AlliBalliBaba Sep 24, 2024
e40d455
Update frankenphp.c
AlliBalliBaba Sep 24, 2024
26f02bb
Update watcher/watcher.go
AlliBalliBaba Sep 24, 2024
dbbdf5e
Update docs/config.md
AlliBalliBaba Sep 24, 2024
393be86
Update frankenphp_with_watcher_test.go
AlliBalliBaba Sep 24, 2024
9df7894
Update testdata/files/.gitignore
AlliBalliBaba Sep 24, 2024
b2837df
Update watcher/watcher-c.h
AlliBalliBaba Sep 24, 2024
9a1ac7c
Update watcher/watcher.c
AlliBalliBaba Sep 24, 2024
4ce9d37
Fixes test and Dockerfile.
Sep 24, 2024
01cc6eb
Fixes Dockerfiles.
Sep 24, 2024
672f7ee
Resets go versions.
Sep 26, 2024
5c3e0b9
Replaces unsafe.pointer with uintptr_t
Sep 26, 2024
08eaf89
Prevents worker channels from being destroyed on reload.
Sep 26, 2024
df4e144
Minimizes the public api by only passing a []string.
Sep 26, 2024
3c7c7cc
Adds support for directory patterns and multiple '**' globs.
Sep 27, 2024
5af705f
Adjusts label.
Sep 27, 2024
9fbeeaf
go fmt.
Sep 27, 2024
cd86650
Merge branch 'main' into file-watchers
Sep 27, 2024
bfc07f2
go mod tidy.
Sep 27, 2024
b399a3f
Fixes merge conflict.
Sep 27, 2024
e154531
Refactoring and formatting.
Sep 27, 2024
ea15b7e
Cleans up unused vars and functions.
Sep 27, 2024
3feba9c
Allows dirs with a dot.
Sep 27, 2024
26672c3
Makes test nicer.
Sep 27, 2024
67fcd28
Add dir tests.
Sep 27, 2024
bdd603d
Moves the watch directive inside the worker directive.
Sep 29, 2024
f2122fb
Adds debug log on special events.
Sep 29, 2024
8670acb
Removes line about symlinks.
Sep 30, 2024
27b4314
Hints at multiple possible --watch flags.
Sep 30, 2024
bc746e1
Adds ./**/*.php as default watch configuration.
Oct 2, 2024
6e685a0
Changes error to a warning.
Oct 2, 2024
ef7ab94
Changes the default to './**/*.{php,yaml,yml,twig,env}' and supports …
Oct 2, 2024
b8d915c
Fixes linting.
Oct 2, 2024
620d010
Merge branch 'main' into file-watchers
Oct 5, 2024
043bb86
Fixes merge conflict and adjust values.
Oct 5, 2024
8a2fb45
Adjusts values.
Oct 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .github/workflows/sanitizers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ jobs:
matrix:
sanitizer: ['asan', 'msan']
env:
CFLAGS: -g -O0 -fsanitize=${{ matrix.sanitizer == 'asan' && 'address' || 'memory' }} -DZEND_TRACK_ARENA_ALLOC
CFLAGS: -g -O0 -fsanitize=${{ matrix.sanitizer == 'asan' && 'address' || 'memory' }} -DZEND_TRACK_ARENA_ALLOC
LDFLAGS: -fsanitize=${{ matrix.sanitizer == 'asan' && 'address' || 'memory' }}
CC: clang
CXX: clang++
USE_ZEND_ALLOC: 0
LIBRARY_PATH: ${{ github.workspace }}/php/target/lib
LD_LIBRARY_PATH: ${{ github.workspace }}/php/target/lib
EDANT_WATCHER_VERSION: next
steps:
-
name: Remove local PHP
Expand Down Expand Up @@ -95,6 +96,20 @@ jobs:
-
name: Add PHP to the PATH
run: echo "$(pwd)/php/target/bin" >> "$GITHUB_PATH"
-
uses: actions/checkout@v4
name: Checkout watcher
with:
repository: e-dant/watcher
ref: ${{ env.EDANT_WATCHER_VERSION }}
path: 'edant/watcher'
-
name: Compile edant/watcher
run: |
cd edant/watcher/watcher-c/
clang -o libwatcher.so ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -Wall -Wextra -fPIC -shared ${{ matrix.sanitizer == 'msan' && '-fsanitize=memory -fno-omit-frame-pointer -fno-optimize-sibling-calls' || '' }}
sudo cp libwatcher.so /usr/local/lib/libwatcher.so
sudo ldconfig
-
name: Set Set CGO flags
run: |
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
env:
GOEXPERIMENT: cgocheck2
GOMAXPROCS: 10
EDANT_WATCHER_VERSION: next
steps:
-
uses: actions/checkout@v4
Expand All @@ -43,6 +44,20 @@ jobs:
env:
phpts: ts
debug: true
-
uses: actions/checkout@v4
name: Checkout watcher
with:
repository: e-dant/watcher
ref: ${{ env.EDANT_WATCHER_VERSION }}
path: 'edant/watcher'
-
name: Compile edant/watcher
run: |
cd edant/watcher/watcher-c/
gcc -o libwatcher.so ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -O3 -Wall -Wextra -fPIC -shared
AlliBalliBaba marked this conversation as resolved.
Show resolved Hide resolved
sudo cp libwatcher.so /usr/local/lib/libwatcher.so
sudo ldconfig
-
name: Set CGO flags
run: |
Expand Down
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
echo '<?php phpinfo();' > /app/public/index.php

COPY --link caddy/frankenphp/Caddyfile /etc/caddy/Caddyfile
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/

Check warning on line 27 in Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-2-23-bookworm, linux/386)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/386" for current build

Check warning on line 27 in Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-2-23-bookworm, linux/arm/v7)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm/v7" for current build

Check warning on line 27 in Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-2-23-bookworm, linux/arm64)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm64" for current build

Check warning on line 27 in Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-3-11-bookworm, linux/386)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/386" for current build

Check warning on line 27 in Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-3-11-bookworm, linux/arm/v7)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm/v7" for current build

Check warning on line 27 in Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-3-11-bookworm, linux/arm64)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm64" for current build

CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
HEALTHCHECK CMD curl -f http://localhost:2019/metrics || exit 1
Expand Down Expand Up @@ -85,6 +85,16 @@
COPY --link caddy caddy
COPY --link internal internal
COPY --link testdata testdata
COPY --link watcher watcher

# install edant/watcher (necessary for file watching)
ARG EDANT_WATCHER_VERSION=next
WORKDIR /usr/local/src/watcher
RUN curl -L https://github.com/e-dant/watcher/archive/refs/heads/$EDANT_WATCHER_VERSION.tar.gz | tar xz
WORKDIR /usr/local/src/watcher/watcher-$EDANT_WATCHER_VERSION/watcher-c
RUN gcc -o libwatcher.so ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -O3 -Wall -Wextra -fPIC -shared && \
cp libwatcher.so /usr/local/lib/libwatcher.so && \
ldconfig /usr/local/lib

# See https://github.com/docker-library/php/blob/master/8.3/bookworm/zts/Dockerfile#L57-L59 for PHP values
ENV CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS"
Expand All @@ -104,6 +114,13 @@

ENV GODEBUG=cgocheck=0

# copy watcher shared library
COPY --from=builder /usr/local/lib/libwatcher* /usr/local/lib/
# fix for the file watcher on arm
RUN apt-get install -y --no-install-recommends libstdc++6 && \
apt-get clean && \
ldconfig

COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
RUN setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
frankenphp version
26 changes: 22 additions & 4 deletions alpine.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
echo '<?php phpinfo();' > /app/public/index.php

COPY --link caddy/frankenphp/Caddyfile /etc/caddy/Caddyfile
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/

Check warning on line 26 in alpine.Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-2-23-alpine, linux/386)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/386" for current build

Check warning on line 26 in alpine.Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-2-23-alpine, linux/arm/v7)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm/v7" for current build

Check warning on line 26 in alpine.Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-2-23-alpine, linux/arm64)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm64" for current build

Check warning on line 26 in alpine.Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-3-11-alpine, linux/386)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/386" for current build

Check warning on line 26 in alpine.Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-3-11-alpine, linux/arm/v7)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm/v7" for current build

Check warning on line 26 in alpine.Dockerfile

View workflow job for this annotation

GitHub Actions / build (php-8-3-11-alpine, linux/arm64)

Base image platform does not match expected target platform

InvalidBaseImagePlatform: Base image mlocati/php-extension-installer was pulled with platform "linux/amd64", expected "linux/arm64" for current build

CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
HEALTHCHECK CMD curl -f http://localhost:2019/metrics || exit 1
Expand Down Expand Up @@ -58,21 +58,24 @@
RUN apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
# Needed for the custom Go build
bash \
brotli-dev \
coreutils \
curl-dev \
# Needed for the custom Go build
git \
gnu-libiconv-dev \
libsodium-dev \
# Needed for the file watcher
libstdc++ \
libxml2-dev \
linux-headers \
oniguruma-dev \
openssl-dev \
readline-dev \
sqlite-dev \
upx \
# Needed for the custom Go build
git \
bash
upx

# FIXME: temporary workaround for https://github.com/golang/go/issues/68285
WORKDIR /
Expand Down Expand Up @@ -103,6 +106,16 @@
COPY --link caddy caddy
COPY --link internal internal
COPY --link testdata testdata
COPY --link watcher watcher

# install edant/watcher (necessary for file watching)
ARG EDANT_WATCHER_VERSION=next
WORKDIR /usr/local/src/watcher
RUN curl -L https://github.com/e-dant/watcher/archive/refs/heads/$EDANT_WATCHER_VERSION.tar.gz | tar xz
WORKDIR /usr/local/src/watcher/watcher-$EDANT_WATCHER_VERSION/watcher-c
RUN gcc -o libwatcher.so ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -O3 -Wall -Wextra -fPIC -shared && \
cp libwatcher.so /usr/local/lib/libwatcher.so && \
ldconfig /usr/local/lib

# See https://github.com/docker-library/php/blob/master/8.3/alpine3.20/zts/Dockerfile#L53-L55
ENV CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS"
Expand All @@ -122,6 +135,11 @@

ENV GODEBUG=cgocheck=0

# copy watcher shared library (libgcc and libstdc++ are needed for the watcher)
COPY --from=builder /usr/local/lib/libwatcher* /usr/local/lib/
RUN apk add --no-cache libstdc++ && \
ldconfig /usr/local/lib

COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
RUN setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
frankenphp version
10 changes: 10 additions & 0 deletions build-static.sh
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ if [ "${os}" = "linux" ]; then
CGO_LDFLAGS="${CGO_LDFLAGS} -lstdc++"
fi
fi

# install edant/watcher for file watching (static version)
git clone --branch="${EDANT_WATCHER_VERSION:-next}" https://github.com/e-dant/watcher watcher
cd watcher/watcher-c
gcc -c -o libwatcher.o ./src/watcher-c.cpp -I ./include -I ../include -std=c++17 -Wall -Wextra -fPIC
ar rcs libwatcher.a libwatcher.o
cp libwatcher.a "../../buildroot/lib/libwatcher.a"
cd ../../
CGO_LDFLAGS="${CGO_LDFLAGS} -lstdc++ ${PWD}/buildroot/lib/libwatcher.a"

export CGO_LDFLAGS

LIBPHP_VERSION="$(./buildroot/bin/php-config --version)"
Expand Down
11 changes: 10 additions & 1 deletion caddy/caddy.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ type FrankenPHPApp struct {
NumThreads int `json:"num_threads,omitempty"`
// Workers configures the worker scripts to start.
Workers []workerConfig `json:"workers,omitempty"`
// Directories to watch for changes
Watch []watchConfig `json:"watch,omitempty"`
}

// CaddyModule returns the Caddy module information.
Expand All @@ -84,6 +86,9 @@ func (f *FrankenPHPApp) Start() error {
for _, w := range f.Workers {
opts = append(opts, frankenphp.WithWorkers(repl.ReplaceKnown(w.FileName, ""), w.Num, w.Env))
}
for _, watchConfig := range f.Watch {
opts = applyWatchConfig(opts, watchConfig)
}

_, loaded, err := phpInterpreter.LoadOrNew(mainPHPInterpreterKey, func() (caddy.Destructor, error) {
if err := frankenphp.Init(opts...); err != nil {
Expand Down Expand Up @@ -128,7 +133,11 @@ func (f *FrankenPHPApp) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}

f.NumThreads = v

case "watch":
if !d.NextArg() {
return d.Err(`The "watch" directive must be followed by a path`)
}
f.Watch = append(f.Watch, parseWatchConfig(d.Val()))
case "worker":
wc := workerConfig{}
if d.NextArg() {
Expand Down
26 changes: 26 additions & 0 deletions caddy/caddy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,29 @@ func TestPHPServerDirectiveDisableFileServer(t *testing.T) {
tester.AssertGetResponse("http://localhost:9080", http.StatusOK, "I am by birth a Genevese (i not set)")
tester.AssertGetResponse("http://localhost:9080/hello.txt", http.StatusNotFound, "Not found")
}

func TestWorkerWithSleepingWatcher(t *testing.T) {
tester := caddytest.NewTester(t)
tester.InitServer(`
{
skip_install_trust
admin localhost:2999
http_port 9080
https_port 9443

frankenphp {
worker ../testdata/worker-with-watcher.php 1
watch ./**/*.php
}
}

localhost:9080 {
root * ../testdata
rewrite * worker-with-watcher.php
php
}
`, "caddyfile")

tester.AssertGetResponse("http://localhost:9080", http.StatusOK, "requests:1")
tester.AssertGetResponse("http://localhost:9080", http.StatusOK, "requests:2")
}
3 changes: 3 additions & 0 deletions caddy/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/dunglas/mercure/caddy v0.16.3
github.com/dunglas/vulcain/caddy v1.0.5
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
)

Expand Down Expand Up @@ -42,6 +43,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgraph-io/badger v1.6.2 // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
Expand Down Expand Up @@ -119,6 +121,7 @@ require (
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.20.2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
Expand Down
9 changes: 7 additions & 2 deletions caddy/php-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
func init() {
caddycmd.RegisterCommand(caddycmd.Command{
Name: "php-server",
Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--worker /path/to/worker.php<,nb-workers>] [--access-log] [--debug] [--no-compress] [--mercure]",
Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--worker /path/to/worker.php<,nb-workers>] [--watch /path/to/watch] [--access-log] [--debug] [--no-compress] [--mercure]",
Short: "Spins up a production-ready PHP server",
Long: `
A simple but production-ready PHP server. Useful for quick deployments,
Expand All @@ -48,6 +48,7 @@ For more advanced use cases, see https://github.com/dunglas/frankenphp/blob/main
cmd.Flags().StringP("root", "r", "", "The path to the root of the site")
cmd.Flags().StringP("listen", "l", "", "The address to which to bind the listener")
cmd.Flags().StringArrayP("worker", "w", []string{}, "Worker script")
cmd.Flags().StringArrayP("watch", "", []string{}, "Directory to watch for file changes")
cmd.Flags().BoolP("access-log", "a", false, "Enable the access log")
cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs")
cmd.Flags().BoolP("mercure", "m", false, "Enable the built-in Mercure.rocks hub")
Expand All @@ -73,6 +74,10 @@ func cmdPHPServer(fs caddycmd.Flags) (int, error) {
if err != nil {
panic(err)
}
watch, err := fs.GetStringArray("watch")
if err != nil {
panic(err)
}

var workersOption []workerConfig
if len(workers) != 0 {
Expand Down Expand Up @@ -305,7 +310,7 @@ func cmdPHPServer(fs caddycmd.Flags) (int, error) {
},
AppsRaw: caddy.ModuleMap{
"http": caddyconfig.JSON(httpApp, nil),
"frankenphp": caddyconfig.JSON(FrankenPHPApp{Workers: workersOption}, nil),
"frankenphp": caddyconfig.JSON(FrankenPHPApp{Workers: workersOption, Watch: parseWatchConfigs(watch)}, nil),
},
}

Expand Down
57 changes: 57 additions & 0 deletions caddy/watch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package caddy

import (
"github.com/dunglas/frankenphp"
"github.com/dunglas/frankenphp/watcher"
"path/filepath"
"strings"
)

type watchConfig struct {
// Directory that should be watched for changes
Dir string `json:"dir,omitempty"`
// Whether to watch the directory recursively
IsRecursive bool `json:"recursive,omitempty"`
// The shell filename pattern to match against
Pattern string `json:"pattern,omitempty"`
}

func applyWatchConfig(opts []frankenphp.Option, watchConfig watchConfig) []frankenphp.Option {
return append(opts, frankenphp.WithFileWatcher(
watcher.WithWatcherDir(watchConfig.Dir),
watcher.WithWatcherRecursion(watchConfig.IsRecursive),
watcher.WithWatcherPattern(watchConfig.Pattern),
))
}

func parseWatchConfigs(filePatterns []string) []watchConfig {
watchConfigs := []watchConfig{}
for _, filePattern := range filePatterns {
watchConfigs = append(watchConfigs, parseWatchConfig(filePattern))
}
return watchConfigs
}

// TODO: better path validation?
// for the one line short-form in the caddy config, aka: 'watch /path/*pattern'
func parseWatchConfig(filePattern string) watchConfig {
watchConfig := watchConfig{IsRecursive: true}
AlliBalliBaba marked this conversation as resolved.
Show resolved Hide resolved
dirName := filePattern
splitDirName, baseName := filepath.Split(filePattern)
if filePattern != "." && filePattern != ".." && strings.ContainsAny(baseName, "*.[?\\") {
dirName = splitDirName
watchConfig.Pattern = baseName
watchConfig.IsRecursive = false
}
if strings.Contains(filePattern, "**/") {
AlliBalliBaba marked this conversation as resolved.
Show resolved Hide resolved
dirName = strings.Split(filePattern, "**/")[0]
watchConfig.Pattern = strings.Split(filePattern, "**/")[1]
watchConfig.IsRecursive = true
}
watchConfig.Dir = dirName
if dirName != "/" {
AlliBalliBaba marked this conversation as resolved.
Show resolved Hide resolved
watchConfig.Dir = strings.TrimRight(dirName, "/")
}

return watchConfig
}
AlliBalliBaba marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading