From be5f73de6c9ceb6ce92dfe7644d724f59662e3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 16 May 2026 15:58:15 +0200 Subject: [PATCH 1/2] build(docker): make e-dant/watcher install robust The watcher install step fetches the latest release tarball URL from the GitHub API, then pipes the response through grep/awk/sed/xargs into curl and tar. When the API returns anything that does not include a tarball_url (rate limit response, 5xx, auth error), the pipeline silently produces an empty URL and dies with the opaque pair: curl: (2) no URL specified tar: Child returned status 1 Two converging issues caused this in CI: 1. .github/workflows/docker.yaml's bake step did not export GITHUB_TOKEN to the bake-action environment, so the secret mount in docker-bake.hcl resolved to empty and the API call ran unauthenticated. With the 60 req/hr unauth cap, parallel matrix jobs are easy to rate-limit. static.yaml's equivalent bake step already passes the token; docker.yaml was the outlier. 2. The Dockerfile pipeline used `curl -s` (no -f, no error surfacing) and parsed JSON with grep+awk+sed. Any non-success response sent the build down the same opaque tar/curl error path with no clue as to why. Pass GITHUB_TOKEN to the bake step, install jq in both Dockerfile and alpine.Dockerfile, and rewrite the install with `curl -fsSL` plus explicit empty-URL detection so failures surface a clear message instead of a phantom curl/tar error. Failing run that prompted this: php#2430 amd64 job 76318473755 --- .github/workflows/docker.yaml | 1 + Dockerfile | 37 +++++++++++++++++++---------------- alpine.Dockerfile | 33 +++++++++++++++++-------------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 2318411745..8781726767 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -158,6 +158,7 @@ jobs: VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref || 'dev' }} PHP_VERSION: ${{ needs.prepare.outputs.php_version }} BASE_FINGERPRINT: ${{ needs.prepare.outputs.base_fingerprint }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600 name: Export metadata if: fromJson(needs.prepare.outputs.push) diff --git a/Dockerfile b/Dockerfile index 8252e40998..7c5f8e3695 100644 --- a/Dockerfile +++ b/Dockerfile @@ -66,6 +66,7 @@ RUN apt-get update && \ apt-get -y --no-install-recommends install \ cmake \ git \ + jq \ libargon2-dev \ libbrotli-dev \ libcurl4-openssl-dev \ @@ -81,23 +82,25 @@ RUN apt-get update && \ # Install e-dant/watcher (necessary for file watching) WORKDIR /usr/local/src/watcher -RUN --mount=type=secret,id=github-token \ - if [ -f /run/secrets/github-token ] && [ -s /run/secrets/github-token ]; then \ - curl -s -H "Authorization: Bearer $(cat /run/secrets/github-token)" https://api.github.com/repos/e-dant/watcher/releases/latest; \ - else \ - curl -s https://api.github.com/repos/e-dant/watcher/releases/latest; \ - fi | \ - grep tarball_url | \ - awk '{ print $2 }' | \ - sed 's/,$//' | \ - sed 's/"//g' | \ - xargs curl -L | \ - tar xz --strip-components 1 && \ - # -Wno-error=use-after-free: GCC 12 on Bookworm i386 emits a spurious warning in libstdc++ basic_string.h - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wno-error=use-after-free" && \ - cmake --build build && \ - cmake --install build && \ - ldconfig +RUN --mount=type=secret,id=github-token <<'EOF' +set -e +api=https://api.github.com/repos/e-dant/watcher/releases/latest +if [ -s /run/secrets/github-token ]; then + tarball_url=$(curl -fsSL -H "Authorization: Bearer $(cat /run/secrets/github-token)" "${api}" | jq -r '.tarball_url // empty') +else + tarball_url=$(curl -fsSL "${api}" | jq -r '.tarball_url // empty') +fi +if [ -z "${tarball_url}" ]; then + echo "failed to resolve e-dant/watcher tarball URL (rate limited?)" >&2 + exit 1 +fi +curl -fsSL "${tarball_url}" | tar xz --strip-components 1 +# -Wno-error=use-after-free: GCC 12 on Bookworm i386 emits a spurious warning in libstdc++ basic_string.h +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-Wno-error=use-after-free" +cmake --build build +cmake --install build +ldconfig +EOF WORKDIR /go/src/app diff --git a/alpine.Dockerfile b/alpine.Dockerfile index c5d0f64ecb..700bca11f5 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -74,6 +74,7 @@ RUN apk add --no-cache --virtual .build-deps \ # Needed for the custom Go build \ git \ gnu-libiconv-dev \ + jq \ libsodium-dev \ # Needed for the file watcher \ cmake \ @@ -88,21 +89,23 @@ RUN apk add --no-cache --virtual .build-deps \ # Install e-dant/watcher (necessary for file watching) WORKDIR /usr/local/src/watcher -RUN --mount=type=secret,id=github-token \ - if [ -f /run/secrets/github-token ] && [ -s /run/secrets/github-token ]; then \ - curl -s -H "Authorization: Bearer $(cat /run/secrets/github-token)" https://api.github.com/repos/e-dant/watcher/releases/latest; \ - else \ - curl -s https://api.github.com/repos/e-dant/watcher/releases/latest; \ - fi | \ - grep tarball_url | \ - awk '{ print $2 }' | \ - sed 's/,$//' | \ - sed 's/"//g' | \ - xargs curl -L | \ - tar xz --strip-components 1 && \ - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release && \ - cmake --build build && \ - cmake --install build +RUN --mount=type=secret,id=github-token <<'EOF' +set -e +api=https://api.github.com/repos/e-dant/watcher/releases/latest +if [ -s /run/secrets/github-token ]; then + tarball_url=$(curl -fsSL -H "Authorization: Bearer $(cat /run/secrets/github-token)" "${api}" | jq -r '.tarball_url // empty') +else + tarball_url=$(curl -fsSL "${api}" | jq -r '.tarball_url // empty') +fi +if [ -z "${tarball_url}" ]; then + echo "failed to resolve e-dant/watcher tarball URL (rate limited?)" >&2 + exit 1 +fi +curl -fsSL "${tarball_url}" | tar xz --strip-components 1 +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build +cmake --install build +EOF WORKDIR /go/src/app From 1439292fb5c603baaf5b8a27b253446a57dc3e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 16 May 2026 16:41:14 +0200 Subject: [PATCH 2/2] build(docker): use tab indentation inside watcher install heredoc editorconfig-checker flagged the heredoc body as space-indented; the project's .editorconfig requires tabs for *.Dockerfile and Dockerfile already uses tabs everywhere else. --- Dockerfile | 8 ++++---- alpine.Dockerfile | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7c5f8e3695..40bed13988 100644 --- a/Dockerfile +++ b/Dockerfile @@ -86,13 +86,13 @@ RUN --mount=type=secret,id=github-token <<'EOF' set -e api=https://api.github.com/repos/e-dant/watcher/releases/latest if [ -s /run/secrets/github-token ]; then - tarball_url=$(curl -fsSL -H "Authorization: Bearer $(cat /run/secrets/github-token)" "${api}" | jq -r '.tarball_url // empty') + tarball_url=$(curl -fsSL -H "Authorization: Bearer $(cat /run/secrets/github-token)" "${api}" | jq -r '.tarball_url // empty') else - tarball_url=$(curl -fsSL "${api}" | jq -r '.tarball_url // empty') + tarball_url=$(curl -fsSL "${api}" | jq -r '.tarball_url // empty') fi if [ -z "${tarball_url}" ]; then - echo "failed to resolve e-dant/watcher tarball URL (rate limited?)" >&2 - exit 1 + echo "failed to resolve e-dant/watcher tarball URL (rate limited?)" >&2 + exit 1 fi curl -fsSL "${tarball_url}" | tar xz --strip-components 1 # -Wno-error=use-after-free: GCC 12 on Bookworm i386 emits a spurious warning in libstdc++ basic_string.h diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 700bca11f5..b9dbea5c15 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -93,13 +93,13 @@ RUN --mount=type=secret,id=github-token <<'EOF' set -e api=https://api.github.com/repos/e-dant/watcher/releases/latest if [ -s /run/secrets/github-token ]; then - tarball_url=$(curl -fsSL -H "Authorization: Bearer $(cat /run/secrets/github-token)" "${api}" | jq -r '.tarball_url // empty') + tarball_url=$(curl -fsSL -H "Authorization: Bearer $(cat /run/secrets/github-token)" "${api}" | jq -r '.tarball_url // empty') else - tarball_url=$(curl -fsSL "${api}" | jq -r '.tarball_url // empty') + tarball_url=$(curl -fsSL "${api}" | jq -r '.tarball_url // empty') fi if [ -z "${tarball_url}" ]; then - echo "failed to resolve e-dant/watcher tarball URL (rate limited?)" >&2 - exit 1 + echo "failed to resolve e-dant/watcher tarball URL (rate limited?)" >&2 + exit 1 fi curl -fsSL "${tarball_url}" | tar xz --strip-components 1 cmake -S . -B build -DCMAKE_BUILD_TYPE=Release