perf: Experimental environment activation cache (#2367) #5889
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
on: | |
push: | |
tags: | |
- "v*.*.*" | |
branches: | |
- main | |
paths-ignore: | |
- "docs/**" | |
- "mkdocs.yml" | |
- "*.md" | |
workflow_dispatch: | |
pull_request: | |
paths-ignore: | |
- "docs/**" | |
- "mkdocs.yml" | |
- "*.md" | |
name: Rust | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
env: | |
RUST_LOG: info | |
RUST_BACKTRACE: 1 | |
RUSTFLAGS: "-D warnings" | |
CARGO_TERM_COLOR: always | |
CICD_INTERMEDIATES_DIR: "_cicd-intermediates" | |
XDG_CACHE_HOME: ${{ github.workspace }}/.cache | |
jobs: | |
check-rustdoc-links: | |
name: Check intra-doc links | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: Swatinem/rust-cache@v2 | |
with: | |
save-if: false | |
# - name: Run sccache-cache | |
# uses: mozilla-actions/[email protected] | |
- uses: actions-rust-lang/setup-rust-toolchain@v1 | |
- run: | | |
for package in $(cargo metadata --no-deps --format-version=1 | jq -r '.packages[] | .name'); do | |
cargo rustdoc -p "$package" --all-features -- -D warnings -W unreachable-pub | |
done | |
format: | |
name: Cargo Format | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
- uses: actions-rust-lang/setup-rust-toolchain@v1 | |
with: | |
components: rustfmt | |
- name: Run rustfmt | |
uses: actions-rust-lang/rustfmt@v1 | |
lint: | |
name: Cargo Lint | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
- uses: actions-rust-lang/setup-rust-toolchain@v1 | |
with: | |
components: clippy | |
- uses: Swatinem/rust-cache@v2 | |
with: | |
save-if: false | |
- name: Run clippy | |
run: cargo clippy --all-targets --workspace | |
crate_metadata: | |
name: Extract crate metadata | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Extract crate information | |
id: crate_metadata | |
run: | | |
cargo metadata --no-deps --format-version 1 | jq -r '"name=" + (.packages[] | select(.name == "pixi") | .name)' | tee -a $GITHUB_OUTPUT | |
cargo metadata --no-deps --format-version 1 | jq -r '"version=" + (.packages[] | select(.name == "pixi") | .version)' | tee -a $GITHUB_OUTPUT | |
cargo metadata --no-deps --format-version 1 | jq -r '"maintainer=" + (.packages[] | select(.name == "pixi") | .authors[0])' | tee -a $GITHUB_OUTPUT | |
cargo metadata --no-deps --format-version 1 | jq -r '"homepage=" + (.packages[] | select(.name == "pixi") | .homepage)' | tee -a $GITHUB_OUTPUT | |
outputs: | |
name: ${{ steps.crate_metadata.outputs.name }} | |
version: ${{ steps.crate_metadata.outputs.version }} | |
maintainer: ${{ steps.crate_metadata.outputs.maintainer }} | |
homepage: ${{ steps.crate_metadata.outputs.homepage }} | |
# Checks for dependencies that are not used in the codebase | |
cargo-machete: | |
name: Cargo Machete | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Machete | |
uses: bnjbvr/cargo-machete@main | |
cargo-test: | |
name: Cargo Test | ${{ matrix.name }} | |
runs-on: ${{ matrix.os }} | |
timeout-minutes: 30 | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- { | |
name: "Linux", | |
target: x86_64-unknown-linux-musl, | |
os: "${{ contains(github.event.pull_request.labels.*.name, 'ci:free') && 'ubuntu-latest' || '8core_ubuntu_latest_runner' }}", | |
} | |
- { name: "macOS", target: x86_64-apple-darwin, os: macos-13 } | |
- { name: "macOS-arm", target: aarch64-apple-darwin, os: macos-14 } | |
- { | |
name: "Windows", | |
target: x86_64-pc-windows-msvc, | |
os: "${{ contains(github.event.pull_request.labels.*.name, 'ci:free') && 'windows-latest' || '16core_windows_latest_runner' }}", | |
} | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: prefix-dev/[email protected] | |
with: | |
cache: true | |
- uses: Swatinem/rust-cache@v2 | |
with: | |
workspaces: ". -> target-pixi" | |
key: ${{ hashFiles('pixi.lock') }} | |
- name: Test pixi | |
run: pixi run test-slow | |
build: | |
name: Build Binary | ${{ matrix.name }} | |
runs-on: ${{ matrix.os }} | |
needs: [crate_metadata] | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- name: "Linux-x86_64" | |
target: x86_64-unknown-linux-musl | |
os: "${{ contains(github.event.pull_request.labels.*.name, 'ci:free') && 'ubuntu-latest' || '8core_ubuntu_latest_runner' }}" | |
- name: "Linux-aarch64" | |
target: aarch64-unknown-linux-musl | |
os: ubuntu-latest | |
- name: "macOS-x86" | |
target: x86_64-apple-darwin | |
os: macos-13 | |
- name: "macOS-arm" | |
target: aarch64-apple-darwin | |
os: macos-14 | |
- name: "Windows" | |
target: x86_64-pc-windows-msvc | |
os: "${{ contains(github.event.pull_request.labels.*.name, 'ci:free') && 'windows-latest' || '16core_windows_latest_runner' }}" | |
- name: "Windows-arm" | |
target: aarch64-pc-windows-msvc | |
os: windows-latest | |
env: | |
# | |
# These are some environment variables that configure the build so that the binary size is reduced. | |
# Inspiration was taken from this blog: https://arusahni.net/blog/2020/03/optimizing-rust-binary-size.html | |
# They're only enable it on main and releases. | |
# | |
# Pick the profile to build, as defined in Cargo.toml | |
CARGO_PROFILE: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) && 'dist' || 'ci' }} | |
steps: | |
- name: Checkout source code | |
uses: actions/checkout@v4 | |
- name: Install Rust toolchain | |
uses: actions-rust-lang/setup-rust-toolchain@v1 | |
with: | |
target: ${{ matrix.target }} | |
cache: false | |
- uses: taiki-e/setup-cross-toolchain-action@v1 | |
with: | |
target: ${{ matrix.target }} | |
- name: Use static CRT on Windows | |
shell: bash | |
run: echo "RUSTFLAGS=${RUSTFLAGS} -C target-feature=+crt-static" >> "${GITHUB_ENV}" | |
if: endsWith(matrix.target, 'windows-msvc') | |
- uses: Swatinem/rust-cache@v2 | |
- name: Setup | Install cargo-wix [Windows] | |
# aarch64 is only supported in wix 4.0 development builds | |
if: startsWith(matrix.name, 'Windows') && matrix.target != 'aarch64-pc-windows-msvc' | |
run: cargo install --version 0.3.8 cargo-wix | |
env: | |
# cargo-wix does not require static crt | |
RUSTFLAGS: "" | |
- name: Show version information (Rust, cargo, GCC) | |
shell: bash | |
run: | | |
gcc --version || true | |
rustup -V | |
rustup toolchain list | |
cargo -V | |
rustc -V | |
- name: Check for release | |
id: is-release | |
shell: bash | |
run: | | |
unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE='true' ; fi | |
echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT | |
- name: Use rustls on musl targets. | |
id: build-options | |
if: contains(matrix.target, '-musl') | |
run: | | |
echo "CARGO_BUILD_OPTIONS=${CARGO_BUILD_OPTIONS}" >> $GITHUB_OUTPUT | |
- name: Build on Linux / Mac | |
if: runner.os != 'Windows' | |
run: > | |
cargo build | |
--locked | |
--profile $CARGO_PROFILE | |
--features self_update | |
${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}} | |
- name: Build on Windows | |
if: runner.os == 'Windows' | |
run: > | |
cargo build | |
--locked | |
--profile $env:CARGO_PROFILE | |
--features self_update | |
${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}} | |
- name: Set binary name & path | |
id: bin | |
shell: bash | |
run: | | |
# Figure out suffix of binary | |
EXE_SUFFIX="" | |
case ${{ matrix.target }} in | |
*-pc-windows-*) EXE_SUFFIX=".exe" ;; | |
esac; | |
# Setup paths | |
BIN_NAME="${{ needs.crate_metadata.outputs.name }}${EXE_SUFFIX}" | |
BIN_PATH="target/${{ matrix.target }}/${CARGO_PROFILE}/${BIN_NAME}" | |
# Let subsequent steps know where to find the binary | |
{ | |
echo "BIN_PATH=${BIN_PATH}" | |
echo "BIN_NAME=${BIN_NAME}" | |
echo "EXE_SUFFIX=${EXE_SUFFIX}" | |
} >> $GITHUB_OUTPUT | |
- name: Build msi Installer | |
if: startsWith(matrix.name, 'Windows') && matrix.target != 'aarch64-pc-windows-msvc' | |
run: > | |
cargo wix -v --no-build --nocapture -I install/windows/main.wxs | |
--profile $env:CARGO_PROFILE | |
--package pixi | |
--target ${{ matrix.target }} | |
--output target/wix/pixi-${{ matrix.target }}.msi | |
# Here we notarize the binary with a certificate from Apple | |
# To get a certificate, go to XCode and request a Developer ID certificate for the right team. | |
# Then export the certificate from XCode and copy it as base64 into the secrets. | |
# Using e.g. `openssl base64 -in ~/Desktop/DeveloperID.p12 | tr -d '\n' | pbcopy` (to copy to clipboard). | |
# The password is the password you used to export the certificate. | |
# The ident is the ident of the certificate, which you can find in the keychain. | |
# The apple id password is a app specific password that you can get on the apple website (https://support.apple.com/en-us/HT204397) (usually a UUID looking string) | |
# The team id is the team id of the Apple Developer Team. | |
- name: Notarize binary | |
# only execute this step when releasing, or on main branch and on macOS | |
if: startsWith(matrix.os, 'macOS-') && (github.ref == 'refs/heads/main' || steps.is-release.outputs.IS_RELEASE) | |
env: | |
APPLEID_TEAMID: ${{ secrets.APPLEID_TEAMID }} | |
APPLEID_USERNAME: ${{ secrets.APPLEID_USERNAME }} | |
APPLEID_PASSWORD: ${{ secrets.APPLEID_PASSWORD }} | |
DEVELOPER_ID_CERTIFICATE: ${{ secrets.DEVELOPER_ID_CERTIFICATE }} | |
DEVELOPER_ID_PASSWORD: ${{ secrets.DEVELOPER_ID_PASSWORD }} | |
DEVELOPER_ID_IDENT: ${{ secrets.DEVELOPER_ID_IDENT }} | |
KEYCHAIN_FILENAME: app-signing.keychain-db | |
BIN_PATH: ${{ steps.bin.outputs.BIN_PATH }} | |
run: | | |
export KEYCHAIN_ENTRY="AC_PASSWORD" | |
INSTALL_CERTIFICATE_PATH="$RUNNER_TEMP/install_certificate.p12" | |
KEYCHAIN_PATH="$RUNNER_TEMP/$KEYCHAIN_FILENAME" | |
# create temporary keychain | |
KEYCHAIN_PASSWORD=$(openssl rand -base64 32) | |
export KEYCHAIN_PASSWORD | |
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" | |
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
echo -n "$DEVELOPER_ID_CERTIFICATE" | base64 --decode -o $INSTALL_CERTIFICATE_PATH | |
security import $INSTALL_CERTIFICATE_PATH -P "$DEVELOPER_ID_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | |
security list-keychain -d user -s $KEYCHAIN_PATH | |
echo "Successfully imported Developer ID certificate into keychain" | |
# Add Apple Developer ID credentials to keychain | |
xcrun notarytool store-credentials "$KEYCHAIN_ENTRY" \ | |
--team-id "$APPLEID_TEAMID" \ | |
--apple-id "$APPLEID_USERNAME" \ | |
--password "$APPLEID_PASSWORD" \ | |
--keychain "$KEYCHAIN_PATH" | |
echo "Successfully added Apple Developer ID credentials to keychain" | |
echo "Now signing binary..." | |
# codesign binary | |
xcrun codesign --force --options=runtime --keychain "$KEYCHAIN_PATH" \ | |
--timestamp --sign "$DEVELOPER_ID_IDENT" --verbose "$BIN_PATH" \ | |
--identifier "dev.prefix.pixi" | |
zip pixi.zip ${BIN_PATH} | |
# notarize binary | |
xcrun notarytool submit pixi.zip --keychain-profile "$KEYCHAIN_ENTRY" --wait | |
- name: Create tarball | |
id: package | |
shell: bash | |
run: | | |
PKG_suffix=".tar.gz" ; case ${{ matrix.target }} in *-pc-windows-*) PKG_suffix=".zip" ;; esac; | |
PKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-${{ matrix.target }} | |
PKG_NAME=${PKG_BASENAME}${PKG_suffix} | |
echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_OUTPUT | |
PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package" | |
mkdir -p "${PKG_STAGING}" | |
# Binary | |
cp "${{ steps.bin.outputs.BIN_PATH }}" "$PKG_STAGING" | |
# README, LICENSE and CHANGELOG files | |
# cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "CHANGELOG.md" "$PKG_STAGING" | |
# base compressed package | |
pushd "${PKG_STAGING}/" >/dev/null | |
case ${{ matrix.target }} in | |
*-pc-windows-*) 7z -y a "${PKG_NAME}" ./* | tail -2 ;; | |
*) tar czf "${PKG_NAME}" ./* ;; | |
esac; | |
popd >/dev/null | |
cp "${{ steps.bin.outputs.BIN_PATH }}" "$PKG_STAGING/pixi-${{ matrix.target }}${{ steps.bin.outputs.EXE_SUFFIX }}" | |
# Let subsequent steps know where to find the compressed package | |
echo "PKG_PATH=${PKG_STAGING}/${PKG_NAME}" >> $GITHUB_OUTPUT | |
echo "BIN_PATH=$PKG_STAGING/pixi-${{ matrix.target }}${{ steps.bin.outputs.EXE_SUFFIX }}" >> $GITHUB_OUTPUT | |
- name: "Artifact upload: tarball" | |
uses: actions/upload-artifact@master | |
with: | |
name: ${{ steps.package.outputs.PKG_NAME }} | |
path: ${{ steps.package.outputs.PKG_PATH }} | |
- name: "Artifact upload: binary" | |
uses: actions/upload-artifact@master | |
with: | |
name: pixi-${{ matrix.target }}${{ steps.bin.outputs.EXE_SUFFIX }} | |
path: ${{ steps.package.outputs.BIN_PATH }} | |
- name: "Artifact upload: windows installer" | |
if: startsWith(matrix.name, 'Windows') && matrix.target != 'aarch64-pc-windows-msvc' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: pixi-${{ matrix.target }}.msi | |
path: target/wix/pixi-${{ matrix.target }}.msi | |
- name: Publish packages | |
uses: softprops/action-gh-release@v2 | |
if: steps.is-release.outputs.IS_RELEASE | |
with: | |
draft: true | |
files: | | |
${{ steps.package.outputs.PKG_PATH }} | |
${{ steps.package.outputs.BIN_PATH }} | |
target/wix/pixi-${{ matrix.target }}.msi | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
downstream_tests: | |
name: "Test examples, downstream projects and integration" | |
needs: | |
- build | |
uses: ./.github/workflows/test_downstream.yml | |
export-filter: | |
name: Only run example tests if relevant code or manifests have changed | |
runs-on: ubuntu-20.04 | |
needs: | |
- build | |
outputs: | |
exports: ${{ steps.filter.outputs.exports }} | |
steps: | |
- name: checkout repo | |
uses: actions/checkout@v4 | |
- uses: dorny/paths-filter@v3 | |
id: filter | |
with: | |
filters: | | |
exports: | |
- src/cli/project/export/conda_environment.rs | |
- src/cli/project/export/test-data/testenv/* | |
- examples/pypi-source-deps/* | |
- examples/pypi-custom-registry/* | |
- examples/pypi-find-links/* | |
- examples/docker/* | |
export_tests: | |
name: "Export tests" | |
needs: export-filter | |
if: ${{ needs.export-filter.outputs.exports == 'true' }} | |
uses: ./.github/workflows/test_exports.yml | |
test_common_wheels: | |
name: "Test installation of common wheels" | |
needs: | |
- build | |
uses: ./.github/workflows/test_common_wheels.yml |