From cb212d7261f0b84a03eccbf53dfd5594366c6cdd Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 5 Oct 2026 10:11:16 -0700 Subject: [PATCH] Retry transient artifact download failures (#58841) Summary: Pull Request resolved: https://github.com/react/react-native/pull/58841 GitHub-hosted runners intermittently fail `actions/download-artifact` before any transfer begins when the artifact service lookup hits a transient DNS error. The same `Failed to ListArtifacts: ENOTFOUND` signature has affected two iOS workflows on unrelated `main` commits, while sibling matrix jobs using the same artifacts completed successfully. Add a shared composite download action with three bounded attempts and 10-/20- second backoff, then use it in the two affected workflows. The first two failures remain visible as warnings, and the final attempt is not allowed to continue on error, so missing or persistently unavailable artifacts still fail the caller. No deterministic introducing commit was identified: the current head only changes C++ header includes, its Debug sibling passed all five downloads, and the same DNS signature previously appeared in the SwiftPM new-app workflow. Changelog: [Internal] Differential Revision: D123386956 --- .github/actions/download-artifact/action.yml | 59 ++++++++++++++++++++ .github/workflows/e2e-ios-templateapp.yml | 10 ++-- .github/workflows/test-ios-spm-newapp.yml | 10 ++-- 3 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 .github/actions/download-artifact/action.yml diff --git a/.github/actions/download-artifact/action.yml b/.github/actions/download-artifact/action.yml new file mode 100644 index 000000000000..0edcd020fa67 --- /dev/null +++ b/.github/actions/download-artifact/action.yml @@ -0,0 +1,59 @@ +name: Download artifact with retries +description: Downloads an artifact, retrying transient failures up to two times + +inputs: + name: + description: Artifact name + required: true + path: + description: Destination path + required: true + +outputs: + download-path: + description: Absolute path where the artifact was downloaded + value: ${{ steps.download-3.outputs.download-path || steps.download-2.outputs.download-path || steps.download-1.outputs.download-path }} + +runs: + using: composite + steps: + - name: Download artifact (attempt 1 of 3) + id: download-1 + if: ${{ always() }} + continue-on-error: true + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} + + - name: Wait before attempt 2 + if: ${{ always() && steps.download-1.outcome == 'failure' }} + shell: bash + run: | + echo "::warning::Artifact download failed; retrying in 10 seconds" + sleep 10 + + - name: Download artifact (attempt 2 of 3) + id: download-2 + if: ${{ always() && steps.download-1.outcome == 'failure' }} + continue-on-error: true + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} + + - name: Wait before attempt 3 + if: ${{ always() && steps.download-2.outcome == 'failure' }} + shell: bash + run: | + echo "::warning::Artifact download failed again; retrying in 20 seconds" + sleep 20 + + - name: Download artifact (attempt 3 of 3) + id: download-3 + if: ${{ always() && steps.download-2.outcome == 'failure' }} + # Deliberately do not continue on error: the last failure must fail the caller. + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} diff --git a/.github/workflows/e2e-ios-templateapp.yml b/.github/workflows/e2e-ios-templateapp.yml index dbaaaa2b5666..e8d7ba011c08 100644 --- a/.github/workflows/e2e-ios-templateapp.yml +++ b/.github/workflows/e2e-ios-templateapp.yml @@ -33,14 +33,14 @@ jobs: with: ruby-version: 2.6.10 - name: Download React Native Package - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: react-native-package path: /tmp/react-native-tmp - name: Print /tmp folder run: ls -lR /tmp/react-native-tmp - name: Download ReactNativeDependencies - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz path: /tmp/third-party @@ -48,7 +48,7 @@ jobs: shell: bash run: ls -lR /tmp/third-party - name: Download React Native Prebuilds - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: ReactCore${{ matrix.flavor }}.xcframework.tar.gz path: /tmp/ReactCore @@ -114,7 +114,7 @@ jobs: - name: Run yarn uses: ./.github/actions/yarn-install - name: Download app - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: RNTestProject-${{ matrix.flavor }} path: /tmp/RNTestProjectBuild/RNTestProject.app @@ -122,7 +122,7 @@ jobs: run: ls -l /tmp/RNTestProjectBuild/RNTestProject.app - name: Download React Native Package if: ${{ matrix.flavor == 'Debug' }} - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: react-native-package path: /tmp/react-native-tmp diff --git a/.github/workflows/test-ios-spm-newapp.yml b/.github/workflows/test-ios-spm-newapp.yml index 3fcceeb4c117..62e66395bae1 100644 --- a/.github/workflows/test-ios-spm-newapp.yml +++ b/.github/workflows/test-ios-spm-newapp.yml @@ -40,27 +40,27 @@ jobs: # release/ artifact slots together (and `--download skip` refuses an # incomplete slot). Please don't "optimise" this down to one flavor. - name: Download ReactCore (Debug) - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: ReactCoreDebug.xcframework.tar.gz path: /tmp/rc-debug - name: Download ReactCore (Release) - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: ReactCoreRelease.xcframework.tar.gz path: /tmp/rc-release - name: Download ReactNativeDependencies (Debug) - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: ReactNativeDependenciesDebug.xcframework.tar.gz path: /tmp/deps-debug - name: Download ReactNativeDependencies (Release) - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: ReactNativeDependenciesRelease.xcframework.tar.gz path: /tmp/deps-release - name: Download React Native package - uses: actions/download-artifact@v7 + uses: ./.github/actions/download-artifact with: name: react-native-package path: /tmp/react-native-tmp