-
Notifications
You must be signed in to change notification settings - Fork 204
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add trampoline for pixi global (#2381)
Co-authored-by: nichmor <nmorkotilo@gmail.com> Co-authored-by: Wolf Vollprecht <w.vollprecht@gmail.com> Co-authored-by: Ruben Arts <ruben.arts@hotmail.com>
- Loading branch information
1 parent
1ee9605
commit 019c102
Showing
102 changed files
with
1,303 additions
and
512 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
name: Update Trampoline Binary | ||
|
||
on: | ||
push: | ||
paths: | ||
- 'crates/pixi_trampoline/**' | ||
workflow_dispatch: | ||
pull_request: | ||
paths: | ||
- 'crates/pixi_trampoline/**' | ||
|
||
permissions: | ||
contents: write # Allow write permissions for contents (like pushing to the repo) | ||
pull-requests: write | ||
|
||
jobs: | ||
build: | ||
runs-on: ${{ matrix.os }} | ||
defaults: | ||
run: | ||
working-directory: crates/pixi_trampoline | ||
strategy: | ||
fail-fast: true | ||
matrix: | ||
include: | ||
- { name: "Linux-x86_64", target: x86_64-unknown-linux-musl, os: ubuntu-latest } | ||
- { 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: windows-latest } | ||
- { name: "Windows-arm", target: aarch64-pc-windows-msvc, os: windows-latest } | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 # Fetch full history so we have branch information | ||
|
||
- name: Set up Rust | ||
uses: taiki-e/setup-cross-toolchain-action@v1 | ||
with: | ||
target: ${{ matrix.target }} | ||
|
||
- name: Build trampoline binary | ||
run: cargo build --release --target ${{ matrix.target }} | ||
|
||
- name: Move trampoline binary on windows | ||
if: startsWith(matrix.name, 'Windows') | ||
run: | | ||
mkdir -p trampolines-binaries | ||
mv target/${{ matrix.target }}/release/pixi_trampoline.exe trampolines-binaries/pixi-trampoline-${{ matrix.target }}.exe | ||
- name: Move trampoline binary on unix | ||
if: startsWith(matrix.name, 'Windows') == false | ||
run: | | ||
mkdir -p trampolines-binaries | ||
mv target/${{ matrix.target }}/release/pixi_trampoline trampolines-binaries/pixi-trampoline-${{ matrix.target }} | ||
- name: Upload binary artifact | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: trampoline-${{ matrix.target }} | ||
path: crates/pixi_trampoline/trampolines-binaries/ | ||
|
||
aggregate: | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
working-directory: crates/pixi_trampoline | ||
needs: build # This ensures the aggregation job runs after the build jobs | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
|
||
- name: Download all binaries | ||
uses: actions/download-artifact@v3 | ||
with: | ||
path: crates/pixi_trampoline/trampolines-binaries/ | ||
|
||
- name: List downloaded files | ||
run: ls -R trampolines-binaries/ | ||
|
||
- name: Move trampolines | ||
run: | | ||
mkdir -p trampolines | ||
# Iterate through all files in trampolines directory and its subdirectories | ||
find trampolines-binaries -type f -name 'pixi-trampoline-*' -exec mv -f {} trampolines/ \; | ||
# now iterate through all files in trampolines directory and compress them using zstd | ||
# and remove the original file | ||
# by using -f we allow overwriting the file | ||
for file in trampolines/*; do | ||
zstd "$file" -f | ||
rm "$file" | ||
done | ||
ls -R trampolines/ | ||
- name: Upload binary artifact | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: trampolines | ||
path: crates/pixi_trampoline/trampolines/ | ||
|
||
|
||
|
||
- name: Commit and push updated binaries | ||
# Don't run on forks | ||
if: github.repository == 'prefix-dev/pixi' && startsWith(github.ref, 'reaf/heads') | ||
run: | | ||
# Set the repository to push to the repository the workflow is running on | ||
git config user.name "GitHub Actions" | ||
git config user.email "actions@github.com" | ||
git add trampolines/ | ||
git commit -m "[CI]: Update trampoline binaries for all targets" | ||
# Push changes to the branch that triggered the workflow | ||
BRANCH=$(echo "${GITHUB_REF#refs/heads/}") | ||
git push origin HEAD:$BRANCH |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
[package] | ||
authors = ["pixi contributors <hi@prefix.dev>"] | ||
description = "Trampoline binary that is used to run binaries instaled by pixi global" | ||
edition = "2021" | ||
homepage = "https://github.com/prefix-dev/pixi" | ||
license = "BSD-3-Clause" | ||
name = "pixi_trampoline" | ||
readme = "README.md" | ||
repository = "https://github.com/prefix-dev/pixi" | ||
version = "0.1.0" | ||
|
||
[profile.release] | ||
# Enable Link Time Optimization. | ||
lto = true | ||
# Reduce number of codegen units to increase optimizations. | ||
codegen-units = 1 | ||
# Optimize for size. | ||
opt-level = "z" | ||
# Abort on panic. | ||
panic = "abort" | ||
# Automatically strip symbols from the binary. | ||
debug = false | ||
strip = true | ||
|
||
|
||
[dependencies] | ||
ctrlc = "3.4" | ||
serde = { version = "1.0.210", features = ["derive"] } | ||
serde_json = "1.0.128" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# A small trampoline binary that allow to run executables installed by pixi global install. | ||
|
||
|
||
This is the configuration used by trampoline to set the env variables, and run the executable. | ||
|
||
```js | ||
{ | ||
// Full path to the executable | ||
"exe": "/Users/wolfv/.pixi/envs/conda-smithy/bin/conda-smithy", | ||
// One or more path segments to prepend to the PATH environment variable | ||
"path": "/Users/wolfv/.pixi/envs/conda-smithy/bin", | ||
// One or more environment variables to set | ||
"env": { | ||
"CONDA_PREFIX": "/Users/wolfv/.pixi/envs/conda-smithy" | ||
} | ||
} | ||
``` | ||
|
||
# How to build it? | ||
You can use `trampoline.yaml` workflow to build the binary for all the platforms and architectures supported by pixi. | ||
In case of building it manually, you can use the following command, after executing the `cargo build --release`, you need to compress it using `zstd`. | ||
If running it manually or triggered by changes in `crates/pixi_trampoline` from the main repo, they will be automatically committed to the branch. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
use serde::Deserialize; | ||
use std::collections::HashMap; | ||
use std::env; | ||
use std::fs::File; | ||
#[cfg(target_family = "unix")] | ||
use std::os::unix::process::CommandExt; | ||
use std::path::{Path, PathBuf}; | ||
use std::process::{Command, Stdio}; | ||
|
||
|
||
// trampoline configuration folder name | ||
pub const TRAMPOLINE_CONFIGURATION: &str = "trampoline_configuration"; | ||
|
||
#[derive(Deserialize, Debug)] | ||
struct Metadata { | ||
exe: String, | ||
path: String, | ||
env: HashMap<String, String>, | ||
} | ||
|
||
fn read_metadata(current_exe: &Path) -> Metadata { | ||
// the metadata file is next to the current executable parent folder, | ||
// under trampoline_configuration/current_exe_name.json | ||
let exe_parent = current_exe.parent().expect("should have a parent"); | ||
let exe_name = current_exe.file_stem().expect("should have a file name"); | ||
let metadata_path = exe_parent.join(TRAMPOLINE_CONFIGURATION).join(format!("{}{}", exe_name.to_string_lossy(), ".json")); | ||
let metadata_file = File::open(metadata_path).unwrap(); | ||
let metadata: Metadata = serde_json::from_reader(metadata_file).unwrap(); | ||
metadata | ||
} | ||
|
||
fn prepend_path(extra_path: &str) -> String { | ||
let path = env::var("PATH").unwrap(); | ||
let mut split_path = env::split_paths(&path).collect::<Vec<_>>(); | ||
split_path.insert(0, PathBuf::from(extra_path)); | ||
let new_path = env::join_paths(split_path).unwrap(); | ||
new_path.to_string_lossy().into_owned() | ||
} | ||
|
||
fn main() -> () { | ||
// Get command-line arguments (excluding the program name) | ||
let args: Vec<String> = env::args().collect(); | ||
let current_exe = env::current_exe().expect("Failed to get current executable path"); | ||
|
||
// ignore any ctrl-c signals | ||
ctrlc::set_handler(move || {}).expect("Error setting Ctrl-C handler"); | ||
|
||
let metadata = read_metadata(¤t_exe); | ||
|
||
// Create a new Command for the specified executable | ||
let mut cmd = Command::new(metadata.exe); | ||
|
||
let new_path = prepend_path(&metadata.path); | ||
|
||
// Set the PATH environment variable | ||
cmd.env("PATH", new_path); | ||
|
||
// Set any additional environment variables | ||
for (key, value) in metadata.env.iter() { | ||
cmd.env(key, value); | ||
} | ||
|
||
// Add any additional arguments | ||
cmd.args(&args[1..]); | ||
|
||
// Configure stdin, stdout, and stderr to use the current process's streams | ||
cmd.stdin(Stdio::inherit()) | ||
.stdout(Stdio::inherit()) | ||
.stderr(Stdio::inherit()); | ||
|
||
// Spawn the child process | ||
#[cfg(target_family = "unix")] | ||
cmd.exec(); | ||
|
||
#[cfg(target_os = "windows")] | ||
{ | ||
let mut child = cmd.spawn().expect("process spawn should succeed"); | ||
|
||
// Wait for the child process to complete | ||
let status = child.wait().expect("failed to wait on child"); | ||
|
||
// Exit with the same status code as the child process | ||
std::process::exit(status.code().unwrap_or(1)); | ||
} | ||
} |
Binary file added
BIN
+191 KB
crates/pixi_trampoline/trampolines/pixi-trampoline-aarch64-apple-darwin.zst
Binary file not shown.
Binary file added
BIN
+133 KB
crates/pixi_trampoline/trampolines/pixi-trampoline-aarch64-pc-windows-msvc.exe.zst
Binary file not shown.
Binary file added
BIN
+259 KB
crates/pixi_trampoline/trampolines/pixi-trampoline-aarch64-unknown-linux-musl.zst
Binary file not shown.
Binary file added
BIN
+200 KB
crates/pixi_trampoline/trampolines/pixi-trampoline-x86_64-apple-darwin.zst
Binary file not shown.
Binary file added
BIN
+144 KB
crates/pixi_trampoline/trampolines/pixi-trampoline-x86_64-pc-windows-msvc.exe.zst
Binary file not shown.
Binary file added
BIN
+274 KB
crates/pixi_trampoline/trampolines/pixi-trampoline-x86_64-unknown-linux-musl.zst
Binary file not shown.
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
Oops, something went wrong.