blob: b5b1b58208a08551f9322a4788fc761839b64a85 [file]
#
# 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 }}