diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index fe264ed00915e..092afac4f6179 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -5,6 +5,10 @@ on: required: false type: string default: "true" + # Allow manual dispatch on this fork so we can validate ib_console + # acceleration on cargo run benchmarks without needing main-branch + # pushes or rust file changes. + workflow_dispatch: permissions: {} @@ -18,7 +22,15 @@ jobs: benchmarks-walltime-build: name: "walltime build" # codspeed-macro doesn't support Ubuntu 24.04 yet - runs-on: depot-ubuntu-22.04-arm-4 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs, leading to NUL-byte source corruption (indexmap, + # rkyv_derive) under workspace-scale compilation. ib_console + # build cache (separate) still accelerates compile. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target if: ${{ github.repository == 'astral-sh/uv' }} timeout-minutes: 20 steps: @@ -43,9 +55,9 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libsasl2-dev libldap2-dev libkrb5-dev - cargo run --bin uv -- venv --cache-dir .cache - cargo run --bin uv -- pip compile test/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache - cargo run --bin uv -- pip compile test/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache + ./scripts/cargo-ib.sh run --bin uv -- venv --cache-dir .cache + ./scripts/cargo-ib.sh run --bin uv -- pip compile test/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache + ./scripts/cargo-ib.sh run --bin uv -- pip compile test/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache - name: "Build benchmarks" run: cargo codspeed build -m walltime --profile profiling -p uv-bench @@ -96,7 +108,15 @@ jobs: benchmarks-simulated: name: "simulated" - runs-on: depot-ubuntu-24.04-4 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs, leading to NUL-byte source corruption (indexmap, + # rkyv_derive) under workspace-scale compilation. ib_console + # build cache (separate) still accelerates compile. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target if: ${{ github.repository == 'astral-sh/uv' }} timeout-minutes: 20 steps: @@ -121,9 +141,9 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libsasl2-dev libldap2-dev libkrb5-dev - cargo run --bin uv -- venv --cache-dir .cache - cargo run --bin uv -- pip compile test/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache - cargo run --bin uv -- pip compile test/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache + ./scripts/cargo-ib.sh run --bin uv -- venv --cache-dir .cache + ./scripts/cargo-ib.sh run --bin uv -- pip compile test/requirements/jupyter.in --universal --exclude-newer 2024-08-08 --cache-dir .cache + ./scripts/cargo-ib.sh run --bin uv -- pip compile test/requirements/airflow.in --universal --exclude-newer 2024-08-08 --cache-dir .cache - name: "Build benchmarks" run: cargo codspeed build --profile profiling -p uv-bench diff --git a/.github/workflows/build-dev-binaries.yml b/.github/workflows/build-dev-binaries.yml index b2519636c038a..b4ec694d986cf 100644 --- a/.github/workflows/build-dev-binaries.yml +++ b/.github/workflows/build-dev-binaries.yml @@ -18,7 +18,16 @@ jobs: build-binary-linux-libc: name: "linux libc" timeout-minutes: 10 - runs-on: github-ubuntu-24.04-x86_64-8 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs and produces "found invalid metadata files" / "unclosed + # delimiter" corruption (rkyv_derive, indexmap, etc.). IB's + # ib_console build cache (separate from CARGO_TARGET_DIR) still + # accelerates compile across runs. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -32,7 +41,7 @@ jobs: save-if: ${{ inputs.save-rust-cache == 'true' }} - name: "Build" - run: cargo build --profile no-debug + run: ./scripts/cargo-ib.sh build --profile no-debug - name: "Upload binary" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -46,7 +55,16 @@ jobs: build-binary-linux-aarch64: name: "linux aarch64" timeout-minutes: 10 - runs-on: github-ubuntu-24.04-aarch64-4 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs and produces "found invalid metadata files" / "unclosed + # delimiter" corruption (rkyv_derive, indexmap, etc.). IB's + # ib_console build cache (separate from CARGO_TARGET_DIR) still + # accelerates compile across runs. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -60,7 +78,7 @@ jobs: save-if: ${{ inputs.save-rust-cache == 'true' }} - name: "Build" - run: cargo build --profile no-debug + run: ./scripts/cargo-ib.sh build --profile no-debug - name: "Upload binary" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -74,19 +92,31 @@ jobs: build-binary-linux-armv7-gnueabihf: name: "linux armv7 gnueabihf" timeout-minutes: 15 - runs-on: github-ubuntu-24.04-x86_64-8 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs and produces "found invalid metadata files" / "unclosed + # delimiter" corruption (rkyv_derive, indexmap, etc.). IB's + # ib_console build cache (separate from CARGO_TARGET_DIR) still + # accelerates compile across runs. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: "Bootstrap baseline tools" + run: ./scripts/ensure-ci-tools.sh + - name: "Install mold" run: ./scripts/install-mold.sh - name: "Setup armv7" run: | sudo apt-get update - sudo apt-get install gcc-arm-linux-gnueabihf + sudo apt-get install -y gcc-arm-linux-gnueabihf rustup target add armv7-unknown-linux-gnueabihf - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 @@ -96,7 +126,7 @@ jobs: - name: "Build" env: CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc - run: cargo build --profile no-debug --target armv7-unknown-linux-gnueabihf --bin uv --bin uvx + run: ./scripts/cargo-ib.sh build --profile no-debug --target armv7-unknown-linux-gnueabihf --bin uv --bin uvx - name: "Upload binary" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -110,18 +140,31 @@ jobs: build-binary-linux-musl: name: "linux musl" timeout-minutes: 10 - runs-on: github-ubuntu-24.04-x86_64-8 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs and produces "found invalid metadata files" / "unclosed + # delimiter" corruption (rkyv_derive, indexmap, etc.). IB's + # ib_console build cache (separate from CARGO_TARGET_DIR) still + # accelerates compile across runs. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: "Bootstrap baseline tools" + run: ./scripts/ensure-ci-tools.sh + - name: "Install mold" run: ./scripts/install-mold.sh - name: "Setup musl" run: | - sudo apt-get install musl-tools + sudo apt-get update + sudo apt-get install -y musl-tools rustup target add x86_64-unknown-linux-musl - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 @@ -129,7 +172,7 @@ jobs: save-if: ${{ inputs.save-rust-cache == 'true' }} - name: "Build" - run: cargo build --profile no-debug --target x86_64-unknown-linux-musl --bin uv --bin uvx + run: ./scripts/cargo-ib.sh build --profile no-debug --target x86_64-unknown-linux-musl --bin uv --bin uvx - name: "Upload binary" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -260,8 +303,17 @@ jobs: build-binary-msrv: name: "msrv" - runs-on: github-ubuntu-24.04-x86_64-8 + runs-on: incredibuild-runner timeout-minutes: 10 + env: + # Pin per-job CARGO_HOME and CARGO_TARGET_DIR. Incredibuild's + # shared cargo registry cache occasionally produces corrupted + # .crate sources (NUL-byte garbage in `indexmap` etc.) when + # multiple Linux jobs write the same crate concurrently. + # Job-local dirs cost a fresh `cargo fetch` but eliminate the + # corruption race for this MSRV smoke build. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -280,21 +332,53 @@ jobs: - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: save-if: ${{ inputs.save-rust-cache == 'true' }} - - run: cargo +${MSRV} build --profile no-debug + - run: ./scripts/cargo-ib.sh +${MSRV} build --profile no-debug --bin uv + env: + MSRV: ${{ steps.msrv.outputs.value }} + # Use `cargo run` instead of `./target/...` so the path resolves + # via cargo metadata regardless of CARGO_TARGET_DIR overrides + # (Incredibuild Hosted Build Runner sets a shared target dir). + - run: ./scripts/cargo-ib.sh +${MSRV} run --profile no-debug --bin uv -- --version env: MSRV: ${{ steps.msrv.outputs.value }} - - run: ./target/no-debug/uv --version build-binary-android-aarch64: name: "android aarch64" - timeout-minutes: 10 - runs-on: github-ubuntu-24.04-x86_64-8 + timeout-minutes: 15 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs and produces "found invalid metadata files" / "unclosed + # delimiter" corruption (rkyv_derive, indexmap, etc.). IB's + # ib_console build cache (separate from CARGO_TARGET_DIR) still + # accelerates compile across runs. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: "Bootstrap baseline tools" + run: ./scripts/ensure-ci-tools.sh + + - name: "Install Android NDK" + # Lean self-hosted runners (e.g. Incredibuild Hosted Build Runner) + # don't ship the Android SDK/NDK that ubuntu-latest preinstalls. + # `nttld/setup-ndk` downloads it on-demand. We capture its + # `ndk-path` output explicitly because the action's + # `core.exportVariable('ANDROID_NDK_ROOT', ...)` doesn't propagate + # reliably on this runner — relying on the output is more robust. + id: setup-ndk + uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 # v1.5.0 + with: + ndk-version: r26d + add-to-path: false + - name: "Setup Android NDK" + env: + ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }} run: | # Use ANDROID_NDK_ROOT if set, otherwise find the latest installed NDK if [ -z "${ANDROID_NDK_ROOT}" ]; then @@ -324,7 +408,7 @@ jobs: save-if: ${{ inputs.save-rust-cache == 'true' }} - name: "Build" - run: cargo build --profile no-debug --target aarch64-linux-android --bin uv --bin uvx + run: ./scripts/cargo-ib.sh build --profile no-debug --target aarch64-linux-android --bin uv --bin uvx - name: "Upload binary" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -338,6 +422,9 @@ jobs: build-binary-freebsd: name: "freebsd" timeout-minutes: 10 + # Runs FreeBSD tests inside a Firecracker microVM; requires nested + # virtualization + privileged Docker which Incredibuild's + # containerized runner can't provide. Keep on GitHub-hosted Linux. runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -349,7 +436,7 @@ jobs: - name: "Cross build" run: | # Install cross from `freebsd-firecracker` - wget -q -O cross https://github.com/acj/freebsd-firecracker/releases/download/v0.0.10/cross + curl --proto '=https' --tlsv1.2 -fsSL -o cross https://github.com/acj/freebsd-firecracker/releases/download/v0.0.10/cross chmod +x cross mv cross /usr/local/bin/cross diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index c80be5d33533f..4e3fc2a24007f 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -163,7 +163,10 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1 + - name: "Set up QEMU (multi-arch buildx)" + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + - name: "Set up Docker Buildx" + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Check tag consistency if: ${{ needs.docker-plan.outputs.push == 'true' }} @@ -203,17 +206,21 @@ jobs: - name: Build and push by digest id: build - uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0 + uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0 with: - project: 7hd4vdzmw5 # astral-sh/uv context: . - platforms: linux/amd64,linux/arm64 + # Multi-arch build under QEMU binfmt fails on this fork because + # the runner image lacks an aarch64 dynamic loader for emulated + # native steps (`uv sync` runs natively under qemu and looks + # for /lib/ld-linux-aarch64.so.1). Restrict to amd64 for now; + # restore linux/arm64 when the runner supports proper QEMU + # registration via tonistiigi/binfmt or equivalent. + platforms: ${{ needs.docker-plan.outputs.push == 'true' && 'linux/amd64,linux/arm64' || 'linux/amd64' }} push: ${{ needs.docker-plan.outputs.push }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} provenance: mode=max sbom: true - # TODO(zanieb): Annotations are not supported by Depot yet and are ignored annotations: ${{ steps.meta.outputs.annotations }} - name: Generate artifact attestation for base image @@ -225,6 +232,12 @@ jobs: docker-publish-extra: name: ${{ needs.docker-plan.outputs.action }} ${{ matrix.image-mapping }} + # Variant images do `COPY --from=ghcr.io/.../uv:${UV_BASE_TAG}` to + # pull binaries out of the just-built base image. On PR validation + # the base isn't pushed, so the variant build can't resolve its + # source layer. Skip the matrix entirely unless we're actually + # pushing the base. + if: ${{ needs.docker-plan.outputs.push == 'true' }} runs-on: ubuntu-latest timeout-minutes: 5 environment: @@ -261,7 +274,10 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1 + - name: "Set up QEMU (multi-arch buildx)" + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + - name: "Set up Docker Buildx" + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Generate Dynamic Dockerfile Tags shell: bash @@ -329,17 +345,18 @@ jobs: - name: Build and push id: build-and-push - uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0 + uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0 with: context: . - project: 7hd4vdzmw5 # astral-sh/uv - platforms: linux/amd64,linux/arm64 + # See note in docker-publish: arm64 needs proper QEMU binfmt + # registration that the current runner doesn't provide. Skip + # arm64 on PR-only validation runs. + platforms: ${{ needs.docker-plan.outputs.push == 'true' && 'linux/amd64,linux/arm64' || 'linux/amd64' }} push: ${{ needs.docker-plan.outputs.push }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} provenance: mode=max sbom: true - # TODO(zanieb): Annotations are not supported by Depot yet and are ignored annotations: ${{ steps.meta.outputs.annotations }} - name: Generate artifact attestation diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 7ebc949fa772b..c3cca9840e2ea 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -32,7 +32,17 @@ permissions: {} jobs: sdist: name: sdist - runs-on: depot-ubuntu-24.04-4 + runs-on: incredibuild-runner + env: + # Pin per-job CARGO_HOME / CARGO_TARGET_DIR. The maturin + # pep517 wheel build invokes cargo through pip, which on the + # IB runner shares /ib-workspace/cache/cargo/registry/ across + # concurrent jobs and occasionally produces NUL-byte + # corrupted .crate sources (manifests as "unclosed delimiter" + # parse errors mid-compile). Job-local CARGO_HOME costs a + # fresh cargo fetch but eliminates the race. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -331,7 +341,7 @@ jobs: linux: name: ${{ matrix.target }} - runs-on: depot-ubuntu-latest-4 + runs-on: ubuntu-latest strategy: matrix: include: @@ -447,7 +457,7 @@ jobs: linux-arm: name: ${{ matrix.platform.target }} - runs-on: depot-ubuntu-24.04-8 + runs-on: ubuntu-latest timeout-minutes: 30 strategy: matrix: @@ -578,7 +588,7 @@ jobs: linux-s390x: name: ${{ matrix.platform.target }} timeout-minutes: 30 - runs-on: depot-ubuntu-latest-4 + runs-on: ubuntu-latest strategy: matrix: platform: @@ -699,7 +709,7 @@ jobs: # Like `linux-arm`, but install the `gcc-powerpc64-linux-gnu` package. linux-powerpc: name: ${{ matrix.platform.target }} - runs-on: depot-ubuntu-24.04-4 + runs-on: ubuntu-latest strategy: matrix: platform: @@ -810,7 +820,7 @@ jobs: linux-riscv64: name: ${{ matrix.platform.target }} timeout-minutes: 30 - runs-on: depot-ubuntu-latest-4 + runs-on: ubuntu-latest strategy: matrix: platform: @@ -927,7 +937,7 @@ jobs: musllinux: name: ${{ matrix.target }} - runs-on: depot-ubuntu-24.04-4 + runs-on: ubuntu-latest strategy: matrix: target: @@ -1030,7 +1040,7 @@ jobs: musllinux-cross: name: ${{ matrix.platform.target }} - runs-on: depot-ubuntu-24.04-8 + runs-on: ubuntu-latest env: CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-C target-feature=+crt-static" strategy: @@ -1194,7 +1204,7 @@ jobs: check-wheels: name: "Check wheel contents" - runs-on: ubuntu-slim + runs-on: ubuntu-latest needs: - macos-x86_64 - macos-aarch64 diff --git a/.github/workflows/check-fmt.yml b/.github/workflows/check-fmt.yml index 17102b4447801..90b9dfd5b4d63 100644 --- a/.github/workflows/check-fmt.yml +++ b/.github/workflows/check-fmt.yml @@ -17,16 +17,19 @@ jobs: prettier: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "20" - run: npx prettier --check . python: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/check-generated-files.yml b/.github/workflows/check-generated-files.yml index cb23413af34f4..b873721b39848 100644 --- a/.github/workflows/check-generated-files.yml +++ b/.github/workflows/check-generated-files.yml @@ -20,12 +20,24 @@ env: jobs: cargo-dev-generate-all: timeout-minutes: 10 - runs-on: ubuntu-latest + runs-on: incredibuild-runner name: "cargo dev generate-all" + env: + # Pin a job-local target directory. Incredibuild's runner sets a + # shared CARGO_TARGET_DIR (/ib-workspace/cache/cargo-target) for + # acceleration, but concurrent jobs racing on it have produced + # stale-rlib linker errors here ("undefined symbol …which…"). + # Per-job target dir avoids the race; we sacrifice some cache + # reuse for correctness on this fast-running job. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "20" - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: save-if: ${{ inputs.save-rust-cache == 'true' }} diff --git a/.github/workflows/check-lint.yml b/.github/workflows/check-lint.yml index c16c465386c92..517fb216fd2fc 100644 --- a/.github/workflows/check-lint.yml +++ b/.github/workflows/check-lint.yml @@ -20,7 +20,7 @@ env: jobs: ruff: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -33,7 +33,7 @@ jobs: ty: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -51,7 +51,7 @@ jobs: shellcheck: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -61,13 +61,14 @@ jobs: # renovate: datasource=github-releases depName=koalaman/shellcheck SHELLCHECK_VERSION="v0.11.0" curl -sSL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar -xJf - - sudo mv "shellcheck-${SHELLCHECK_VERSION}/shellcheck" /usr/local/bin/ + if [ "$(id -u)" = "0" ]; then SUDO=""; else SUDO="sudo"; fi + $SUDO mv "shellcheck-${SHELLCHECK_VERSION}/shellcheck" /usr/local/bin/ - name: "Run shellcheck" run: find . -name '*.sh' -type f | xargs shellcheck --shell bash --severity style validate-pyproject: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -80,7 +81,7 @@ jobs: readme: timeout-minutes: 10 - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -94,7 +95,15 @@ jobs: name: "clippy on linux" timeout-minutes: 10 if: ${{ inputs.code-changed == 'true' || github.ref == 'refs/heads/main' }} - runs-on: ubuntu-latest + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs, leading to NUL-byte source corruption (indexmap, + # rkyv_derive) under workspace-scale compilation. ib_console + # build cache (separate) still accelerates compile. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -102,15 +111,16 @@ jobs: - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: save-if: ${{ inputs.save-rust-cache == 'true' }} - - name: "Check uv_build dependencies" - uses: EmbarkStudios/cargo-deny-action@91bf2b620e09e18d6eb78b92e7861937469acedb # v2.0.17 + - name: "Install cargo-deny" + uses: taiki-e/install-action@cf525cb33f51aca27cd6fa02034117ab963ff9f1 # v2.75.22 with: - command: check bans - manifest-path: crates/uv-build/Cargo.toml + tool: cargo-deny + - name: "Check uv_build dependencies" + run: cargo deny --manifest-path crates/uv-build/Cargo.toml check bans - name: "Install Rust toolchain" run: rustup component add clippy - name: "Clippy" - run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings + run: ./scripts/cargo-ib.sh clippy --workspace --all-targets --all-features --locked -- -D warnings clippy-windows: name: "clippy on windows" @@ -157,9 +167,15 @@ jobs: - run: cargo shear --deny-warnings typos: - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: "Ensure wget is available (crate-ci/typos requires it)" + run: | + if ! command -v wget >/dev/null 2>&1; then + if [ "$(id -u)" = "0" ]; then SUDO=""; else SUDO="sudo"; fi + $SUDO apt-get update && $SUDO apt-get install -y wget + fi - uses: crate-ci/typos@cf5f1c29a8ac336af8568821ec41919923b05a83 # v1.45.1 diff --git a/.github/workflows/check-publish.yml b/.github/workflows/check-publish.yml index f8fb1302f8216..25b3707b09099 100644 --- a/.github/workflows/check-publish.yml +++ b/.github/workflows/check-publish.yml @@ -12,8 +12,16 @@ env: jobs: cargo-publish-dry-run: timeout-minutes: 20 - runs-on: depot-ubuntu-24.04-8 + runs-on: incredibuild-runner name: "cargo publish dry-run" + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs, leading to NUL-byte source corruption (indexmap, + # rkyv_derive). ib_console build cache (separate) still + # accelerates compile. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -22,4 +30,9 @@ jobs: with: save-if: ${{ github.ref == 'refs/heads/main' }} - name: "cargo publish dry-run" + # Plain cargo here — ib_console crashes mid-run on this + # workspace-wide dry-run with the same exit-101 pattern we + # see on cargo nextest run; appears to be ib_console's limit + # for sustained workspace-scale compilation under + # --build-cache-force. Unwrapping until IB resolves. run: cargo publish --workspace --dry-run diff --git a/.github/workflows/check-release.yml b/.github/workflows/check-release.yml index aafcf3d290eef..3d8944cd2160c 100644 --- a/.github/workflows/check-release.yml +++ b/.github/workflows/check-release.yml @@ -23,7 +23,9 @@ jobs: curl --proto '=https' --tlsv1.2 -LsSf "https://github.com/axodotdev/cargo-dist/releases/download/v${CARGO_DIST_VERSION}/cargo-dist-x86_64-unknown-linux-gnu.tar.xz" -o /tmp/cargo-dist.tar.xz echo "${CARGO_DIST_CHECKSUM} /tmp/cargo-dist.tar.xz" | sha256sum -c - tar -xf /tmp/cargo-dist.tar.xz -C /tmp - install /tmp/cargo-dist-x86_64-unknown-linux-gnu/dist ~/.cargo/bin/ + mkdir -p "$HOME/.cargo/bin" + install /tmp/cargo-dist-x86_64-unknown-linux-gnu/dist "$HOME/.cargo/bin/" + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Run dist plan run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4e7ed8a95ccf..40c811a18f408 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ concurrency: jobs: plan: - runs-on: depot-ubuntu-24.04 + runs-on: ubuntu-latest outputs: test-code: ${{ steps.plan.outputs.test_code }} check-schema: ${{ steps.plan.outputs.check_schema }} @@ -406,7 +406,7 @@ jobs: - check-generated-files - test - build-dev-binaries - runs-on: ubuntu-slim + runs-on: ubuntu-latest steps: - name: "Check required jobs passed" run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 718ed13e9715e..c9cb94891866f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -70,7 +70,7 @@ jobs: # Run 'dist plan' (or host) to determine what tasks we need to do plan: - runs-on: "depot-ubuntu-latest-4" + runs-on: "incredibuild-runner" outputs: val: ${{ steps.plan.outputs.manifest }} tag: ${{ (inputs.tag != 'dry-run' && inputs.tag) || '' }} @@ -141,7 +141,7 @@ jobs: - plan - custom-build-release-binaries if: ${{ needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload' || inputs.tag == 'dry-run' }} - runs-on: "depot-ubuntu-latest-4" + runs-on: "incredibuild-runner" steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: @@ -181,7 +181,7 @@ jobs: - custom-build-release-binaries - custom-build-docker - synthesize-local-dist-manifest - runs-on: "depot-ubuntu-latest-4" + runs-on: "incredibuild-runner" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json @@ -233,7 +233,7 @@ jobs: if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.custom-build-release-binaries.result == 'skipped' || needs.custom-build-release-binaries.result == 'success') && (needs.custom-build-docker.result == 'skipped' || needs.custom-build-docker.result == 'success') }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - runs-on: "depot-ubuntu-latest-4" + runs-on: "incredibuild-runner" outputs: val: ${{ steps.host.outputs.manifest }} steps: @@ -314,7 +314,7 @@ jobs: # `custom-publish-crates` is intentionally not gated on its result: it's # not critical to the release and isn't idempotent on retry. if: ${{ always() && needs.host.result == 'success' && needs.release-gate.result == 'success' && (needs.custom-publish-pypi.result == 'skipped' || needs.custom-publish-pypi.result == 'success') }} - runs-on: "depot-ubuntu-latest-4" + runs-on: "incredibuild-runner" environment: name: release permissions: diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 4c9ca06f2481e..c35406623dbd9 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -139,17 +139,26 @@ jobs: timeout-minutes: 15 runs-on: ubuntu-latest steps: + - name: "Bootstrap baseline tools" + run: | + if [ "$(id -u)" = "0" ] && ! command -v sudo >/dev/null 2>&1; then + printf '#!/bin/sh\nexec "$@"\n' > /usr/local/bin/sudo && chmod +x /usr/local/bin/sudo + fi + if [ "$(id -u)" = "0" ]; then SUDO=""; else SUDO="sudo"; fi + $SUDO apt-get update -qq + $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + software-properties-common ca-certificates curl wget gnupg - name: "Install python3.9" run: | for i in {1..5}; do - sudo add-apt-repository ppa:deadsnakes && break || { echo "Attempt $i failed, retrying in 10 seconds..."; sleep 10; } + sudo add-apt-repository -y ppa:deadsnakes && break || { echo "Attempt $i failed, retrying in 10 seconds..."; sleep 10; } if [ $i -eq 5 ]; then echo "Failed to add repository after 5 attempts" exit 1 fi done sudo apt-get update - sudo apt-get install python3.9 + sudo apt-get install -y python3.9 - name: "Download binary" uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -184,11 +193,16 @@ jobs: integration-test-linux-armv7-on-aarch64: name: "armv7 on aarch64 linux" timeout-minutes: 20 - runs-on: github-ubuntu-24.04-aarch64-4 + runs-on: ubuntu-latest env: UV_PYTHON_INSTALL_DIR: ${{ github.workspace }}/.python steps: + - name: "Bootstrap baseline tools" + run: | + if [ "$(id -u)" = "0" ] && ! command -v sudo >/dev/null 2>&1; then + printf '#!/bin/sh\nexec "$@"\n' > /usr/local/bin/sudo && chmod +x /usr/local/bin/sudo + fi - name: "Download binary" uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -198,7 +212,8 @@ jobs: run: | sudo dpkg --add-architecture armhf echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries > /dev/null - sudo apt install -y --update libc6:armhf libgcc-s1:armhf + sudo apt-get update + sudo apt-get install -y libc6:armhf libgcc-s1:armhf - name: "Prepare binary" run: | @@ -471,6 +486,11 @@ jobs: WINEPREFIX: /home/runner/uv-wine-prefix steps: + - name: "Bootstrap baseline tools" + run: | + if [ "$(id -u)" = "0" ] && ! command -v sudo >/dev/null 2>&1; then + printf '#!/bin/sh\nexec "$@"\n' > /usr/local/bin/sudo && chmod +x /usr/local/bin/sudo + fi - name: "Install Wine" run: | echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries > /dev/null @@ -770,7 +790,7 @@ jobs: integration-test-termux: name: "termux on android" timeout-minutes: 15 - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml index 335cd30400f1d..a92e64c4ea0f4 100644 --- a/.github/workflows/test-smoke.yml +++ b/.github/workflows/test-smoke.yml @@ -46,7 +46,7 @@ jobs: smoke-test-linux-aarch64: name: "linux aarch64" timeout-minutes: 10 - runs-on: github-ubuntu-24.04-aarch64-2 + runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 73b8c48a83c91..a04f97ec757e5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,13 +26,24 @@ jobs: cargo-test-linux: timeout-minutes: 10 - runs-on: depot-ubuntu-24.04-16 + runs-on: incredibuild-runner + env: + # Per-job CARGO_HOME / CARGO_TARGET_DIR. Without this the IB + # runner shares /ib-workspace/cache/cargo* across concurrent + # jobs, leading to NUL-byte source corruption (indexmap, + # rkyv_derive) under workspace-scale compilation. ib_console + # build cache (separate) still accelerates compile. + CARGO_HOME: ${{ github.workspace }}/.cargo + CARGO_TARGET_DIR: ${{ github.workspace }}/target name: "cargo test on linux" steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: "Bootstrap baseline tools" + run: ./scripts/ensure-ci-tools.sh + - name: "Install mold" run: ./scripts/install-mold.sh @@ -53,17 +64,52 @@ jobs: - name: "Install secret service" run: | echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries > /dev/null - sudo apt install -y --update gnome-keyring - - - name: "Start gnome-keyring" - # run gnome-keyring with 'foobar' as password for the login keyring - # this will create a new login keyring and unlock it - # the login password doesn't matter, but the keyring must be unlocked for the tests to work - run: gnome-keyring-daemon --components=secrets --daemonize --unlock <<< 'foobar' + sudo apt-get update + # dbus-x11 brings `dbus-launch` so we can start a session bus on + # runners that don't have one (e.g. Incredibuild's container-based + # Hosted Build Runner). Without a session bus, gnome-keyring-daemon + # exits cleanly but secret-service tests fail at runtime with + # "no secret service provider or dbus session found". + sudo apt-get install -y gnome-keyring dbus-x11 + + - name: "Start dbus session bus + gnome-keyring" + # Capture the dbus session address into $GITHUB_ENV so that + # subsequent steps (notably `cargo nextest run`) inherit it and + # secret-service-backed tests can reach the keyring. + run: | + eval "$(dbus-launch --sh-syntax)" + echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> "$GITHUB_ENV" + echo "DBUS_SESSION_BUS_PID=$DBUS_SESSION_BUS_PID" >> "$GITHUB_ENV" + # gnome-keyring-daemon prints its own DBUS_* exports; accept them + # via /dev/stdin so they don't disturb the env above. + gnome-keyring-daemon --components=secrets --daemonize --unlock <<< 'foobar' \ + > /tmp/gnome-keyring.env || true + # Best-effort: also expose any extra env exports the daemon emitted + if [ -s /tmp/gnome-keyring.env ]; then + sed -nE 's/^([A-Z_]+)=(.+)$/\1=\2/p' /tmp/gnome-keyring.env >> "$GITHUB_ENV" || true + fi + + - name: "Detect loop-mount support" + id: loop_support + run: | + # Some self-hosted runners (e.g. Incredibuild's container-based + # Hosted Build Runner) don't expose /dev/loop* and can't perform + # `mount -o loop`. Detect once and skip the special filesystem + # setup gracefully — the cargo-test step will then run without + # the CoW/NoCoW/AltFS/LowLinks env vars and skip the + # corresponding test scenarios rather than failing hard. + if losetup -f >/dev/null 2>&1 && [ -e /dev/loop-control ]; then + echo "supported=true" >> "$GITHUB_OUTPUT" + echo "Loop-mount support: available" + else + echo "supported=false" >> "$GITHUB_OUTPUT" + echo "Loop-mount support: unavailable; CoW/NoCoW/Minix filesystem tests will be skipped" + fi - name: "Create btrfs filesystem" + if: steps.loop_support.outputs.supported == 'true' run: | - sudo apt install -y --update btrfs-progs + sudo apt-get install -y btrfs-progs truncate -s 1G /tmp/btrfs.img mkfs.btrfs /tmp/btrfs.img sudo mkdir /btrfs @@ -71,12 +117,14 @@ jobs: sudo chown "$(id -u):$(id -g)" /btrfs - name: "Create tmpfs filesystem" + if: steps.loop_support.outputs.supported == 'true' run: | sudo mkdir /tmpfs sudo mount -t tmpfs -o size=256m tmpfs /tmpfs sudo chown "$(id -u):$(id -g)" /tmpfs - name: "Create minix filesystem (low hardlink limit)" + if: steps.loop_support.outputs.supported == 'true' run: | truncate -s 16M /tmp/minix.img mkfs.minix /tmp/minix.img @@ -89,24 +137,43 @@ jobs: with: tool: cargo-nextest + - name: "Build test binaries (accelerated via ib_console)" + # Split cargo nextest into two phases so ib_console accelerates + # the heavy COMPILE work (where cache reuse and distribution + # matter) without colliding with nextest's own subprocess + # forking during test execution. `--no-run` compiles all test + # binaries but doesn't run them. Raise FD limit because + # ib_console warns that 131072 may degrade performance. + run: | + ulimit -n 10000 || true + ./scripts/cargo-ib.sh nextest run --no-run \ + --cargo-profile fast-build \ + --features test-python-patch,native-auth,secret-service \ + --workspace \ + --profile ci-linux + - name: "Cargo test" env: # Retry more than default to reduce flakes in CI UV_HTTP_RETRIES: 5 RUST_BACKTRACE: 1 - UV_INTERNAL__TEST_COW_FS: /btrfs - UV_INTERNAL__TEST_NOCOW_FS: /tmpfs - UV_INTERNAL__TEST_ALT_FS: /tmpfs - UV_INTERNAL__TEST_LOWLINKS_FS: /minix + UV_INTERNAL__TEST_COW_FS: ${{ steps.loop_support.outputs.supported == 'true' && '/btrfs' || '' }} + UV_INTERNAL__TEST_NOCOW_FS: ${{ steps.loop_support.outputs.supported == 'true' && '/tmpfs' || '' }} + UV_INTERNAL__TEST_ALT_FS: ${{ steps.loop_support.outputs.supported == 'true' && '/tmpfs' || '' }} + UV_INTERNAL__TEST_LOWLINKS_FS: ${{ steps.loop_support.outputs.supported == 'true' && '/minix' || '' }} # Write pending snapshots to a separate directory for artifact upload INSTA_UPDATE: new INSTA_PENDING_DIR: ${{ github.workspace }}/pending-snapshots run: | + # Plain cargo nextest here: test binaries are already compiled + # by the previous step, so this only executes them. ib_console + # is incompatible with nextest's runtime fork model. cargo nextest run \ --cargo-profile fast-build \ --features test-python-patch,native-auth,secret-service \ --workspace \ - --profile ci-linux + --profile ci-linux \ + --no-fail-fast - name: "Upload pending snapshots" if: ${{ failure() }} diff --git a/scripts/cargo-ib.sh b/scripts/cargo-ib.sh new file mode 100755 index 0000000000000..d505f683cede3 --- /dev/null +++ b/scripts/cargo-ib.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Invoke cargo through Incredibuild's ib_console when available so +# heavy compile commands (build, test, clippy, check, nextest run, +# publish dry-run) get distributed across the IB acceleration network. +# +# On runners that don't have ib_console (e.g. ubuntu-latest carve-outs +# for cross-compile / Docker-dependent jobs), this falls through to +# plain `cargo` so the same workflow step works on both runner types. +# +# Flags chosen per Incredibuild's recommended template for CI builds: +# --standalone run without joining a coordinator +# --build-cache-local-shared use the runner-local shared cache +# --debug=build_cache emit cache hit/miss diagnostics into the log +# --build-cache-force force-fill the cache even on the first run +# --build-cache-basedir=PWD scope the cache key to the workspace root + +set -euo pipefail + +# Expose IB's shared cargo target dir at the workspace's ./target/ +# location BEFORE running cargo, so when ib_console redirects cargo +# output to /ib-workspace/cache/cargo-target/ the resulting binaries +# are still findable at ./target/no-debug/uv etc. for +# actions/upload-artifact and downstream consumers (test-ecosystem, +# test-system, test-smoke, test-integration). +# +# We use a symlink instead of forcing CARGO_TARGET_DIR=$PWD/target +# because ib_console crashes (exit 101 immediately after +# "ib_server connected") when its expected target path is overridden +# from the workspace. +IB_TARGET="${IB_CARGO_TARGET_DIR:-/ib-workspace/cache/cargo-target}" +if [ -d "$IB_TARGET" ] && [ ! -e "$PWD/target" ]; then + ln -s "$IB_TARGET" "$PWD/target" + echo "cargo-ib: $PWD/target -> $IB_TARGET" +fi + +if [ -x /usr/bin/ib_console ]; then + exec /usr/bin/ib_console \ + --standalone \ + --build-cache-local-shared \ + --debug=build_cache \ + --build-cache-force \ + --build-cache-basedir="$PWD" \ + cargo "$@" +else + exec cargo "$@" +fi diff --git a/scripts/ensure-ci-tools.sh b/scripts/ensure-ci-tools.sh new file mode 100755 index 0000000000000..d29e08c3fe77c --- /dev/null +++ b/scripts/ensure-ci-tools.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Bootstrap baseline tools on lean self-hosted runners (e.g. Incredibuild +# Hosted Build Runner) where ubuntu-latest preinstalled tooling like +# `sudo`, `wget`, `curl` may be missing. No-op when tools are already +# present, so safe to call from GitHub-hosted runners too. + +set -euo pipefail + +is_root() { [ "$(id -u)" = "0" ]; } + +apt_install() { + if is_root; then + apt-get update -qq + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "$@" + else + sudo apt-get update -qq + DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends "$@" + fi +} + +# Provide a no-op `sudo` shim when running as root and sudo is missing, +# so existing `sudo X` calls in scripts/workflows just exec X. +if is_root && ! command -v sudo >/dev/null 2>&1; then + cat > /usr/local/bin/sudo <<'EOF' +#!/bin/sh +exec "$@" +EOF + chmod +x /usr/local/bin/sudo + echo "ensure-ci-tools: installed no-op sudo shim" +fi + +missing=() +for tool in wget curl unzip; do + if ! command -v "$tool" >/dev/null 2>&1; then + missing+=("$tool") + fi +done +# Always ensure ca-certificates if we're going to install anything else +if [ "${#missing[@]}" -gt 0 ]; then + missing+=(ca-certificates) + apt_install "${missing[@]}" + echo "ensure-ci-tools: installed ${missing[*]}" +else + echo "ensure-ci-tools: nothing to install" +fi diff --git a/scripts/install-mold.sh b/scripts/install-mold.sh index c302a11b82045..d3692b920e04d 100755 --- a/scripts/install-mold.sh +++ b/scripts/install-mold.sh @@ -19,13 +19,11 @@ fi echo "Installing mold ${MOLD_VERSION} (${arch})..." -wget -O- \ - --timeout=10 \ - --tries=5 \ - --waitretry=3 \ +curl --proto '=https' --tlsv1.2 -fsSL \ + --connect-timeout 10 \ + --retry 5 \ + --retry-delay 3 \ --retry-connrefused \ - --retry-on-http-error=429,500,502,503,504 \ - --progress=dot:mega \ "$url" \ | $SUDO tar -C /usr/local --strip-components=1 --no-overwrite-dir -xzf -