diff --git a/.github/actions/linux-deps/action.yml b/.github/actions/linux-deps/action.yml index 62402fa4..62cf9d30 100644 --- a/.github/actions/linux-deps/action.yml +++ b/.github/actions/linux-deps/action.yml @@ -7,14 +7,45 @@ description: > runs: using: composite steps: - - shell: bash + # The .deb files are cached because the runners' Ubuntu mirror is sometimes + # very slow: the same 64 MB took 20 s on one run and 13-18 minutes on + # others. The key is the exact set of files apt would download, so a new + # package version or runner image makes a new cache instead of installing + # stale ones. + - id: debs + shell: bash + env: + PACKAGES: >- + libdbus-1-dev + libgtk-3-dev + libayatana-appindicator3-dev + librsvg2-dev + libsoup-3.0-dev + libjavascriptcoregtk-4.1-dev + libwebkit2gtk-4.1-dev run: | sudo apt-get update - sudo apt-get install -y \ - libdbus-1-dev \ - libgtk-3-dev \ - libayatana-appindicator3-dev \ - librsvg2-dev \ - libsoup-3.0-dev \ - libjavascriptcoregtk-4.1-dev \ - libwebkit2gtk-4.1-dev + # Field 2 is the file name (package_version_arch.deb); the URL in field + # 1 names whichever mirror this runner got, so it stays out of the key. + key=$(sudo apt-get install -y -qq --print-uris $PACKAGES | awk '{print $2}' | sort | sha256sum | cut -c1-16) + echo "packages=$PACKAGES" >> "$GITHUB_OUTPUT" + echo "key=$key" >> "$GITHUB_OUTPUT" + echo "dir=$RUNNER_TEMP/apt-debs" >> "$GITHUB_OUTPUT" + + - uses: actions/cache@v6 + with: + path: ${{ steps.debs.outputs.dir }} + key: apt-debs-${{ runner.os }}-${{ runner.arch }}-${{ steps.debs.outputs.key }} + + - shell: bash + env: + PACKAGES: ${{ steps.debs.outputs.packages }} + DEBS: ${{ steps.debs.outputs.dir }} + run: | + # apt reads and downloads its archives in our directory instead of + # /var/cache/apt/archives, so a restored cache is used as it is and a + # fresh download lands where the cache step saves from. + mkdir -p "$DEBS/partial" + sudo apt-get install -y -o Dir::Cache::Archives="$DEBS" $PACKAGES + # apt's lock file is root-only; the cache is saved as the runner user. + sudo rm -rf "$DEBS/lock" "$DEBS/partial" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d8d75ada..36654439 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -117,7 +117,11 @@ jobs: cache: pnpm cache-dependency-path: app/main/pnpm-lock.yaml - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + # No rust-cache. The version stamp rebuilds our crates anyway, and a + # release's cache was always evicted before the next release (the repo + # sits at GitHub's 10 GB cache limit), so saving one cost time and pushed + # out the caches Build and Check do reuse. + # protoc for prost-build. A composite action (no Node runtime): # arduino/setup-protoc is still on the deprecated Node 20. - uses: taiki-e/install-action@v2 diff --git a/Cargo.toml b/Cargo.toml index eca74dad..88ab7221 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,10 @@ version = "1.0.0" # Profiles must live at the workspace root (per-crate profiles are ignored). [profile.release] -lto = true +# Thin LTO with the default 16 codegen units, not fat LTO with one. A release +# always compiles from scratch, and fat LTO's single-threaded final step was +# over half of it: ~4 of ~7.5 minutes per OS in CI. A cold local build went +# from 207 s to 118 s. The exe grows about 3 MB (15.5 to 18.9 MB on Windows); +# transfers are bound by the network and Bluetooth, not the CPU. +lto = "thin" opt-level = 3 -codegen-units = 1