diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2c21ca2f..27f06f5c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -29,7 +29,7 @@ permissions: env: # ------------------------------------------------------------------ # GeoServer Version Series Configuration - # + # # These variables define the currently supported GeoServer release series. # They MUST be updated when a new major or minor series is released (every 6 months). # @@ -74,6 +74,7 @@ jobs: major: ${{ steps.parse.outputs.major }} minor: ${{ steps.parse.outputs.minor }} base_image: ${{ steps.parse.outputs.base_image }} + builder_base_image: ${{ steps.parse.outputs.builder_base_image }} branch: ${{ steps.parse.outputs.branch }} is_nightly: ${{ steps.parse.outputs.is_nightly }} war_url: ${{ steps.parse.outputs.war_url }} @@ -81,13 +82,13 @@ jobs: community_plugin_url: ${{ steps.parse.outputs.community_plugin_url }} primary_tag: ${{ steps.parse.outputs.primary_tag }} additional_tags: ${{ steps.parse.outputs.additional_tags }} - + steps: - name: Parse Version and Determine Build Parameters id: parse run: | set -euo pipefail - + VERSION="${{ inputs.version }}" BUILD="${{ inputs.build_number }}" @@ -97,19 +98,19 @@ jobs: BUILD="${GITHUB_RUN_NUMBER:-github}" echo "No version input (push trigger). Falling back to VERSION=$VERSION BUILD=$BUILD" fi - + # If BUILD is empty, use a default if [ -z "$BUILD" ]; then BUILD="${GITHUB_RUN_NUMBER:-github}" echo "Build number not provided. Using BUILD=$BUILD" fi - + # Output version and build number for use in other jobs echo "version=$VERSION" >> $GITHUB_OUTPUT echo "build_number=$BUILD" >> $GITHUB_OUTPUT - + echo "Parsing version: $VERSION" - + # Extract major.minor version if [[ $VERSION =~ ^([0-9]+)\.([0-9]+) ]]; then MAJOR="${BASH_REMATCH[1]}" @@ -120,19 +121,24 @@ jobs: echo "ERROR: Unable to parse version $VERSION" exit 1 fi - + # Determine base image based on version if [[ "$VERSION" == "3"* ]]; then BASE_IMAGE="tomcat:11.0-jdk21-temurin-noble" + BUILDER_BASE_IMAGE=eclipse-temurin:21-jdk-noble elif [[ "$VERSION" == "2.28"* ]]; then BASE_IMAGE="tomcat:9.0-jdk21-temurin-noble" + BUILDER_BASE_IMAGE=eclipse-temurin:21-jdk-noble elif [[ "$VERSION" == "2.27"* ]] || [[ "$VERSION" == "2.26"* ]]; then BASE_IMAGE="tomcat:9.0-jdk17-temurin-noble" + BUILDER_BASE_IMAGE=eclipse-temurin:17-jdk-noble else BASE_IMAGE="tomcat:9.0-jdk11-temurin-noble" + BUILDER_BASE_IMAGE=eclipse-temurin:11-jdk-noble fi echo "base_image=$BASE_IMAGE" >> $GITHUB_OUTPUT - + echo "builder_base_image=$BUILDER_BASE_IMAGE" >> $GITHUB_OUTPUT + # Determine branch and tag based on version pattern if [[ "$VERSION" == *"-M"* ]]; then # Milestone release (e.g., 2.28-M0) @@ -167,11 +173,11 @@ jobs: IS_NIGHTLY="false" fi fi - + echo "branch=$BRANCH" >> $GITHUB_OUTPUT echo "is_nightly=$IS_NIGHTLY" >> $GITHUB_OUTPUT echo "primary_tag=$PRIMARY_TAG" >> $GITHUB_OUTPUT - + # Determine download URLs if [[ "$IS_NIGHTLY" == "true" ]]; then WAR_URL="https://build.geoserver.org/geoserver/$BRANCH/geoserver-$BRANCH-latest-war.zip" @@ -182,19 +188,19 @@ jobs: STABLE_PLUGIN_URL="https://downloads.sourceforge.net/project/geoserver/GeoServer/${VERSION}/extensions" COMMUNITY_PLUGIN_URL="https://build.geoserver.org/geoserver/${BRANCH}/community-latest" fi - + echo "war_url=$WAR_URL" >> $GITHUB_OUTPUT echo "stable_plugin_url=$STABLE_PLUGIN_URL" >> $GITHUB_OUTPUT echo "community_plugin_url=$COMMUNITY_PLUGIN_URL" >> $GITHUB_OUTPUT - + # Determine additional tags based on version pattern ADDITIONAL_TAGS="" - + # Add series-latest tag (e.g., 2.28-latest) if [[ "$IS_NIGHTLY" == "false" ]]; then ADDITIONAL_TAGS="${MAJOR}.${MINOR}-latest" fi - + # Add semantic tags for stable/maintenance releases only # (main releases get x.y-latest but no semantic tag since they're experimental) if [[ "$VERSION" == "${STABLE_VERSION}."* ]] && [[ "$IS_NIGHTLY" == "false" ]]; then @@ -202,7 +208,7 @@ jobs: elif [[ "$VERSION" == "${MAINTENANCE_VERSION}."* ]] && [[ "$IS_NIGHTLY" == "false" ]]; then ADDITIONAL_TAGS="$ADDITIONAL_TAGS,maintenance-latest" fi - + # Add nightly tags for snapshot builds if [[ "$VERSION" == "${MAIN_VERSION}"*"-SNAPSHOT" ]]; then ADDITIONAL_TAGS="$ADDITIONAL_TAGS,nightly" @@ -211,23 +217,24 @@ jobs: elif [[ "$VERSION" == "${MAINTENANCE_VERSION}"*"-SNAPSHOT" ]]; then ADDITIONAL_TAGS="$ADDITIONAL_TAGS,maintenance-nightly" fi - + # Clean up leading comma ADDITIONAL_TAGS=$(echo "$ADDITIONAL_TAGS" | sed 's/^,//') - + echo "additional_tags=$ADDITIONAL_TAGS" >> $GITHUB_OUTPUT - + echo "============================================" echo "Build Configuration:" echo " Version: $VERSION" echo " Branch: $BRANCH" echo " Base Image: $BASE_IMAGE" + echo " (GDAL) Builder Base Image: $BUILDER_BASE_IMAGE" echo " Is Nightly: $IS_NIGHTLY" echo " Primary Tag: $PRIMARY_TAG" echo " Additional Tags: $ADDITIONAL_TAGS" echo " WAR URL: $WAR_URL" echo "============================================" - + - name: Validate GeoServer WAR URL run: | set -euo pipefail @@ -268,38 +275,40 @@ jobs: runner: ubuntu-24.04-arm arch: arm64 gdal: true - + steps: - name: Checkout repository uses: actions/checkout@v6 - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - + - name: Login to Primary Registry (OSGeo) uses: docker/login-action@v3 with: registry: geoserver-docker.osgeo.org username: ${{ secrets.OSGEO_REPO_USERNAME }} password: ${{ secrets.OSGEO_REPO_PASSWORD }} - + - name: Download GeoServer WAR run: | mkdir -p geoserver cd geoserver wget -c "${{ needs.prepare.outputs.war_url }}" - + - name: Build and export digest id: build uses: docker/build-push-action@v6 with: context: . platforms: ${{ matrix.platform }} + pull: true build-args: | GS_VERSION=${{ needs.prepare.outputs.version }} GS_BUILD=${{ needs.prepare.outputs.build_number }} BUILD_GDAL=${{ matrix.gdal }} GEOSERVER_BASE_IMAGE=${{ needs.prepare.outputs.base_image }} + BUILDER_BASE_IMAGE=${{ needs.prepare.outputs.builder_base_image }} WAR_ZIP_URL=${{ needs.prepare.outputs.war_url }} STABLE_PLUGIN_URL=${{ needs.prepare.outputs.stable_plugin_url }} COMMUNITY_PLUGIN_URL=${{ needs.prepare.outputs.community_plugin_url }} @@ -308,13 +317,13 @@ jobs: provenance: true sbom: true outputs: type=image,name=${{ env.PRIMARY_REGISTRY }},push-by-digest=true,name-canonical=true,push=true - + - name: Export digest run: | mkdir -p /tmp/digests digest="${{ steps.build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" - + - name: Upload digest uses: actions/upload-artifact@v4 with: @@ -329,11 +338,11 @@ jobs: merge: name: Create Multi-Arch Manifests runs-on: ubuntu-latest - needs: + needs: - prepare - build timeout-minutes: 15 - + steps: - name: Download all digests (no GDAL) uses: actions/download-artifact@v4 @@ -341,29 +350,29 @@ jobs: pattern: digests-*-nogdal merge-multiple: true path: /tmp/digests-nogdal - + - name: Download all digests (with GDAL) uses: actions/download-artifact@v4 with: pattern: digests-*-gdal merge-multiple: true path: /tmp/digests-gdal - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - + - name: Login to Primary Registry (OSGeo) uses: docker/login-action@v3 with: registry: geoserver-docker.osgeo.org username: ${{ secrets.OSGEO_REPO_USERNAME }} password: ${{ secrets.OSGEO_REPO_PASSWORD }} - + - name: Create manifest list and push to Primary Registry (no GDAL) working-directory: /tmp/digests-nogdal run: | set -euo pipefail - + # Validate digest files exist DIGEST_COUNT=$(ls -1 2>/dev/null | wc -l) if [ "$DIGEST_COUNT" -eq 0 ]; then @@ -372,31 +381,31 @@ jobs: exit 1 fi echo "Found $DIGEST_COUNT digest file(s)" - + PRIMARY_TAG="${{ needs.prepare.outputs.primary_tag }}" ADDITIONAL_TAGS="${{ needs.prepare.outputs.additional_tags }}" - + # Build tag list for primary registry TAGS="${{ env.PRIMARY_REGISTRY }}:$PRIMARY_TAG" - + if [ -n "$ADDITIONAL_TAGS" ]; then IFS=',' read -ra TAG_ARRAY <<< "$ADDITIONAL_TAGS" for tag in "${TAG_ARRAY[@]}"; do TAGS="$TAGS ${{ env.PRIMARY_REGISTRY }}:$tag" done fi - + # Create manifest and push to primary registry docker buildx imagetools create $(printf -- '-t %s ' $TAGS) \ $(printf '${{ env.PRIMARY_REGISTRY }}@sha256:%s ' *) - + echo "Created manifest for tags: $TAGS" - + - name: Create manifest list and push (with GDAL) working-directory: /tmp/digests-gdal run: | set -euo pipefail - + # Validate digest files exist DIGEST_COUNT=$(ls -1 2>/dev/null | wc -l) if [ "$DIGEST_COUNT" -eq 0 ]; then @@ -405,49 +414,50 @@ jobs: exit 1 fi echo "Found $DIGEST_COUNT digest file(s)" - + PRIMARY_TAG="${{ needs.prepare.outputs.primary_tag }}-gdal" ADDITIONAL_TAGS="${{ needs.prepare.outputs.additional_tags }}" - + # Build tag list with -gdal suffix TAGS="${{ env.PRIMARY_REGISTRY }}:$PRIMARY_TAG" - + if [ -n "$ADDITIONAL_TAGS" ]; then IFS=',' read -ra TAG_ARRAY <<< "$ADDITIONAL_TAGS" for tag in "${TAG_ARRAY[@]}"; do TAGS="$TAGS ${{ env.PRIMARY_REGISTRY }}:$tag-gdal" done fi - + # Create manifest docker buildx imagetools create $(printf -- '-t %s ' $TAGS) \ $(printf '${{ env.PRIMARY_REGISTRY }}@sha256:%s ' *) - + echo "Created manifest for tags: $TAGS" - + - name: Inspect manifests run: | docker buildx imagetools inspect ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }} docker buildx imagetools inspect ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}-gdal - + - name: Generate Job Summary run: | cat >> $GITHUB_STEP_SUMMARY << 'EOF' ## GeoServer Multi-Arch Build Summary - + ### Build Information - **Version**: ${{ needs.prepare.outputs.version }} - **Build Number**: ${{ needs.prepare.outputs.build_number }} - **Base Image**: ${{ needs.prepare.outputs.base_image }} + - **(GDAL) Builder Base Image**: ${{ needs.prepare.outputs.builder_base_image }} - **Is Nightly**: ${{ needs.prepare.outputs.is_nightly }} - + ### Images Created - + #### Without GDAL EOF echo "- Primary: ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}" >> $GITHUB_STEP_SUMMARY - + # Add additional tags if present ADDITIONAL_TAGS="${{ needs.prepare.outputs.additional_tags }}" if [ -n "$ADDITIONAL_TAGS" ]; then @@ -456,31 +466,31 @@ jobs: echo "- Additional: ${{ env.PRIMARY_REGISTRY }}:$tag" >> $GITHUB_STEP_SUMMARY done fi - + cat >> $GITHUB_STEP_SUMMARY << 'EOF' - + #### With GDAL - Primary: ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}-gdal EOF - + if [ -n "$ADDITIONAL_TAGS" ]; then IFS=',' read -ra TAG_ARRAY <<< "$ADDITIONAL_TAGS" for tag in "${TAG_ARRAY[@]}"; do echo "- Additional: ${{ env.PRIMARY_REGISTRY }}:$tag-gdal" >> $GITHUB_STEP_SUMMARY done fi - + cat >> $GITHUB_STEP_SUMMARY << 'EOF' - + ### Architectures - linux/amd64 - linux/arm64 - + ### Pull Commands ```bash # Without GDAL docker pull ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }} - + # With GDAL docker pull ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}-gdal ``` @@ -492,28 +502,28 @@ jobs: publish-secondary: name: Mirror Images to Secondary Registry runs-on: ubuntu-latest - needs: + needs: - prepare - merge timeout-minutes: 15 - + steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - + - name: Login to Secondary Registry (Docker Hub) uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - + - name: Copy multi-arch manifests to secondary registry run: | # Copy multi-arch manifest from primary to secondary registry docker buildx imagetools create \ -t ${{ env.SECONDARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }} \ ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }} - + # Apply additional tags if present ADDITIONAL_TAGS="${{ needs.prepare.outputs.additional_tags }}" if [ -n "$ADDITIONAL_TAGS" ]; then @@ -524,12 +534,12 @@ jobs: ${{ env.PRIMARY_REGISTRY }}:${tag} done fi - + # Copy multi-arch manifest for the GDAL variant docker buildx imagetools create \ -t ${{ env.SECONDARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}-gdal \ ${{ env.PRIMARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}-gdal - + if [ -n "$ADDITIONAL_TAGS" ]; then IFS=',' read -ra TAG_ARRAY <<< "$ADDITIONAL_TAGS" for tag in "${TAG_ARRAY[@]}"; do @@ -538,15 +548,15 @@ jobs: ${{ env.PRIMARY_REGISTRY }}:${tag}-gdal done fi - + echo "Successfully copied multi-arch manifests to ${{ env.SECONDARY_REGISTRY }}." echo "Verify at: https://hub.docker.com/r/${{ env.SECONDARY_REGISTRY }}/tags" - + # Inspect to confirm multi-arch echo "" echo "Inspecting primary manifest:" docker buildx imagetools inspect ${{ env.SECONDARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }} - + echo "" echo "Inspecting primary manifest (with GDAL):" docker buildx imagetools inspect ${{ env.SECONDARY_REGISTRY }}:${{ needs.prepare.outputs.primary_tag }}-gdal diff --git a/build/release.sh b/build/release.sh index 0befb349..fa8dbc55 100755 --- a/build/release.sh +++ b/build/release.sh @@ -22,13 +22,16 @@ function build_geoserver_image() { local BRANCH=$5 if [ -n "$VERSION" ] && [ -n "$BUILD" ] && [ -n "$BUILD_GDAL" ] && [ -n "$TAG" ]; then - + if [[ "$VERSION" == "3"* ]]; then GEOSERVER_BASE_IMAGE=tomcat:11.0-jdk21-temurin-noble + BUILDER_BASE_IMAGE=eclipse-temurin:21-jdk-noble elif [[ "$VERSION" == "2.28"* ]]; then # removing trailing dot, as the check must support both 2.28.x and 2.28-SNAPSHOT GEOSERVER_BASE_IMAGE=tomcat:9.0-jdk21-temurin-noble + BUILDER_BASE_IMAGE=eclipse-temurin:21-jdk-noble else GEOSERVER_BASE_IMAGE=tomcat:9.0-jdk17-temurin-noble + BUILDER_BASE_IMAGE=eclipse-temurin:17-jdk-noble fi if [ -n "$BRANCH" ]; then @@ -44,6 +47,8 @@ function build_geoserver_image() { --build-arg GS_BUILD="$BUILD" \ --build-arg BUILD_GDAL="$BUILD_GDAL" \ --build-arg GEOSERVER_BASE_IMAGE="$GEOSERVER_BASE_IMAGE" \ + --build-arg BUILDER_BASE_IMAGE="$BUILDER_BASE_IMAGE" \ + --pull \ -t "$TAG" .) elif [ -z "$BRANCH" ]; then # BRANCH is not set @@ -133,7 +138,7 @@ if [[ $1 == *build* ]]; then echo " nightly build from https://build.geoserver.org/geoserver/$BRANCH" echo " downloading geoserver-$BRANCH-latest-war.zip" wget -c -q -P./geoserver/ \ - "https://build.geoserver.org/geoserver/$BRANCH/geoserver-$BRANCH-latest-war.zip" + "https://build.geoserver.org/geoserver/$BRANCH/geoserver-$BRANCH-latest-war.zip" echo build_geoserver_image $VERSION $BUILD "false" $TAG $BRANCH # without gdal build_geoserver_image $VERSION $BUILD "true" $GDAL_TAG $BRANCH # with gdal @@ -142,7 +147,7 @@ if [[ $1 == *build* ]]; then echo " downloading geoserver-${VERSION}-war.zip" wget -c -q -P./geoserver/ \ "https://downloads.sourceforge.net/project/geoserver/GeoServer/${VERSION}/geoserver-${VERSION}-war.zip" - echo + echo build_geoserver_image $VERSION $BUILD "false" $TAG # without gdal build_geoserver_image $VERSION $BUILD "true" $GDAL_TAG # with gdal fi