Skip to content

Commit

Permalink
refactor(website,cli,serverless): introduce production/preview deploy…
Browse files Browse the repository at this point in the history
…ments (#238)

* refactor(website): rename isCurrent to isProduction

* refactor(website): only select needed cols

* refactor(website): add prod deployments

* feat(cli): add prod option to deploy

* refactor(website): rename rollback to promote

* fix(website): custom domains link

* feat(serverless,website): add live deployments promoting

* feat(website): domains update trigger undeploy and deploy

* feat(docs): add --prod option to CLI

* chore: add changesets
  • Loading branch information
QuiiBz committed Nov 5, 2022
1 parent 747774b commit 045977c
Show file tree
Hide file tree
Showing 22 changed files with 271 additions and 263 deletions.
6 changes: 6 additions & 0 deletions .changeset/heavy-terms-grow.md
@@ -0,0 +1,6 @@
---
'@lagon/cli': patch
'@lagon/docs': patch
---

Add --prod option to `lagon deploy`
6 changes: 6 additions & 0 deletions .changeset/rich-lies-pull.md
@@ -0,0 +1,6 @@
---
'@lagon/serverless': patch
'@lagon/website': patch
---

Add production/preview deployments
15 changes: 12 additions & 3 deletions packages/cli/src/commands/deploy.rs
Expand Up @@ -57,7 +57,7 @@ pub async fn deploy(
file: PathBuf,
client: Option<PathBuf>,
public_dir: Option<PathBuf>,
_force: bool,
prod: bool,
) -> Result<()> {
let config = Config::new()?;

Expand Down Expand Up @@ -112,8 +112,15 @@ pub async fn deploy(
organization_id: organization.id.clone(),
})?;

create_deployment(function.id.clone(), &file, &client, &public_dir, &config)
.await?;
create_deployment(
function.id.clone(),
&file,
&client,
&public_dir,
&config,
prod,
)
.await?;
}
false => {
let name = Input::<String>::new()
Expand Down Expand Up @@ -149,6 +156,7 @@ pub async fn deploy(
&client,
&public_dir,
&config,
prod,
)
.await?;
}
Expand All @@ -163,6 +171,7 @@ pub async fn deploy(
&client,
&public_dir,
&config,
prod,
)
.await
}
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/main.rs
Expand Up @@ -42,9 +42,9 @@ enum Commands {
/// Path to the public directory to serve assets from
#[clap(short, long, value_parser)]
public_dir: Option<PathBuf>,
/// Force the creation of a new Function
#[clap(short, long)]
force: bool,
/// Deploy as a production deployment
#[clap(visible_alias = "production", long)]
prod: bool,
},
/// Undeploy an existing Function
Undeploy {
Expand Down Expand Up @@ -99,8 +99,8 @@ async fn main() {
file,
client,
public_dir,
force,
} => commands::deploy(file, client, public_dir, force).await,
prod,
} => commands::deploy(file, client, public_dir, prod).await,
Commands::Undeploy { file } => commands::undeploy(file).await,
Commands::Dev {
file,
Expand Down
12 changes: 5 additions & 7 deletions packages/cli/src/utils/deployments.rs
Expand Up @@ -171,12 +171,12 @@ struct CreateDeploymentResponse {
struct DeployDeploymentRequest {
function_id: String,
deployment_id: String,
is_production: bool,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct DeployDeploymentResponse {
function_name: String,
url: String,
}

pub async fn create_deployment(
Expand All @@ -185,6 +185,7 @@ pub async fn create_deployment(
client: &Option<PathBuf>,
public_dir: &PathBuf,
config: &Config,
prod: bool,
) -> Result<()> {
let (index, assets) = bundle_function(file, client, public_dir)?;

Expand Down Expand Up @@ -240,18 +241,15 @@ pub async fn create_deployment(
DeployDeploymentRequest {
function_id,
deployment_id,
is_production: prod,
},
)
.await?;

println!();
println!("{}", success("Function deployed!"));
println!();
println!(
" {} https://{}.lagon.app",
"➤".black(),
response.result.data.function_name.blue()
);
println!(" {} {}", "➤".black(), response.result.data.url.blue());
println!();

Ok(())
Expand Down
27 changes: 16 additions & 11 deletions packages/docs/pages/cli.mdx
@@ -1,11 +1,13 @@
import { Callout, Collapse } from 'nextra-theme-docs'
import { Callout, Collapse } from 'nextra-theme-docs';

The easiest way to deploy and manage Functions is through our [Command-line interface](https://en.wikipedia.org/wiki/Command-line_interface).

## Installation

<Callout type="warning">
The CLI is not stable yet, so you might encounter bugs. Please [open an issue](https://github.com/lagonapp/lagon/issues/new?assignees=&labels=bug&template=bug_report.md&title=) if it's the case.
The CLI is not stable yet, so you might encounter bugs. Please [open an
issue](https://github.com/lagonapp/lagon/issues/new?assignees=&labels=bug&template=bug_report.md&title=) if it's the
case.
</Callout>

Lagon CLI is available for the following operating systems:
Expand All @@ -26,10 +28,10 @@ pnpm install --global @lagon/cli
```

<Callout type="info">
You will also be able to install it through [Cargo](https://doc.rust-lang.org/stable/cargo/) - Rust's package manager - soon.
You will also be able to install it through [Cargo](https://doc.rust-lang.org/stable/cargo/) - Rust's package manager
- soon.
</Callout>


## Usage

Once installed, execute the `lagon` CLI to see all the commands available.
Expand All @@ -50,14 +52,15 @@ To proceed, run `lagon logout` and follow the instructions.

Create a new Function or a new Deployment for the given files. Make sure you are [logged in](#lagon-login) before proceeding. If you are executing the command for the first time:

1) You will be prompted to select an Organization
2) You will be able to link to an existing Function, or create a new one by specifying a name
1. You will be prompted to select an Organization
2. You will be able to link to an existing Function, or create a new one by specifying a name

If you then want to trigger a new Deployment, re-run the same command. This command accept the following arguments and options:

- `<FILE>` is the only required argument. It should be the path to a file containing and exporting a Function.
- `--client, -c <CLIENT>` allows you to specify a path to an additional file to bundle as a client-side script.
- `--public, -p <CLIENT>` allows you to specify a path a custom assets directory, that will be served at the root (`/`) of the Function. (Default: `public`)
- `--production, --prod` allows you to deploy the Function in production mode. (Default: `false`)

Examples:

Expand All @@ -69,7 +72,8 @@ lagon deploy ./server.tsx --client App.tsx --public ./assets
### `lagon undeploy`

<Callout type="error">
Un-deploying a Function deletes permanently all of its Deployments, statistics and logs. You will be prompted to confirm before continuing.
Un-deploying a Function deletes permanently all of its Deployments, statistics and logs. You will be prompted to
confirm before continuing.
</Callout>

Un-deploy completely a Function. Make sure you are [logged in](#lagon-login) before proceeding. This command accept only one argument:
Expand All @@ -80,7 +84,7 @@ Example:

```bash
lagon undeploy ./index.ts
````
```

### `lagon dev`

Expand All @@ -93,7 +97,9 @@ This command accept the same arguments and options as `lagon deploy` and `lagon
- `--env <PATH>` allows you to specify an environment file (typically `.env`) to use to inject environment variables.

<Callout type="warning">
Although the `dev` command uses the exact same Runtime as when deployed, the local HTTP server itself doesn't have the same optimizations. As such, you shouldn't run a production environment on it, or run any kind of load tests/benchmarks.
Although the `dev` command uses the exact same Runtime as when deployed, the local HTTP server itself doesn't have the
same optimizations. As such, you shouldn't run a production environment on it, or run any kind of load
tests/benchmarks.
</Callout>

Examples:
Expand Down Expand Up @@ -123,9 +129,8 @@ If you are [self-hosting](/self-hosted/installation) Lagon, you will need to upd
```json
{
"token": "**************",
"site_url":"https://dash.lagon.app" // Replace this field
"site_url": "https://dash.lagon.app" // Replace this field
}
```

Replace the `site_url` field by the one configured during the installation. To verify if it's working correctly, login to your installation using `lagon login`.
6 changes: 2 additions & 4 deletions packages/docs/pages/index.mdx
@@ -1,10 +1,8 @@
import { Callout } from 'nextra-theme-docs'
import { Callout } from 'nextra-theme-docs';

Lagon is a free Open Source Runtime and SaaS that make it easy to deploy TypeScript and JavaScript Serverless Functions at the Edge, using V8 Isolates. It's also self-hostable.

<Callout type="warning">
Lagon is still in heavy development. Do not use for production usages.
</Callout>
<Callout type="warning">Lagon is still in heavy development. Do not use for production usages.</Callout>

Current status:

Expand Down
14 changes: 5 additions & 9 deletions packages/docs/pages/runtime-apis.mdx
@@ -1,4 +1,4 @@
import { Callout } from 'nextra-theme-docs'
import { Callout } from 'nextra-theme-docs';

The following APIs are the same as the Web APIS you already know. Additionally, we follow the [WinterCG](https://wintercg.org/) conventions.

Expand All @@ -8,7 +8,7 @@ The only required code to make your Function runnable is to export a `handler` f

```typescript
export function handler(request: Request): Response {
return new Response('Hello World!')
return new Response('Hello World!');
}
```

Expand Down Expand Up @@ -36,7 +36,7 @@ Example:

```typescript
export function handler(request: Request): Response {
return new Response(`My secret is: ${process.env.SECRET}`)
return new Response(`My secret is: ${process.env.SECRET}`);
}
```

Expand All @@ -50,9 +50,7 @@ The standard `TextDecoder` object. [See the documentation on MDN](https://develo

### Fetch

<Callout type="info">
Looking for the `fetch()` method? [Jump to fetch()](#fetch-1).
</Callout>
<Callout type="info">Looking for the `fetch()` method? [Jump to fetch()](#fetch-1).</Callout>

#### `Request`

Expand All @@ -69,9 +67,7 @@ You can pass a [`ReadableStream`](#readablestream) object as the `body` of a `Re

The standard `URL` object. [See the documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/API/URL).

<Callout type="warning">
This URL implementation only supports URLs with a scheme.
</Callout>
<Callout type="warning">This URL implementation only supports URLs with a scheme.</Callout>

#### `URLSearchParams`

Expand Down
23 changes: 15 additions & 8 deletions packages/serverless/src/deployments/mod.rs
Expand Up @@ -31,6 +31,7 @@ pub struct Deployment {
pub environment_variables: HashMap<String, String>,
pub memory: usize, // in MB (MegaBytes)
pub timeout: usize, // in ms (MilliSeconds)
pub is_production: bool,
}

impl Deployment {
Expand All @@ -43,13 +44,16 @@ impl Deployment {
dotenv::var("LAGON_ROOT_DOMAIN").expect("LAGON_ROOT_DOMAIN must be set")
));

// TODO: should only set function name and domains deployments when deployment is the production one
domains.push(format!(
"{}.{}",
self.function_name,
dotenv::var("LAGON_ROOT_DOMAIN").expect("LAGON_ROOT_DOMAIN must be set")
));
domains.extend(self.domains.clone());
// Default domain (function's name) and custom domains are only set in production deployments
if self.is_production {
domains.push(format!(
"{}.{}",
self.function_name,
dotenv::var("LAGON_ROOT_DOMAIN").expect("LAGON_ROOT_DOMAIN must be set")
));

domains.extend(self.domains.clone());
}

domains
}
Expand All @@ -67,6 +71,7 @@ pub async fn get_deployments(
r"
SELECT
Deployment.id,
Deployment.isProduction,
Function.id,
Function.name,
Function.memory,
Expand All @@ -82,8 +87,9 @@ pub async fn get_deployments(
LEFT JOIN Asset
ON Deployment.id = Asset.deploymentId
",
|(id, function_id, function_name, memory, timeout, domain, asset): (
|(id, is_production, function_id, function_name, memory, timeout, domain, asset): (
String,
bool,
String,
String,
usize,
Expand Down Expand Up @@ -123,6 +129,7 @@ pub async fn get_deployments(
environment_variables: HashMap::new(),
memory,
timeout,
is_production,
});
},
)?;
Expand Down

0 comments on commit 045977c

Please sign in to comment.