diff --git a/.github/workflows/playwright-e2e-reusable.yml b/.github/workflows/playwright-e2e-reusable.yml index 886daa3ba3da..d70ac489d393 100644 --- a/.github/workflows/playwright-e2e-reusable.yml +++ b/.github/workflows/playwright-e2e-reusable.yml @@ -719,15 +719,25 @@ jobs: mkdir -p "$core_output/node_modules" "$core_output/dist" "$core_output/vite-temp" # Dependency installation can execute repository-controlled package-manager # configuration even with lifecycle scripts disabled. Keep it off the runner. - docker run --rm --read-only \ - --cap-drop ALL --security-opt no-new-privileges \ - --user "$(id -u):$(id -g)" \ - --tmpfs /tmp:rw,nosuid,size=4g \ - --mount "type=bind,source=$GITHUB_WORKSPACE,target=/workspace,readonly" \ - --mount "type=bind,source=$core_output/node_modules,target=/workspace/$core_dir/node_modules" \ - --workdir "/workspace/$core_dir" \ - node:22.22.2-bookworm-slim \ - yarn --ignore-scripts --frozen-lockfile --cache-folder /tmp/yarn-cache + # Retry transient registry failures — yarn v1 does not retry HTTP errors. + for attempt in 1 2 3; do + docker run --rm --read-only \ + --cap-drop ALL --security-opt no-new-privileges \ + --user "$(id -u):$(id -g)" \ + --tmpfs /tmp:rw,nosuid,size=4g \ + --mount "type=bind,source=$GITHUB_WORKSPACE,target=/workspace,readonly" \ + --mount "type=bind,source=$core_output/node_modules,target=/workspace/$core_dir/node_modules" \ + --workdir "/workspace/$core_dir" \ + node:22.22.2-bookworm-slim \ + yarn --ignore-scripts --frozen-lockfile --cache-folder /tmp/yarn-cache \ + --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done # Only temporary build output is writable; dependencies and source stay read-only. mkdir -p "$core_output/node_modules/.vite-temp" diff --git a/.github/workflows/playwright-knowledge-graph-postgresql-e2e.yml b/.github/workflows/playwright-knowledge-graph-postgresql-e2e.yml index b777679f9156..c738d776e1e5 100644 --- a/.github/workflows/playwright-knowledge-graph-postgresql-e2e.yml +++ b/.github/workflows/playwright-knowledge-graph-postgresql-e2e.yml @@ -366,7 +366,18 @@ jobs: - name: Install dependencies working-directory: openmetadata-ui/src/main/resources/ui/ - run: yarn --ignore-scripts --frozen-lockfile + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn --ignore-scripts --frozen-lockfile --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Install Playwright Browsers run: npx playwright@1.57.0 install chromium --with-deps diff --git a/.github/workflows/playwright-search-nightly.yml b/.github/workflows/playwright-search-nightly.yml index 854946f9c3fb..2bcc6140ea57 100644 --- a/.github/workflows/playwright-search-nightly.yml +++ b/.github/workflows/playwright-search-nightly.yml @@ -64,7 +64,18 @@ jobs: - name: Install dependencies working-directory: openmetadata-ui/src/main/resources/ui/ - run: yarn --ignore-scripts --frozen-lockfile + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn --ignore-scripts --frozen-lockfile --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Install Playwright Browsers run: npx playwright@1.57.0 install chromium --with-deps diff --git a/.github/workflows/playwright-sso-login-nightly.yml b/.github/workflows/playwright-sso-login-nightly.yml index d49080322bcf..a39e8b77cdb7 100644 --- a/.github/workflows/playwright-sso-login-nightly.yml +++ b/.github/workflows/playwright-sso-login-nightly.yml @@ -340,7 +340,18 @@ jobs: - name: Install dependencies if: env.SKIP_LEG != 'true' working-directory: openmetadata-ui/src/main/resources/ui/ - run: yarn --ignore-scripts --frozen-lockfile + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn --ignore-scripts --frozen-lockfile --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Install Playwright Browsers if: env.SKIP_LEG != 'true' diff --git a/.github/workflows/playwright-visual.yml b/.github/workflows/playwright-visual.yml index 90d5180acb21..a2c2791acaaf 100644 --- a/.github/workflows/playwright-visual.yml +++ b/.github/workflows/playwright-visual.yml @@ -161,7 +161,18 @@ jobs: - name: Install dependencies working-directory: openmetadata-ui/src/main/resources/ui/ - run: yarn --ignore-scripts --frozen-lockfile + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn --ignore-scripts --frozen-lockfile --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done # Runs inside the same Playwright image the baselines were generated with (see header # comment) instead of on the bare runner. `--network host` lets the container reach the diff --git a/.github/workflows/release-branch-validate.yml b/.github/workflows/release-branch-validate.yml index 4a4ad0ba30a2..bfd02d48acf9 100644 --- a/.github/workflows/release-branch-validate.yml +++ b/.github/workflows/release-branch-validate.yml @@ -242,7 +242,18 @@ jobs: - name: Install UI yarn packages if: steps.files.outputs.any == 'true' working-directory: ${{ env.UI_WORKING_DIRECTORY }} - run: yarn install --frozen-lockfile + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn install --frozen-lockfile --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: ESLint + Prettier on changed files if: steps.files.outputs.any == 'true' diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index 3895fbd07acc..211380060b35 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -46,7 +46,18 @@ jobs: - name: Install UI dependencies working-directory: openmetadata-ui/src/main/resources/ui - run: yarn install --frozen-lockfile --ignore-scripts + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn install --frozen-lockfile --ignore-scripts --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Run Retire.js scan id: retire-scan diff --git a/.github/workflows/typescript-type-generation.yml b/.github/workflows/typescript-type-generation.yml index 5f988d733412..bf685a0d434f 100644 --- a/.github/workflows/typescript-type-generation.yml +++ b/.github/workflows/typescript-type-generation.yml @@ -139,7 +139,17 @@ jobs: - name: Install dependencies run: | - yarn install --frozen-lockfile + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn install --frozen-lockfile --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Generate TypeScript types run: | @@ -160,7 +170,15 @@ jobs: # skips preinstall (core-components build) and postinstall (js-antlr), neither # of which parseSchemas.js needs. rm -f node_modules - yarn install --frozen-lockfile --ignore-scripts + for attempt in 1 2 3; do + yarn install --frozen-lockfile --ignore-scripts --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done yarn parse-schema - name: Check for changes diff --git a/.github/workflows/ui-sonarcloud-nightly.yml b/.github/workflows/ui-sonarcloud-nightly.yml index fefd2b4190dd..edfe6209093e 100644 --- a/.github/workflows/ui-sonarcloud-nightly.yml +++ b/.github/workflows/ui-sonarcloud-nightly.yml @@ -74,7 +74,18 @@ jobs: - name: Install Yarn Packages working-directory: ${{ env.UI_WORKING_DIRECTORY }} - run: yarn install + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn install --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Run Coverage working-directory: ${{ env.UI_WORKING_DIRECTORY }} diff --git a/.github/workflows/update-playwright-e2e-docs.yml b/.github/workflows/update-playwright-e2e-docs.yml index a39229c47bf4..517c8b8d50dd 100644 --- a/.github/workflows/update-playwright-e2e-docs.yml +++ b/.github/workflows/update-playwright-e2e-docs.yml @@ -44,7 +44,18 @@ jobs: - name: Install Dependencies working-directory: openmetadata-ui/src/main/resources/ui - run: yarn install --frozen-lockfile --ignore-scripts + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn install --frozen-lockfile --ignore-scripts --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Install Playwright Browsers working-directory: openmetadata-ui/src/main/resources/ui diff --git a/.github/workflows/yarn-coverage.yml b/.github/workflows/yarn-coverage.yml index e97427fa2359..b7f3acd0d10d 100644 --- a/.github/workflows/yarn-coverage.yml +++ b/.github/workflows/yarn-coverage.yml @@ -136,7 +136,18 @@ jobs: sudo make install_antlr_cli - name: Install Yarn Packages working-directory: ${{ env.UI_WORKING_DIRECTORY }} - run: yarn install + run: | + # Retry transient registry failures (5xx on tarball fetches) — + # yarn v1 does not retry HTTP errors on its own. + for attempt in 1 2 3; do + yarn install --network-timeout 100000 && break + if [[ "$attempt" -eq 3 ]]; then + echo "yarn install failed after 3 attempts" >&2 + exit 1 + fi + echo "::warning::yarn install attempt $attempt failed (registry blip?); retrying in $((attempt * 15))s" + sleep $((attempt * 15)) + done - name: Run Coverage working-directory: ${{ env.UI_WORKING_DIRECTORY }} run: yarn test:cov-summary diff --git a/docs/decisions/2026-10-16-ci-yarn-installs-retry-transient-registry-errors.md b/docs/decisions/2026-10-16-ci-yarn-installs-retry-transient-registry-errors.md new file mode 100644 index 000000000000..21bd12b0b796 --- /dev/null +++ b/docs/decisions/2026-10-16-ci-yarn-installs-retry-transient-registry-errors.md @@ -0,0 +1,29 @@ +# CI yarn installs retry transient registry errors + +- **Status:** Accepted +- **Revisions:** v1 2026-10-16 (initial) +- **Deciders:** Chirag Madlani +- **Guard:** reviewer +- **Related:** #35556; RDF Playwright run 38749383300 attempt 1 + +## Context +Yarn v1 does not retry HTTP 5xx responses on tarball fetches. One `502 Bad Gateway` from +`registry.yarnpkg.com` aborts the whole install and fails the job before any test runs, as it did +in the RDF Playwright run above. `playwright-e2e-reusable.yml` already wrapped its installs in a +retry loop; the other workflows did not. + +## Decision +Every CI yarn v1 install whose failure fails the job runs in a 3-attempt loop with 15s then 30s +linear backoff and `--network-timeout 100000`. The loop is written inline in each workflow step, +not in a shared composite action or script: several of these workflows run on +`pull_request_target` with the PR head checked out, where a shared helper would execute the PR's +own copy of it. + +Exempt: installs marked `continue-on-error` (their failure cannot fail the job) and the +`frontend-maven-plugin` installs in the poms. + +## Consequences +A registry blip costs up to ~45s of waiting instead of a red job. A real outage fails after three +attempts, at most about three install durations plus the waits. A new workflow that runs +`yarn install` copies the same block. Revisit when the UI moves to yarn ≥2, which retries network +errors itself, at which point the loops can go.