Move common build plugin #6002
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: github-workflow | |
| permissions: | |
| actions: write | |
| contents: read | |
| on: | |
| pull_request: | |
| branches: [ main, 3.2.x, 3.3.x ] | |
| # Manual trigger with optional branch override | |
| workflow_dispatch: | |
| inputs: | |
| branch: | |
| description: "Which branch should be built" | |
| required: true | |
| default: 'main' | |
| type: string | |
| jdk-version: | |
| description: "Java version to use for build" | |
| required: false | |
| default: '17' | |
| type: string | |
| should-deploy: | |
| description: "Whether to run deployment after tests pass" | |
| required: false | |
| default: 'false' | |
| type: string | |
| runs-on: | |
| description: "Runner label for the jobs that run Maven" | |
| required: false | |
| default: 'ubuntu-latest' | |
| type: string | |
| build-docs: | |
| description: "Whether the deploy build includes the docs profile" | |
| required: false | |
| default: true | |
| type: boolean | |
| # Allow calls from ci.yaml | |
| workflow_call: | |
| inputs: | |
| branch: | |
| description: "Which branch should be built" | |
| required: true | |
| type: string | |
| jdk-version: | |
| description: "Java version to use for build" | |
| required: true | |
| type: string | |
| should-deploy: | |
| description: "Whether to run deployment after tests pass" | |
| required: true | |
| type: boolean | |
| runs-on: | |
| description: > | |
| Runner label for the jobs that run Maven. Defaults to ubuntu-latest, which is | |
| correct for open source builds. Commercial branches must pass a runner from the | |
| spring-enterprise-builds group, because commercial Artifactory only accepts | |
| requests from those runners and answers anything else with a 403 no matter what | |
| credentials are supplied. Also used for the deploy job. | |
| required: false | |
| default: 'ubuntu-latest' | |
| type: string | |
| build-docs: | |
| description: > | |
| Whether the deploy build includes the docs profile. | |
| required: false | |
| default: true | |
| type: boolean | |
| jobs: | |
| build: | |
| name: Build (${{ inputs.branch || github.ref_name }} with JDK ${{ inputs.jdk-version || '17' }}) | |
| runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} | |
| env: | |
| # this might get set to true if there is an existing cache of test times | |
| # this happens in 'matrix-bounds-on-test-times-cache-hit' | |
| TEST_TIMES_CACHE_PRESENT: false | |
| SEGMENT_DOWNLOAD_TIMEOUT_MINS: 30 | |
| JDK_VERSION: ${{ inputs.jdk-version || '17' }} | |
| BRANCH: ${{ inputs.branch || github.ref_name }} | |
| # this job ('build') outputs a value from step 'test_times_cache_present_init', that has the name of: | |
| # 'test_times_cache_present'. This can later be used by other jobs. For example, we use this one | |
| # to skip the job responsible for running the tests, if a previous cache that has the test times is not present. | |
| # Same for other two variables 'number_of_matrix_instances' and 'matrix_array'. | |
| outputs: | |
| branch_safe: ${{ steps.sanitize_branch.outputs.branch_safe }} # this is the branch name with / removed so it can be used in cache names safely | |
| test_times_cache_present: ${{ steps.test_times_cache_present_init.outputs.test_times_cache_present }} | |
| number_of_matrix_instances: ${{ steps.test_times_cache_present_init.outputs.number_of_matrix_instances }} | |
| matrix_array: ${{ steps.test_times_cache_present_init.outputs.matrix_array }} | |
| average_time_per_instance: ${{ steps.test_times_cache_present_init.outputs.average_time_per_instance }} | |
| steps: | |
| - name: checkout project | |
| uses: actions/checkout@v7.0.1 | |
| with: | |
| ref: ${{ inputs.branch || github.ref }} | |
| - name: Sanitize branch name for artifacts | |
| id: sanitize_branch | |
| shell: bash | |
| run: | | |
| SANITIZED_BRANCH=$(echo "${{ env.BRANCH }}" | sed 's/\//-/g') | |
| echo "BRANCH_SAFE=${SANITIZED_BRANCH}" >> $GITHUB_ENV | |
| echo "branch_safe=${SANITIZED_BRANCH}" >> $GITHUB_OUTPUT | |
| - name: set env variables | |
| env: | |
| # Read-write commercial credentials, deliberately blank on pull requests so that | |
| # forked PRs fall back to the read-only secrets. The composite picks whichever | |
| # pair is populated and exports COMMERCIAL_ARTIFACTORY_USERNAME/PASSWORD, which | |
| # release-ci-settings.xml interpolates to reach commercial Artifactory. | |
| PASSWORD: ${{ github.event_name != 'pull_request' && secrets.COMMERCIAL_ARTIFACTORY_PASSWORD || '' }} | |
| USERNAME: ${{ github.event_name != 'pull_request' && secrets.COMMERCIAL_ARTIFACTORY_USERNAME || '' }} | |
| RO_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD || secrets.ARTIFACTORY_RO_PASSWORD }} | |
| RO_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME || secrets.ARTIFACTORY_RO_USERNAME }} | |
| uses: ./.github/workflows/composites/env-variables | |
| - name: setup project jdk | |
| uses: ./.github/workflows/composites/setup-jdk | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| - name: cache local maven repository | |
| uses: ./.github/workflows/composites/cache | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| - name: Show caches | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const caches = await github.rest.actions.getActionsCacheList({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| }) | |
| console.log(caches.data) | |
| - name: maven build with dry-run for tests | |
| uses: ./.github/workflows/composites/maven-build-with-dry-run-for-tests | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| - name: restore test times cache if it exists | |
| id: restore_test_times_cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: /tmp/sorted.txt | |
| key: ${{ runner.os }}-spring-cloud-k8s-jdk${{ env.JDK_VERSION }}-test-times-cache-${{ github.run_id }} | |
| restore-keys: ${{ runner.os }}-spring-cloud-k8s-jdk${{ env.JDK_VERSION }}-test-times-cache- | |
| - name: check test times cache exists | |
| id: check_files | |
| uses: andstor/file-existence-action@v3 | |
| with: | |
| files: /tmp/sorted.txt | |
| - name: show existing cache of test times | |
| if: steps.check_files.outputs.files_exists == 'true' | |
| shell: bash | |
| run: cat /tmp/sorted.txt | |
| - name: compute matrix related fields when cache is present | |
| if: steps.check_files.outputs.files_exists == 'true' | |
| uses: ./.github/workflows/composites/matrix-bounds-on-test-times-cache-hit | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| - name: matrix related variables when cache is present | |
| id: test_times_cache_present_init | |
| run: | | |
| echo "test_times_cache_present=${{ env.TEST_TIMES_CACHE_PRESENT }}" >> $GITHUB_OUTPUT | |
| echo "number_of_matrix_instances=${{ env.NUMBER_OF_MATRIX_INSTANCES }}" >> $GITHUB_OUTPUT | |
| echo "matrix_array=${{ env.MATRIX_ARRAY }}" >> $GITHUB_OUTPUT | |
| echo "average_time_per_instance=${{ env.AVERAGE_TIME_PER_INSTANCE }}" >> $GITHUB_OUTPUT | |
| test_when_cache_present: | |
| name: Test with cache (runner ${{ matrix.current_index }}) | |
| needs: [ build ] | |
| runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} | |
| env: | |
| SEGMENT_DOWNLOAD_TIMEOUT_MINS: 30 | |
| JDK_VERSION: ${{ inputs.jdk-version || '17' }} | |
| BRANCH: ${{ inputs.branch || github.ref_name }} | |
| BRANCH_SAFE: ${{ needs.build.outputs.branch_safe }} | |
| # only run this one if there is a previous cache of test times | |
| if: needs.build.outputs.test_times_cache_present == 'true' | |
| timeout-minutes: 120 | |
| strategy: | |
| # let every shard finish so a single failing shard does not hide failures | |
| # (or successes) in the others | |
| fail-fast: false | |
| matrix: | |
| current_index: [ "${{ fromJSON(needs.build.outputs.matrix_array) }}" ] | |
| number_of_jobs: [ "${{ fromJSON(needs.build.outputs.number_of_matrix_instances) }}" ] | |
| average_time_per_instance: [ "${{ fromJSON(needs.build.outputs.average_time_per_instance) }}" ] | |
| steps: | |
| - name: checkout project | |
| uses: actions/checkout@v7.0.1 | |
| with: | |
| ref: ${{ inputs.branch || github.ref }} | |
| - name: clean space | |
| uses: ./.github/workflows/composites/clean-space | |
| - name: set env variables | |
| env: | |
| # Read-write commercial credentials, deliberately blank on pull requests so that | |
| # forked PRs fall back to the read-only secrets. The composite picks whichever | |
| # pair is populated and exports COMMERCIAL_ARTIFACTORY_USERNAME/PASSWORD, which | |
| # release-ci-settings.xml interpolates to reach commercial Artifactory. | |
| PASSWORD: ${{ github.event_name != 'pull_request' && secrets.COMMERCIAL_ARTIFACTORY_PASSWORD || '' }} | |
| USERNAME: ${{ github.event_name != 'pull_request' && secrets.COMMERCIAL_ARTIFACTORY_USERNAME || '' }} | |
| RO_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD || secrets.ARTIFACTORY_RO_PASSWORD }} | |
| RO_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME || secrets.ARTIFACTORY_RO_USERNAME }} | |
| uses: ./.github/workflows/composites/env-variables | |
| - name: setup project jdk | |
| uses: ./.github/workflows/composites/setup-jdk | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| - name: pre-test-actions | |
| uses: ./.github/workflows/composites/pre-test-actions | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| - name: testcontainers reuse support | |
| shell: bash | |
| run: echo "testcontainers.reuse.enable=true" > ~/.testcontainers.properties | |
| - name: run and save test times when cache is present | |
| uses: ./.github/workflows/composites/run-and-save-test-times-when-cache-present | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| env: | |
| CURRENT_INDEX: ${{ matrix.current_index }} | |
| NUMBER_OF_JOBS: ${{ matrix.number_of_jobs }} | |
| AVERAGE_TIME_PER_INSTANCE: ${{ matrix.average_time_per_instance }} | |
| # how many extra times a shard re-runs the test classes that failed. | |
| # 0 disables retries, 2 means up to three maven runs, and so on. | |
| TEST_RETRY_COUNT: 1 | |
| test_when_cache_missing: | |
| name: Test without cache (runner ${{ matrix.current_index }}) | |
| needs: [ build ] | |
| runs-on: ${{ inputs.runs-on || 'ubuntu-latest' }} | |
| env: | |
| SEGMENT_DOWNLOAD_TIMEOUT_MINS: 30 | |
| JDK_VERSION: ${{ inputs.jdk-version || '17' }} | |
| BRANCH: ${{ inputs.branch || github.ref_name }} | |
| BRANCH_SAFE: ${{ needs.build.outputs.branch_safe }} | |
| timeout-minutes: 120 | |
| # only run this one if there is no previous cache of test times | |
| if: needs.build.outputs.test_times_cache_present == 'false' | |
| strategy: | |
| # let every shard finish so a single failing shard does not hide failures | |
| # (or successes) in the others | |
| fail-fast: false | |
| matrix: | |
| current_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] | |
| number_of_jobs: [32] | |
| steps: | |
| - name: checkout project | |
| uses: actions/checkout@v7.0.1 | |
| with: | |
| ref: ${{ inputs.branch || github.ref }} | |
| - name: clean space | |
| uses: ./.github/workflows/composites/clean-space | |
| - name: set env variables | |
| env: | |
| # Read-write commercial credentials, deliberately blank on pull requests so that | |
| # forked PRs fall back to the read-only secrets. The composite picks whichever | |
| # pair is populated and exports COMMERCIAL_ARTIFACTORY_USERNAME/PASSWORD, which | |
| # release-ci-settings.xml interpolates to reach commercial Artifactory. | |
| PASSWORD: ${{ github.event_name != 'pull_request' && secrets.COMMERCIAL_ARTIFACTORY_PASSWORD || '' }} | |
| USERNAME: ${{ github.event_name != 'pull_request' && secrets.COMMERCIAL_ARTIFACTORY_USERNAME || '' }} | |
| RO_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD || secrets.ARTIFACTORY_RO_PASSWORD }} | |
| RO_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME || secrets.ARTIFACTORY_RO_USERNAME }} | |
| uses: ./.github/workflows/composites/env-variables | |
| - name: setup project jdk | |
| uses: ./.github/workflows/composites/setup-jdk | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| - name: pre-test-actions | |
| uses: ./.github/workflows/composites/pre-test-actions | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| - name: compute single step test bounds | |
| uses: ./.github/workflows/composites/test-bounds | |
| env: | |
| CURRENT_INDEX: ${{ matrix.current_index }} | |
| NUMBER_OF_JOBS: ${{ matrix.number_of_jobs }} | |
| - name: testcontainers reuse support | |
| shell: bash | |
| run: echo "testcontainers.reuse.enable=true" > ~/.testcontainers.properties | |
| - name: run and save individual test times | |
| uses: ./.github/workflows/composites/run-and-save-test-times-when-cache-missing | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| env: | |
| CURRENT_INDEX: ${{ matrix.current_index }} | |
| # how many extra times a shard re-runs the test classes that failed. | |
| # 0 disables retries, 2 means up to three maven runs, and so on. | |
| TEST_RETRY_COUNT: 1 | |
| save_test_times_when_cache_missing: | |
| name: Save test times | |
| runs-on: ubuntu-latest | |
| needs: [build, test_when_cache_missing ] | |
| env: | |
| JDK_VERSION: ${{ inputs.jdk-version || '17' }} | |
| BRANCH: ${{ inputs.branch || github.ref_name }} | |
| BRANCH_SAFE: ${{ needs.build.outputs.branch_safe }} | |
| steps: | |
| - name: checkout project | |
| uses: actions/checkout@v7.0.1 | |
| with: | |
| ref: ${{ inputs.branch || github.ref }} | |
| - name: compute and save running time of tests | |
| uses: ./.github/workflows/composites/test-times | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| save_test_times_when_cache_present: | |
| name: Save test times | |
| runs-on: ubuntu-latest | |
| needs: [ build, test_when_cache_present ] | |
| env: | |
| JDK_VERSION: ${{ inputs.jdk-version || '17' }} | |
| BRANCH: ${{ inputs.branch || github.ref_name }} | |
| BRANCH_SAFE: ${{ needs.build.outputs.branch_safe }} | |
| steps: | |
| - name: checkout project | |
| uses: actions/checkout@v7.0.1 | |
| with: | |
| ref: ${{ inputs.branch || github.ref }} | |
| - name: compute and save running time of tests | |
| uses: ./.github/workflows/composites/test-times | |
| with: | |
| jdk-version: ${{ env.JDK_VERSION }} | |
| branch: ${{ env.BRANCH_SAFE }} | |
| # Gate job to handle mutually exclusive test jobs | |
| # Either test_when_cache_present OR test_when_cache_missing runs (not both) | |
| # This job succeeds only if the appropriate test jobs succeeded | |
| all-tests-passed: | |
| if: always() | |
| needs: [test_when_cache_present, test_when_cache_missing, save_test_times_when_cache_missing, save_test_times_when_cache_present] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check test results | |
| run: | | |
| echo "test_when_cache_present: ${{ needs.test_when_cache_present.result }}" | |
| echo "test_when_cache_missing: ${{ needs.test_when_cache_missing.result }}" | |
| if [ "${{ needs.test_when_cache_present.result }}" == "success" ] || \ | |
| [ "${{ needs.test_when_cache_missing.result }}" == "success" ]; then | |
| echo "Tests passed" | |
| exit 0 | |
| else | |
| echo "No test job succeeded (see the results above). A result of 'cancelled'" | |
| echo "means a test job timed out or was cancelled, not that a test assertion" | |
| echo "failed - check the test job logs to tell them apart." | |
| exit 1 | |
| fi | |
| # Deploy job that runs after all tests pass | |
| # Only runs when should-deploy input is 'true' | |
| deploy: | |
| if: always() && inputs.should-deploy && needs.all-tests-passed.result == 'success' | |
| needs: [all-tests-passed] | |
| uses: spring-cloud/spring-cloud-github-actions/.github/workflows/deploy.yml@b6a6b1963b8762420526591c3d363bd7d09e7d4b # v1.1.1 | |
| with: | |
| trigger_ci_on_non_default_branches: false | |
| branches: ${{ inputs.branch }} | |
| # Commercial branches must deploy from a spring-enterprise-builds runner, the same as | |
| # the jobs above; commercial Artifactory rejects anything else with a 403. | |
| runs_on: ${{ inputs.runs-on }} | |
| # MAVEN_SETTINGS and MAVEN_DEPLOY_FLAGS are set by deploy.yml. | |
| custom_build_command: | | |
| if [[ "$SHOULD_DEPLOY" == "true" ]]; then | |
| ./mvnw $MAVEN_SETTINGS clean deploy -Pspring${{ inputs.build-docs && ',docs' || '' }} -DskipTests -DskipITs -Dspring-boot.build-image.skip=true -B -U $MAVEN_DEPLOY_FLAGS | |
| else | |
| echo "Will not deploy artifacts" | |
| fi | |
| secrets: | |
| ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} | |
| ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} | |
| COMMERCIAL_ARTIFACTORY_USERNAME: ${{ secrets.COMMERCIAL_ARTIFACTORY_USERNAME }} | |
| COMMERCIAL_ARTIFACTORY_PASSWORD: ${{ secrets.COMMERCIAL_ARTIFACTORY_PASSWORD }} | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} |