| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| name: Docker release - tika-server and tika-grpc |
| |
| # Auto-trigger on tag push for GA-style version tags only. The convention is: |
| # release:prepare creates `X.Y.Z-rcN` for the vote (workflow stays silent), |
| # vote passes, the release manager pushes a separate `X.Y.Z` tag pointing |
| # at the same commit, and *that* push triggers this workflow. |
| # Manual rebuilds (CVE in base image, plugin refresh) use workflow_dispatch |
| # with an explicit build_number. |
| # |
| # GH Actions doesn't allow combining `tags` (include) and `tags-ignore` on |
| # a single event, so the filter is expressed as `tags-ignore` only. Any tag |
| # without a hyphen or underscore fires the workflow; this rejects prerelease |
| # tags (`4.0.0-rc1`, `4.0.0-alpha-1`, `4.0.0-BETA`) and branch-style tags |
| # (`branch_4x`). The `Compute tags` step has a separate prerelease check |
| # (`*-*`) that gates `:latest` defense-in-depth for the workflow_dispatch |
| # path where the auto-trigger filter isn't in play. |
| on: |
| push: |
| tags-ignore: |
| - '*-*' # anything with a hyphen is a prerelease/non-GA tag |
| - '*_*' # anything with an underscore is a branch/non-version tag |
| workflow_dispatch: |
| inputs: |
| tag: |
| description: 'Tika release tag (e.g. 4.0.0-alpha-1). Must already exist as a git tag.' |
| required: true |
| build_number: |
| description: 'Docker build number for this Tika tag (1 for first build, increment on rebuilds).' |
| required: true |
| default: '1' |
| source_ref: |
| description: 'Git ref to build from. Defaults to `tag`. Override only for Dockerfile-update rebuilds where the source has changed since the original tag was cut.' |
| required: false |
| |
| # Resolve the effective tag and build number from either trigger source. |
| # `inputs.*` is populated only by workflow_dispatch; on a tag push, fall |
| # back to the tag's short name (e.g. `4.0.0`) and build_number=1. |
| env: |
| TAG: ${{ inputs.tag || github.ref_name }} |
| BUILD: ${{ inputs.build_number || '1' }} |
| |
| jobs: |
| # Gating job for push triggers: refuse to publish if the tag isn't shaped |
| # like a GA version (digit+ . digit+ . digit+). The `tags-ignore` filter at |
| # the `on:` level already blocks anything with `-` or `_`, but it doesn't |
| # reject other oddities like `wip`, `foo`, or `test`. This job is the |
| # belt-and-suspenders to those (which were the suspenders). |
| # |
| # workflow_dispatch trigger is permissive — humans pick the tag (which can |
| # be alpha/beta/RC) — so the strict check is push-only. |
| validate-tag: |
| runs-on: ubuntu-latest |
| steps: |
| - name: Reject non-GA-style tags on push triggers |
| run: | |
| if [[ "${{ github.event_name }}" != "push" ]]; then |
| echo "workflow_dispatch trigger — skipping strict tag-shape validation." |
| exit 0 |
| fi |
| tag='${{ github.ref_name }}' |
| if [[ ! "$tag" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then |
| echo "::error title=Non-GA tag::Refusing to publish: tag '$tag' is not a GA-style X.Y.Z." |
| echo "::error::For prerelease publishes (alpha/BETA/RC), use workflow_dispatch with an explicit tag and build_number." |
| exit 1 |
| fi |
| echo "Tag '$tag' is GA-style. Proceeding." |
| |
| release-tika-server: |
| needs: validate-tag |
| runs-on: ubuntu-latest |
| timeout-minutes: 60 |
| |
| steps: |
| - uses: actions/checkout@v6 |
| with: |
| ref: ${{ inputs.source_ref || env.TAG }} |
| fetch-depth: 0 # full history so we can push a provenance tag at the end |
| |
| # Compute the tag set for each image. Three tags per image at minimum: |
| # apache/tika:<tag> (mutable; moves on each rebuild) |
| # apache/tika:<tag>-<build> (immutable; one per rebuild) |
| # apache/tika:latest (only for non-prerelease tags) |
| # The grpc image always pushes :latest (no 3.x incumbent to protect). |
| - name: Compute tags |
| id: tags |
| run: | |
| tag='${{ env.TAG }}' |
| build='${{ env.BUILD }}' |
| minimal="apache/tika:${tag} |
| apache/tika:${tag}-${build}" |
| full="apache/tika:${tag}-full |
| apache/tika:${tag}-${build}-full" |
| grpc="apache/tika-grpc:${tag} |
| apache/tika-grpc:${tag}-${build} |
| apache/tika-grpc:latest" |
| # Any hyphen in the tag = prerelease (alpha/beta/rc/SNAPSHOT/etc., |
| # in any case). Mirrors the `tags-ignore: ['*-*']` rule on the |
| # auto-trigger so manual workflow_dispatch behaves the same way. |
| case "$tag" in |
| *-*) |
| echo "Prerelease tag $tag — skipping :latest for apache/tika." |
| ;; |
| *) |
| minimal="${minimal} |
| apache/tika:latest" |
| full="${full} |
| apache/tika:latest-full" |
| ;; |
| esac |
| { |
| echo "minimal<<EOF"; echo "$minimal"; echo "EOF" |
| echo "full<<EOF"; echo "$full"; echo "EOF" |
| echo "grpc<<EOF"; echo "$grpc"; echo "EOF" |
| } >> "$GITHUB_OUTPUT" |
| |
| - name: Set up Docker Buildx |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 |
| |
| - name: Set up QEMU for multi-arch |
| run: docker run --privileged --rm tonistiigi/binfmt --install all |
| |
| - name: Login to Docker Hub |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 |
| with: |
| username: ${{ secrets.DOCKERHUB_USER }} |
| password: ${{ secrets.DOCKERHUB_TOKEN }} |
| |
| - name: Build and push tika-server minimal |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 |
| with: |
| file: tika-server/docker-build/minimal/Dockerfile |
| platforms: linux/amd64,linux/arm64,linux/s390x |
| push: true |
| build-args: | |
| TIKA_VERSION=${{ env.TAG }} |
| tags: ${{ steps.tags.outputs.minimal }} |
| |
| - name: Build and push tika-server full |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 |
| with: |
| file: tika-server/docker-build/full/Dockerfile |
| platforms: linux/amd64,linux/arm64,linux/s390x |
| push: true |
| build-args: | |
| TIKA_VERSION=${{ env.TAG }} |
| tags: ${{ steps.tags.outputs.full }} |
| |
| # After a successful publish, push a `<tag>-<build_number>` git tag for |
| # provenance. Skipped on build_number=1 because the original `<tag>` already |
| # marks the source state of build 1. Lives in the server job (not the grpc |
| # job) to avoid both jobs racing to push the same tag. |
| - name: Push provenance git tag |
| if: ${{ env.BUILD != '1' }} |
| env: |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| run: | |
| git config user.name "github-actions[bot]" |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" |
| git tag "${TAG}-${BUILD}" |
| git push origin "${TAG}-${BUILD}" |
| |
| release-tika-grpc: |
| needs: validate-tag |
| runs-on: ubuntu-latest |
| timeout-minutes: 120 |
| |
| steps: |
| - uses: actions/checkout@v6 |
| with: |
| ref: ${{ inputs.source_ref || env.TAG }} |
| |
| - name: Set up JDK 17 |
| uses: actions/setup-java@v5 |
| with: |
| distribution: 'temurin' |
| java-version: '17' |
| cache: 'maven' |
| |
| - name: Build with Maven (skip tests) |
| run: mvn clean install -DskipTests -B "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" |
| |
| - name: Set up Docker Buildx |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 |
| |
| - name: Set up QEMU for multi-arch |
| run: docker run --privileged --rm tonistiigi/binfmt --install all |
| |
| - name: Login to Docker Hub |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 |
| with: |
| username: ${{ secrets.DOCKERHUB_USER }} |
| password: ${{ secrets.DOCKERHUB_TOKEN }} |
| |
| - name: Compute grpc tags |
| id: grpc_tags |
| run: | |
| tag='${{ env.TAG }}' |
| build='${{ env.BUILD }}' |
| { |
| echo "tags<<EOF" |
| echo "apache/tika-grpc:${tag}" |
| echo "apache/tika-grpc:${tag}-${build}" |
| echo "apache/tika-grpc:latest" |
| echo "EOF" |
| } >> "$GITHUB_OUTPUT" |
| |
| - name: Prepare tika-grpc Docker build context |
| run: | |
| TIKA_VERSION='${{ env.TAG }}' |
| OUT_DIR=target/tika-grpc-docker |
| |
| 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/" |
| 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 |
| plugin_name=$(basename "$dir") |
| zip_file="${dir}target/${plugin_name}-${TIKA_VERSION}.zip" |
| if [ -f "$zip_file" ]; then |
| cp "$zip_file" "${OUT_DIR}/plugins/" |
| fi |
| done |
| |
| # Copy parser packages |
| for parser_package in \ |
| "tika-parsers/tika-parsers-standard/tika-parsers-standard-package" \ |
| "tika-parsers/tika-parsers-extended/tika-parser-scientific-package" \ |
| "tika-parsers/tika-parsers-extended/tika-parser-sqlite3-package" \ |
| "tika-parsers/tika-parsers-ml/tika-parser-nlp-package"; do |
| package_name=$(basename "$parser_package") |
| jar_file="${parser_package}/target/${package_name}-${TIKA_VERSION}.jar" |
| if [ -f "$jar_file" ]; then |
| cp "$jar_file" "${OUT_DIR}/plugins/" |
| fi |
| done |
| |
| cp "tika-grpc/docker-build/start-tika-grpc.sh" "${OUT_DIR}/bin/" |
| cp "tika-grpc/docker-build/Dockerfile" "${OUT_DIR}/Dockerfile" |
| |
| - name: Build and push tika-grpc |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 |
| with: |
| context: target/tika-grpc-docker |
| platforms: linux/amd64,linux/arm64 |
| push: true |
| build-args: | |
| VERSION=${{ env.TAG }} |
| # apache/tika-grpc is new in 4.x with no prior `:latest` to protect, so |
| # we track latest from the start (unlike apache/tika the server image, |
| # whose :latest stays on 3.x until 4.0.0 GA). |
| tags: ${{ steps.grpc_tags.outputs.tags }} |