From d9392fa02b832d76688e8205ecb27b128d8fa7d2 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Fri, 31 Jul 2026 14:54:37 +0100 Subject: [PATCH 01/19] initial gradle workflows --- .DS_Store | Bin 0 -> 6148 bytes .github/workflows/gradle-build-metadata.yml | 62 +++++++ .github/workflows/gradle-build.yml | 73 ++++++++ .../gradle-dependency-submission.yml | 52 ++++++ .github/workflows/gradle-docker-build.yml | 59 +++++++ .github/workflows/gradle-docker-publish.yml | 56 +++++++ .../workflows/gradle-get-version-number.yml | 40 +++++ .../gradle-module-descriptor-publish.yml | 54 ++++++ .github/workflows/gradle.yml | 158 ++++++++++++++++++ 9 files changed, 554 insertions(+) create mode 100644 .DS_Store create mode 100644 .github/workflows/gradle-build-metadata.yml create mode 100644 .github/workflows/gradle-build.yml create mode 100644 .github/workflows/gradle-dependency-submission.yml create mode 100644 .github/workflows/gradle-docker-build.yml create mode 100644 .github/workflows/gradle-docker-publish.yml create mode 100644 .github/workflows/gradle-get-version-number.yml create mode 100644 .github/workflows/gradle-module-descriptor-publish.yml create mode 100644 .github/workflows/gradle.yml diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a6c49b895e9622c0ae6d0fb42c668506640b3b96 GIT binary patch literal 6148 zcmeHKu}%U(5Pb`mK(ryo!pdA{EF@Z5n4AO~8w-8_0RMc zx4lud^XyXEX=lfmX{-T7v#1=-?YNH!9Xs)>bd~;A9y&t;v z){pjHCv`S#?lKpJWN&mZK*Ncy9zU`x(mA}n-q-JLbq-VegwZ6E`Kz3K@;>L|p@j%d zTsxVdP)Xa;Ieb2ik{rgq>FBfUPF#KNVhuxzdxcA!qf5OZcF@NeLiA{Ss{2zpZ5>li z3;CtZ602 z91Yp-F|tsfe<>J!i-E=1AX!M1aV0da%3d*)ai@9Tt_v*228}zEj!gU5$jaVOl#WjG zzFrO$7?f5R5C&WZ@@81#`hPV4{_i@;NEi?X{uKkttJbP~$+fjL^Ke{iebPE93$Kd} lY8Ps3Io2I6#T%qr$mVm0Ft8XKq!|+V5zsV9BMkg01K-`|nN9!z literal 0 HcmV?d00001 diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml new file mode 100644 index 0000000..548b453 --- /dev/null +++ b/.github/workflows/gradle-build-metadata.yml @@ -0,0 +1,62 @@ +name: Build Metadata + +description: Generates build metadata for snapshot and release builds. + +inputs: + + gradle-version: + description: Gradle project version. + required: true + +outputs: + + version: + description: Build version. + value: ${{ steps.metadata.outputs.version }} + + is-release: + description: Whether the build is a release. + value: ${{ steps.metadata.outputs.is-release }} + + docker-organization: + description: Docker organization. + value: ${{ steps.metadata.outputs.docker-organization }} + +runs: + using: composite + + steps: + + - id: metadata + shell: bash + env: + GRADLE_VERSION: ${{ inputs.gradle-version }} + + run: | + set -euo pipefail + + REF="${GITHUB_REF}" + + RUN_NUMBER="${GITHUB_RUN_NUMBER}" + + if [[ "${REF}" == refs/tags/* ]]; then + + VERSION="${GRADLE_VERSION}" + IS_RELEASE=true + DOCKER_ORG="folioorg" + elif [[ "${GRADLE_VERSION}" == *"-SNAPSHOT" ]]; then + + VERSION="${GRADLE_VERSION}.${RUN_NUMBER}" + IS_RELEASE=false + DOCKER_ORG="folioci" + else + VERSION="${GRADLE_VERSION}" + IS_RELEASE=false + DOCKER_ORG="folioci" + fi + + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + echo "is-release=$IS_RELEASE" >> "$GITHUB_OUTPUT" + + echo "docker-organization=$DOCKER_ORG" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml new file mode 100644 index 0000000..31bb125 --- /dev/null +++ b/.github/workflows/gradle-build.yml @@ -0,0 +1,73 @@ +name: Gradle Build + +on: + workflow_call: + inputs: + gradle-directory: + description: Directory containing the Gradle project. + required: false + type: string + default: service + + java-version: + description: Java version. + required: false + type: string + default: "17" + + build-command: + description: Gradle command. + required: false + type: string + default: "clean build" + +jobs: + + build: + runs-on: ubuntu-latest + timeout-minutes: 30 + + permissions: + contents: read + + defaults: + run: + shell: bash + working-directory: ${{ inputs.gradle-directory }} + + steps: + - name: Checkout source + uses: actions/checkout@v4 + + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ inputs.java-version }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build Project + run: | + ./gradlew \ + ${{ inputs.build-command }} \ + --stacktrace \ + --no-daemon + + - name: Upload application JAR + uses: actions/upload-artifact@v7 + with: + name: gradle-jar + path: | + ${{ inputs.gradle-directory }}/build/libs/*.jar + + - name: Upload ModuleDescriptor + uses: actions/upload-artifact@v7 + with: + name: ModuleDescriptor.json + path: | + ${{ inputs.gradle-directory }}/build/resources/main/okapi/ModuleDescriptor.json \ No newline at end of file diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml new file mode 100644 index 0000000..e96c978 --- /dev/null +++ b/.github/workflows/gradle-dependency-submission.yml @@ -0,0 +1,52 @@ +name: Dependency Submission + +on: + workflow_call: + inputs: + gradle-directory: + description: Directory containing the Gradle project. + required: false + type: string + default: service + + java-version: + description: Java version. + required: false + type: string + default: "17" + +jobs: + + dependency-submission: + + runs-on: ubuntu-latest + + timeout-minutes: 15 + + permissions: + contents: write + + defaults: + run: + shell: bash + working-directory: ${{ inputs.gradle-directory }} + + steps: + + - name: Checkout source + uses: actions/checkout@v4 + + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ inputs.java-version }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Submit Dependency Graph + uses: gradle/actions/dependency-submission@v4 \ No newline at end of file diff --git a/.github/workflows/gradle-docker-build.yml b/.github/workflows/gradle-docker-build.yml new file mode 100644 index 0000000..0174201 --- /dev/null +++ b/.github/workflows/gradle-docker-build.yml @@ -0,0 +1,59 @@ +name: Docker Build + +on: + workflow_call: + inputs: + image-name: + required: true + type: string + + docker-organization: + required: true + type: string + + version: + required: true + type: string + +jobs: + + docker-build: + + runs-on: ubuntu-latest + + timeout-minutes: 20 + + permissions: + contents: read + + steps: + + - name: Checkout source + uses: actions/checkout@v4 + + - name: Download application JAR + uses: actions/download-artifact@v4 + with: + name: gradle-jar + path: service/build/libs + + - name: Build Docker image + run: | + IMAGE=${{ inputs.docker-organization }}/${{ inputs.image-name }}:${{ inputs.version }} + + docker build \ + -t "$IMAGE" \ + . + + - name: Export Docker image + run: | + IMAGE=${{ inputs.docker-organization }}/${{ inputs.image-name }}:${{ inputs.version }} + + docker save "$IMAGE" \ + -o docker-image.tar + + - name: Upload Docker image + uses: actions/upload-artifact@v4 + with: + name: docker-image + path: docker-image.tar \ No newline at end of file diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml new file mode 100644 index 0000000..1bfd766 --- /dev/null +++ b/.github/workflows/gradle-docker-publish.yml @@ -0,0 +1,56 @@ +name: Docker Publish + +on: + workflow_call: + inputs: + docker-organization: + required: true + type: string + + image-name: + required: true + type: string + + version: + required: true + type: string + + secrets: + dockerhub-username: + required: true + + dockerhub-token: + required: true + +jobs: + + publish: + + runs-on: ubuntu-latest + + timeout-minutes: 15 + + permissions: + contents: read + + steps: + + - name: Download Docker image + uses: actions/download-artifact@v4 + with: + name: docker-image + + - name: Load Docker image + run: docker load -i docker-image.tar + + - name: Login to Docker Hub + run: | + echo "${{ secrets.dockerhub-token }}" \ + | docker login \ + --username "${{ secrets.dockerhub-username }}" \ + --password-stdin + + - name: Push Docker image + run: | + docker push \ + "${{ inputs.docker-organization }}/${{ inputs.image-name }}:${{ inputs.version }}" \ No newline at end of file diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml new file mode 100644 index 0000000..030b14a --- /dev/null +++ b/.github/workflows/gradle-get-version-number.yml @@ -0,0 +1,40 @@ +name: Get Gradle Version + +description: Retrieves the Gradle project version. + +inputs: + working-directory: + description: Directory containing the Gradle project. + required: false + default: service + +outputs: + version: + description: Gradle project version. + value: ${{ steps.version.outputs.version }} + +runs: + using: composite + steps: + + - name: Read project version + id: version + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + set -euo pipefail + + VERSION=$( + ./gradlew properties \ + --quiet \ + | awk -F': ' '/^version:/ {print $2}' + ) + + if [[ -z "$VERSION" ]]; then + echo "::error::Unable to determine Gradle version." + exit 1 + fi + + echo "Detected Gradle version: $VERSION" + + echo "version=$VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/gradle-module-descriptor-publish.yml b/.github/workflows/gradle-module-descriptor-publish.yml new file mode 100644 index 0000000..a3c4772 --- /dev/null +++ b/.github/workflows/gradle-module-descriptor-publish.yml @@ -0,0 +1,54 @@ +name: Publish ModuleDescriptor + +on: + workflow_call: + inputs: + module-descriptor-registry: + description: URL of the ModuleDescriptor registry. + required: true + type: string + + secrets: + registry-username: + required: true + + registry-password: + required: true + +jobs: + publish: + + name: Publish ModuleDescriptor + + runs-on: ubuntu-latest + + timeout-minutes: 10 + + permissions: + contents: read + + steps: + + # Download ModuleDescriptor produced by gradle-build.yml + - name: Download ModuleDescriptor + uses: actions/download-artifact@v4 + with: + name: ModuleDescriptor.json + + # Publish ModuleDescriptor + - name: Publish ModuleDescriptor + uses: fjogeleit/http-request-action@v2 + with: + url: ${{ inputs.module-descriptor-registry }}/_/proxy/modules + method: POST + contentType: application/json; charset=utf-8 + customHeaders: > + { + "Accept": "application/json; charset=utf-8" + } + timeout: 10000 + retry: 10 + retryWait: 21000 + file: ModuleDescriptor.json + username: ${{ secrets.registry-username }} + password: ${{ secrets.registry-password }} \ No newline at end of file diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..58dd98d --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,158 @@ +name: Backend Module CI + +on: + workflow_call: + inputs: + image-name: + description: Docker image name. + required: true + type: string + + module-descriptor-registry: + description: ModuleDescriptor registry URL. + required: true + type: string + + gradle-directory: + description: Directory containing the Gradle project. + required: false + type: string + default: service + + java-version: + description: Java version. + required: false + type: string + default: "17" + + build-command: + description: Gradle build command. + required: false + type: string + default: clean build + + secrets: + dockerhub-username: + required: true + + dockerhub-token: + required: true + + registry-username: + required: true + + registry-password: + required: true + +jobs: + + # Determine build metadata + metadata: + + name: Build Metadata + + runs-on: ubuntu-latest + + outputs: + version: ${{ steps.metadata.outputs.version }} + docker-organization: ${{ steps.metadata.outputs.docker-organization }} + is-release: ${{ steps.metadata.outputs.is-release }} + + steps: + + - name: Checkout + uses: actions/checkout@v4 + + - name: Get Gradle Version + id: gradle-version + uses: ./.github/workflows/gradle-get-version-number + with: + working-directory: ${{ inputs.gradle-directory }} + + - name: Generate Build Metadata + id: metadata + uses: ./.github/workflows/gradle-build-metadata + with: + gradle-version: ${{ steps.gradle-version.outputs.version }} + + # Build application + gradle-build: + + needs: metadata + + uses: ./.github/workflows/gradle-build.yml + + with: + gradle-directory: ${{ inputs.gradle-directory }} + java-version: ${{ inputs.java-version }} + build-command: ${{ inputs.build-command }} + + + # Submit dependency graph + dependency-submission: + + needs: metadata + + uses: ./.github/workflows/dependency-submission.yml + + with: + gradle-directory: ${{ inputs.gradle-directory }} + java-version: ${{ inputs.java-version }} + + + # Build Docker image + docker-build: + + needs: + - metadata + - gradle-build + + uses: ./.github/workflows/docker-build.yml + + with: + image-name: ${{ inputs.image-name }} + docker-organization: ${{ needs.metadata.outputs.docker-organization }} + version: ${{ needs.metadata.outputs.version }} + + + # Push Docker image + docker-publish: + + needs: + - metadata + - docker-build + + if: | + github.ref == 'refs/heads/master' || + startsWith(github.ref, 'refs/tags/v') + + uses: ./.github/workflows/docker-publish.yml + + with: + docker-organization: ${{ needs.metadata.outputs.docker-organization }} + image-name: ${{ inputs.image-name }} + version: ${{ needs.metadata.outputs.version }} + + secrets: + dockerhub-username: ${{ secrets.dockerhub-username }} + dockerhub-token: ${{ secrets.dockerhub-token }} + + # Publish ModuleDescriptor + publish-module-descriptor: + + needs: + - gradle-build + - metadata + + if: | + github.ref == 'refs/heads/master' || + startsWith(github.ref, 'refs/tags/v') + + uses: ./.github/workflows/publish-module-descriptor.yml + + with: + module-descriptor-registry: ${{ inputs.module-descriptor-registry }} + + secrets: + registry-username: ${{ secrets.registry-username }} + registry-password: ${{ secrets.registry-password }} \ No newline at end of file From 2a2774213bfef16b423af7e9e161ee40daf6ebf3 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Sat, 1 Aug 2026 15:45:57 +0100 Subject: [PATCH 02/19] Modify to match maven style --- .github/workflows/gradle-build-metadata.yml | 107 ++++++++---- .github/workflows/gradle-build.yml | 2 +- .github/workflows/gradle-docker-build.yml | 59 ------- .github/workflows/gradle-docker-publish.yml | 170 +++++++++++++++++--- .github/workflows/gradle.yml | 143 ++++++---------- 5 files changed, 281 insertions(+), 200 deletions(-) delete mode 100644 .github/workflows/gradle-docker-build.yml diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index 548b453..16e3ece 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -1,62 +1,113 @@ name: Build Metadata -description: Generates build metadata for snapshot and release builds. +description: Generate build metadata for Gradle backend modules. inputs: - gradle-version: - description: Gradle project version. + description: Resolved Gradle project version. required: true outputs: + artifact-version: + description: Version to use for artifacts and Docker images. + value: ${{ steps.metadata.outputs.artifact-version }} - version: - description: Build version. - value: ${{ steps.metadata.outputs.version }} + docker-registry: + description: Docker Hub organization. + value: ${{ steps.metadata.outputs.docker-registry }} is-release: - description: Whether the build is a release. + description: Whether this is a release build. value: ${{ steps.metadata.outputs.is-release }} - docker-organization: - description: Docker organization. - value: ${{ steps.metadata.outputs.docker-organization }} + is-main-branch: + description: Whether this build is running on the master branch. + value: ${{ steps.metadata.outputs.is-main-branch }} + + do-docker-push: + description: Whether Docker images should be pushed. + value: ${{ steps.metadata.outputs.do-docker-push }} runs: using: composite steps: - - id: metadata + - name: Generate build metadata + id: metadata shell: bash env: GRADLE_VERSION: ${{ inputs.gradle-version }} - + GITHUB_REF: ${{ github.ref }} + GITHUB_RUN_NUMBER: ${{ github.run_number }} run: | - set -euo pipefail - REF="${GITHUB_REF}" + set -euo pipefail RUN_NUMBER="${GITHUB_RUN_NUMBER}" - if [[ "${REF}" == refs/tags/* ]]; then + # + # Determine build type + # + if [[ "${GITHUB_REF}" =~ ^refs/tags/v[0-9] ]]; then + + echo "Release build detected." + + ARTIFACT_VERSION="${GRADLE_VERSION}" + IS_RELEASE=true + DOCKER_REGISTRY="folioorg" - VERSION="${GRADLE_VERSION}" - IS_RELEASE=true - DOCKER_ORG="folioorg" elif [[ "${GRADLE_VERSION}" == *"-SNAPSHOT" ]]; then - - VERSION="${GRADLE_VERSION}.${RUN_NUMBER}" - IS_RELEASE=false - DOCKER_ORG="folioci" + + echo "Snapshot build detected." + + ARTIFACT_VERSION="${GRADLE_VERSION}.${RUN_NUMBER}" + IS_RELEASE=false + DOCKER_REGISTRY="folioci" + else - VERSION="${GRADLE_VERSION}" - IS_RELEASE=false - DOCKER_ORG="folioci" + + echo "Non-tagged release version detected." + + # + # Safety net: + # Never publish an untagged release image to the official + # Docker organization. + # + ARTIFACT_VERSION="${GRADLE_VERSION}" + IS_RELEASE=false + DOCKER_REGISTRY="folioci" + fi - echo "version=$VERSION" >> "$GITHUB_OUTPUT" + # + # Determine whether this is the master branch. + # + if [[ "${GITHUB_REF}" == "refs/heads/master" ]]; then + IS_MAIN_BRANCH=true + else + IS_MAIN_BRANCH=false + fi - echo "is-release=$IS_RELEASE" >> "$GITHUB_OUTPUT" + # + # Docker images are only published from: + # - master + # - version tags + # + if [[ "${IS_MAIN_BRANCH}" == "true" || "${IS_RELEASE}" == "true" ]]; then + DO_DOCKER_PUSH=true + else + DO_DOCKER_PUSH=false + fi - echo "docker-organization=$DOCKER_ORG" >> "$GITHUB_OUTPUT" \ No newline at end of file + echo "artifact-version=${ARTIFACT_VERSION}" >> "${GITHUB_OUTPUT}" + echo "docker-registry=${DOCKER_REGISTRY}" >> "${GITHUB_OUTPUT}" + echo "is-release=${IS_RELEASE}" >> "${GITHUB_OUTPUT}" + echo "is-main-branch=${IS_MAIN_BRANCH}" >> "${GITHUB_OUTPUT}" + echo "do-docker-push=${DO_DOCKER_PUSH}" >> "${GITHUB_OUTPUT}" + + echo "Artifact Version : ${ARTIFACT_VERSION}" + echo "Docker Registry : ${DOCKER_REGISTRY}" + echo "Release Build : ${IS_RELEASE}" + echo "Main Branch : ${IS_MAIN_BRANCH}" + echo "Docker Push : ${DO_DOCKER_PUSH}" \ No newline at end of file diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index 31bb125..c41f2cb 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -61,7 +61,7 @@ jobs: - name: Upload application JAR uses: actions/upload-artifact@v7 with: - name: gradle-jar + name: built-jars path: | ${{ inputs.gradle-directory }}/build/libs/*.jar diff --git a/.github/workflows/gradle-docker-build.yml b/.github/workflows/gradle-docker-build.yml deleted file mode 100644 index 0174201..0000000 --- a/.github/workflows/gradle-docker-build.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Docker Build - -on: - workflow_call: - inputs: - image-name: - required: true - type: string - - docker-organization: - required: true - type: string - - version: - required: true - type: string - -jobs: - - docker-build: - - runs-on: ubuntu-latest - - timeout-minutes: 20 - - permissions: - contents: read - - steps: - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Download application JAR - uses: actions/download-artifact@v4 - with: - name: gradle-jar - path: service/build/libs - - - name: Build Docker image - run: | - IMAGE=${{ inputs.docker-organization }}/${{ inputs.image-name }}:${{ inputs.version }} - - docker build \ - -t "$IMAGE" \ - . - - - name: Export Docker image - run: | - IMAGE=${{ inputs.docker-organization }}/${{ inputs.image-name }}:${{ inputs.version }} - - docker save "$IMAGE" \ - -o docker-image.tar - - - name: Upload Docker image - uses: actions/upload-artifact@v4 - with: - name: docker-image - path: docker-image.tar \ No newline at end of file diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index 1bfd766..23788c2 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -1,20 +1,40 @@ -name: Docker Publish +name: Gradle Docker Build and Publish on: workflow_call: inputs: - docker-organization: + artifact-id: + description: Docker image name. required: true type: string - image-name: + artifact-version: + description: Artifact version. required: true type: string - version: + docker-registry: + description: Docker registry/organization. required: true type: string + docker-health-command: + description: Docker health check command. + required: false + type: string + default: "" + + do-docker-push: + description: Whether to publish the Docker image. + required: true + type: boolean + + docker-label-documentation: + description: Documentation URL for OCI label. + required: false + type: string + default: "" + secrets: dockerhub-username: required: true @@ -23,34 +43,148 @@ on: required: true jobs: - - publish: + docker: + name: Docker Build${{ inputs.do-docker-push && ' and Publish' || '' }} runs-on: ubuntu-latest - timeout-minutes: 15 + timeout-minutes: 30 permissions: contents: read steps: + # Checkout + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 - - name: Download Docker image + # Download Gradle build artifacts + - name: Download built JARs uses: actions/download-artifact@v4 with: - name: docker-image + name: built-jars + path: . - - name: Load Docker image - run: docker load -i docker-image.tar + - name: Restore Gradle build directory + run: | + mkdir -p service/build/libs + mv *.jar service/build/libs/ + # Notify whether publishing Docker image + - name: Notify whether doing Docker push + run: | + if ${{ inputs.do-docker-push }}; then + echo "Will build and publish Docker image." | tee -a "$GITHUB_STEP_SUMMARY" + else + echo "Will build Docker image only (publish=false)." | tee -a "$GITHUB_STEP_SUMMARY" + fi + + # Login to Docker Hub - name: Login to Docker Hub + if: inputs.do-docker-push + uses: docker/login-action@v4 + with: + username: ${{ secrets.dockerhub-username }} + password: ${{ secrets.dockerhub-token }} + + # Extract Docker metadata + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.docker-registry }}/${{ inputs.artifact-id }} + + labels: | + org.opencontainers.image.title=FOLIO ${{ inputs.artifact-id }} + org.opencontainers.image.documentation=${{ inputs.docker-label-documentation }} + org.opencontainers.image.vendor=The Open Library Foundation + org.opencontainers.image.licenses=Apache-2.0 + org.opencontainers.image.version=${{ inputs.artifact-version }} + + tags: | + type=raw,value=latest + type=raw,value=${{ inputs.artifact-version }} + + # Prepare Docker test image + - name: Prepare Docker test tag + id: prepare-docker-test-tag run: | - echo "${{ secrets.dockerhub-token }}" \ - | docker login \ - --username "${{ secrets.dockerhub-username }}" \ - --password-stdin + echo "docker-test-tag=folioci/${{ inputs.artifact-id }}:test" >> "$GITHUB_OUTPUT" - - name: Push Docker image + if ${{ inputs.docker-health-command != '' }}; then + echo "docker-health-command='${{ inputs.docker-health-command }}'" | tee -a $GITHUB_STEP_SUMMARY + else + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + { + echo "> Not doing docker health check. The inputs.docker-health-command is not declared." + echo "> The docker image might not be reliable." + echo "> Refer to [documentation](https://github.com/folio-org/.github/blob/master/README-maven.md#configuration-docker-health-command)." + } | tee -a $GITHUB_STEP_SUMMARY + fi + + # Build and validate Docker image + - name: Build and test Docker image + if: inputs.docker-health-command != '' run: | - docker push \ - "${{ inputs.docker-organization }}/${{ inputs.image-name }}:${{ inputs.version }}" \ No newline at end of file + echo "Building test image..." + docker build \ + --pull=true \ + --no-cache=true \ + -t "${{ steps.prepare-docker-test-tag.outputs.docker-test-tag }}" . + + echo "Starting test container..." + + docker run \ + --detach \ + --health-timeout=2s \ + --health-retries=2 \ + --cidfile docker_test.cid \ + --health-cmd='${{ inputs.docker-health-command }}' \ + "${{ steps.prepare-docker-test-tag.outputs.docker-test-tag }}" + + cid=$(cat docker_test.cid) + + echo "Waiting for container health..." + + max_startup_wait=60 + + for ((i=1;i<=max_startup_wait;i++)); do + + health=$(docker inspect "$cid" | jq -r '.[0].State.Health.Status') + + echo "Current status: ${health}" + + if [[ "${health}" == "starting" ]]; then + sleep 1 + else + break + fi + + done + + if [[ "${health}" != "healthy" ]]; then + + echo "Container health check failed." + + echo "========== Docker Logs ==========" + docker logs "$cid" || true + + echo "========== Docker Inspect ==========" + docker inspect "$cid" || true + + exit 1 + + fi + + echo "Container health check passed." + + # Build and optionally publish Docker image + - name: Build${{ inputs.do-docker-push && ' and Publish' || '' }} Docker image + uses: docker/build-push-action@v7 + with: + context: . + push: ${{ inputs.do-docker-push }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 58dd98d..b0d0f7d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,155 +1,110 @@ -name: Backend Module CI +name: Gradle Backend Module on: workflow_call: inputs: - image-name: - description: Docker image name. - required: true - type: string - - module-descriptor-registry: - description: ModuleDescriptor registry URL. + artifact-id: + description: Artifact/module name (e.g. mod-agreements). required: true type: string gradle-directory: description: Directory containing the Gradle project. required: false - type: string default: service + type: string + + module-descriptor-registry: + description: Okapi ModuleDescriptor registry URL. + required: true + default: https://folio-registry.dev.folio.org + type: string - java-version: - description: Java version. + docker-health-command: + description: Docker health check command. required: false + default: "" type: string - default: "17" - build-command: - description: Gradle build command. + docker-label-documentation: + description: OCI documentation label. required: false + default: "" type: string - default: clean build secrets: dockerhub-username: required: true - dockerhub-token: required: true - registry-username: required: true - registry-password: required: true +# Determine Gradle version jobs: + get-gradle-version: + name: Determine Gradle Version + uses: ./.github/workflows/get-gradle-version.yml + with: + gradle-directory: ${{ inputs.gradle-directory }} - # Determine build metadata +# Build metadata metadata: - name: Build Metadata + needs: + - get-gradle-version + uses: ./.github/workflows/build-metadata.yml + with: + gradle-version: ${{ needs.get-gradle-version.outputs.gradle-version }} - runs-on: ubuntu-latest - - outputs: - version: ${{ steps.metadata.outputs.version }} - docker-organization: ${{ steps.metadata.outputs.docker-organization }} - is-release: ${{ steps.metadata.outputs.is-release }} - - steps: - - - name: Checkout - uses: actions/checkout@v4 - - - name: Get Gradle Version - id: gradle-version - uses: ./.github/workflows/gradle-get-version-number - with: - working-directory: ${{ inputs.gradle-directory }} - - - name: Generate Build Metadata - id: metadata - uses: ./.github/workflows/gradle-build-metadata - with: - gradle-version: ${{ steps.gradle-version.outputs.version }} - - # Build application +# Build application gradle-build: - - needs: metadata - + name: Gradle Build + needs: + - metadata uses: ./.github/workflows/gradle-build.yml - with: gradle-directory: ${{ inputs.gradle-directory }} - java-version: ${{ inputs.java-version }} - build-command: ${{ inputs.build-command }} - + artifact-version: ${{ needs.metadata.outputs.artifact-version }} - # Submit dependency graph +# Dependency submission dependency-submission: - - needs: metadata - + name: Dependency Submission + needs: + - gradle-build uses: ./.github/workflows/dependency-submission.yml - with: gradle-directory: ${{ inputs.gradle-directory }} - java-version: ${{ inputs.java-version }} - - # Build Docker image +# Docker build docker-build: - + name: Docker Build needs: - metadata - gradle-build - uses: ./.github/workflows/docker-build.yml - with: - image-name: ${{ inputs.image-name }} - docker-organization: ${{ needs.metadata.outputs.docker-organization }} - version: ${{ needs.metadata.outputs.version }} - - - # Push Docker image - docker-publish: - - needs: - - metadata - - docker-build - - if: | - github.ref == 'refs/heads/master' || - startsWith(github.ref, 'refs/tags/v') - - uses: ./.github/workflows/docker-publish.yml - - with: - docker-organization: ${{ needs.metadata.outputs.docker-organization }} - image-name: ${{ inputs.image-name }} - version: ${{ needs.metadata.outputs.version }} + artifact-id: ${{ inputs.artifact-id }} + artifact-version: ${{ needs.metadata.outputs.artifact-version }} + docker-registry: ${{ needs.metadata.outputs.docker-registry }} + docker-health-command: ${{ inputs.docker-health-command }} + docker-label-documentation: ${{ inputs.docker-label-documentation }} + do-docker-push: ${{ fromJSON(needs.metadata.outputs.do-docker-push) }} secrets: dockerhub-username: ${{ secrets.dockerhub-username }} dockerhub-token: ${{ secrets.dockerhub-token }} - # Publish ModuleDescriptor +# Publish ModuleDescriptor publish-module-descriptor: - + name: Publish ModuleDescriptor + if: needs.metadata.outputs.do-docker-push == 'true' needs: - - gradle-build - metadata - - if: | - github.ref == 'refs/heads/master' || - startsWith(github.ref, 'refs/tags/v') - + - docker-build uses: ./.github/workflows/publish-module-descriptor.yml - with: module-descriptor-registry: ${{ inputs.module-descriptor-registry }} From e068fd48faa51fe20828c225e1df6e5ca27b6025 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Sun, 2 Aug 2026 00:37:19 +0100 Subject: [PATCH 03/19] implement actionlint recommendations --- .github/workflows/gradle-build-metadata.yml | 217 +++++++++--------- .github/workflows/gradle-docker-publish.yml | 6 +- .../workflows/gradle-get-version-number.yml | 88 ++++--- .github/workflows/gradle.yml | 13 +- 4 files changed, 167 insertions(+), 157 deletions(-) diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index 16e3ece..3e95894 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -1,113 +1,108 @@ name: Build Metadata -description: Generate build metadata for Gradle backend modules. - -inputs: - gradle-version: - description: Resolved Gradle project version. - required: true - -outputs: - artifact-version: - description: Version to use for artifacts and Docker images. - value: ${{ steps.metadata.outputs.artifact-version }} - - docker-registry: - description: Docker Hub organization. - value: ${{ steps.metadata.outputs.docker-registry }} - - is-release: - description: Whether this is a release build. - value: ${{ steps.metadata.outputs.is-release }} - - is-main-branch: - description: Whether this build is running on the master branch. - value: ${{ steps.metadata.outputs.is-main-branch }} - - do-docker-push: - description: Whether Docker images should be pushed. - value: ${{ steps.metadata.outputs.do-docker-push }} - -runs: - using: composite - - steps: - - - name: Generate build metadata - id: metadata - shell: bash - env: - GRADLE_VERSION: ${{ inputs.gradle-version }} - GITHUB_REF: ${{ github.ref }} - GITHUB_RUN_NUMBER: ${{ github.run_number }} - run: | - - set -euo pipefail - - RUN_NUMBER="${GITHUB_RUN_NUMBER}" - - # - # Determine build type - # - if [[ "${GITHUB_REF}" =~ ^refs/tags/v[0-9] ]]; then - - echo "Release build detected." - - ARTIFACT_VERSION="${GRADLE_VERSION}" - IS_RELEASE=true - DOCKER_REGISTRY="folioorg" - - elif [[ "${GRADLE_VERSION}" == *"-SNAPSHOT" ]]; then - - echo "Snapshot build detected." - - ARTIFACT_VERSION="${GRADLE_VERSION}.${RUN_NUMBER}" - IS_RELEASE=false - DOCKER_REGISTRY="folioci" - - else - - echo "Non-tagged release version detected." - - # - # Safety net: - # Never publish an untagged release image to the official - # Docker organization. - # - ARTIFACT_VERSION="${GRADLE_VERSION}" - IS_RELEASE=false - DOCKER_REGISTRY="folioci" - - fi - - # - # Determine whether this is the master branch. - # - if [[ "${GITHUB_REF}" == "refs/heads/master" ]]; then - IS_MAIN_BRANCH=true - else - IS_MAIN_BRANCH=false - fi - - # - # Docker images are only published from: - # - master - # - version tags - # - if [[ "${IS_MAIN_BRANCH}" == "true" || "${IS_RELEASE}" == "true" ]]; then - DO_DOCKER_PUSH=true - else - DO_DOCKER_PUSH=false - fi - - echo "artifact-version=${ARTIFACT_VERSION}" >> "${GITHUB_OUTPUT}" - echo "docker-registry=${DOCKER_REGISTRY}" >> "${GITHUB_OUTPUT}" - echo "is-release=${IS_RELEASE}" >> "${GITHUB_OUTPUT}" - echo "is-main-branch=${IS_MAIN_BRANCH}" >> "${GITHUB_OUTPUT}" - echo "do-docker-push=${DO_DOCKER_PUSH}" >> "${GITHUB_OUTPUT}" - - echo "Artifact Version : ${ARTIFACT_VERSION}" - echo "Docker Registry : ${DOCKER_REGISTRY}" - echo "Release Build : ${IS_RELEASE}" - echo "Main Branch : ${IS_MAIN_BRANCH}" - echo "Docker Push : ${DO_DOCKER_PUSH}" \ No newline at end of file +on: + workflow_call: + inputs: + gradle-version: + description: Version returned from get-gradle-version workflow. + required: true + type: string + + outputs: + artifact-version: + description: Final artifact version. + value: ${{ jobs.metadata.outputs.artifact-version }} + + docker-registry: + description: Docker Hub organization. + value: ${{ jobs.metadata.outputs.docker-registry }} + + is-release: + description: Whether this is a release build. + value: ${{ jobs.metadata.outputs.is-release }} + + is-main-branch: + description: Whether this build is running on the default branch. + value: ${{ jobs.metadata.outputs.is-main-branch }} + + do-docker-push: + description: Whether Docker images should be pushed. + value: ${{ jobs.metadata.outputs.do-docker-push }} + +jobs: + metadata: + name: Generate Build Metadata + + runs-on: ubuntu-latest + + timeout-minutes: 10 + + outputs: + artifact-version: ${{ steps.metadata.outputs.artifact-version }} + docker-registry: ${{ steps.metadata.outputs.docker-registry }} + is-release: ${{ steps.metadata.outputs.is-release }} + is-main-branch: ${{ steps.metadata.outputs.is-main-branch }} + do-docker-push: ${{ steps.metadata.outputs.do-docker-push }} + + steps: + - name: Generate metadata + id: metadata + shell: bash + env: + GRADLE_VERSION: ${{ inputs.gradle-version }} + RUN_NUMBER: ${{ github.run_number }} + REF_TYPE: ${{ github.ref_type }} + REF_NAME: ${{ github.ref_name }} + EVENT_NAME: ${{ github.event_name }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: | + echo "Gradle version: ${GRADLE_VERSION}" + echo "Git ref: ${REF_NAME} (${REF_TYPE})" + + if [[ "${REF_TYPE}" == "tag" ]]; then + ARTIFACT_VERSION="${GRADLE_VERSION}" + IS_RELEASE=true + DOCKER_REGISTRY="folioorg" + elif [[ "${GRADLE_VERSION}" == *"-SNAPSHOT" ]]; then + ARTIFACT_VERSION="${GRADLE_VERSION}.${RUN_NUMBER}" + IS_RELEASE=false + DOCKER_REGISTRY="folioci" + else + ARTIFACT_VERSION="${GRADLE_VERSION}" + IS_RELEASE=false + DOCKER_REGISTRY="folioci" + fi + + if [[ "${REF_NAME}" == "${DEFAULT_BRANCH}" ]]; then + IS_MAIN_BRANCH=true + else + IS_MAIN_BRANCH=false + fi + + if [[ "${EVENT_NAME}" == "pull_request" ]]; then + DO_DOCKER_PUSH=false + elif [[ "${IS_RELEASE}" == "true" || "${IS_MAIN_BRANCH}" == "true" ]]; then + DO_DOCKER_PUSH=true + else + DO_DOCKER_PUSH=false + fi + + { + echo "artifact-version=${ARTIFACT_VERSION}" + echo "docker-registry=${DOCKER_REGISTRY}" + echo "is-release=${IS_RELEASE}" + echo "is-main-branch=${IS_MAIN_BRANCH}" + echo "do-docker-push=${DO_DOCKER_PUSH}" + } >> "$GITHUB_OUTPUT" + + { + echo "### Build Metadata" + echo "" + echo "| Property | Value |" + echo "|----------|-------|" + echo "| Artifact Version | ${ARTIFACT_VERSION} |" + echo "| Docker Registry | ${DOCKER_REGISTRY} |" + echo "| Release Build | ${IS_RELEASE} |" + echo "| Main Branch | ${IS_MAIN_BRANCH} |" + echo "| Docker Push | ${DO_DOCKER_PUSH} |" + } >> "$GITHUB_STEP_SUMMARY" \ No newline at end of file diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index 23788c2..f65d8be 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -22,7 +22,7 @@ on: description: Docker health check command. required: false type: string - default: "" + default: '' do-docker-push: description: Whether to publish the Docker image. @@ -33,7 +33,7 @@ on: description: Documentation URL for OCI label. required: false type: string - default: "" + default: '' secrets: dockerhub-username: @@ -70,7 +70,7 @@ jobs: - name: Restore Gradle build directory run: | mkdir -p service/build/libs - mv *.jar service/build/libs/ + mv -- *.jar service/build/libs/ # Notify whether publishing Docker image - name: Notify whether doing Docker push diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml index 030b14a..36ee5a9 100644 --- a/.github/workflows/gradle-get-version-number.yml +++ b/.github/workflows/gradle-get-version-number.yml @@ -1,40 +1,56 @@ name: Get Gradle Version -description: Retrieves the Gradle project version. +on: + workflow_call: + inputs: + gradle-directory: + description: Directory containing the Gradle project. + required: false + type: string + default: service + + outputs: + gradle-version: + description: Version reported by Gradle. + value: ${{ jobs.version.outputs.gradle-version }} + +jobs: + version: + name: Determine Gradle Version -inputs: - working-directory: - description: Directory containing the Gradle project. - required: false - default: service + runs-on: ubuntu-latest -outputs: - version: - description: Gradle project version. - value: ${{ steps.version.outputs.version }} - -runs: - using: composite - steps: - - - name: Read project version - id: version - shell: bash - working-directory: ${{ inputs.working-directory }} - run: | - set -euo pipefail - - VERSION=$( - ./gradlew properties \ - --quiet \ - | awk -F': ' '/^version:/ {print $2}' - ) - - if [[ -z "$VERSION" ]]; then - echo "::error::Unable to determine Gradle version." - exit 1 - fi - - echo "Detected Gradle version: $VERSION" - - echo "version=$VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file + timeout-minutes: 10 + + outputs: + gradle-version: ${{ steps.version.outputs.gradle-version }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 1 + + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up Temurin JDK 17 + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: '17' + + - name: Read Gradle version + id: version + working-directory: ${{ inputs.gradle-directory }} + shell: bash + run: | + VERSION="$(./gradlew properties --quiet | awk -F': ' '/^version:/ {print $2}')" + + if [[ -z "$VERSION" ]]; then + echo "Unable to determine Gradle project version." + exit 1 + fi + + echo "Detected Gradle version: $VERSION" + echo "gradle-version=$VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index b0d0f7d..7aec490 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -16,7 +16,7 @@ on: module-descriptor-registry: description: Okapi ModuleDescriptor registry URL. - required: true + required: false default: https://folio-registry.dev.folio.org type: string @@ -46,7 +46,7 @@ on: jobs: get-gradle-version: name: Determine Gradle Version - uses: ./.github/workflows/get-gradle-version.yml + uses: ./.github/workflows/gradle-get-version-number.yml with: gradle-directory: ${{ inputs.gradle-directory }} @@ -55,7 +55,7 @@ jobs: name: Build Metadata needs: - get-gradle-version - uses: ./.github/workflows/build-metadata.yml + uses: ./.github/workflows/gradle-build-metadata.yml with: gradle-version: ${{ needs.get-gradle-version.outputs.gradle-version }} @@ -67,14 +67,13 @@ jobs: uses: ./.github/workflows/gradle-build.yml with: gradle-directory: ${{ inputs.gradle-directory }} - artifact-version: ${{ needs.metadata.outputs.artifact-version }} # Dependency submission dependency-submission: name: Dependency Submission needs: - gradle-build - uses: ./.github/workflows/dependency-submission.yml + uses: ./.github/workflows/gradle-dependency-submission.yml with: gradle-directory: ${{ inputs.gradle-directory }} @@ -84,7 +83,7 @@ jobs: needs: - metadata - gradle-build - uses: ./.github/workflows/docker-build.yml + uses: ./.github/workflows/gradle-docker-publish.yml with: artifact-id: ${{ inputs.artifact-id }} artifact-version: ${{ needs.metadata.outputs.artifact-version }} @@ -104,7 +103,7 @@ jobs: needs: - metadata - docker-build - uses: ./.github/workflows/publish-module-descriptor.yml + uses: ./.github/workflows/gradle-module-descriptor-publish.yml with: module-descriptor-registry: ${{ inputs.module-descriptor-registry }} From 607b62655e0ad4e1d9ae3fbb7d37c355dde19e97 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Mon, 3 Aug 2026 11:54:24 +0100 Subject: [PATCH 04/19] Update action versions --- .github/workflows/gradle-build.yml | 9 ++++++--- .github/workflows/gradle-dependency-submission.yml | 11 +++++++---- .github/workflows/gradle-docker-publish.yml | 6 +++--- .github/workflows/gradle-get-version-number.yml | 4 ++-- .../workflows/gradle-module-descriptor-publish.yml | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index c41f2cb..e3e1324 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -37,10 +37,13 @@ jobs: steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + fetch-depth: 1 + submodules: recursive - name: Validate Gradle Wrapper - uses: gradle/actions/wrapper-validation@v4 + uses: gradle/actions/wrapper-validation@v6 - name: Setup Java uses: actions/setup-java@v5 @@ -49,7 +52,7 @@ jobs: java-version: ${{ inputs.java-version }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 - name: Build Project run: | diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index e96c978..3bfb213 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -34,10 +34,13 @@ jobs: steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + fetch-depth: 1 + submodules: recursive - name: Validate Gradle Wrapper - uses: gradle/actions/wrapper-validation@v4 + uses: gradle/actions/wrapper-validation@v6 - name: Setup Java uses: actions/setup-java@v5 @@ -46,7 +49,7 @@ jobs: java-version: ${{ inputs.java-version }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 - name: Submit Dependency Graph - uses: gradle/actions/dependency-submission@v4 \ No newline at end of file + uses: gradle/actions/dependency-submission@v6 \ No newline at end of file diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index f65d8be..e00da91 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -56,13 +56,13 @@ jobs: steps: # Checkout - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 1 # Download Gradle build artifacts - name: Download built JARs - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: built-jars path: . @@ -92,7 +92,7 @@ jobs: # Extract Docker metadata - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: ${{ inputs.docker-registry }}/${{ inputs.artifact-id }} diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml index 36ee5a9..430a705 100644 --- a/.github/workflows/gradle-get-version-number.yml +++ b/.github/workflows/gradle-get-version-number.yml @@ -27,12 +27,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 1 - name: Validate Gradle Wrapper - uses: gradle/actions/wrapper-validation@v4 + uses: gradle/actions/wrapper-validation@v6 - name: Set up Temurin JDK 17 uses: actions/setup-java@v5 diff --git a/.github/workflows/gradle-module-descriptor-publish.yml b/.github/workflows/gradle-module-descriptor-publish.yml index a3c4772..d3a0c59 100644 --- a/.github/workflows/gradle-module-descriptor-publish.yml +++ b/.github/workflows/gradle-module-descriptor-publish.yml @@ -31,7 +31,7 @@ jobs: # Download ModuleDescriptor produced by gradle-build.yml - name: Download ModuleDescriptor - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: ModuleDescriptor.json From e419e075007e49dbc838279155fe004f86525667 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Mon, 3 Aug 2026 12:35:17 +0100 Subject: [PATCH 05/19] do not publish for now --- .github/workflows/gradle-docker-publish.yml | 2 +- .../gradle-module-descriptor-publish.yml | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index e00da91..2fd7f04 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -185,6 +185,6 @@ jobs: uses: docker/build-push-action@v7 with: context: . - push: ${{ inputs.do-docker-push }} + push: false tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/gradle-module-descriptor-publish.yml b/.github/workflows/gradle-module-descriptor-publish.yml index d3a0c59..708b29f 100644 --- a/.github/workflows/gradle-module-descriptor-publish.yml +++ b/.github/workflows/gradle-module-descriptor-publish.yml @@ -36,19 +36,19 @@ jobs: name: ModuleDescriptor.json # Publish ModuleDescriptor - - name: Publish ModuleDescriptor - uses: fjogeleit/http-request-action@v2 - with: - url: ${{ inputs.module-descriptor-registry }}/_/proxy/modules - method: POST - contentType: application/json; charset=utf-8 - customHeaders: > - { - "Accept": "application/json; charset=utf-8" - } - timeout: 10000 - retry: 10 - retryWait: 21000 - file: ModuleDescriptor.json - username: ${{ secrets.registry-username }} - password: ${{ secrets.registry-password }} \ No newline at end of file + # - name: Publish ModuleDescriptor + # uses: fjogeleit/http-request-action@v2 + # with: + # url: ${{ inputs.module-descriptor-registry }}/_/proxy/modules + # method: POST + # contentType: application/json; charset=utf-8 + # customHeaders: > + # { + # "Accept": "application/json; charset=utf-8" + # } + # timeout: 10000 + # retry: 10 + # retryWait: 21000 + # file: ModuleDescriptor.json + # username: ${{ secrets.registry-username }} + # password: ${{ secrets.registry-password }} \ No newline at end of file From f3ec5d69fbc7e34c45a99785f06c185a69e33b64 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Mon, 3 Aug 2026 12:43:36 +0100 Subject: [PATCH 06/19] change build command --- .github/workflows/gradle-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index e3e1324..e376363 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -19,7 +19,7 @@ on: description: Gradle command. required: false type: string - default: "clean build" + default: "assemble" jobs: @@ -58,7 +58,7 @@ jobs: run: | ./gradlew \ ${{ inputs.build-command }} \ - --stacktrace \ + --console plain \ --no-daemon - name: Upload application JAR From d20f3ee2fa31445b49fe0f9cf1ffd13ad2c8f490 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Mon, 3 Aug 2026 14:14:11 +0100 Subject: [PATCH 07/19] correct secret names --- .github/workflows/gradle.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 7aec490..efcf272 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -33,13 +33,13 @@ on: type: string secrets: - dockerhub-username: + DOCKERHUB_USERNAME: required: true - dockerhub-token: + DOCKERHUB_TOKEN: required: true - registry-username: + FOLIO_REGISTRY_USERNAME: required: true - registry-password: + FOLIO_REGISTRY_PASSWORD: required: true # Determine Gradle version @@ -93,8 +93,8 @@ jobs: do-docker-push: ${{ fromJSON(needs.metadata.outputs.do-docker-push) }} secrets: - dockerhub-username: ${{ secrets.dockerhub-username }} - dockerhub-token: ${{ secrets.dockerhub-token }} + dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN}} # Publish ModuleDescriptor publish-module-descriptor: @@ -108,5 +108,5 @@ jobs: module-descriptor-registry: ${{ inputs.module-descriptor-registry }} secrets: - registry-username: ${{ secrets.registry-username }} - registry-password: ${{ secrets.registry-password }} \ No newline at end of file + registry-username: ${{ secrets.FOLIO_REGISTRY_USERNAME }} + registry-password: ${{ secrets.FOLIO_REGISTRY_PASSWORD }} \ No newline at end of file From 83b65915c15c69b0baeecf1c9209d9d8e061d4ca Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Mon, 3 Aug 2026 18:01:24 +0100 Subject: [PATCH 08/19] dependency submission path --- .github/workflows/gradle-dependency-submission.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index 3bfb213..c5f488c 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -52,4 +52,6 @@ jobs: uses: gradle/actions/setup-gradle@v6 - name: Submit Dependency Graph - uses: gradle/actions/dependency-submission@v6 \ No newline at end of file + uses: gradle/actions/dependency-submission@v6 + with: + build-root-directory: ${{ inputs.gradle-directory }} \ No newline at end of file From b1f86ad5060603b6bd9108a523303c2df39a1faa Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Tue, 4 Aug 2026 15:52:04 +0100 Subject: [PATCH 09/19] recalculate build number --- .github/workflows/gradle-build-metadata.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index 3e95894..b288044 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -56,6 +56,8 @@ jobs: EVENT_NAME: ${{ github.event_name }} DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} run: | + BASE_NUMBER=2000 + BUILD_NUMBER=$(( BASE_NUMBER + RUN_NUMBER )) echo "Gradle version: ${GRADLE_VERSION}" echo "Git ref: ${REF_NAME} (${REF_TYPE})" @@ -64,7 +66,7 @@ jobs: IS_RELEASE=true DOCKER_REGISTRY="folioorg" elif [[ "${GRADLE_VERSION}" == *"-SNAPSHOT" ]]; then - ARTIFACT_VERSION="${GRADLE_VERSION}.${RUN_NUMBER}" + ARTIFACT_VERSION="${GRADLE_VERSION}.${BUILD_NUMBER}" IS_RELEASE=false DOCKER_REGISTRY="folioci" else From 58ceab8a3cc3f38666f17a9bb21e2cda30801e02 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Tue, 4 Aug 2026 16:26:46 +0100 Subject: [PATCH 10/19] read app version directly from gradle.properties instead of calling ./gradlew --- .github/workflows/gradle-get-version-number.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml index 430a705..bc87f61 100644 --- a/.github/workflows/gradle-get-version-number.yml +++ b/.github/workflows/gradle-get-version-number.yml @@ -45,7 +45,7 @@ jobs: working-directory: ${{ inputs.gradle-directory }} shell: bash run: | - VERSION="$(./gradlew properties --quiet | awk -F': ' '/^version:/ {print $2}')" + VERSION="$(awk -F= '/^appVersion=/ {print $2}' gradle.properties)" if [[ -z "$VERSION" ]]; then echo "Unable to determine Gradle project version." From 9cecfbdb76ea9f3909e32a585e68b467fb9e89ae Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Tue, 4 Aug 2026 16:47:31 +0100 Subject: [PATCH 11/19] uncomment publish --- .github/workflows/gradle-docker-publish.yml | 2 +- .../gradle-module-descriptor-publish.yml | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index 2fd7f04..19bbff1 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -185,6 +185,6 @@ jobs: uses: docker/build-push-action@v7 with: context: . - push: false + push: ${{ inputs.do-docker-push }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/gradle-module-descriptor-publish.yml b/.github/workflows/gradle-module-descriptor-publish.yml index 708b29f..d3a0c59 100644 --- a/.github/workflows/gradle-module-descriptor-publish.yml +++ b/.github/workflows/gradle-module-descriptor-publish.yml @@ -36,19 +36,19 @@ jobs: name: ModuleDescriptor.json # Publish ModuleDescriptor - # - name: Publish ModuleDescriptor - # uses: fjogeleit/http-request-action@v2 - # with: - # url: ${{ inputs.module-descriptor-registry }}/_/proxy/modules - # method: POST - # contentType: application/json; charset=utf-8 - # customHeaders: > - # { - # "Accept": "application/json; charset=utf-8" - # } - # timeout: 10000 - # retry: 10 - # retryWait: 21000 - # file: ModuleDescriptor.json - # username: ${{ secrets.registry-username }} - # password: ${{ secrets.registry-password }} \ No newline at end of file + - name: Publish ModuleDescriptor + uses: fjogeleit/http-request-action@v2 + with: + url: ${{ inputs.module-descriptor-registry }}/_/proxy/modules + method: POST + contentType: application/json; charset=utf-8 + customHeaders: > + { + "Accept": "application/json; charset=utf-8" + } + timeout: 10000 + retry: 10 + retryWait: 21000 + file: ModuleDescriptor.json + username: ${{ secrets.registry-username }} + password: ${{ secrets.registry-password }} \ No newline at end of file From 699dfc34882cc9a066b9a9646fa0fc0448f7cbfe Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Tue, 4 Aug 2026 23:28:03 +0100 Subject: [PATCH 12/19] confirm tag matches appversion --- .github/workflows/gradle-build-metadata.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index b288044..1266286 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -62,6 +62,11 @@ jobs: echo "Git ref: ${REF_NAME} (${REF_TYPE})" if [[ "${REF_TYPE}" == "tag" ]]; then + TAG_VERSION="${REF_NAME#v}" + if [[ "${TAG_VERSION}" != "${GRADLE_VERSION}" ]]; then + echo "ERROR: Git tag '${REF_NAME}' does not match project version '${GRADLE_VERSION} from gradle.properties." + exit 1 + fi ARTIFACT_VERSION="${GRADLE_VERSION}" IS_RELEASE=true DOCKER_REGISTRY="folioorg" @@ -83,7 +88,9 @@ jobs: if [[ "${EVENT_NAME}" == "pull_request" ]]; then DO_DOCKER_PUSH=false - elif [[ "${IS_RELEASE}" == "true" || "${IS_MAIN_BRANCH}" == "true" ]]; then + elif [[ "${IS_RELEASE}" == "true" ]]; then + DO_DOCKER_PUSH=true + elif [[ "${GRADLE_VERSION}" == *"-SNAPSHOT" && "${IS_MAIN_BRANCH}" == "true" ]]; then DO_DOCKER_PUSH=true else DO_DOCKER_PUSH=false @@ -107,4 +114,5 @@ jobs: echo "| Release Build | ${IS_RELEASE} |" echo "| Main Branch | ${IS_MAIN_BRANCH} |" echo "| Docker Push | ${DO_DOCKER_PUSH} |" + echo "| Git Ref | ${REF_NAME} (${REF_TYPE}) |" } >> "$GITHUB_STEP_SUMMARY" \ No newline at end of file From a47099736fd7f240bb131045d0febcf795027dee Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Tue, 4 Aug 2026 23:43:04 +0100 Subject: [PATCH 13/19] rm .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index a6c49b895e9622c0ae6d0fb42c668506640b3b96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKu}%U(5Pb`mK(ryo!pdA{EF@Z5n4AO~8w-8_0RMc zx4lud^XyXEX=lfmX{-T7v#1=-?YNH!9Xs)>bd~;A9y&t;v z){pjHCv`S#?lKpJWN&mZK*Ncy9zU`x(mA}n-q-JLbq-VegwZ6E`Kz3K@;>L|p@j%d zTsxVdP)Xa;Ieb2ik{rgq>FBfUPF#KNVhuxzdxcA!qf5OZcF@NeLiA{Ss{2zpZ5>li z3;CtZ602 z91Yp-F|tsfe<>J!i-E=1AX!M1aV0da%3d*)ai@9Tt_v*228}zEj!gU5$jaVOl#WjG zzFrO$7?f5R5C&WZ@@81#`hPV4{_i@;NEi?X{uKkttJbP~$+fjL^Ke{iebPE93$Kd} lY8Ps3Io2I6#T%qr$mVm0Ft8XKq!|+V5zsV9BMkg01K-`|nN9!z From d67990b53f82768bb6bc622c5363b1b279164745 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Wed, 5 Aug 2026 14:25:01 +0100 Subject: [PATCH 14/19] remove blank spaces --- .github/workflows/gradle-build-metadata.yml | 6 ----- .github/workflows/gradle-build.yml | 5 ---- .../gradle-dependency-submission.yml | 7 ------ .github/workflows/gradle-docker-publish.yml | 24 ------------------- .../workflows/gradle-get-version-number.yml | 7 +----- .../gradle-module-descriptor-publish.yml | 8 ------- .github/workflows/gradle.yml | 7 ------ 7 files changed, 1 insertion(+), 63 deletions(-) diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index 1266286..de7412e 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -12,19 +12,15 @@ on: artifact-version: description: Final artifact version. value: ${{ jobs.metadata.outputs.artifact-version }} - docker-registry: description: Docker Hub organization. value: ${{ jobs.metadata.outputs.docker-registry }} - is-release: description: Whether this is a release build. value: ${{ jobs.metadata.outputs.is-release }} - is-main-branch: description: Whether this build is running on the default branch. value: ${{ jobs.metadata.outputs.is-main-branch }} - do-docker-push: description: Whether Docker images should be pushed. value: ${{ jobs.metadata.outputs.do-docker-push }} @@ -32,9 +28,7 @@ on: jobs: metadata: name: Generate Build Metadata - runs-on: ubuntu-latest - timeout-minutes: 10 outputs: diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index e376363..acfe571 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -8,13 +8,11 @@ on: required: false type: string default: service - java-version: description: Java version. required: false type: string default: "17" - build-command: description: Gradle command. required: false @@ -22,14 +20,11 @@ on: default: "assemble" jobs: - build: runs-on: ubuntu-latest timeout-minutes: 30 - permissions: contents: read - defaults: run: shell: bash diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index c5f488c..9e2c3e3 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -8,7 +8,6 @@ on: required: false type: string default: service - java-version: description: Java version. required: false @@ -16,23 +15,17 @@ on: default: "17" jobs: - dependency-submission: - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: contents: write - defaults: run: shell: bash working-directory: ${{ inputs.gradle-directory }} steps: - - name: Checkout source uses: actions/checkout@v6 with: diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index 19bbff1..23635a9 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -7,49 +7,39 @@ on: description: Docker image name. required: true type: string - artifact-version: description: Artifact version. required: true type: string - docker-registry: description: Docker registry/organization. required: true type: string - docker-health-command: description: Docker health check command. required: false type: string default: '' - do-docker-push: description: Whether to publish the Docker image. required: true type: boolean - docker-label-documentation: description: Documentation URL for OCI label. required: false type: string default: '' - secrets: dockerhub-username: required: true - dockerhub-token: required: true jobs: docker: name: Docker Build${{ inputs.do-docker-push && ' and Publish' || '' }} - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: contents: read @@ -145,39 +135,25 @@ jobs: "${{ steps.prepare-docker-test-tag.outputs.docker-test-tag }}" cid=$(cat docker_test.cid) - echo "Waiting for container health..." - max_startup_wait=60 - for ((i=1;i<=max_startup_wait;i++)); do - health=$(docker inspect "$cid" | jq -r '.[0].State.Health.Status') - echo "Current status: ${health}" - if [[ "${health}" == "starting" ]]; then sleep 1 else break fi - done - if [[ "${health}" != "healthy" ]]; then - echo "Container health check failed." - echo "========== Docker Logs ==========" docker logs "$cid" || true - echo "========== Docker Inspect ==========" docker inspect "$cid" || true - exit 1 - fi - echo "Container health check passed." # Build and optionally publish Docker image diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml index bc87f61..e72e8fb 100644 --- a/.github/workflows/gradle-get-version-number.yml +++ b/.github/workflows/gradle-get-version-number.yml @@ -17,11 +17,8 @@ on: jobs: version: name: Determine Gradle Version - runs-on: ubuntu-latest - timeout-minutes: 10 - outputs: gradle-version: ${{ steps.version.outputs.gradle-version }} @@ -39,18 +36,16 @@ jobs: with: distribution: temurin java-version: '17' - + - name: Read Gradle version id: version working-directory: ${{ inputs.gradle-directory }} shell: bash run: | VERSION="$(awk -F= '/^appVersion=/ {print $2}' gradle.properties)" - if [[ -z "$VERSION" ]]; then echo "Unable to determine Gradle project version." exit 1 fi - echo "Detected Gradle version: $VERSION" echo "gradle-version=$VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/gradle-module-descriptor-publish.yml b/.github/workflows/gradle-module-descriptor-publish.yml index d3a0c59..691f780 100644 --- a/.github/workflows/gradle-module-descriptor-publish.yml +++ b/.github/workflows/gradle-module-descriptor-publish.yml @@ -7,28 +7,20 @@ on: description: URL of the ModuleDescriptor registry. required: true type: string - secrets: registry-username: required: true - registry-password: required: true jobs: publish: - name: Publish ModuleDescriptor - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: contents: read - steps: - # Download ModuleDescriptor produced by gradle-build.yml - name: Download ModuleDescriptor uses: actions/download-artifact@v8 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index efcf272..47dd63c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -7,31 +7,26 @@ on: description: Artifact/module name (e.g. mod-agreements). required: true type: string - gradle-directory: description: Directory containing the Gradle project. required: false default: service type: string - module-descriptor-registry: description: Okapi ModuleDescriptor registry URL. required: false default: https://folio-registry.dev.folio.org type: string - docker-health-command: description: Docker health check command. required: false default: "" type: string - docker-label-documentation: description: OCI documentation label. required: false default: "" type: string - secrets: DOCKERHUB_USERNAME: required: true @@ -91,7 +86,6 @@ jobs: docker-health-command: ${{ inputs.docker-health-command }} docker-label-documentation: ${{ inputs.docker-label-documentation }} do-docker-push: ${{ fromJSON(needs.metadata.outputs.do-docker-push) }} - secrets: dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }} dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN}} @@ -106,7 +100,6 @@ jobs: uses: ./.github/workflows/gradle-module-descriptor-publish.yml with: module-descriptor-registry: ${{ inputs.module-descriptor-registry }} - secrets: registry-username: ${{ secrets.FOLIO_REGISTRY_USERNAME }} registry-password: ${{ secrets.FOLIO_REGISTRY_PASSWORD }} \ No newline at end of file From d10dfaa0784f175159bbdce3320a5abbd6a5f5d1 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Wed, 5 Aug 2026 14:47:25 +0100 Subject: [PATCH 15/19] remove trailing whitespaces and add missing-final-newline --- .github/workflows/gradle-build-metadata.yml | 2 +- .github/workflows/gradle-build.yml | 2 +- .github/workflows/gradle-dependency-submission.yml | 2 +- .github/workflows/gradle-docker-publish.yml | 4 ++-- .github/workflows/gradle-get-version-number.yml | 4 ++-- .github/workflows/gradle-module-descriptor-publish.yml | 2 +- .github/workflows/gradle.yml | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index de7412e..446feaa 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -109,4 +109,4 @@ jobs: echo "| Main Branch | ${IS_MAIN_BRANCH} |" echo "| Docker Push | ${DO_DOCKER_PUSH} |" echo "| Git Ref | ${REF_NAME} (${REF_TYPE}) |" - } >> "$GITHUB_STEP_SUMMARY" \ No newline at end of file + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index acfe571..4f5eb8c 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -68,4 +68,4 @@ jobs: with: name: ModuleDescriptor.json path: | - ${{ inputs.gradle-directory }}/build/resources/main/okapi/ModuleDescriptor.json \ No newline at end of file + ${{ inputs.gradle-directory }}/build/resources/main/okapi/ModuleDescriptor.json diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index 9e2c3e3..094154d 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -47,4 +47,4 @@ jobs: - name: Submit Dependency Graph uses: gradle/actions/dependency-submission@v6 with: - build-root-directory: ${{ inputs.gradle-directory }} \ No newline at end of file + build-root-directory: ${{ inputs.gradle-directory }} diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index 23635a9..5938a36 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -161,6 +161,6 @@ jobs: uses: docker/build-push-action@v7 with: context: . - push: ${{ inputs.do-docker-push }} + push: ${{ inputs.do-docker-push }} tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml index e72e8fb..bcdae82 100644 --- a/.github/workflows/gradle-get-version-number.yml +++ b/.github/workflows/gradle-get-version-number.yml @@ -36,7 +36,7 @@ jobs: with: distribution: temurin java-version: '17' - + - name: Read Gradle version id: version working-directory: ${{ inputs.gradle-directory }} @@ -48,4 +48,4 @@ jobs: exit 1 fi echo "Detected Gradle version: $VERSION" - echo "gradle-version=$VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file + echo "gradle-version=$VERSION" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/gradle-module-descriptor-publish.yml b/.github/workflows/gradle-module-descriptor-publish.yml index 691f780..f46c4f6 100644 --- a/.github/workflows/gradle-module-descriptor-publish.yml +++ b/.github/workflows/gradle-module-descriptor-publish.yml @@ -43,4 +43,4 @@ jobs: retryWait: 21000 file: ModuleDescriptor.json username: ${{ secrets.registry-username }} - password: ${{ secrets.registry-password }} \ No newline at end of file + password: ${{ secrets.registry-password }} diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 47dd63c..504d94d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -102,4 +102,4 @@ jobs: module-descriptor-registry: ${{ inputs.module-descriptor-registry }} secrets: registry-username: ${{ secrets.FOLIO_REGISTRY_USERNAME }} - registry-password: ${{ secrets.FOLIO_REGISTRY_PASSWORD }} \ No newline at end of file + registry-password: ${{ secrets.FOLIO_REGISTRY_PASSWORD }} From 5bd63456708ab1607b44607bbe712b803d67ef0b Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Wed, 5 Aug 2026 14:54:32 +0100 Subject: [PATCH 16/19] double quote to prevent globbing and word splitting --- .github/workflows/gradle-docker-publish.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gradle-docker-publish.yml b/.github/workflows/gradle-docker-publish.yml index 5938a36..b2dad9a 100644 --- a/.github/workflows/gradle-docker-publish.yml +++ b/.github/workflows/gradle-docker-publish.yml @@ -104,14 +104,14 @@ jobs: echo "docker-test-tag=folioci/${{ inputs.artifact-id }}:test" >> "$GITHUB_OUTPUT" if ${{ inputs.docker-health-command != '' }}; then - echo "docker-health-command='${{ inputs.docker-health-command }}'" | tee -a $GITHUB_STEP_SUMMARY + echo "docker-health-command='${{ inputs.docker-health-command }}'" | tee -a "$GITHUB_STEP_SUMMARY" else - echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> [!WARNING]" >> "$GITHUB_STEP_SUMMARY" { echo "> Not doing docker health check. The inputs.docker-health-command is not declared." echo "> The docker image might not be reliable." echo "> Refer to [documentation](https://github.com/folio-org/.github/blob/master/README-maven.md#configuration-docker-health-command)." - } | tee -a $GITHUB_STEP_SUMMARY + } | tee -a "$GITHUB_STEP_SUMMARY" fi # Build and validate Docker image @@ -134,7 +134,7 @@ jobs: --health-cmd='${{ inputs.docker-health-command }}' \ "${{ steps.prepare-docker-test-tag.outputs.docker-test-tag }}" - cid=$(cat docker_test.cid) + cid="$(cat docker_test.cid)" echo "Waiting for container health..." max_startup_wait=60 for ((i=1;i<=max_startup_wait;i++)); do From 80e5af6b6ec275d557fc93c2b2856a1023c07192 Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Wed, 5 Aug 2026 15:08:08 +0100 Subject: [PATCH 17/19] Update CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d807d11..4b55501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## IN PROGRESS +* FOLIO-4554 Create Reusable workflows for Gradle based modules - in #165 +* (Add more progress summary items here.) + * FOLIO-4555 Double-quote variables - in #164 * (Add more progress summary items here.) From 9ac506d5f2bb4cc9d440d2137182abd9e537ccf7 Mon Sep 17 00:00:00 2001 From: David Crossley Date: Thu, 6 Aug 2026 13:16:00 +1000 Subject: [PATCH 18/19] Fix the CHANGELOG --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b55501..9132d8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,8 @@ ## IN PROGRESS -* FOLIO-4554 Create Reusable workflows for Gradle based modules - in #165 -* (Add more progress summary items here.) - * FOLIO-4555 Double-quote variables - in #164 +* FOLIO-4554 Create Reusable workflows for Gradle based modules - in #165 * (Add more progress summary items here.) ## [1.16.3](https://github.com/folio-org/.github/tree/v1.16.3) (2026-07-14) From 3a4fcf7887954f0977385225b25698730a3032ba Mon Sep 17 00:00:00 2001 From: David Igbinedion Date: Fri, 7 Aug 2026 17:11:20 +0100 Subject: [PATCH 19/19] add image description publish and modify inputs --- .github/workflows/gradle-build-metadata.yml | 11 + .github/workflows/gradle-build.yml | 6 +- .../gradle-dependency-submission.yml | 6 +- .../workflows/gradle-get-version-number.yml | 9 +- .github/workflows/gradle.yml | 33 +- README-gradle.md | 346 ++++++++++++++++++ 6 files changed, 394 insertions(+), 17 deletions(-) create mode 100644 README-gradle.md diff --git a/.github/workflows/gradle-build-metadata.yml b/.github/workflows/gradle-build-metadata.yml index 446feaa..73364ff 100644 --- a/.github/workflows/gradle-build-metadata.yml +++ b/.github/workflows/gradle-build-metadata.yml @@ -24,6 +24,12 @@ on: do-docker-push: description: Whether Docker images should be pushed. value: ${{ jobs.metadata.outputs.do-docker-push }} + repo-name: + description: Name of the GitHub Repository. + value: ${{ jobs.metadata.outputs.repo-name}} + repo-description: + description: Description of the GitHub Repository. + value: ${{ jobs.metadata.outputs.repo-description }} jobs: metadata: @@ -37,6 +43,8 @@ jobs: is-release: ${{ steps.metadata.outputs.is-release }} is-main-branch: ${{ steps.metadata.outputs.is-main-branch }} do-docker-push: ${{ steps.metadata.outputs.do-docker-push }} + repo-name: ${{ steps.metadata.outputs.repo-name }} + repo-description: ${{ steps.metadata.outputs.repo-description }} steps: - name: Generate metadata @@ -49,6 +57,7 @@ jobs: REF_NAME: ${{ github.ref_name }} EVENT_NAME: ${{ github.event_name }} DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + REPO_DESC: ${{ github.event.repository.description }} run: | BASE_NUMBER=2000 BUILD_NUMBER=$(( BASE_NUMBER + RUN_NUMBER )) @@ -96,6 +105,8 @@ jobs: echo "is-release=${IS_RELEASE}" echo "is-main-branch=${IS_MAIN_BRANCH}" echo "do-docker-push=${DO_DOCKER_PUSH}" + echo "repo-name=${GITHUB_REPOSITORY##*/}" + echo "repo-description=${REPO_DESC}" } >> "$GITHUB_OUTPUT" { diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index 4f5eb8c..aecdb12 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -5,14 +5,12 @@ on: inputs: gradle-directory: description: Directory containing the Gradle project. - required: false + required: true type: string - default: service java-version: description: Java version. - required: false + required: true type: string - default: "17" build-command: description: Gradle command. required: false diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index 094154d..e456c81 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -5,14 +5,12 @@ on: inputs: gradle-directory: description: Directory containing the Gradle project. - required: false + required: true type: string - default: service java-version: description: Java version. - required: false + required: true type: string - default: "17" jobs: dependency-submission: diff --git a/.github/workflows/gradle-get-version-number.yml b/.github/workflows/gradle-get-version-number.yml index bcdae82..01ebe71 100644 --- a/.github/workflows/gradle-get-version-number.yml +++ b/.github/workflows/gradle-get-version-number.yml @@ -5,9 +5,8 @@ on: inputs: gradle-directory: description: Directory containing the Gradle project. - required: false + required: true type: string - default: service outputs: gradle-version: @@ -31,12 +30,6 @@ jobs: - name: Validate Gradle Wrapper uses: gradle/actions/wrapper-validation@v6 - - name: Set up Temurin JDK 17 - uses: actions/setup-java@v5 - with: - distribution: temurin - java-version: '17' - - name: Read Gradle version id: version working-directory: ${{ inputs.gradle-directory }} diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 504d94d..5e3b045 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -12,6 +12,11 @@ on: required: false default: service type: string + publish-module-descriptor: + description: Publish module descriptor? + required: false + type: boolean + default: true module-descriptor-registry: description: Okapi ModuleDescriptor registry URL. required: false @@ -27,6 +32,11 @@ on: required: false default: "" type: string + java-version: + description: Java version. + required: false + type: string + default: "17" secrets: DOCKERHUB_USERNAME: required: true @@ -62,6 +72,7 @@ jobs: uses: ./.github/workflows/gradle-build.yml with: gradle-directory: ${{ inputs.gradle-directory }} + java-version: ${{ inputs.java-version }} # Dependency submission dependency-submission: @@ -71,6 +82,7 @@ jobs: uses: ./.github/workflows/gradle-dependency-submission.yml with: gradle-directory: ${{ inputs.gradle-directory }} + java-version: ${{ inputs.java-version }} # Docker build docker-build: @@ -90,10 +102,29 @@ jobs: dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }} dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN}} +# Docker image description + docker-description: + name: Publish image description + needs: + - metadata + - docker-build + if: | + !cancelled() && needs.metadata.outputs.do-docker-push == 'true' + uses: ./.github/workflows/docker-description.yml + with: + artifact-id: ${{ inputs.artifact-id }} + docker-registry: ${{ needs.metadata.outputs.docker-registry }} + repo-description: ${{ needs.metadata.outputs.repo-description }} + publish-module-descriptor: ${{ inputs.publish-module-descriptor }} + secrets: + dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} + # Publish ModuleDescriptor publish-module-descriptor: name: Publish ModuleDescriptor - if: needs.metadata.outputs.do-docker-push == 'true' + if: | + !cancelled() && inputs.publish-module-descriptor && needs.metadata.outputs.do-docker-push == 'true' needs: - metadata - docker-build diff --git a/README-gradle.md b/README-gradle.md new file mode 100644 index 0000000..589efa8 --- /dev/null +++ b/README-gradle.md @@ -0,0 +1,346 @@ +# Centralised GitHub Workflows for Gradle + + +* [Introduction](#introduction) +* [Usage](#usage) +* [Configuration](#configuration) + * [Configuration: java-version](#configuration-java-version) + * [Configuration: publish-module-descriptor](#configuration-publish-module-descriptor) + * [Configuration: allow-snapshots-release](#configuration-allow-snapshots-release) + * [Configuration: apt-packages](#configuration-apt-packages) + * [Configuration: do-sonar-scan](#configuration-do-sonar-scan) + * [Configuration: do-docker](#configuration-do-docker) + * [Configuration: docker-enable-other-artifacts](#configuration-docker-enable-other-artifacts) + * [Configuration: docker-health-command](#configuration-docker-health-command) + * [Configuration: docker-label-documentation](#configuration-docker-label-documentation) +* [Docker image metadata](#docker-image-metadata) +* [Install the caller Workflow](#install-the-caller-workflow) +* [Release procedures](#release-procedures) + * [Release procedures FAQ](#release-procedures-faq) +* [Limitations](#limitations) + * [Only top-level Dockerfile](#only-top-level-dockerfile) +* [Oddities](#oddities) + * [Timeout at ModuleDescriptor registry](#timeout-at-moduledescriptor-registry) + +## Introduction + +The Workflows in this repository named `maven*.yml` are for building Maven-based back-end modules. +Docker images are published to FOLIO Docker Hub. +ModuleDescriptors are published to the FOLIO Registry. + +Refer to example build system and workflows at https://github.com/folio-org/mod-settings + +## Usage + +Create a `.github/workflows` directory in the root of the module repository, and add a file named `maven.yml` with the following content. + +If there is already a workflow named maven.yml for verifying basic Maven builds, then rename that file. +It will ease management to have the same filename at every repository. + +Follow [Install the caller Workflow](#install-the-caller-workflow) section below to install the initial workflow. + +After the first Actions run, do not rename the filename of this caller workflow, as that will reset the GitHub run number and so wreck the sequential order of the ModuleDescriptor identifiers. + + +```yaml +# https://github.com/folio-org/.github/blob/master/README-maven.md + +name: Maven central workflow + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + maven: + uses: folio-org/.github/.github/workflows/maven.yml@v1 + # Only handle push events from the main branch or tags, to decrease PR noise + if: github.ref_name == github.event.repository.default_branch || github.event_name != 'push' || github.ref_type == 'tag' + secrets: inherit +``` + +## Configuration + +If there is a need to over-ride defaults, then add configuration variables to the single "with:" section of the module maven.yml Workflow. + +Add the section at the end of the Workflow immediately after the "secrets" item. +For example: + +```yaml + # ... + secrets: inherit + with: + java-version: '17' + # Add configuration variables here if needed. +``` + +### Configuration: java-version + +Allowed values: 17 or 21 or 25 + +Optional. Default = '21' + +```yaml + with: + java-version: '17' +``` + +### Configuration: publish-module-descriptor + +Some Maven-based projects do not have a ModuleDescriptor. + +Optional. Default = true + +```yaml + with: + publish-module-descriptor: false +``` + +### Configuration: allow-snapshots-release + +Normally a release must not use dependencies that are "snapshot" versions. + +On rare occasions this might be needed. + +Optional. Default = false + +```yaml + with: + allow-snapshots-release: true +``` + +### Configuration: apt-packages + +Some Maven-based repositories need extra dependencies, e.g. mod-copycat. + +There is a restricted list of packages that can be installed via apt-get. \ +The current list: 'libyaz5' + +Note that the GitHub runner already provides various other software. +Visit the "Set up job > Runner Image" section of a recent run to see the "Included Software" list. + +If there is another dependency needed, then follow the FAQ [How to raise a DevOps Jira ticket](https://dev.folio.org/faqs/how-to-raise-devops-ticket/). + +This configuration variable is a comma-separated list. + +Optional. Default = '' (i.e. none) + +```yaml + with: + apt-packages: 'libyaz5' +``` + +### Configuration: do-sonar-scan + +Sonar can be disabled if that is needed, for example when a new project is not yet ready to commence the scans. + +Optional. Default = true + +```yaml + with: + do-sonar-scan: false +``` + +### Configuration: do-docker + +Some Maven-based projects do not utilise Docker. If so then provide this variable as "false". + +If this variable is "false", then also no ModuleDescriptor will be published. + +> [!NOTE] +> See [Limitations - Only top-level Dockerfile](#only-top-level-dockerfile) at this stage. + +Optional. Default = true + +```yaml + with: + do-docker: false +``` + +### Configuration: docker-enable-other-artifacts + +If this variable is provided and "true", then do download the "build-artifacts" artifact which was prepared via the earlier job. +(Otherwise only the default "built-jars" artifact is downloaded.) + +This will include everything from the "target" directory. + +Be sure to use the `.dockerignore` file to filter only the desired pieces. + +Optional. Default = false + +```yaml + with: + docker-enable-other-artifacts: true +``` + +### Configuration: docker-health-command + +If this variable is provided, then the Docker Health Check will be run prior to the final building of the image. +If it fails, then no Docker image is built, and a ModuleDescriptor will not be published. + +> [!IMPORTANT] +> The Health Check is required for Docker-providing modules. +> Refer to [DR-000007 - Back End Module Health Check Protocol](https://folio-org.atlassian.net/wiki/x/kiJN). + +Note that the workflow will utilise this variable if provided, but does not enforce it. +The status will be reported to the workflow "Summary". + +Optional. Default = None + +```yaml + with: + docker-health-command: 'wget --no-verbose --tries=1 --spider http://localhost:8081/admin/health || exit 1' +``` + +### Configuration: docker-label-documentation + +If not provided then the "org.opencontainers.image.documentation" label of the Docker image will be empty. + +Optional. Default = None + +```yaml + with: + docker-label-documentation: 'https://.../documentation.md' +``` + +## Docker image metadata + +The docker image will have various labels automatically applied. + +Note: If the "org.opencontainers.image.description" label of the generated image is empty, then that is because the module's GitHub repository is missing the "About" description in the top-right corner of its GitHub front page. +See advice at [Create a new FOLIO module and do initial setup](https://dev.folio.org/guidelines/create-new-repo/), +and bear in mind that Docker Hub imposes a [content length limit](https://github.com/peter-evans/dockerhub-description#content-limits) of 100 bytes for that short-description, so it will be truncated at that. + +See also the [Configuration: docker-label-documentation](#configuration-docker-label-documentation) variable. + +## Install the caller Workflow + +> [!NOTE] +> If there is not yet a JIRA ticket at the co-ordination Epic [FOLIO-4443](https://folio-org.atlassian.net/browse/FOLIO-4443) then please raise one in a similar manner to the others, and add that as the Parent. + +Create a new branch at the module repository. + +Create a file at `.github/workflows/maven.yml` as explained at the [Usage](#usage) section. + +Add other [Configuration](#configuration) variables to suit the needs of the module, e.g. `docker-health-command` variable. +Align properties with the old Jenkinsfile (noting the defaults shown in the [Configuration](#configuration) section). + +Do `git mv Jenkinsfile Jenkinsfile-disabled` (so that it can be restored quickly if needed, and still be able to review its properties). + +Commit and push. + +(If it is desired to do a branch run prior to raising the pull-request, then "dispatch" the workflow on that branch. +However the line 12 "if:" will need to be temporarily commented-out for one run, because the workflow does not yet exist on mainline branch.) + +Raise the pull-request, and review the run results. + +The merge will be denied. The "check" for the old Jenkins "pr-merge" will fail. + +Edit "Branch protection" to delete that check, and add a new `GitHub Actions` check: + +For most Docker-providing repositories the check will be: \ +`maven / docker-publish / Docker build` + +For non-Docker repositories the check will be: \ +`maven / Build / Build` + +If assistance is needed with "Branch protection" then [contact](https://dev.folio.org/faqs/how-to-raise-devops-ticket/#general-folio-devops) FOLIO DevOps and advise the checks that you need. + +Wait until after the next "Platform build" to give some time if things go amiss. +https://dev.folio.org/guides/automation/#platform-hourly-build (finishes approx 53m past) +https://github.com/folio-org/platform-complete/commits/snapshot/ + +Merge and watch the mainline branch run. + +Review the results for the Docker image and ModuleDescriptor. The identifier for all modules will use base number 2000 plus the sequential workflow run_number (e.g. 2002 for the second run). + +Visit the following resources (adjusted for the relevant repository name): +* https://hub.docker.com/r/folioci/mod-settings/tags +* https://hub.docker.com/r/folioci/mod-settings (for new generated description) +* https://folio-registry.dev.folio.org/_/proxy/modules?filter=mod-settings&latest=1 +* https://folio-registry.dev.folio.org/_/proxy/modules?filter=mod-settings&latest=1&full=true +* https://repository.folio.org/#browse/browse:maven-snapshots:org%2Ffolio%2Fmod-settings +* https://sonarcloud.io/project/overview?id=org.folio:mod-settings + +Await success of the subsequent "Platform hourly build" and see snapshot branch updated. + +If there is a need to quickly revert to Jenkins-based build, then [delete](https://github.com/folio-org/mod-settings/blob/master/.github/workflows/delete-test-md.yml) the published ModuleDescriptor (with great care), re-configure the branch protection checks, restore the Jenkinsfile. + +## Release procedures + +1. Create a temporary release branch `tmp-release-X.Y.Z`; +2. Commit all relevant changes and this release's date to `NEWS.md`; + - `git log --pretty=format:"%s" $(git describe --tags --abbrev=0)..HEAD | grep -e '^.[A-Z]\+-[0-9]\+' | sort -u` can be used to grab all commits with Jira-like names since the last tag +4. Run `mvn -DautoVersionSubmodules=true release:clean release:prepare` and follow the interactive instructions: + - Ensure all snapshot dependencies are resolved (unless the workflow has [allow-snapshots-release](#configuration-allow-snapshots-release) enabled), + - Use the format `vX.Y.Z` for the created tag, + - Set the new development version by: + - Incrementing the **minor** version for regular releases (`X.Y+1.0`) or + - Incrementing the **patch version** for bugfix releases (`X.Y.Z+1`); +5. Push the temporary branch to GitHub and create a pull request against the mainline branch; +6. Once the PR passes, merge the pull request (do _not_ use a squash commit — merge the full release branch history) and push the tag (`git push --tags`); +7. Wait for the tag's GitHub Actions build to run (you can find it in the list under the `Actions` tab — look for the middle column specifying the tag's name); +8. Announce it to the world: + - Create a release on GitHub using the tag already pushed; the description should be the same as the entries in `NEWS.md` and `latest` should be set if applicable; + - Send an annoucement to [#folio-releases on Slack](https://open-libr-foundation.slack.com/archives/CGPMHLX9B); + - Ensure all applicable Jira tickets were given the proper `Fix version`; and + - Mark the Jira version as released and create a new one; and +9. Prepare for future development locally by running `mvn release:clean`. + +### Release procedures FAQ + +
+ Can't use Maven's release plugin due to failing tests? + + If you are unable to use the Maven release plugin due to test issues (e.g. unable to run tests on your machine's architecture), you may skip tests with the following command: + ```sh + mvn -DskipTests -Darguments=-DskipTests -DautoVersionSubmodules=true release:clean release:prepare + ``` +
+ +
+ Don't want to use Maven's release plugin whatsoever? + + If you don't want to use the release plugin, you may perform its steps manually. Instead of running step 3 manually, do the following (and then resume the normal release procedure): + 1. Resolve all snapshot dependencies, remove the `-SNAPSHOT` from the POM's current version, and set the source control's `` to the current `vX.Y.Z` (see [this example](https://github.com/folio-org/mod-lists/pull/265/changes/b00c3820f01f741f22c94bd21a703e357883ff95)); + 2. Commit these changes to your branch and create a tag `vX.Y.Z`; + 3. Restore snapshot dependencies as applicable, restore the source control's tag to `HEAD`, and set the POM's version to the next snapshot; and + 4. Commit these changes as a separate commit. +
+ +
+ Doing a hotfix to an older branch of your repository that still uses Jenkins? + + You have two options if you need to release on an older branch that does not use the new GitHub Actions workflow. + + However note that Option 1 is preferred because Jenkins might go away soon. + + 1. Migrate the branch to GitHub Actions (see [Usage](#usage)); or + 2. Use Jenkins for the release. + + If using Jenkins, everything will be the same except step six. Instead, navigate to the tag's build page at `https://jenkins-aws.indexdata.com/job/folio-org/job/mod-MY-MODULE/view/tags/job/vX.Y.Z/` and click `Build now` in the sidebar. Once this is complete, resume the normal release procedure. +
+ +> [!NOTE] +> +> Skipping local test execution (in the plugin or by bypassing the plugin entirely) will only skip tests locally — tests still **must** pass in GitHub Actions for the release to proceed. + +## Limitations + +### Only top-level Dockerfile + +At this stage only a top-level Dockerfile is utilised. So these Workflows are not yet ready for projects that have lower-level Dockerfile. + +## Oddities + +### Timeout at ModuleDescriptor registry + +Occasionally the job to "Publish ModuleDescriptor" gets a timeout at the registry. + +In this case the Docker image would be published but not the associated ModuleDescriptor. + +Either re-run that failed job, or "dispatch" the complete workflow again to publish a new Docker image and ModuleDescriptor.