diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 907516a5c5..3c327df4c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,11 @@ env: CCDB_CONNECTION: 'sqlite:///${{ github.workspace }}/coatjava/etc/data/sqlite/ccdb.sqlite' RCDB_CONNECTION: 'sqlite:///${{ github.workspace }}/coatjava/etc/data/sqlite/rcdb.sqlite' nthreads: 1 + # Maven 3.9+ reads MAVEN_ARGS automatically, including inside build-coatjava.sh: + # --no-snapshot-updates : don't re-check remote repos (j4ml) for newer SNAPSHOTs; + # use whatever `warm_maven_cache` resolved + # retryHandler.count : built-in HTTP retries for transient 403/429/5xx + MAVEN_ARGS: --no-snapshot-updates -Daether.connector.http.retryHandler.count=5 jobs: @@ -52,10 +57,58 @@ jobs: git clone --depth 1 https://code.jlab.org/hallb/clas12/validation-data cp validation-data/raw/rg-d/clas_018779.evio.00001 . + # Resolve all Maven dependencies ONCE (with retries and a single download + # thread, to avoid tripping Cloudflare), save them to a cache, and let every + # other job restore that cache instead of hitting the remote repos. + # + # The cache key is: m2-- + # - a pom.xml change gives a new key, so dependencies are re-resolved + # - the week component forces a weekly refresh, so SNAPSHOTs don't go stale + # - to force a refresh sooner, delete the `m2-*` caches in the Actions UI + warm_maven_cache: + runs-on: ubuntu-latest + outputs: + key: ${{ steps.key.outputs.key }} + steps: + - uses: actions/checkout@v7 + - name: compute cache key + id: key + run: echo "key=m2-$(date +%G-%V)-${{ hashFiles('**/pom.xml') }}" | tee -a $GITHUB_OUTPUT + - uses: actions/cache/restore@v6 + id: restore + with: + path: ~/.m2/repository + key: ${{ steps.key.outputs.key }} + restore-keys: | + m2- + - uses: actions/setup-java@v6.0.1 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.java_distribution }} + - name: resolve dependencies (with retries) + if: ${{ steps.restore.outputs.cache-hit != 'true' }} + uses: nick-fields/retry@v4.0.0 + env: + # override the global flags: here we DO want SNAPSHOTs refreshed (-U) + MAVEN_ARGS: -U -Daether.connector.http.retryHandler.count=5 + with: + timeout_minutes: 30 + max_attempts: 5 + retry_wait_seconds: 90 + command: mvn -B -ntp -Dmaven.artifact.threads=1 -DexcludeReactor=true dependency:go-offline + - name: save maven cache + # only on success, so a half-populated cache is never saved under the real key + if: ${{ success() && steps.restore.outputs.cache-hit != 'true' }} + uses: actions/cache/save@v6 + with: + path: ~/.m2/repository + key: ${{ steps.key.outputs.key }} + # build ############################################################################# build_macos: + needs: [ warm_maven_cache ] strategy: fail-fast: true runs-on: macos-latest @@ -65,7 +118,11 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven + - uses: actions/cache/restore@v6 + with: + path: ~/.m2/repository + key: ${{ needs.warm_maven_cache.outputs.key }} + fail-on-cache-miss: true - name: bump version to tag if tag trigger if: ${{ github.ref_type == 'tag' }} run: libexec/version-bump.sh ${{ github.ref_name }} @@ -86,6 +143,7 @@ jobs: clara.tar.gz build: + needs: [ warm_maven_cache ] strategy: fail-fast: true runs-on: ubuntu-latest @@ -95,7 +153,11 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven + - uses: actions/cache/restore@v6 + with: + path: ~/.m2/repository + key: ${{ needs.warm_maven_cache.outputs.key }} + fail-on-cache-miss: true - name: bump version to tag if tag trigger if: ${{ github.ref_type == 'tag' }} run: libexec/version-bump.sh ${{ github.ref_name }} @@ -116,7 +178,14 @@ jobs: clara.tar.gz dependency_info: + # Informational job. It deliberately does a clean (uncached) resolve to see where + # dependencies really come from, so it always hits the remote repos. + # - run after `warm_maven_cache`, so it doesn't add to the parallel burst + # - retry the build step + needs: [ warm_maven_cache ] runs-on: ubuntu-latest + env: + MAVEN_ARGS: -Daether.connector.http.retryHandler.count=5 # no -nsu: want a true fresh resolve steps: - uses: actions/checkout@v7 - name: Set up JDK @@ -126,8 +195,12 @@ jobs: distribution: ${{ env.java_distribution }} # NOTE: do not use `cache: maven` here, so stale `_remote.repositories` data aren't read - name: build - run: | - ./build-coatjava.sh --no-aux --no-progress --quiet -T${{ env.nthreads }} + uses: nick-fields/retry@v4.0.0 + with: + timeout_minutes: 30 + max_attempts: 3 + retry_wait_seconds: 120 + command: ./build-coatjava.sh --no-aux --no-progress --quiet -T${{ env.nthreads }} - name: collect info run: libexec/dependency-info.rb - name: print dependency trees @@ -148,8 +221,7 @@ jobs: run: echo versions="[\"${{ env.JAVA_VERSION }}\",\"${{ env.JAVA_VERSION_LATEST }}\"]" | tee -a $GITHUB_OUTPUT unit_tests: - needs: - - java_matrix + needs: [ java_matrix, warm_maven_cache ] strategy: fail-fast: false matrix: @@ -161,7 +233,11 @@ jobs: with: java-version: ${{ matrix.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven + - uses: actions/cache/restore@v6 + with: + path: ~/.m2/repository + key: ${{ needs.warm_maven_cache.outputs.key }} + fail-on-cache-miss: true - name: unit tests run: ./build-coatjava.sh --lfs --unittests --no-progress -T${{ env.nthreads }} - name: collect jacoco report @@ -176,7 +252,7 @@ jobs: retention-days: 1 spotbugs: - needs: [ build ] + needs: [ build, warm_maven_cache ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -185,7 +261,11 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven + - uses: actions/cache/restore@v6 + with: + path: ~/.m2/repository + key: ${{ needs.warm_maven_cache.outputs.key }} + fail-on-cache-miss: true - uses: actions/download-artifact@v8 with: name: build_ubuntu-latest @@ -204,7 +284,6 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven - uses: actions/download-artifact@v8 with: name: build_ubuntu-latest @@ -233,7 +312,6 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven - uses: actions/download-artifact@v8 with: name: build_ubuntu-latest @@ -291,7 +369,6 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven - uses: actions/download-artifact@v8 with: name: build_${{ matrix.runner }} @@ -319,7 +396,6 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven - uses: actions/download-artifact@v8 with: name: build_macos @@ -344,7 +420,6 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven - name: setup groovy uses: wtfjoke/setup-groovy@v3 with: @@ -367,7 +442,6 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven - uses: actions/download-artifact@v8 with: name: test_clara_result @@ -386,7 +460,7 @@ jobs: generate_documentation: runs-on: ubuntu-latest - needs: [ unit_tests ] + needs: [ unit_tests, warm_maven_cache ] steps: ### zensical - uses: actions/checkout@v7 @@ -408,7 +482,11 @@ jobs: with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.java_distribution }} - cache: maven + - uses: actions/cache/restore@v6 + with: + path: ~/.m2/repository + key: ${{ needs.warm_maven_cache.outputs.key }} + fail-on-cache-miss: true - name: build coatjava javadocs # javadoc:aggregate output dir cannot be controlled, so assume the latest "standard" path and `mv` it run: | libexec/build-javadocs.sh