From 8b6dd80a7513c51e744e39922708505965e7cd72 Mon Sep 17 00:00:00 2001 From: Nicholas DiPiazza Date: Mon, 27 Apr 2026 08:48:16 -0500 Subject: [PATCH 1/4] TIKA-4703: Fix tika-grpc Docker image missing runtime dependencies Use 'mvn dependency:copy-dependencies' to populate the lib/ directory of runtime jars that the MANIFEST.MF Class-Path entries reference. Without this the image only contained the thin jar and Java threw: NoClassDefFoundError: io/grpc/BindableService The jar's MANIFEST.MF (set by maven-jar-plugin classpathPrefix=lib/) expects dependencies at lib/ relative to the jar, i.e. /tika/libs/lib/ in the image. Running dependency:copy-dependencies into that path after the main build ensures all runtime deps are present. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/docker-release.yml | 6 +++++- .github/workflows/docker-snapshot.yml | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index d6e6971dfd9..51833d469ab 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -107,14 +107,18 @@ jobs: username: ${{ secrets.DOCKERHUB_USER }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Collect tika-grpc runtime dependencies + run: mvn -pl tika-grpc dependency:copy-dependencies -DoutputDirectory=target/lib -DincludeScope=runtime -B "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" + - name: Prepare tika-grpc Docker build context run: | TIKA_VERSION="${{ steps.version.outputs.tag }}" OUT_DIR=target/tika-grpc-docker - mkdir -p "${OUT_DIR}/libs" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" + mkdir -p "${OUT_DIR}/libs/lib" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" cp "tika-grpc/target/tika-grpc-${TIKA_VERSION}.jar" "${OUT_DIR}/libs/" + cp tika-grpc/target/lib/*.jar "${OUT_DIR}/libs/lib/" # Copy tika-pipes plugin zip files for dir in tika-pipes/tika-pipes-plugins/*/; do diff --git a/.github/workflows/docker-snapshot.yml b/.github/workflows/docker-snapshot.yml index 5b4e0414155..925ab7bdea1 100644 --- a/.github/workflows/docker-snapshot.yml +++ b/.github/workflows/docker-snapshot.yml @@ -101,14 +101,18 @@ jobs: apache/tika:${{ steps.version.outputs.tika_version }}-full # --- tika-grpc --- + - name: Collect tika-grpc runtime dependencies + run: mvn -pl tika-grpc dependency:copy-dependencies -DoutputDirectory=target/lib -DincludeScope=runtime -B "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" + - name: Prepare tika-grpc Docker build context run: | TIKA_VERSION="${{ steps.version.outputs.tika_version }}" OUT_DIR=target/tika-grpc-docker - mkdir -p "${OUT_DIR}/libs" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" + mkdir -p "${OUT_DIR}/libs/lib" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" cp "tika-grpc/target/tika-grpc-${TIKA_VERSION}.jar" "${OUT_DIR}/libs/" + cp tika-grpc/target/lib/*.jar "${OUT_DIR}/libs/lib/" # Copy tika-pipes plugin zip files for dir in tika-pipes/tika-pipes-plugins/*/; do From 7bd2ad4d78bcec1f5563fea9867880e2e89d482d Mon Sep 17 00:00:00 2001 From: Nicholas DiPiazza Date: Mon, 27 Apr 2026 09:08:13 -0500 Subject: [PATCH 2/4] TIKA-4703: Rename lib dir to tika-grpc, consolidate dep step, add grpc smoke test - Rename classpathPrefix from lib/ to tika-grpc/ in maven-jar-plugin so MANIFEST.MF Class-Path matches the actual directory layout in the image - Update docker-snapshot.yml and docker-release.yml: rename libs/lib -> libs/tika-grpc, consolidate separate 'Collect' + 'Prepare' steps into a single Prepare step - Add smoke test to docker-snapshot.yml: builds single-arch image with --load, starts container, polls for 'Server started' log line, fails CI if not seen within 30s Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/docker-release.yml | 9 +++---- .github/workflows/docker-snapshot.yml | 35 +++++++++++++++++++++++---- tika-grpc/pom.xml | 2 +- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index 51833d469ab..dadf630887a 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -107,18 +107,17 @@ jobs: username: ${{ secrets.DOCKERHUB_USER }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Collect tika-grpc runtime dependencies - run: mvn -pl tika-grpc dependency:copy-dependencies -DoutputDirectory=target/lib -DincludeScope=runtime -B "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" - - name: Prepare tika-grpc Docker build context run: | TIKA_VERSION="${{ steps.version.outputs.tag }}" OUT_DIR=target/tika-grpc-docker - mkdir -p "${OUT_DIR}/libs/lib" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" + mkdir -p "${OUT_DIR}/libs/tika-grpc" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" cp "tika-grpc/target/tika-grpc-${TIKA_VERSION}.jar" "${OUT_DIR}/libs/" - cp tika-grpc/target/lib/*.jar "${OUT_DIR}/libs/lib/" + mvn -pl tika-grpc dependency:copy-dependencies \ + -DoutputDirectory="${PWD}/${OUT_DIR}/libs/tika-grpc" \ + -DincludeScope=runtime -q -B # Copy tika-pipes plugin zip files for dir in tika-pipes/tika-pipes-plugins/*/; do diff --git a/.github/workflows/docker-snapshot.yml b/.github/workflows/docker-snapshot.yml index 925ab7bdea1..74cbddbd9b9 100644 --- a/.github/workflows/docker-snapshot.yml +++ b/.github/workflows/docker-snapshot.yml @@ -101,18 +101,17 @@ jobs: apache/tika:${{ steps.version.outputs.tika_version }}-full # --- tika-grpc --- - - name: Collect tika-grpc runtime dependencies - run: mvn -pl tika-grpc dependency:copy-dependencies -DoutputDirectory=target/lib -DincludeScope=runtime -B "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" - - name: Prepare tika-grpc Docker build context run: | TIKA_VERSION="${{ steps.version.outputs.tika_version }}" OUT_DIR=target/tika-grpc-docker - mkdir -p "${OUT_DIR}/libs/lib" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" + mkdir -p "${OUT_DIR}/libs/tika-grpc" "${OUT_DIR}/plugins" "${OUT_DIR}/config" "${OUT_DIR}/bin" cp "tika-grpc/target/tika-grpc-${TIKA_VERSION}.jar" "${OUT_DIR}/libs/" - cp tika-grpc/target/lib/*.jar "${OUT_DIR}/libs/lib/" + mvn -pl tika-grpc dependency:copy-dependencies \ + -DoutputDirectory="${PWD}/${OUT_DIR}/libs/tika-grpc" \ + -DincludeScope=runtime -q -B # Copy tika-pipes plugin zip files for dir in tika-pipes/tika-pipes-plugins/*/; do @@ -139,6 +138,32 @@ jobs: cp "tika-grpc/docker-build/start-tika-grpc.sh" "${OUT_DIR}/bin/" cp "tika-grpc/docker-build/Dockerfile" "${OUT_DIR}/Dockerfile" + - name: Build tika-grpc image for smoke test + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: target/tika-grpc-docker + platforms: linux/amd64 + load: true + build-args: | + VERSION=${{ steps.version.outputs.tika_version }} + tags: tika-grpc-smoke:ci + + - name: Smoke test tika-grpc image + run: | + docker run -d --name tika-grpc-smoke -p 9090:9090 tika-grpc-smoke:ci + for i in $(seq 1 15); do + if docker logs tika-grpc-smoke 2>&1 | grep -q "Server started, listening on"; then + echo "tika-grpc started successfully" + docker stop tika-grpc-smoke + exit 0 + fi + sleep 2 + done + echo "ERROR: tika-grpc did not start within 30 seconds" + docker logs tika-grpc-smoke + docker stop tika-grpc-smoke + exit 1 + - name: Build and push tika-grpc snapshot uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: diff --git a/tika-grpc/pom.xml b/tika-grpc/pom.xml index b3b3fe02cbb..68fc531a0f5 100644 --- a/tika-grpc/pom.xml +++ b/tika-grpc/pom.xml @@ -474,7 +474,7 @@ org.apache.tika.pipes.grpc.TikaGrpcServer true - lib/ + tika-grpc/ From acd2d733fce53decee7330354cc416b2a7974a99 Mon Sep 17 00:00:00 2001 From: Nicholas DiPiazza Date: Mon, 27 Apr 2026 09:15:40 -0500 Subject: [PATCH 3/4] TIKA-4703: Add smoke tests for tika-server minimal and full Docker images - Build single-arch (amd64) image with --load before each multi-arch push - Poll for 'Started Apache Tika server' log line for up to 40 seconds - Fail CI job if server does not start; dump logs on failure - tika-server has no missing-deps issue (bin.tgz already bundles lib/) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/docker-snapshot.yml | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/.github/workflows/docker-snapshot.yml b/.github/workflows/docker-snapshot.yml index 74cbddbd9b9..4723f7d38d6 100644 --- a/.github/workflows/docker-snapshot.yml +++ b/.github/workflows/docker-snapshot.yml @@ -69,6 +69,32 @@ jobs: tar xzf "tika-server/tika-server-standard/target/tika-server-standard-${TIKA_VERSION}-bin.tgz" -C "${OUT_DIR}/tika-server" cp "tika-server/docker-build/minimal/Dockerfile.snapshot" "${OUT_DIR}/Dockerfile" + - name: Build tika-server minimal image for smoke test + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: target/tika-server-minimal-docker + platforms: linux/amd64 + load: true + build-args: | + TIKA_VERSION=${{ steps.version.outputs.tika_version }} + tags: tika-server-minimal-smoke:ci + + - name: Smoke test tika-server minimal image + run: | + docker run -d --name tika-server-minimal-smoke -p 9998:9998 tika-server-minimal-smoke:ci + for i in $(seq 1 20); do + if docker logs tika-server-minimal-smoke 2>&1 | grep -q "Started Apache Tika server"; then + echo "tika-server minimal started successfully" + docker stop tika-server-minimal-smoke + exit 0 + fi + sleep 2 + done + echo "ERROR: tika-server minimal did not start within 40 seconds" + docker logs tika-server-minimal-smoke + docker stop tika-server-minimal-smoke + exit 1 + - name: Build and push tika-server minimal snapshot uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: @@ -89,6 +115,32 @@ jobs: tar xzf "tika-server/tika-server-standard/target/tika-server-standard-${TIKA_VERSION}-bin.tgz" -C "${OUT_DIR}/tika-server" cp "tika-server/docker-build/full/Dockerfile.snapshot" "${OUT_DIR}/Dockerfile" + - name: Build tika-server full image for smoke test + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: target/tika-server-full-docker + platforms: linux/amd64 + load: true + build-args: | + TIKA_VERSION=${{ steps.version.outputs.tika_version }} + tags: tika-server-full-smoke:ci + + - name: Smoke test tika-server full image + run: | + docker run -d --name tika-server-full-smoke -p 9999:9998 tika-server-full-smoke:ci + for i in $(seq 1 20); do + if docker logs tika-server-full-smoke 2>&1 | grep -q "Started Apache Tika server"; then + echo "tika-server full started successfully" + docker stop tika-server-full-smoke + exit 0 + fi + sleep 2 + done + echo "ERROR: tika-server full did not start within 40 seconds" + docker logs tika-server-full-smoke + docker stop tika-server-full-smoke + exit 1 + - name: Build and push tika-server full snapshot uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: From cf1d3f322be6cf873c2c55e7a469d26b87118155 Mon Sep 17 00:00:00 2001 From: Nicholas DiPiazza Date: Mon, 27 Apr 2026 09:37:42 -0500 Subject: [PATCH 4/4] TIKA-4703: Fix assembly.xml dep dir and use trap-based cleanup in smoke tests - Update assembly.xml outputDirectory from lib/ to tika-grpc/ to match classpathPrefix in pom.xml; without this the binary zip would have deps under lib/ while MANIFEST.MF Class-Path references tika-grpc/*.jar - Replace bare docker stop/exit in all three smoke test steps with a trap cleanup function using docker rm -f; this prevents bash -e from failing on a stop of an already-exited container and ensures logs are always collected on failure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/docker-snapshot.yml | 38 ++++++++++++++++++------ tika-grpc/src/main/assembly/assembly.xml | 2 +- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker-snapshot.yml b/.github/workflows/docker-snapshot.yml index 4723f7d38d6..cb82d05592a 100644 --- a/.github/workflows/docker-snapshot.yml +++ b/.github/workflows/docker-snapshot.yml @@ -81,18 +81,24 @@ jobs: - name: Smoke test tika-server minimal image run: | + cleanup() { + status=$? + if [ "$status" -ne 0 ]; then + docker logs tika-server-minimal-smoke || true + fi + docker rm -f tika-server-minimal-smoke >/dev/null 2>&1 || true + exit "$status" + } + trap cleanup EXIT docker run -d --name tika-server-minimal-smoke -p 9998:9998 tika-server-minimal-smoke:ci for i in $(seq 1 20); do if docker logs tika-server-minimal-smoke 2>&1 | grep -q "Started Apache Tika server"; then echo "tika-server minimal started successfully" - docker stop tika-server-minimal-smoke exit 0 fi sleep 2 done echo "ERROR: tika-server minimal did not start within 40 seconds" - docker logs tika-server-minimal-smoke - docker stop tika-server-minimal-smoke exit 1 - name: Build and push tika-server minimal snapshot @@ -127,18 +133,24 @@ jobs: - name: Smoke test tika-server full image run: | + cleanup() { + status=$? + if [ "$status" -ne 0 ]; then + docker logs tika-server-full-smoke || true + fi + docker rm -f tika-server-full-smoke >/dev/null 2>&1 || true + exit "$status" + } + trap cleanup EXIT docker run -d --name tika-server-full-smoke -p 9999:9998 tika-server-full-smoke:ci for i in $(seq 1 20); do if docker logs tika-server-full-smoke 2>&1 | grep -q "Started Apache Tika server"; then echo "tika-server full started successfully" - docker stop tika-server-full-smoke exit 0 fi sleep 2 done echo "ERROR: tika-server full did not start within 40 seconds" - docker logs tika-server-full-smoke - docker stop tika-server-full-smoke exit 1 - name: Build and push tika-server full snapshot @@ -202,18 +214,26 @@ jobs: - name: Smoke test tika-grpc image run: | + cleanup() { + status=$? + if [ "$status" -ne 0 ]; then + docker logs tika-grpc-smoke || true + docker ps -a --filter "name=^tika-grpc-smoke$" || true + docker inspect -f '{{.State.ExitCode}}' tika-grpc-smoke || true + fi + docker rm -f tika-grpc-smoke >/dev/null 2>&1 || true + exit "$status" + } + trap cleanup EXIT docker run -d --name tika-grpc-smoke -p 9090:9090 tika-grpc-smoke:ci for i in $(seq 1 15); do if docker logs tika-grpc-smoke 2>&1 | grep -q "Server started, listening on"; then echo "tika-grpc started successfully" - docker stop tika-grpc-smoke exit 0 fi sleep 2 done echo "ERROR: tika-grpc did not start within 30 seconds" - docker logs tika-grpc-smoke - docker stop tika-grpc-smoke exit 1 - name: Build and push tika-grpc snapshot diff --git a/tika-grpc/src/main/assembly/assembly.xml b/tika-grpc/src/main/assembly/assembly.xml index 37c48d40324..849f2675720 100644 --- a/tika-grpc/src/main/assembly/assembly.xml +++ b/tika-grpc/src/main/assembly/assembly.xml @@ -25,7 +25,7 @@ - lib + tika-grpc false false runtime