feat(cli): Install/remove multiple packages globally #1717
Workflow file for this run
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" | |
TEST_FEATURES: "slow_integration_tests" | |
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: 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_and_lint: | |
name: Format and Lint | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
- uses: actions-rust-lang/setup-rust-toolchain@v1 | |
with: | |
components: clippy, rustfmt | |
- name: Run rustfmt | |
uses: actions-rust-lang/rustfmt@v1 | |
- name: Run clippy | |
run: cargo clippy | |
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[0].name' | tee -a $GITHUB_OUTPUT | |
cargo metadata --no-deps --format-version 1 | jq -r '"version=" + .packages[0].version' | tee -a $GITHUB_OUTPUT | |
cargo metadata --no-deps --format-version 1 | jq -r '"maintainer=" + .packages[0].authors[0]' | tee -a $GITHUB_OUTPUT | |
cargo metadata --no-deps --format-version 1 | jq -r '"homepage=" + .packages[0].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 }} | |
build: | |
name: ${{ matrix.name }} | |
runs-on: ${{ matrix.os }} | |
needs: [ crate_metadata, format_and_lint ] | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- { name: "Linux-x86_64", target: x86_64-unknown-linux-musl, os: ubuntu-20.04 } | |
- { name: "Linux-aarch64", target: aarch64-unknown-linux-musl, os: ubuntu-latest, skip-tests: true } | |
- { name: "macOS-x86_64", target: x86_64-apple-darwin, os: macOS-latest } | |
- { name: "macOS-aarch64", target: aarch64-apple-darwin, os: macOS-latest, skip-tests: true } | |
- { name: "Windows-x86_64", target: x86_64-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 | |
# | |
# Enable Link Time Optimization (LTO) for our release builds. This increases link time but drastically reduces | |
# binary size. | |
CARGO_PROFILE_RELEASE_LTO: true | |
# Use a single code gen unit, this effectively disables parallel linking but ensures that everything is linked | |
# together in a single unit which reduces the file-size at the cost of link time. | |
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 1 | |
# Strip the binaries. This reduces the filesize of the final release. | |
CARGO_PROFILE_RELEASE_STRIP: "symbols" | |
# Optimize the binary for size. This reduces the filesize at the cost of a slower binary. | |
CARGO_PROFILE_OPT_LEVEL: s | |
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] | |
continue-on-error: true | |
# aarch64 is only supported in wix 4.0 development builds | |
if: startsWith(matrix.os, 'windows') && matrix.target != 'aarch64-pc-windows-msvc' | |
run: cargo install --version 0.3.4 cargo-wix | |
env: | |
# cargo-wix does not require static crt | |
RUSTFLAGS: "" | |
- name: Ensure cache directory exists | |
shell: bash | |
if: matrix.os == 'ubuntu-20.04' && matrix.use-cross | |
run: | | |
mkdir -p ${XDG_CACHE_HOME} | |
- 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} --no-default-features --features rustls-tls" >> $GITHUB_OUTPUT | |
- name: Build | |
run: > | |
cargo build | |
--locked | |
--release | |
${{ 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 }}/release/${BIN_NAME}" | |
# Let subsequent steps know where to find the binary | |
echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT | |
echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_OUTPUT | |
echo "EXE_SUFFIX=${EXE_SUFFIX}" >> $GITHUB_OUTPUT | |
- name: Set testing options | |
id: test-options | |
if: ${{ !matrix.skip-tests }} | |
shell: bash | |
run: | | |
# test only library unit tests and binary for arm-type targets | |
unset CARGO_TEST_OPTIONS | |
unset CARGO_TEST_OPTIONS ; case ${{ matrix.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--bin ${{ needs.crate_metadata.outputs.name }}" ;; esac; | |
CARGO_TEST_OPTIONS="${CARGO_TEST_OPTIONS} --features ${{ env.TEST_FEATURES }}" | |
echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT | |
- name: Run tests | |
if: ${{ !matrix.skip-tests }} | |
run: > | |
cargo test | |
--locked | |
--release | |
${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}} | |
${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}} | |
- name: Build Installer | |
continue-on-error: true | |
if: matrix.os == 'windows-latest' && matrix.target != 'aarch64-pc-windows-msvc' | |
run: > | |
cargo wix -v --no-build --nocapture -I install/windows/main.wxs | |
--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 | |
export KEYCHAIN_PASSWORD=$(openssl rand -base64 32) | |
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 --output $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" | |
continue-on-error: true | |
if: matrix.os == 'windows-latest' && 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@v1 | |
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 }} | |
test-examples: | |
name: Integration test ${{ matrix.name }} | |
runs-on: ${{ matrix.os }} | |
needs: build | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- { name: "Linux-x86_64", target: x86_64-unknown-linux-musl, os: ubuntu-20.04 } | |
# - { name: "Linux-aarch64", target: aarch64-unknown-linux-musl, os: ubuntu-latest } Doesn't work yet | |
- { name: "macOS-x86_64", target: x86_64-apple-darwin, os: macOS-latest } | |
- { name: "macOS-aarch64", target: aarch64-apple-darwin, os: macOS-14 } # macOS-14 is the ARM chipset | |
- { name: "Windows-x86_64", target: x86_64-pc-windows-msvc, os: windows-latest , extension: .exe} | |
steps: | |
- name: checkout repo | |
uses: actions/checkout@v4 | |
- name: Download binary from build | |
uses: actions/download-artifact@v4 | |
with: | |
name: pixi-${{ matrix.target }}${{ matrix.extension }} | |
path: pixi_bin | |
- name: Debug | |
run: | | |
pwd | |
- name: Setup unix binary, add to github path | |
if: matrix.os != 'windows-latest' | |
run: | | |
mv pixi_bin/pixi-${{ matrix.target }} pixi_bin/pixi | |
chmod a+x pixi_bin/pixi | |
echo "$(pwd)/pixi_bin" >> $GITHUB_PATH | |
- name: Create Directory and Move Executable | |
if: matrix.os == 'windows-latest' && matrix.target == 'x86_64-pc-windows-msvc' | |
run: | | |
New-Item -ItemType Directory -Force -Path "D:\.pixi" | |
Move-Item -Path "pixi_bin/pixi-${{ matrix.target }}${{ matrix.extension }}" -Destination "D:\.pixi\pixi.exe" | |
shell: pwsh | |
- name: Add to PATH | |
if: matrix.os == 'windows-latest' && matrix.target == 'x86_64-pc-windows-msvc' | |
run: echo "D:\.pixi" | Out-File -Append -Encoding utf8 -FilePath $env:GITHUB_PATH | |
shell: pwsh | |
- name: Verify and Use Executable | |
if: matrix.os == 'windows-latest' && matrix.target == 'x86_64-pc-windows-msvc' | |
run: | | |
echo "Current PATH: $env:PATH" | |
pixi --version | |
shell: pwsh | |
- name: Help | |
run: pixi --help | |
- name: Info | |
run: pixi info | |
- name: Install pixi | |
run: pixi install -v | |
- name: Test examples | |
shell: bash | |
run: bash tests/test_examples.sh |