Skip to content

Commit

Permalink
Merge pull request NixOS#12 from railwayapp/jr/rust-provider
Browse files Browse the repository at this point in the history
Rust provider
  • Loading branch information
coffee-cup authored Apr 2, 2022
2 parents afcea56 + 7f754c8 commit 34ab6b3
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 3 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
tempdir = "0.3.7"
thiserror = "1.0.30"
toml = "0.5.8"
uuid = { version = "0.8.2", features = ["v4"] }
14 changes: 14 additions & 0 deletions examples/rust-rocket/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust

### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# End of https://www.toptal.com/developers/gitignore/api/rust

9 changes: 9 additions & 0 deletions examples/rust-rocket/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "rocket"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rocket = "0.5.0-rc.1"
12 changes: 12 additions & 0 deletions examples/rust-rocket/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#[macro_use]
extern crate rocket;

#[get("/")]
fn index() -> &'static str {
"Hello, from Rocket!"
}

#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use std::fs;

use crate::{
nixpacks::{app::App, logger::Logger, plan::BuildPlan, AppBuilder, AppBuilderOptions},
providers::{go::GolangProvider, npm::NpmProvider, yarn::YarnProvider, Pkg},
providers::{
go::GolangProvider, npm::NpmProvider, rust::RustProvider, yarn::YarnProvider, Pkg,
},
};
use anyhow::{Context, Result};
use providers::Provider;
Expand All @@ -11,7 +13,12 @@ pub mod nixpacks;
pub mod providers;

pub fn get_providers() -> Vec<&'static dyn Provider> {
vec![&YarnProvider {}, &NpmProvider {}, &GolangProvider {}]
vec![
&YarnProvider {},
&NpmProvider {},
&GolangProvider {},
&RustProvider {},
]
}

pub fn gen_plan(
Expand Down
27 changes: 27 additions & 0 deletions src/nixpacks/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ impl App {
let value: T = serde_json::from_str(contents.as_str())?;
Ok(value)
}

pub fn read_toml<T>(&self, name: &str) -> Result<T>
where
T: DeserializeOwned,
{
let contents = self.read_file(name)?;
let toml_file = toml::from_str(contents.as_str())?;
Ok(toml_file)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -96,4 +105,22 @@ mod tests {
assert_eq!(value.scripts.get("build").unwrap(), "tsc -p tsconfig.json");
Ok(())
}

#[test]
fn test_read_toml_file() -> Result<()> {
let app = App::new("./examples/rust-rocket")?;
let toml_file: toml::Value = app.read_toml("Cargo.toml")?;
assert!(toml_file.get("package").is_some());
assert_eq!(
toml_file
.get("package")
.unwrap()
.get("name")
.unwrap()
.as_str()
.unwrap(),
"rocket"
);
Ok(())
}
}
5 changes: 4 additions & 1 deletion src/nixpacks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,15 @@ impl<'a> AppBuilder<'a> {
RUN nix-channel --update
COPY . /app
RUN mkdir /app
COPY environment.nix /app
WORKDIR /app
# Load Nix environment
RUN nix-env -if environment.nix
COPY . /app
# Install
{install_cmd}
Expand Down
1 change: 1 addition & 0 deletions src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize};

pub mod go;
pub mod npm;
pub mod rust;
pub mod yarn;

#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
Expand Down
53 changes: 53 additions & 0 deletions src/providers/rust.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use super::Provider;
use crate::{nixpacks::app::App, providers::Pkg};
use anyhow::{Context, Result};

pub struct RustProvider {}

impl Provider for RustProvider {
fn name(&self) -> &str {
"rust"
}

fn detect(&self, app: &App) -> Result<bool> {
Ok(app.includes_file("Cargo.toml"))
}

fn pkgs(&self, _app: &App) -> Vec<Pkg> {
vec![
Pkg::new("pkgs.stdenv"),
Pkg::new("pkgs.gcc"),
Pkg::new("pkgs.rustc"),
Pkg::new("pkgs.cargo"),
]
}

fn install_cmd(&self, _app: &App) -> Result<Option<String>> {
Ok(None)
}

fn suggested_build_cmd(&self, _app: &App) -> Result<Option<String>> {
Ok(Some("cargo build --release".to_string()))
}

fn suggested_start_command(&self, app: &App) -> Result<Option<String>> {
if app.includes_file("Cargo.toml") {
// Parse name from Cargo.toml so we can run ./target/release/{name}
let toml_file: toml::Value =
app.read_toml("Cargo.toml").context("Reading Cargo.toml")?;
let name = toml_file
.get("package")
.and_then(|package| package.get("name"))
.and_then(|v| v.as_str());

if let Some(name) = name {
return Ok(Some(format!(
"ROCKET_ADDRESS=0.0.0.0 ./target/release/{}",
name
)));
}
}

Ok(None)
}
}
13 changes: 13 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,16 @@ fn test_pin_archive() -> Result<()> {

Ok(())
}

#[test]
fn test_rust_rocket() -> Result<()> {
let plan = gen_plan("./examples/rust-rocket", Vec::new(), None, None, true)?;
assert_eq!(plan.build_cmd, Some("cargo build --release".to_string()));
assert!(plan.start_cmd.is_some());

if let Some(start_cmd) = plan.start_cmd {
assert!(start_cmd.contains("./target/release/rocket"));
}

Ok(())
}

0 comments on commit 34ab6b3

Please sign in to comment.