From 37e827048aaa4980abbae1098e248e17c0988f65 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:46:59 -0700 Subject: [PATCH 01/36] Add retry command action Add a repo-local composite action for running shell commands with three attempts and exponential backoff. Keeping this local avoids another marketplace dependency while giving workflows a consistent way to handle transient network failures from package registries, release asset uploads, and other external services. Store the caller command in an environment variable before writing it to a temporary script, so command text cannot accidentally terminate a heredoc in the action implementation. --- .github/actions/retry-command/action.yml | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/actions/retry-command/action.yml diff --git a/.github/actions/retry-command/action.yml b/.github/actions/retry-command/action.yml new file mode 100644 index 0000000000..97241fd7ba --- /dev/null +++ b/.github/actions/retry-command/action.yml @@ -0,0 +1,55 @@ +name: Retry command +description: Run a shell command with retries and exponential backoff. +inputs: + command: + description: Command to run. + required: true + working-directory: + description: Directory to run the command in. + required: false + default: . + attempts: + description: Maximum number of attempts. + required: false + default: "3" + delay-seconds: + description: Initial delay between attempts. + required: false + default: "20" +runs: + using: composite + steps: + - shell: bash + env: + RETRY_COMMAND: ${{ inputs.command }} + working-directory: ${{ inputs.working-directory }} + run: | + set -euo pipefail + + attempts="${{ inputs.attempts }}" + delay="${{ inputs.delay-seconds }}" + script="$(mktemp)" + trap 'rm -f "$script"' EXIT + + printf '%s\n' "$RETRY_COMMAND" > "$script" + + for attempt in $(seq 1 "$attempts"); do + echo "Running attempt ${attempt}/${attempts}" + set +e + bash -euo pipefail "$script" + status=$? + set -e + + if [ "$status" -eq 0 ]; then + exit 0 + fi + + if [ "$attempt" -eq "$attempts" ]; then + echo "Command failed after ${attempts} attempts" + exit "$status" + fi + + echo "Command failed with exit code ${status}; retrying in ${delay}s" + sleep "$delay" + delay=$((delay * 2)) + done From 9a850e2d7e74f448b73059bf942ef297a216b5cf Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:47:08 -0700 Subject: [PATCH 02/36] Retry Scrut install in pyrefly workflow The Scrut install downloads from crates.io and can fail for transient Cargo registry or network issues. Retrying the pinned install gives fresh runners a chance to recover without hiding deterministic failures after the final attempt. --- .github/workflows/pyrefly.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pyrefly.yml b/.github/workflows/pyrefly.yml index e597d2d15a..9f41904e6d 100644 --- a/.github/workflows/pyrefly.yml +++ b/.github/workflows/pyrefly.yml @@ -28,7 +28,9 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} run: echo "CARGO_HOME=C:\\cargo" >> ${{ matrix.github_env }} - name: install Scrut - run: cargo install scrut --locked + uses: ./.github/actions/retry-command + with: + command: cargo install scrut --version 0.4.3 --locked # Scrut doesn't support Windows yet if: ${{ matrix.os != 'windows-latest' }} - name: set up rust cache From a80df4980ecb6fd0b4e6334658727177ad9139a2 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:47:16 -0700 Subject: [PATCH 03/36] Retry Cargo fetch in pyrefly workflow Cargo dependency resolution and downloads have shown transient registry and Git network failures on recent main-branch runs. Fetch dependencies explicitly with retries so later build, clippy, and test steps are less likely to fail mid-build from the same temporary network problem. --- .github/workflows/pyrefly.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pyrefly.yml b/.github/workflows/pyrefly.yml index 9f41904e6d..5f40c38d46 100644 --- a/.github/workflows/pyrefly.yml +++ b/.github/workflows/pyrefly.yml @@ -41,6 +41,10 @@ jobs: with: toolchain: stable components: clippy, rustfmt + - name: Fetch Cargo dependencies + uses: ./.github/actions/retry-command + with: + command: cargo fetch --locked - run: cargo fmt -- --check - run: cargo clippy --release - run: cargo build --release From a0e40eb782028f4da138675722b3a1c756df29f3 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:47:25 -0700 Subject: [PATCH 04/36] Retry website yarn install The website dependency install reaches the Yarn/npm registry and can fail when network or registry responses are transiently unavailable. Use the shared retry action around the frozen-lockfile install so lockfile-invalidated runs can recover from short registry outages. --- .github/workflows/build_and_test_website.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index d0754d0ea0..6c4b66fc89 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -30,7 +30,10 @@ jobs: with: node-version: "20.x" - name: Install yarn deps - run: cd website && yarn install + uses: ./.github/actions/retry-command + with: + working-directory: website + command: yarn install --frozen-lockfile - name: Install wasm-pack run: cargo install wasm-pack wasm-opt - name: Build From a738cfb94c88e55a6b6b8ba6ef328caf1e2daa22 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:47:34 -0700 Subject: [PATCH 05/36] Retry website wasm tool install Installing wasm-pack and wasm-opt downloads from crates.io, which is one of the network surfaces that has failed transiently in recent CI. Pin the tool versions and retry the installs so cache misses still have a reliable path to rebuild the tools. --- .github/workflows/build_and_test_website.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index 6c4b66fc89..e29ce6ac4f 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -35,7 +35,11 @@ jobs: working-directory: website command: yarn install --frozen-lockfile - name: Install wasm-pack - run: cargo install wasm-pack wasm-opt + uses: ./.github/actions/retry-command + with: + command: | + cargo install wasm-pack --version 0.15.0 --locked + cargo install wasm-opt --version 0.116.1 --locked - name: Build working-directory: ./website run: cargo version && chmod +x scripts/build.sh && scripts/build.sh && yarn build-wasm-for-test From fb71ebe4969ca52bb6e54cf786516d8d7b41249f Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:47:47 -0700 Subject: [PATCH 06/36] Retry website Cargo dependency fetch The website wasm build needs the wasm32 target and Cargo dependencies. Fetching them before the build with retries isolates transient rustup, registry, or Git network failures from the later build step and gives invalidated caches a chance to refill successfully. --- .github/workflows/build_and_test_website.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index e29ce6ac4f..3461b9cd5f 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -40,6 +40,12 @@ jobs: command: | cargo install wasm-pack --version 0.15.0 --locked cargo install wasm-opt --version 0.116.1 --locked + - name: Fetch wasm Cargo dependencies + uses: ./.github/actions/retry-command + with: + command: | + rustup target add wasm32-unknown-unknown + cargo fetch --locked --manifest-path pyrefly_wasm/Cargo.toml --target wasm32-unknown-unknown - name: Build working-directory: ./website run: cargo version && chmod +x scripts/build.sh && scripts/build.sh && yarn build-wasm-for-test From 820e223ffff5fadd303f960911e2d85d3d2d0c4c Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:47:57 -0700 Subject: [PATCH 07/36] Retry extension container dependency install Ubuntu container setup depends on apt mirrors and can fail for temporary mirror or network issues. Retrying the apt update/install step makes those arm Linux extension builds less sensitive to short-lived package repository failures. --- .github/workflows/build_extension.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_extension.yml b/.github/workflows/build_extension.yml index e75878fb1c..333e7d17d1 100644 --- a/.github/workflows/build_extension.yml +++ b/.github/workflows/build_extension.yml @@ -107,9 +107,9 @@ jobs: - uses: actions/checkout@v6 - name: install toolchain dependencies if: ${{ matrix.container == 'ubuntu:20.04' }} - shell: bash - run: | - apt-get update && apt-get -y install curl build-essential + uses: ./.github/actions/retry-command + with: + command: apt-get update && apt-get -y install curl build-essential - uses: dtolnay/rust-toolchain@stable - name: set windows cargo home # we need to set CARGO_HOME to a high-up directory on Windows machines, since some dependencies cloned From b9c644aa15281a2322d10e8e1dd0c040cc281fed Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:48:07 -0700 Subject: [PATCH 08/36] Retry extension npm install The extension package step runs npm ci against the npm registry. Recent CI has seen registry/network flakes, so retry the install to let transient failures recover while keeping the lockfile-controlled dependency set unchanged. --- .github/workflows/build_extension.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_extension.yml b/.github/workflows/build_extension.yml index 333e7d17d1..7cdce0886c 100644 --- a/.github/workflows/build_extension.yml +++ b/.github/workflows/build_extension.yml @@ -157,8 +157,11 @@ jobs: cache: npm - name: save platform name run: echo "platform=${{ matrix.platform }}-${{ matrix.arch }}" >> ${{ matrix.github_env }} - - run: npm ci - working-directory: lsp/ + - name: Install extension npm dependencies + uses: ./.github/actions/retry-command + with: + working-directory: lsp/ + command: npm ci - run: npx vsce package --target ${{ env.platform }} ${{ needs.get_version.outputs.prerelease_flag }} ${{needs.get_version.outputs.marketplace_version}} working-directory: lsp/ - uses: actions/upload-artifact@v6 From 9d0da0df7df79f0a5aceef0dff7125457e82cde9 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:48:17 -0700 Subject: [PATCH 09/36] Retry extension test npm install Extension test jobs also run npm ci before compiling and testing. Retrying this registry-backed step reduces failures from temporary npm/network issues, especially on cache misses or newly provisioned runners. --- .github/workflows/test_extension.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_extension.yml b/.github/workflows/test_extension.yml index 271047abc9..3211b98160 100644 --- a/.github/workflows/test_extension.yml +++ b/.github/workflows/test_extension.yml @@ -78,8 +78,11 @@ jobs: with: node-version: 22 cache: npm - - run: npm ci - working-directory: lsp/ + - name: Install extension npm dependencies + uses: ./.github/actions/retry-command + with: + working-directory: lsp/ + command: npm ci - run: npm run compile working-directory: lsp/ - run: xvfb-run -a npm run test From 4badcc6e4c823bc6e1f68239e98d5a1826690e94 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:48:29 -0700 Subject: [PATCH 10/36] Retry extension VS Code tests The VS Code test command can download a large VS Code test binary, and that download has failed transiently in recent CI runs. Retrying the test invocation keeps Linux xvfb behavior intact while allowing temporary download failures to recover. --- .github/workflows/test_extension.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_extension.yml b/.github/workflows/test_extension.yml index 3211b98160..ceba0f76cd 100644 --- a/.github/workflows/test_extension.yml +++ b/.github/workflows/test_extension.yml @@ -85,9 +85,15 @@ jobs: command: npm ci - run: npm run compile working-directory: lsp/ - - run: xvfb-run -a npm run test - working-directory: lsp/ + - name: Run extension tests on Linux + uses: ./.github/actions/retry-command if: runner.os == 'Linux' - - run: npm run test - working-directory: lsp/ + with: + working-directory: lsp/ + command: xvfb-run -a npm run test + - name: Run extension tests + uses: ./.github/actions/retry-command if: runner.os != 'Linux' + with: + working-directory: lsp/ + command: npm run test From e44190531f3c7196e2af7b50d5b31dafec98b444 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:48:41 -0700 Subject: [PATCH 11/36] Retry primer type checker install Primer comparison installs pyright and mypy from Python package indexes. Retrying this install protects scheduled primer runs from transient package index or network failures without changing the selected package versions. --- .github/workflows/primer_comparison.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/primer_comparison.yml b/.github/workflows/primer_comparison.yml index 056b1340b4..25a10f03f1 100644 --- a/.github/workflows/primer_comparison.yml +++ b/.github/workflows/primer_comparison.yml @@ -38,7 +38,9 @@ jobs: toolchain: stable - name: Install type checkers - run: pip install pyright mypy + uses: ./.github/actions/retry-command + with: + command: pip install pyright mypy - name: Build pyrefly run: | From e7a0e299bec21538ca71a52f50723018846bd988 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:49:00 -0700 Subject: [PATCH 12/36] Retry primer Cargo dependency fetch Primer comparison builds Pyrefly after resolving Cargo dependencies. Adding a retried fetch step lets temporary Cargo registry or Git fetch failures recover before the expensive primer shard work starts. --- .github/workflows/primer_comparison.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/primer_comparison.yml b/.github/workflows/primer_comparison.yml index 25a10f03f1..3e899c76bf 100644 --- a/.github/workflows/primer_comparison.yml +++ b/.github/workflows/primer_comparison.yml @@ -42,6 +42,11 @@ jobs: with: command: pip install pyright mypy + - name: Fetch Cargo dependencies + uses: ./.github/actions/retry-command + with: + command: cargo fetch --locked --manifest-path pyrefly/Cargo.toml + - name: Build pyrefly run: | cargo build --release --manifest-path pyrefly/Cargo.toml From 5934260ad49127dde388344e44770fe9ab68378a Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:49:12 -0700 Subject: [PATCH 13/36] Retry issue ranking primer type checker install The optional issue-ranking primer job installs pyright and mypy from external package indexes. Retrying the install makes manual runs more resilient to transient package index and network failures. --- .github/workflows/issue_ranking.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/issue_ranking.yml b/.github/workflows/issue_ranking.yml index a26db83f9b..abc7ecd0b8 100644 --- a/.github/workflows/issue_ranking.yml +++ b/.github/workflows/issue_ranking.yml @@ -52,7 +52,9 @@ jobs: toolchain: stable - name: Install type checkers - run: pip install pyright mypy + uses: ./.github/actions/retry-command + with: + command: pip install pyright mypy - name: Build pyrefly run: | From 31fe9eef2e077f443db6514f1b1e7bf73527430f Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:49:21 -0700 Subject: [PATCH 14/36] Retry issue ranking Cargo dependency fetch Issue ranking's optional primer path builds Pyrefly, so it has the same Cargo registry and Git fetch exposure as primer comparison. Fetch with retries before building so temporary dependency download failures do not fail the whole run. --- .github/workflows/issue_ranking.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/issue_ranking.yml b/.github/workflows/issue_ranking.yml index abc7ecd0b8..08aeedcad7 100644 --- a/.github/workflows/issue_ranking.yml +++ b/.github/workflows/issue_ranking.yml @@ -56,6 +56,11 @@ jobs: with: command: pip install pyright mypy + - name: Fetch Cargo dependencies + uses: ./.github/actions/retry-command + with: + command: cargo fetch --locked --manifest-path pyrefly/Cargo.toml + - name: Build pyrefly run: | cargo build --release --manifest-path pyrefly/Cargo.toml From 80c225f9856b29e919a4dea682d67e1902141d08 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:49:31 -0700 Subject: [PATCH 15/36] Retry issue ranking snippet tool install Snippet checking installs pyrefly, pyright, and mypy from package indexes. Retrying that install helps manual issue-ranking runs survive temporary PyPI or network failures while preserving the existing install command and diagnostics. --- .github/workflows/issue_ranking.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/issue_ranking.yml b/.github/workflows/issue_ranking.yml index 08aeedcad7..22d34ebab7 100644 --- a/.github/workflows/issue_ranking.yml +++ b/.github/workflows/issue_ranking.yml @@ -168,13 +168,15 @@ jobs: # Install type checkers for snippet checking - name: Install type checkers if: ${{ inputs.check_snippets }} - run: | - echo "=== Installing type checkers ===" - pip install pyrefly pyright mypy - echo "pyrefly version: $(pyrefly --version 2>&1 || echo 'not found')" - echo "pyright version: $(pyright --version 2>&1 || echo 'not found')" - echo "mypy version: $(mypy --version 2>&1 || echo 'not found')" - echo "pyrefly path: $(which pyrefly 2>&1 || echo 'not found')" + uses: ./.github/actions/retry-command + with: + command: | + echo "=== Installing type checkers ===" + pip install pyrefly pyright mypy + echo "pyrefly version: $(pyrefly --version 2>&1 || echo 'not found')" + echo "pyright version: $(pyright --version 2>&1 || echo 'not found')" + echo "mypy version: $(mypy --version 2>&1 || echo 'not found')" + echo "pyrefly path: $(which pyrefly 2>&1 || echo 'not found')" # Download primer results if available - name: Download primer results From 1ca8e73b68117bbf2b4e25858b5794febef7609a Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:49:42 -0700 Subject: [PATCH 16/36] Retry mypy primer dependency install mypy_primer is installed from GitHub via pip, which depends on both package index and Git network access. Retrying the dependency install reduces PR job failures from short-lived network problems before the expensive shard work begins. --- .github/workflows/mypy_primer.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index bf6ed29334..5722eaedc9 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -36,9 +36,11 @@ jobs: with: python-version: "3.13" - name: Install dependencies - run: | - python -m pip install -U pip - pip install git+https://github.com/hauntsaninja/mypy_primer.git + uses: ./pyrefly_to_test/.github/actions/retry-command + with: + command: | + python -m pip install -U pip + pip install git+https://github.com/hauntsaninja/mypy_primer.git - uses: dtolnay/rust-toolchain@master with: toolchain: stable From 32a1c8fac366b6471274a0fa570c9db1d4f3283d Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:49:55 -0700 Subject: [PATCH 17/36] Retry mypy primer Cargo dependency fetch Each mypy_primer shard builds both the PR commit and base commit. Fetching their Cargo registry or Git dependencies can fail on transient network errors, so retry cargo fetch for each checkout before building. The cargo build steps remain single-shot so compiler errors are reported without repeated backoff. --- .github/workflows/mypy_primer.yml | 55 +++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index 5722eaedc9..18cf514a59 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -45,7 +45,7 @@ jobs: with: toolchain: stable components: clippy, rustfmt - - name: Run mypy_primer + - name: Prepare mypy_primer comparison shell: bash run: | cd pyrefly_to_test @@ -57,35 +57,62 @@ jobs: echo "base commit" git rev-list --format=%s --max-count=1 base_commit + git checkout "$GITHUB_SHA" + echo '' cd .. BASE_DIR=$(pwd)/primer_base mkdir -p $BASE_DIR + echo "BASE_DIR=$BASE_DIR" >> "$GITHUB_ENV" - # Build pyrefly for "new" commit and install wrapper NEW_DIR=$BASE_DIR/pyrefly_new mkdir -p $NEW_DIR - cd pyrefly_to_test && git checkout $GITHUB_SHA - CARGO_TARGET_DIR=$NEW_DIR/target cargo build --release --manifest-path pyrefly/Cargo.toml - BINARY_DIR=$NEW_DIR/target/release - mv $BINARY_DIR/pyrefly $BINARY_DIR/pyrefly-real - cp scripts/pyrefly_primer_wrapper.sh $BINARY_DIR/pyrefly - chmod +x $BINARY_DIR/pyrefly + echo "NEW_DIR=$NEW_DIR" >> "$GITHUB_ENV" - # Build pyrefly for "old" commit and install wrapper OLD_DIR=$BASE_DIR/pyrefly_old mkdir -p $OLD_DIR - git checkout base_commit - CARGO_TARGET_DIR=$OLD_DIR/target cargo build --release --manifest-path pyrefly/Cargo.toml + echo "OLD_DIR=$OLD_DIR" >> "$GITHUB_ENV" + - name: Fetch new Pyrefly Cargo dependencies + uses: ./pyrefly_to_test/.github/actions/retry-command + with: + working-directory: pyrefly_to_test + command: cargo fetch --manifest-path pyrefly/Cargo.toml + - name: Build new Pyrefly + shell: bash + working-directory: pyrefly_to_test + run: CARGO_TARGET_DIR="$NEW_DIR/target" cargo build --release --manifest-path pyrefly/Cargo.toml + - name: Install new Pyrefly primer wrapper + shell: bash + run: | + BINARY_DIR=$NEW_DIR/target/release + mv $BINARY_DIR/pyrefly $BINARY_DIR/pyrefly-real + cp pyrefly_to_test/scripts/pyrefly_primer_wrapper.sh $BINARY_DIR/pyrefly + chmod +x $BINARY_DIR/pyrefly + - name: Fetch old Pyrefly Cargo dependencies + uses: ./pyrefly_to_test/.github/actions/retry-command + with: + working-directory: pyrefly_to_test + command: | + git checkout base_commit + cargo fetch --manifest-path pyrefly/Cargo.toml + - name: Build old Pyrefly + shell: bash + working-directory: pyrefly_to_test + run: CARGO_TARGET_DIR="$OLD_DIR/target" cargo build --release --manifest-path pyrefly/Cargo.toml + - name: Install old Pyrefly primer wrapper + shell: bash + run: | BINARY_DIR=$OLD_DIR/target/release mv $BINARY_DIR/pyrefly $BINARY_DIR/pyrefly-real # Use the wrapper from the new commit (old commit may not have it) - git checkout $GITHUB_SHA -- scripts/pyrefly_primer_wrapper.sh + cd pyrefly_to_test + git checkout "$GITHUB_SHA" -- scripts/pyrefly_primer_wrapper.sh cp scripts/pyrefly_primer_wrapper.sh $BINARY_DIR/pyrefly chmod +x $BINARY_DIR/pyrefly - - cd .. + - name: Run mypy_primer + shell: bash + run: | # fail action if exit code isn't zero or one ( MYPY_PRIMER_NO_REBUILD=1 mypy_primer \ From 998b43de933d88f069e39c54516a631b4f596467 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:50:06 -0700 Subject: [PATCH 18/36] Retry Alpine package install in wheel tests The musllinux wheel smoke test installs python3 from Alpine repositories inside Docker. Retrying apk add protects the test from temporary Alpine mirror or network failures without changing the wheel being tested. --- .github/workflows/build_binaries.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml index 09123181ae..f9eda7290d 100644 --- a/.github/workflows/build_binaries.yml +++ b/.github/workflows/build_binaries.yml @@ -244,7 +244,18 @@ jobs: -v ${{ github.workspace }}:/io -w /io \ --env PACKAGE_NAME --env BINARY_NAME \ alpine:latest sh -c ' - apk add --no-cache python3 + attempt=1 + delay=20 + until apk add --no-cache python3; do + status=$? + if [ "$attempt" -eq 3 ]; then + exit "$status" + fi + echo "apk add failed with exit code ${status}; retrying in ${delay}s" + sleep "$delay" + attempt=$((attempt + 1)) + delay=$((delay * 2)) + done python3 -m venv .venv .venv/bin/pip install "${PACKAGE_NAME}" --no-index --find-links pyrefly/dist/ --force-reinstall .venv/bin/"${BINARY_NAME}" --version From 49ae8061375d985ca60595d86e4acbaedc66e916 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:50:17 -0700 Subject: [PATCH 19/36] Retry release container dependency install Release container setup depends on apt mirrors and the GitHub CLI package repository. Retrying the setup step makes release binary builds more robust to temporary package mirror, keyring download, or network failures. --- .github/workflows/release_binaries.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release_binaries.yml b/.github/workflows/release_binaries.yml index da4170aa2e..9f51d0f796 100644 --- a/.github/workflows/release_binaries.yml +++ b/.github/workflows/release_binaries.yml @@ -94,14 +94,16 @@ jobs: - name: Install container dependencies if: matrix.container == 'ubuntu:20.04' - run: | - apt-get update && apt-get -y install curl build-essential git - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg - chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null - apt-get update && apt-get -y install gh - # Fix git safe.directory for container builds (checkout creates repo with different owner) - git config --global --add safe.directory "$GITHUB_WORKSPACE" + uses: ./.github/actions/retry-command + with: + command: | + apt-get update && apt-get -y install curl build-essential git + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg + chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null + apt-get update && apt-get -y install gh + # Fix git safe.directory for container builds (checkout creates repo with different owner) + git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable From ca5e81396a217e8ad1cbda9c75a3799a7ef081d1 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:50:27 -0700 Subject: [PATCH 20/36] Retry Unix release asset upload Uploading release assets calls the GitHub Releases API and can fail for transient service or network issues. Retrying the Unix upload step improves release reliability while keeping --clobber behavior unchanged. --- .github/workflows/release_binaries.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release_binaries.yml b/.github/workflows/release_binaries.yml index 9f51d0f796..4988df04f8 100644 --- a/.github/workflows/release_binaries.yml +++ b/.github/workflows/release_binaries.yml @@ -174,11 +174,13 @@ jobs: - name: Upload to release (Unix) if: runner.os != 'Windows' - run: | - gh release upload ${{ env.TAG_NAME }} \ - ${{ matrix.artifact_name }}.tar.gz \ - ${{ matrix.artifact_name }}.tar.gz.sha256 \ - --clobber + uses: ./.github/actions/retry-command + with: + command: | + gh release upload "$TAG_NAME" \ + ${{ matrix.artifact_name }}.tar.gz \ + ${{ matrix.artifact_name }}.tar.gz.sha256 \ + --clobber - name: Upload to release (Windows) if: runner.os == 'Windows' From 4b4b503644979809d1b69a93b28d873b39a38988 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:50:37 -0700 Subject: [PATCH 21/36] Retry Windows release asset upload Windows release asset uploads use the same GitHub Releases API as the Unix jobs and can hit transient network or service errors. Retry the upload with the same artifact names and --clobber semantics. --- .github/workflows/release_binaries.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release_binaries.yml b/.github/workflows/release_binaries.yml index 4988df04f8..3372b26bfe 100644 --- a/.github/workflows/release_binaries.yml +++ b/.github/workflows/release_binaries.yml @@ -184,12 +184,13 @@ jobs: - name: Upload to release (Windows) if: runner.os == 'Windows' - shell: pwsh - run: | - gh release upload ${{ env.TAG_NAME }} ` - "${{ matrix.artifact_name }}.zip" ` - "${{ matrix.artifact_name }}.zip.sha256" ` - --clobber + uses: ./.github/actions/retry-command + with: + command: | + gh release upload "$TAG_NAME" \ + "${{ matrix.artifact_name }}.zip" \ + "${{ matrix.artifact_name }}.zip.sha256" \ + --clobber wasm: name: Build pyrefly-wasm From 05697eb2e34e5f1fb9c27fb0479f6449bb3190d3 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:51:07 -0700 Subject: [PATCH 22/36] Cache website Yarn dependencies Cache the Yarn package-manager cache used by the website install. The key is derived from website/yarn.lock through setup-node, so dependency changes invalidate the cache while unchanged lockfiles avoid repeated registry downloads. --- .github/workflows/build_and_test_website.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index 3461b9cd5f..1e84df1f74 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -29,6 +29,8 @@ jobs: uses: actions/setup-node@v6 with: node-version: "20.x" + cache: yarn + cache-dependency-path: website/yarn.lock - name: Install yarn deps uses: ./.github/actions/retry-command with: From 825f163d023a84e3dde3679ad545fa2cc42cfae3 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:51:21 -0700 Subject: [PATCH 23/36] Cache website wasm tools Cache the installed wasm-pack and wasm-opt binaries so website runs do not rebuild tool dependencies on every cacheable run. The cache key includes OS, runner architecture, and explicit tool versions, which are the inputs that determine whether the cached binaries are compatible. --- .github/workflows/build_and_test_website.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index 1e84df1f74..34a0b775dd 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -31,12 +31,21 @@ jobs: node-version: "20.x" cache: yarn cache-dependency-path: website/yarn.lock + - name: Restore wasm tool cache + id: wasm-tool-cache + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/wasm-pack + ~/.cargo/bin/wasm-opt + key: ${{ runner.os }}-wasm-pack-0.15.0-wasm-opt-0.116.1 - name: Install yarn deps uses: ./.github/actions/retry-command with: working-directory: website command: yarn install --frozen-lockfile - name: Install wasm-pack + if: steps.wasm-tool-cache.outputs.cache-hit != 'true' uses: ./.github/actions/retry-command with: command: | From acc92886335163b519b87ba70a2143836260396a Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:51:34 -0700 Subject: [PATCH 24/36] Cache website Cargo registry Cache Cargo registry and Git dependency data for the website wasm build, and keep rust-cache's default CARGO_HOME/bin caching for installed Cargo CLI entries. The size-sensitive part is cache-targets: false: that avoids caching Pyrefly or wasm target outputs while still reducing dependency and tool download work on warm runs. rust-cache includes the Rust environment and Cargo lockfiles in its key, so dependency or toolchain changes invalidate the cache. wasm-pack and wasm-opt also have a separate OS/architecture/version-keyed cache. --- .github/workflows/build_and_test_website.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index 34a0b775dd..b22fae8f36 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -39,6 +39,11 @@ jobs: ~/.cargo/bin/wasm-pack ~/.cargo/bin/wasm-opt key: ${{ runner.os }}-wasm-pack-0.15.0-wasm-opt-0.116.1 + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-website + cache-targets: false - name: Install yarn deps uses: ./.github/actions/retry-command with: From 6f22ca4cbb2a79d9bcba255df339f2c3454c36b5 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:51:46 -0700 Subject: [PATCH 25/36] Use extension lockfile for build npm cache The extension build runs npm ci in lsp, so setup-node should key the npm cache from lsp/package-lock.json rather than relying on repository-root defaults. That invalidates the cache when extension dependencies change and avoids stale or unrelated root lockfile cache entries. --- .github/workflows/build_extension.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_extension.yml b/.github/workflows/build_extension.yml index 7cdce0886c..13d4c9d48f 100644 --- a/.github/workflows/build_extension.yml +++ b/.github/workflows/build_extension.yml @@ -155,6 +155,7 @@ jobs: with: node-version: 22 cache: npm + cache-dependency-path: lsp/package-lock.json - name: save platform name run: echo "platform=${{ matrix.platform }}-${{ matrix.arch }}" >> ${{ matrix.github_env }} - name: Install extension npm dependencies From 483c8a25f2c8a3ceae505d2c6bfbc7310b4e5c0c Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:52:02 -0700 Subject: [PATCH 26/36] Use extension lockfile for test npm cache Extension test jobs also install dependencies from lsp/package-lock.json. Using that lockfile as the setup-node cache dependency path makes cache invalidation match the dependency set that npm ci actually installs. --- .github/workflows/test_extension.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_extension.yml b/.github/workflows/test_extension.yml index ceba0f76cd..73e8e4f0fd 100644 --- a/.github/workflows/test_extension.yml +++ b/.github/workflows/test_extension.yml @@ -78,6 +78,7 @@ jobs: with: node-version: 22 cache: npm + cache-dependency-path: lsp/package-lock.json - name: Install extension npm dependencies uses: ./.github/actions/retry-command with: From 2fbd5f1dca8fd22f826fcf46d843707fe307cdab Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:52:14 -0700 Subject: [PATCH 27/36] Cache VS Code extension test binary Cache the VS Code test binary directories used by @vscode/test-electron so test jobs do not repeatedly download the large editor archive. The key includes OS, extension platform/arch, and the extension lockfile because those determine which test dependency and binary shape is expected. --- .github/workflows/test_extension.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/test_extension.yml b/.github/workflows/test_extension.yml index 73e8e4f0fd..816762fc54 100644 --- a/.github/workflows/test_extension.yml +++ b/.github/workflows/test_extension.yml @@ -79,6 +79,16 @@ jobs: node-version: 22 cache: npm cache-dependency-path: lsp/package-lock.json + - name: Restore VS Code test binary cache + uses: actions/cache@v4 + with: + path: | + ~/.vscode-test + .vscode-test + lsp/.vscode-test + key: ${{ runner.os }}-${{ matrix.platform }}-${{ matrix.arch }}-vscode-test-${{ hashFiles('lsp/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.platform }}-${{ matrix.arch }}-vscode-test- - name: Install extension npm dependencies uses: ./.github/actions/retry-command with: From ace9557d6075a2dfa91ed92f28392d5dcd62aad6 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:52:37 -0700 Subject: [PATCH 28/36] Cache wheel build Cargo registry Wheel builds download the same Cargo registry and Git dependencies across a large maturin matrix. Cache that Cargo dependency data and the default CARGO_HOME/bin contents, but keep cache-targets: false so platform-specific wheel build outputs are not stored in GitHub's cache. rust-cache keys include the job family plus the Rust environment and Cargo lockfiles, which is the right invalidation boundary for shared dependency downloads without creating huge target-dir caches for every wheel target. --- .github/workflows/build_binaries.yml | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/build_binaries.yml b/.github/workflows/build_binaries.yml index f9eda7290d..c2199c8441 100644 --- a/.github/workflows/build_binaries.yml +++ b/.github/workflows/build_binaries.yml @@ -25,6 +25,12 @@ jobs: - uses: actions/setup-python@v6 with: python-version: ${{ env.PYTHON_VERSION }} + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-build-binaries + shared-key: sdist + cache-targets: false - name: Build sdist uses: PyO3/maturin-action@v1 with: @@ -62,6 +68,12 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} architecture: ${{ matrix.platform.arch }} + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-build-binaries + shared-key: macos + cache-targets: false - name: Set jemalloc page size for macOS ARM64 if: ${{ matrix.platform.target == 'aarch64' }} run: echo "JEMALLOC_SYS_WITH_LG_PAGE=14" >> $GITHUB_ENV @@ -109,6 +121,12 @@ jobs: # we need to set CARGO_HOME to a high-up directory on Windows machines, since some dependencies cloned # by Cargo have long paths and will cause builds/tests to fail run: echo "CARGO_HOME=C:\\cargo" >> $env:GITHUB_ENV + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-build-binaries + shared-key: windows + cache-targets: false - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -148,6 +166,12 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-build-binaries + shared-key: linux + cache-targets: false - name: Build wheels if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'i686-unknown-linux-gnu' }} uses: PyO3/maturin-action@v1 @@ -217,6 +241,12 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-build-binaries + shared-key: musllinux + cache-targets: false - name: Build wheels if: ${{ matrix.target == 'x86_64-unknown-linux-musl' }} uses: PyO3/maturin-action@v1 From 7174d9e09c7b75e3a4ee94394ebb1aa6cb4a4123 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:52:49 -0700 Subject: [PATCH 29/36] Cache primer comparison Cargo registry Primer comparison builds Pyrefly in each shard and repeatedly needs Cargo registry and Git dependency data. Cache those downloads and CARGO_HOME/bin while leaving target directories uncached, which keeps cache size bounded for scheduled runs. rust-cache's Rust environment and lockfile keying invalidates this cache when Cargo inputs or the toolchain change, without tying it to Pyrefly build artifacts. --- .github/workflows/primer_comparison.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/primer_comparison.yml b/.github/workflows/primer_comparison.yml index 3e899c76bf..de32c5149b 100644 --- a/.github/workflows/primer_comparison.yml +++ b/.github/workflows/primer_comparison.yml @@ -37,6 +37,12 @@ jobs: with: toolchain: stable + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-primer-comparison + cache-targets: false + - name: Install type checkers uses: ./.github/actions/retry-command with: From db3cf513d9a08567db73544e428b29fa8099e9e2 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:53:00 -0700 Subject: [PATCH 30/36] Cache issue ranking primer Cargo registry The optional issue-ranking primer shards build Pyrefly and benefit from the same Cargo dependency cache as primer comparison. Cache registry/Git downloads and CARGO_HOME/bin, but not target outputs, so manual runs avoid repeated network work without storing bulky build artifacts. The rust-cache environment hash covers the Cargo lockfiles and toolchain, so dependency changes invalidate the cache naturally. --- .github/workflows/issue_ranking.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/issue_ranking.yml b/.github/workflows/issue_ranking.yml index 22d34ebab7..1bf04508b4 100644 --- a/.github/workflows/issue_ranking.yml +++ b/.github/workflows/issue_ranking.yml @@ -51,6 +51,12 @@ jobs: with: toolchain: stable + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-issue-ranking-primer + cache-targets: false + - name: Install type checkers uses: ./.github/actions/retry-command with: From 96fee15c1f4f886734e85578b2885fe6cf51a3b8 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:53:13 -0700 Subject: [PATCH 31/36] Cache mypy primer Cargo registry mypy_primer PR jobs build Pyrefly for both new and base commits across many shards. Cache Cargo registry/Git data and CARGO_HOME/bin for the checked-out workspace, but keep target outputs disabled so the cache does not balloon with per-shard build artifacts. Using the pyrefly_to_test workspace lets rust-cache compute invalidation from that checkout's Cargo lockfiles and Rust environment, which is the dependency boundary these builds need. --- .github/workflows/mypy_primer.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index 18cf514a59..e6604e66aa 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -45,6 +45,12 @@ jobs: with: toolchain: stable components: clippy, rustfmt + - name: Set up Rust cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: pyrefly-mypy-primer + cache-targets: false + workspaces: pyrefly_to_test - name: Prepare mypy_primer comparison shell: bash run: | From b4b0b7b7ba87029c2b277e9720269fe1c32ad870 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:55:15 -0700 Subject: [PATCH 32/36] Key website wasm tools by runner architecture The cached wasm-pack and wasm-opt binaries are architecture-specific. Include runner.arch in the cache key so x64 and arm64 runners cannot restore incompatible binaries while still sharing cache entries across identical OS/architecture/version combinations. --- .github/workflows/build_and_test_website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test_website.yml b/.github/workflows/build_and_test_website.yml index b22fae8f36..a0ed273eaa 100644 --- a/.github/workflows/build_and_test_website.yml +++ b/.github/workflows/build_and_test_website.yml @@ -38,7 +38,7 @@ jobs: path: | ~/.cargo/bin/wasm-pack ~/.cargo/bin/wasm-opt - key: ${{ runner.os }}-wasm-pack-0.15.0-wasm-opt-0.116.1 + key: ${{ runner.os }}-${{ runner.arch }}-wasm-pack-0.15.0-wasm-opt-0.116.1 - name: Set up Rust cache uses: Swatinem/rust-cache@v2 with: From e5db9c96ea8f68dd615b67f975b7f6c94ba3e46b Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 09:55:58 -0700 Subject: [PATCH 33/36] Refresh VS Code test cache weekly The VS Code test config does not pin an editor version, so the downloaded stable VS Code binary can change even when package-lock.json does not. Add a weekly key component and hash the test config so caches stay useful but periodically refresh as upstream VS Code stable advances. --- .github/workflows/test_extension.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_extension.yml b/.github/workflows/test_extension.yml index 816762fc54..8e641cf55d 100644 --- a/.github/workflows/test_extension.yml +++ b/.github/workflows/test_extension.yml @@ -79,6 +79,9 @@ jobs: node-version: 22 cache: npm cache-dependency-path: lsp/package-lock.json + - name: Set VS Code cache week + shell: bash + run: echo "VSCODE_CACHE_WEEK=$(date -u +%G-%V)" >> "$GITHUB_ENV" - name: Restore VS Code test binary cache uses: actions/cache@v4 with: @@ -86,8 +89,9 @@ jobs: ~/.vscode-test .vscode-test lsp/.vscode-test - key: ${{ runner.os }}-${{ matrix.platform }}-${{ matrix.arch }}-vscode-test-${{ hashFiles('lsp/package-lock.json') }} + key: ${{ runner.os }}-${{ matrix.platform }}-${{ matrix.arch }}-vscode-test-${{ env.VSCODE_CACHE_WEEK }}-${{ hashFiles('lsp/package-lock.json', 'lsp/.vscode-test.mjs') }} restore-keys: | + ${{ runner.os }}-${{ matrix.platform }}-${{ matrix.arch }}-vscode-test-${{ env.VSCODE_CACHE_WEEK }}- ${{ runner.os }}-${{ matrix.platform }}-${{ matrix.arch }}-vscode-test- - name: Install extension npm dependencies uses: ./.github/actions/retry-command From 1a6d3b07eb06122a464c021de6b8cc5d904e56b7 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 11:28:44 -0700 Subject: [PATCH 34/36] Cache Scrut binary in pyrefly workflow Scrut is installed with cargo install on every non-Windows pyrefly run. That install can require registry downloads and local build work, so cache the installed scrut binary plus Cargo's install metadata under a key that includes OS, runner architecture, and the pinned Scrut version. The versioned key gives precise invalidation when the workflow moves to a different Scrut release, while leaving Pyrefly target outputs untouched. The install step still runs on cache misses and is retried for transient crates.io or network failures. --- .github/workflows/pyrefly.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pyrefly.yml b/.github/workflows/pyrefly.yml index 5f40c38d46..1af02aae30 100644 --- a/.github/workflows/pyrefly.yml +++ b/.github/workflows/pyrefly.yml @@ -27,10 +27,24 @@ jobs: # by Cargo have long paths and will cause builds/tests to fail if: ${{ matrix.os == 'windows-latest' }} run: echo "CARGO_HOME=C:\\cargo" >> ${{ matrix.github_env }} - - name: install Scrut + - name: Restore Scrut cache + uses: actions/cache@v4 + if: ${{ matrix.os != 'windows-latest' }} + with: + path: | + ~/.cargo/bin/scrut + ~/.cargo/.crates.toml + ~/.cargo/.crates2.json + key: ${{ runner.os }}-${{ runner.arch }}-scrut-0.4.3-v2 + - name: Install Scrut uses: ./.github/actions/retry-command with: - command: cargo install scrut --version 0.4.3 --locked + command: | + if command -v scrut >/dev/null 2>&1 && scrut --version | grep -q '0\.4\.3'; then + scrut --version + else + cargo install scrut --version 0.4.3 --locked --force + fi # Scrut doesn't support Windows yet if: ${{ matrix.os != 'windows-latest' }} - name: set up rust cache From bcab4abb7e05b2a0dceb83df39ab644ce85a15a9 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 12:12:39 -0700 Subject: [PATCH 35/36] Add packaged Rust toolchain file The repository already has pyrefly_wasm/rust-toolchain as a symlink to ../pyrefly/rust-toolchain, and the pyrefly package metadata includes a rust-toolchain file in source distributions. The target file was missing, leaving the symlink broken. Swatinem/rust-cache scans rust-toolchain files when constructing its environment hash, so the broken symlink made cache setup emit ENOENT in the branch workflow runs and prevented clean cache restore/save behavior. Add the missing stable toolchain file so the symlink resolves and the cache key can include the toolchain input normally. --- pyrefly/rust-toolchain | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 pyrefly/rust-toolchain diff --git a/pyrefly/rust-toolchain b/pyrefly/rust-toolchain new file mode 100644 index 0000000000..292fe499e3 --- /dev/null +++ b/pyrefly/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "stable" From bd492e11fd62eb61e5d1af0c0674e9d8475bd6e4 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Wed, 17 Jun 2026 12:17:55 -0700 Subject: [PATCH 36/36] Retry extension Cargo dependency fetch The extension workflows build Pyrefly before packaging or testing the VS Code extension. A branch run hit a transient crates.io connection reset inside the actions-rust-cross cargo build step while fetching serde, which bypassed the retry wrapper because the fetch happened inside the third-party build action. Fetch the Pyrefly Cargo dependencies explicitly through the local retry-command action before either the cross-compile action or native cargo build runs. For cross targets, include the matrix target in cargo fetch so target-specific dependencies are covered. This keeps the existing Rust cache useful on warm runs and gives cold or invalidated caches retry coverage before the expensive build step. --- .github/workflows/build_extension.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build_extension.yml b/.github/workflows/build_extension.yml index 13d4c9d48f..99f7b30bb4 100644 --- a/.github/workflows/build_extension.yml +++ b/.github/workflows/build_extension.yml @@ -126,6 +126,17 @@ jobs: - name: set jemalloc page size for ARM64 macOS if: ${{ matrix.arch == 'arm64' && matrix.platform == 'darwin' }} run: echo "JEMALLOC_SYS_WITH_LG_PAGE=14" >> ${{ matrix.github_env }} + - name: Fetch Cargo dependencies + uses: ./.github/actions/retry-command + env: + RUST_TARGET: ${{ matrix.rust_target }} + with: + command: | + if [ -n "$RUST_TARGET" ]; then + cargo fetch --locked --manifest-path pyrefly/Cargo.toml --target "$RUST_TARGET" + else + cargo fetch --locked --manifest-path pyrefly/Cargo.toml + fi - name: build pyrefly binary (cross-compile) if: ${{ matrix.rust_target != '' }} uses: houseabsolute/actions-rust-cross@v1