Skip to content
Merged
2 changes: 0 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -631,10 +631,8 @@ workflows:
parameters:
path:
- resources/aws-rds
- resources/metadata
- resources/persist
- resources/qdrant
- resources/secrets
- resources/shared-db
- resources/turso
- resources/opendal
Expand Down
3 changes: 2 additions & 1 deletion cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,8 @@ impl Shuttle {
} else {
get_templates_schema()
.await
.map_err(|_| {
.map_err(|e| {
error!(err = %e, "Failed to get templates");
println!(
"{}",
"Failed to look up template list. Falling back to internal list."
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mod shuttle_main;
/// | `ShuttlePoem` | [shuttle-poem](https://crates.io/crates/shuttle-poem) | [poem](https://docs.rs/poem/2.0) | 2.0 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/poem/hello-world) |
/// | `ShuttleRocket` | [shuttle-rocket](https://crates.io/crates/shuttle-rocket) | [rocket](https://docs.rs/rocket/0.5) | 0.5 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/rocket/hello-world) |
/// | `ShuttleSalvo` | [shuttle-salvo](https://crates.io/crates/shuttle-salvo) | [salvo](https://docs.rs/salvo/0.63) | 0.63 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/salvo/hello-world) |
/// | `ShuttleSerenity` | [shuttle-serenity](https://crates.io/crates/shuttle-serenity | [serenity](https://docs.rs/serenity/0.12) and [poise](https://docs.rs/poise/0.6) | 0.12 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/serenity/hello-world) |
/// | `ShuttleSerenity` | [shuttle-serenity](https://crates.io/crates/shuttle-serenity) | [serenity](https://docs.rs/serenity/0.12) and [poise](https://docs.rs/poise/0.6) | 0.12 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/serenity/hello-world) |
/// | `ShuttleThruster` | [shuttle-thruster](https://crates.io/crates/shuttle-thruster) | [thruster](https://docs.rs/thruster/1.3) | 1.3 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/thruster/hello-world) |
/// | `ShuttleTower` | [shuttle-tower](https://crates.io/crates/shuttle-tower) | [tower](https://docs.rs/tower/0.4) | 0.4 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/tower/hello-world) |
/// | `ShuttleTide` | [shuttle-tide](https://crates.io/crates/shuttle-tide) | [tide](https://docs.rs/tide/0.16) | 0.16 | [GitHub](https://github.com/shuttle-hq/shuttle-examples/tree/main/tide/hello-world) |
Expand Down
4 changes: 2 additions & 2 deletions common/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ pub struct Response {
/// The type of this resource.
pub r#type: Type,

/// The config used when creating this resource. Use the [Self::r#type] to know how to parse this data.
/// The config used when creating this resource. Use the `r#type` to know how to parse this data.
pub config: Value,

/// The data associated with this resource. Use the [Self::r#type] to know how to parse this data.
/// The data associated with this resource. Use the `r#type` to know how to parse this data.
pub data: Value,
}

Expand Down
2 changes: 1 addition & 1 deletion common/src/secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use zeroize::Zeroize;

/// Wrapper type for secret values such as passwords or authentication keys.
///
/// Once wrapped, the inner value cannot leak accidentally, as both the [`Display`] and [`Debug`]
/// Once wrapped, the inner value cannot leak accidentally, as both the [`std::fmt::Display`] and [`Debug`]
/// implementations cover up the actual value and only show the type.
///
/// If you need access to the inner value, there is an [expose](`Secret::expose`) method.
Expand Down
2 changes: 0 additions & 2 deletions resources/metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@ description = "Plugin to get Shuttle service information"
keywords = ["shuttle-service", "metadata"]

[dependencies]
async-trait = "0.1.56"
shuttle-service = { path = "../../service", version = "0.41.0" }
21 changes: 1 addition & 20 deletions resources/metadata/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
# Shuttle Metadata

This plugin allows applications to obtain certain information about their runtime environment.

## Usage

Add `shuttle-metadata` to the dependencies for your service.

You can get this resource using the `shuttle_metadata::ShuttleMetadata` attribute to get a `Metadata`. This struct will contain information such as the Shuttle service name.

```rust
#[shuttle_runtime::main]
async fn app(
#[shuttle_metadata::ShuttleMetadata] metadata: shuttle_metadata::Metadata,
) -> __ { ... }
```

#### Example projects that use `shuttle-metadata`

| Framework | Link |
| --------- | -------------------------------------------------------------------------------------- |
| Axum | [axum example](https://github.com/shuttle-hq/shuttle-examples/tree/main/axum/metadata) |
This plugin has been moved to [shuttle-runtime](https://crates.io/crates/shuttle-runtime).
15 changes: 0 additions & 15 deletions resources/metadata/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@
use async_trait::async_trait;
pub use shuttle_service::{DeploymentMetadata as Metadata, Environment, SecretStore};
use shuttle_service::{Error, ResourceFactory, ResourceInputBuilder};

#[derive(Default)]
pub struct ShuttleMetadata;

#[async_trait]
impl ResourceInputBuilder for ShuttleMetadata {
type Input = Metadata;
type Output = Metadata;

async fn build(self, factory: &ResourceFactory) -> Result<Self::Input, crate::Error> {
Ok(factory.get_metadata())
}
}
3 changes: 0 additions & 3 deletions resources/secrets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,3 @@ description = "Plugin to for managing secrets on shuttle"
keywords = ["shuttle-service", "secrets"]

[dependencies]
async-trait = "0.1.56"
serde_json = "1"
shuttle-service = { path = "../../service", version = "0.41.0" }
31 changes: 1 addition & 30 deletions resources/secrets/README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
# Shuttle Secrets

This plugin manages secrets on [Shuttle](https://www.shuttle.rs).

## Usage

Add `shuttle-secrets` to the dependencies for your service, and add a `Secrets.toml` to the root of your project
with the secrets you'd like to store. Make sure to add `Secrets*.toml` to a `.gitignore` to omit your secrets from version control.

Next, pass `#[shuttle_secrets::Secrets] secret_store: SecretStore` as an argument to your `shuttle_service::main` function.
`SecretStore::get` can now be called to retrieve your API keys and other secrets at runtime.

## Example

```rust,ignore
#[shuttle_runtime::main]
async fn rocket(
#[shuttle_secrets::Secrets] secret_store: SecretStore,
) -> ShuttleRocket {
// get secret defined in `Secrets.toml` file.
let secret = if let Some(secret) = secret_store.get("MY_API_KEY") {
secret
} else {
return Err(anyhow!("secret was not found").into());
};

let state = MyState { secret };
let rocket = rocket::build().mount("/", routes![secret]).manage(state);

Ok(rocket.into())
}
```
This plugin has been moved to [shuttle-runtime](https://crates.io/crates/shuttle-runtime).
24 changes: 0 additions & 24 deletions resources/secrets/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1 @@
#![doc = include_str!("../README.md")]
use async_trait::async_trait;
pub use shuttle_service::SecretStore;
use shuttle_service::{
resource::{ProvisionResourceRequest, ShuttleResourceOutput, Type},
Error, ResourceFactory, ResourceInputBuilder,
};

/// Secrets plugin that provides service secrets
#[derive(Default)]
pub struct Secrets;

#[async_trait]
impl ResourceInputBuilder for Secrets {
type Input = ProvisionResourceRequest;
type Output = ShuttleResourceOutput<SecretStore>;

async fn build(self, _factory: &ResourceFactory) -> Result<Self::Input, crate::Error> {
Ok(ProvisionResourceRequest::new(
Type::Secrets,
serde_json::Value::Null,
serde_json::Value::Null,
))
}
}
96 changes: 87 additions & 9 deletions runtime/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,93 @@
# shuttle-runtime
# Shuttle - Deploy Rust apps with a single Cargo subcommand

[Shuttle](https://www.shuttle.rs/) is a Rust-native cloud development platform that lets you deploy your Rust apps for free.

Shuttle is built for productivity, reliability and performance:
<div style="display: flex; margin-top: 30px; margin-bottom: 30px;">
<img src="https://raw.githubusercontent.com/shuttle-hq/shuttle/main/assets/logo-rectangle-transparent.png" width="400px" style="margin-left: auto; margin-right: auto;"/>
</div>

- Zero-Configuration support for Rust using annotations
- Automatic resource provisioning (databases, caches, subdomains, etc.) via [Infrastructure-From-Code](https://www.shuttle.rs/blog/2022/05/09/ifc)
- First-class support for popular Rust frameworks ([Actix Web](https://docs.shuttle.rs/examples/actix), [Rocket](https://docs.shuttle.rs/examples/rocket), [Axum](https://docs.shuttle.rs/examples/axum), and [more](https://docs.shuttle.rs/examples/other))
- Support for deploying Discord bots using [Serenity](https://docs.shuttle.rs/examples/serenity)
- Scalable hosting (with optional self-hosting in the future)
[Shuttle](https://www.shuttle.rs/) is a Rust-native cloud development platform that lets you deploy your Rust apps for free.

📖 Check out our documentation to get started quickly: [docs.shuttle.rs](https://docs.shuttle.rs)

🙋‍♂️ If you have any questions, join our [Discord](https://discord.gg/shuttle) server.

## Usage

Start by installing the [`cargo shuttle`](https://docs.rs/crate/cargo-shuttle/latest) subcommand by running the following in a terminal:

```bash
cargo install cargo-shuttle
```

Now that Shuttle is installed, you can initialize a project with Axum boilerplate:

```bash
cargo shuttle init --template axum my-axum-app
```

By looking at the `Cargo.toml` file of the generated `my-axum-app` project you will see it has been made to
be a binary crate with a few dependencies including `shuttle-runtime` and `shuttle-axum`.

```toml
axum = "0.7.3"
shuttle-axum = "0.41.0"
shuttle-runtime = "0.41.0"
tokio = "1.28.2"
```

A boilerplate code for your axum project can also be found in `src/main.rs`:

```rust,no_run
use axum::{routing::get, Router};

async fn hello_world() -> &'static str {
"Hello, world!"
}

#[shuttle_runtime::main]
async fn main() -> shuttle_axum::ShuttleAxum {
let router = Router::new().route("/", get(hello_world));

Ok(router.into())
}
```

Check out [our docs](https://docs.shuttle.rs/introduction/welcome) to see all the frameworks we support, or
our [examples](https://github.com/shuttle-hq/shuttle-examples) if you prefer that format.

## Running locally

To test your app locally before deploying, use:

```bash
cargo shuttle run
```

You should see your app build and start on the default port 8000. You can test this using;

```bash
curl http://localhost:8000/
# Hello, world!
```

## Deploying

Before you can deploy, you have to create a project. This will start a deployer container for your
project under the hood, ensuring isolation from other users' projects. PS. you don't have to do this
now if you did in in the `cargo shuttle init` flow.

```bash
cargo shuttle project start
```

Then, deploy the service with:

```bash
cargo shuttle deploy
```

Your service will immediately be available at `https://{project_name}.shuttleapp.rs/`. For example:

```bash
curl https://my-axum-app.shuttleapp.rs/
# Hello, world!
```
27 changes: 6 additions & 21 deletions runtime/src/alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ use tokio::sync::{
use tokio_stream::wrappers::ReceiverStream;
use tonic::{transport::Server, Request, Response, Status};

use crate::__internals::print_version;

use crate::args::args;
use crate::print_version;

// uses custom macro instead of clap to reduce dependency weight
args! {
Expand All @@ -49,17 +48,14 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S
Ok(args) => args,
Err(e) => {
eprintln!("Runtime received malformed or incorrect args, {e}");
let help_str = "[HINT]: Run shuttle with `cargo shuttle run`";
let help_str = "[HINT]: Run your Shuttle app with `cargo shuttle run`";
let wrapper_str = "-".repeat(help_str.len());
eprintln!("{wrapper_str}\n{help_str}\n{wrapper_str}");
return;
}
};

println!(
"shuttle-runtime executable started (version {})",
crate::VERSION
);
println!("{} {} executable started", crate::NAME, crate::VERSION);

// this is handled after arg parsing to not interfere with --version above
#[cfg(feature = "setup-tracing")]
Expand All @@ -81,21 +77,10 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S
.init();

println!(
"{}\n\
{}\n\
To disable the subscriber and use your own,\n\
turn off the default features for {}:\n\
\n\
{}\n\
{}",
"=".repeat(63).yellow(),
"Shuttle's default tracing subscriber is initialized!"
.yellow()
.bold(),
"shuttle-runtime".italic(),
r#"shuttle-runtime = { version = "...", default-features = false }"#.italic(),
"=".repeat(63).yellow(),
"{}",
"Shuttle's default tracing subscriber is initialized!".yellow(),
);
println!("To disable it and use your own, check the docs: https://docs.shuttle.rs/configuration/logs");
}

// where to serve the gRPC control layer
Expand Down
Loading