Skip to content

Commit

Permalink
new: Add new built-in tools. (#704)
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj authored Jan 22, 2025
1 parent f298f9e commit f684706
Show file tree
Hide file tree
Showing 17 changed files with 318 additions and 55 deletions.
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,46 @@
- [Bun](https://github.com/moonrepo/plugins/blob/master/tools/bun/CHANGELOG.md)
- [Deno](https://github.com/moonrepo/plugins/blob/master/tools/deno/CHANGELOG.md)
- [Go](https://github.com/moonrepo/plugins/blob/master/tools/go/CHANGELOG.md)
- [moon](https://github.com/moonrepo/plugins/blob/master/tools/moon/CHANGELOG.md)
- [Node](https://github.com/moonrepo/plugins/blob/master/tools/node/CHANGELOG.md)
- [npm, pnpm, yarn](https://github.com/moonrepo/plugins/blob/master/tools/node-depman/CHANGELOG.md)
- [Python](https://github.com/moonrepo/plugins/blob/master/tools/python/CHANGELOG.md)
- [uv](https://github.com/moonrepo/plugins/blob/master/tools/python_uv/CHANGELOG.md)
- [Ruby](https://github.com/moonrepo/plugins/blob/master/tools/ruby/CHANGELOG.md)
- [Rust](https://github.com/moonrepo/plugins/blob/master/tools/rust/CHANGELOG.md)
- [Schema (TOML, JSON, YAML)](https://github.com/moonrepo/plugins/blob/master/tools/internal-schema/CHANGELOG.md)

## Unreleased

#### 🚀 Updates

- Added new built-in tools: `moon`, `uv` (Python), and `ruby`.
- Added a new interactive "build from source" flow for many built-in tools.
- Added `--build` and `--no-build` to `proto install`.
- Supported for `deno`, `go`, `node`, `python`, and `ruby`.
- Supported for `deno`, `go`, `moon`, `node`, `python`, and `ruby`.
- WASM API
- Added a `build_instructions` plugin function for building from source, with associated structs and enums.
- Added a `ToolMetadataOutput.default_install_strategy` field, which defaults to prebuilds.
- Added a `ToolMetadataOutput.unstable` field, which can mark the tool as unstable.
- Added a `ToolContext.temp_dir` field.

#### 🧩 Plugins

- Added `moon_tool` v0.1.
- Added `python_uv_tool` v0.1.
- Added `ruby_tool` v0.1 (via `ruby-build`).
- Updated `bun_tool` to v0.14.1.
- Updated `deno_tool` to v0.14.
- Added build from source support.
- Updated `go_tool` to v0.15.
- Added build from source support.
- Updated `node_tool` to v0.14.
- Added build from source support.
- Updated `node_depman_tool` to v0.14.2.
- Updated `python_tool` to v0.13.
- Added build from source support (via `python-build`).
- Updated `rust_tool` to v0.12.1.

## 0.44.7

#### 🚀 Updates
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ serde_json = "1.0.137"
sha2 = "0.10.8"
shell-words = "1.1.0"
starbase = { version = "0.9.9" }
starbase_archive = { version = "0.9.3", features = [
starbase_archive = { version = "0.9.4", features = [
"gz",
"miette",
"tar-bz2",
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ proto is a pluggable next-generation version manager for multiple programming la
- Bun
- Deno
- Go
- moon
- Node (and npm, pnpm, yarn)
- Python
- Python (and uv)
- Ruby
- Rust
- ... [and more via plugins!](https://moonrepo.dev/docs/proto/tools)

Expand Down
18 changes: 16 additions & 2 deletions crates/cli/src/workflows/install_workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use crate::telemetry::*;
use crate::utils::tool_record::ToolRecord;
use proto_core::flow::install::{InstallOptions, InstallPhase};
use proto_core::{PinLocation, UnresolvedVersionSpec, PROTO_PLUGIN_KEY};
use proto_pdk_api::{InstallHook, InstallStrategy, SyncShellProfileInput, SyncShellProfileOutput};
use proto_pdk_api::{
InstallHook, InstallStrategy, Switch, SyncShellProfileInput, SyncShellProfileOutput,
};
use starbase_console::ui::{ProgressDisplay, ProgressReporter};
use starbase_console::utils::formats::format_duration;
use starbase_shell::ShellType;
use std::env;
use std::time::{Duration, Instant};
use tracing::debug;
use tracing::{debug, warn};

pub enum InstallOutcome {
AlreadyInstalled,
Expand All @@ -37,6 +39,18 @@ pub struct InstallWorkflow {

impl InstallWorkflow {
pub fn new(tool: ToolRecord, console: ProtoConsole) -> Self {
if tool.metadata.unstable.is_enabled() {
warn!(
"{} is currently unstable. {}",
tool.get_name(),
if let Switch::Message(msg) = &tool.metadata.unstable {
msg
} else {
""
}
);
}

Self {
console,
progress_reporter: ProgressReporter::default(),
Expand Down
61 changes: 61 additions & 0 deletions crates/cli/tests/plugins_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,26 @@ mod plugins {
);
}

#[test]
fn supports_moon() {
let sandbox = create_empty_proto_sandbox();

sandbox
.run_bin(|cmd| {
cmd.arg("install").arg("moon");
})
.success();

create_shim_command(sandbox.path(), "moon")
.arg("--version")
.assert()
.success();

assert_snapshot!(
fs::read_to_string(sandbox.path().join(".proto/shims/registry.json")).unwrap()
);
}

#[test]
fn supports_node() {
let sandbox = create_empty_proto_sandbox();
Expand Down Expand Up @@ -352,6 +372,47 @@ mod plugins {
);
}

#[test]
fn supports_uv() {
let sandbox = create_empty_proto_sandbox();

sandbox
.run_bin(|cmd| {
cmd.arg("install").arg("uv");
})
.success();

create_shim_command(sandbox.path(), "uv")
.arg("--version")
.assert()
.success();

assert_snapshot!(
fs::read_to_string(sandbox.path().join(".proto/shims/registry.json")).unwrap()
);
}

#[cfg(unix)]
#[test]
fn supports_ruby() {
let sandbox = create_empty_proto_sandbox();

sandbox
.run_bin(|cmd| {
cmd.arg("install").arg("ruby").arg("--yes");
})
.success();

create_shim_command(sandbox.path(), "ruby")
.arg("--version")
.assert()
.success();

assert_snapshot!(
fs::read_to_string(sandbox.path().join(".proto/shims/registry.json")).unwrap()
);
}

#[test]
fn supports_rust() {
let sandbox = create_empty_proto_sandbox();
Expand Down
20 changes: 16 additions & 4 deletions crates/cli/tests/run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ mod run {
})
.success();

assert.stdout(predicate::str::contains("installed"));
// Output on macos is truncated
if cfg!(not(target_os = "macos")) {
assert.stdout(predicate::str::contains("installed"));
}
}

#[test]
Expand All @@ -209,7 +212,10 @@ mod run {
})
.success();

assert.stdout(predicate::str::contains("installed"));
// Output on macos is truncated
if cfg!(not(target_os = "macos")) {
assert.stdout(predicate::str::contains("installed"));
}

env::remove_var("PROTO_AUTO_INSTALL");
}
Expand Down Expand Up @@ -247,7 +253,10 @@ mod run {
})
.success();

assert.stdout(predicate::str::contains("Node.js 19.0.0 installed"));
// Output on macos is truncated
if cfg!(not(target_os = "macos")) {
assert.stdout(predicate::str::contains("Node.js 19.0.0 installed"));
}

let assert = sandbox
.run_bin(|cmd| {
Expand All @@ -259,7 +268,10 @@ mod run {
})
.success();

assert.stdout(predicate::str::contains("Node.js 19.0.0 installed").not());
// Output on macos is truncated
if cfg!(not(target_os = "macos")) {
assert.stdout(predicate::str::contains("Node.js 19.0.0 installed").not());
}
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/cli/tests/plugins_test.rs
expression: "fs::read_to_string(sandbox.path().join(\".proto/shims/registry.json\")).unwrap()"
---
{
"moon": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
source: crates/cli/tests/plugins_test.rs
expression: "fs::read_to_string(sandbox.path().join(\".proto/shims/registry.json\")).unwrap()"
---
{
"bundle": {
"alt_bin": true,
"parent": "ruby"
},
"gem": {
"alt_bin": true,
"parent": "ruby"
},
"rake": {
"alt_bin": true,
"parent": "ruby"
},
"ruby": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: crates/cli/tests/plugins_test.rs
expression: "fs::read_to_string(sandbox.path().join(\".proto/shims/registry.json\")).unwrap()"
---
{
"uv": {},
"uvx": {
"alt_bin": true,
"parent": "uv"
}
}
2 changes: 1 addition & 1 deletion crates/cli/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn apply_settings(sandbox: &mut Sandbox) {
env.insert("PROTO_TEST", "true");

sandbox.settings.bin = "proto".into();
sandbox.settings.timeout = 240;
sandbox.settings.timeout = 300;

sandbox
.settings
Expand Down
30 changes: 25 additions & 5 deletions crates/core/src/flow/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use starbase_console::ui::{
};
use starbase_styles::color;
use starbase_utils::{fs, net};
use std::env;
use std::path::{Path, PathBuf};
use std::process::Stdio;
use system_env::{find_command_on_path, is_command_on_path, System};
Expand Down Expand Up @@ -49,6 +50,11 @@ impl StepManager<'_> {
self.errors > 0
}

#[allow(dead_code)]
pub fn is_ci(&self) -> bool {
env::var("CI").is_ok_and(|v| !v.is_empty())
}

pub fn render_header(&self, title: impl AsRef<str>) -> miette::Result<()> {
let title = title.as_ref();

Expand Down Expand Up @@ -294,19 +300,32 @@ pub async fn install_system_dependencies(
func(InstallPhase::InstallDeps);
});

if let Some(mut index_args) = system
// In CI, like GitHub Actions, package manager commands
// need to be ran with sudo on Linux. Has to be a better way?
let wrap_with_sudo = |base_args| {
let mut args = vec![];
#[cfg(target_os = "linux")]
if step.is_ci() {
args.push("sudo".to_string());
}
args.extend(base_args);
args
};

if let Some(index_args) = system
.get_update_index_command(!options.skip_prompts)
.into_diagnostic()?
{
step.render_checkpoint("Updating package manager index")?;

exec_command(Command::new(index_args.remove(0)).args(index_args)).await?;
let mut args = wrap_with_sudo(index_args);
exec_command(Command::new(args.remove(0)).args(args)).await?;
}

let dep_configs = system.resolve_dependencies(&build.system_dependencies);

if !dep_configs.is_empty() {
if let Some(mut install_args) = system
if let Some(install_args) = system
.get_install_packages_command(&dep_configs, !options.skip_prompts)
.into_diagnostic()?
{
Expand All @@ -324,7 +343,8 @@ pub async fn install_system_dependencies(

step.prompt_continue("Install packages?").await?;

exec_command(Command::new(install_args.remove(0)).args(install_args)).await?;
let mut args = wrap_with_sudo(install_args);
exec_command(Command::new(args.remove(0)).args(args)).await?;
}
}

Expand Down Expand Up @@ -730,7 +750,7 @@ pub async fn execute_instructions(
"{prefix} Setting environment variable <property>{key}</property> to <symbol>{value}</symbol>",
))?;

std::env::set_var(key, value);
env::set_var(key, value);
}
};
}
Expand Down
Loading

0 comments on commit f684706

Please sign in to comment.