Skip to content

Commit

Permalink
Prepare 0.1.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
ellmetha committed Oct 24, 2022
1 parent 5843588 commit faf59c5
Show file tree
Hide file tree
Showing 70 changed files with 9,175 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
docs/versioned_docs/* linguist-vendored
docs/versioned_sidebars/* linguist-vendored
2 changes: 1 addition & 1 deletion docs/docs/prologue.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ The Marten documentation contains multiple pages and references that don't neces
* **Reference pages** provide a curated technical reference of the framework APIs
* **How-to guides** document how to solve common problems whem working with the framework. Those can cover things like deployments, app development, etc

Additionally, an automatically-generated [API reference](pathname:///api) is also available in order to dig into Marten's internals.
Additionally, an automatically-generated [API reference](pathname:///api/index.html) is also available in order to dig into Marten's internals.
2 changes: 1 addition & 1 deletion docs/docs/the-marten-project/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ Here are listed the release notes for each version of the Marten web framework.

## Marten 0.1

* [Marten 0.1 release notes (UNDER DEVELOPMENT)](./release-notes/0.1)
* [Marten 0.1 release notes](./release-notes/0.1)
2 changes: 1 addition & 1 deletion docs/docs/the-marten-project/release-notes/0.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pagination_prev: null
pagination_next: null
---

_UNDER DEVELOPMENT_
_October 23, 2022._

## Requirements and compatibility

Expand Down
15 changes: 15 additions & 0 deletions docs/versioned_docs/version-0.1/deployment.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Deployment
---

import DocCard from '@theme/DocCard';

The section explains the steps involved when it comes to deploying a Marten project. It also gives useful tips in order to secure Marten web applications in production.

## Guides

<div className="row">
<article key="introduction" className="col col--6">
<DocCard item={{type: "link", href: "./deployment/introduction", label: "Introduction", docId: "deployment/introduction" }} />
</article>
</div>
118 changes: 118 additions & 0 deletions docs/versioned_docs/version-0.1/deployment/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
title: Deploying Marten projects
description: Learn about the things to consider when deploying Marten web applications.
sidebar_label: Introduction
---

This section describes what's involved when it comes to deploying a Marten web application and highlights some important things to consider before performing deploys.

## Overview

Each deployment pipeline is unique and will vary from one project to another. That being said, a few things and requirements will be commonly encountered when it comes to deploying a Marten projects:

1. installing your project's dependencies
2. compiling your project's server and [management CLI](../development/management-commands)
3. collecting your project's [assets](../files/asset-handling)
4. applying any pending migrations to your database
5. starting the compiled server

Where, when, and how these steps are performed will vary from one project to another. Each of these steps is highlighted below along with some recommendations.

### Installing dependencies

One of the first things you need to do when deploying a Marten project is to ensure that the dependencies of the projects are available. In this light, you can leverage the `shards install` command in order to install your project's Crystal dependencies (assuming that Crystal is installed on your destination machine). Obviously your project may require the installation of other types of dependencies (such as Node.js dependencies for example), which you have to take care as well.

### Compiling your project

Your project server and [management CLI](../development/management-commands) need to be compiled in order to run your project's server and to execute additional deployment-related management commands (eg. in order to [collect assets](#collecting-assets) or [apply migrations](#applying-migrations)).

When it comes to your project server, you will usually need to compile the `src/server.cr` file (which is automatically created when generating new projects via the [`new`](../development/reference/management-commands#new) management command). This can be achieved with the following command:

```bash
crystal build src/server.cr -o bin/server --release
```

:::tip
In the above example, the server binary is compiled using the `-o bin/server` option, which ensures that the compiled binary will be named `server` and stored under the related `bin` folder. You should obviously adapt this to your production environment.
:::

The [management CLI](../development/management-commands) is provided by the `manage.cr` file located at the root of your project. As usual, this file is also automatically generated for you when creating Marten projects through the use of the [`new`](../development/reference/management-commands#new) management command. Compiling this binary can be done with the following command:

```bash
crystal build manage.cr -o bin/manage --release
```

:::info
The above compilation commands make use of the `--release` flag, which enables compiler optimizations. As a result, the compilation of the final binaries may take quite some time depending on your project. You can also avoid using `--release` if needed but technically performances could be impacted. See [Release builds](https://crystal-lang.org/reference/man/crystal/index.html#release-builds) for more details on this subject.
:::

### Collecting assets

You need to ensure that your project and applications assets (eg. JavaScripts, CSS files, etc) are "collected" at deploy time so that they are placed at the final destination from which they will be served: this operation is made available through the use of the [`collectassets`](../development/reference/management-commands#collectassets) management command. This "destination" depends on your deployment strategy and your configured [assets settings](../development/reference/settings#assets-settings): it can be as simple as moving all these assets to a dedicated folder in your server (so that they can be served by your web server), or it can involve uploading these assets to an S3 or GCS bucket for example.

In order to collect assets at deploy time, you will want to use the compiled `manage` binary and run the [`collectassets`](../development/reference/management-commands#collectassets) management command (as mentioned previously) with the `--no-input` flag set in order to disable user prompts:

```bash
bin/manage collectassets --no-input
```

:::info
The assets handling documentation also provides a few [guidelines](../files/asset-handling#serving-assets-in-production) on how to serve asset files in production that may be worth reading.
:::

### Applying migrations

You projects will likely make use of models, which means that you will need to ensure that those are properly created at your configured database level by running the associated migrations.

To do so, you can use the compiled `manage` binary and run the [`migrate`](../development/reference/management-commands#migrate) management command:

```bash
bin/manage migrate
```

Please refer to [Migrations](../models-and-databases/migrations) to learn more about model migrations.

### Running the server

You can run the compiled Marten server using the following command (obviously the location of the binary depends on [how the compilation was actually performed](#compiling-your-project)):

```bash
bin/server
```

It's important to note that the Marten server is intended to be used behind a reverse proxy such as [Nginx](https://www.nginx.com/) or [Apache](https://httpd.apache.org/): you will usually want to configure such reverse proxy so that it targets your configured Marten server host and port. In this light, you should ensure that your Marten server is not using the HTTP port 80 (instead it could use something like 8080 or 8000 for example).

Depending on your use cases, a reverse proxy will also allow you to easily serve other contents such as [assets](../files/asset-handling) or [uploaded files](../files/managing-files), and to use SSL/TLS.

:::tip
It is possible to run multiple processes of the same server behind a reverse proxy such as Nginx. Indeed, each compiled server can accept optional parameters in order to override the host and / or port being used. These parameter are respectively `--bind` (or `-b`) and `--port` (or `-p`). For example:

```bash
bin/server -b 127.0.0.1
bin/server -p 8080
```
:::

## Additional tips

This section lists a few additional things to consider when deploying Marten projects.

### Secure critical setting values

You should pay attention to the value of some of your settings in production environments.

#### Debug mode

You should ensure that the [`debug`](../development/reference/settings#debug) setting is always set to `false` in production environments. Indeed, the debug mode can help for development purposes because it outputs useful tracebacks and site-related information. But there is a risk that all this information leaks somewhere if you enable this mode in production.

#### Secret key

You should ensure that the value of the [`secret_key`](../development/reference/settings#secret_key) setting is not hardcoded in your [config files](../development/settings). Indeed, this setting value must be kept secret and you should ensure that it's loaded dynamically instead. For example, this setting's value could be set in a dedicated environment variable (or dotenv file) and loaded as follows:

```crystal
Marten.configure do |config|
config.secret_key = ENV.fetch("MARTEN_SECRET_KEY") { raise "Missing MARTEN_SECRET_KEY env variable" }
# [...]
end
```
43 changes: 43 additions & 0 deletions docs/versioned_docs/version-0.1/development.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Development
---

import DocCard from '@theme/DocCard';

Marten provides various tools and mechanisms that you can leverage in order to develop, structure, and test projects and applications.

## Guides

<div className="row">
<article key="settings" className="col col--6">
<DocCard item={{type: "link", href: "./development/settings", label: "Settings", docId: "development/settings" }} />
</article>
<article key="applications" className="col col--6">
<DocCard item={{type: "link", href: "./development/applications", label: "Applications", docId: "development/applications" }} />
</article>
<article key="management-commands" className="col col--6">
<DocCard item={{type: "link", href: "./development/management-commands", label: "Management commands", docId: "development/management-commands" }} />
</article>
<article key="testing" className="col col--6">
<DocCard item={{type: "link", href: "./development/testing", label: "Testing", docId: "development/testing" }} />
</article>
</div>

## How-to's

<div className="row">
<article key="create-custom-commands" className="col col--6">
<DocCard item={{type: "link", href: "./development/how-to/create-custom-commands", label: "Create custom commands", docId: "development/how-to/create-custom-commands" }} />
</article>
</div>

## Reference

<div className="row">
<article key="settings" className="col col--6">
<DocCard item={{type: "link", href: "./development/reference/settings", label: "Settings", docId: "development/reference/settings" }} />
</article>
<article key="management-commands" className="col col--6">
<DocCard item={{type: "link", href: "./development/reference/management-commands", label: "Management commands", docId: "development/reference/management-commands" }} />
</article>
</div>
119 changes: 119 additions & 0 deletions docs/versioned_docs/version-0.1/development/applications.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
title: Applications
description: Learn how to leverage applications to structure your projects.
sidebar_label: Applications
---

Marten projects can be organized into logical and reusable components called "applications". These applications can contribute specific behaviors and abstractions to a project, including [models](../models-and-databases), [handlers](../handlers-and-http), and [templates](../templates). They can be packaged and reused across various projects as well.

## Overview

A Marten **application** is a set of abstractions (defined under a dedicated and unique folder) that provides some set of features. These abstractions can correspond to [models](../models-and-databases), [handlers](../handlers-and-http), [templates](../templates), [schemas](../schemas/), etc.

Marten projects always use one or many applications. Indeed, each Marten project comes with a default [main application](#the-main-application) that corresponds to the standard `src` folder: models, migrations, or other classes defined in this folder are associated with the main application by default (unless they are part of another _explicitly defined_ application). As projects grow in size and scope, it is generally encouraged to start thinking in terms of applications and how to split models, handlers, or features accross multiple apps depending on their intended responsibilities.

Another benefit of applications is that they can be packaged and reused across multiple projects. This allows third-party libraries and shards to easily contribute models, migrations, handlers, or templates to other projects.

## Using applications

The use of application must be manually enabled within projects: this is done through the use of the [`installed_apps`](./reference/settings#installedapps) setting.

This setting corresponds to an array of installed app classes. Indeed, each Marten application must define a subclass of [`Marten::App`](pathname:///api/Marten/App.html) in order to specify a few things such as the application label (see [Creating applications](#creating-applications) for more information about this). When those subclasses are specified in the `installed_apps` setting, the applications' models, migrations, assets, and templates will be made available to the considered project.

For example:

```crystal
Marten.configure do |config|
config.installed_apps = [
FooApp,
BarApp,
]
end
```

Adding an application class inside this array will have the following impact on the considered project:

* the models of this application and the associated migrations will be used
* the templates of the application will be made available to the templates engine
* the assets of the application will be made available to the assets engine
* the management commands defined by the application will be made available to the Marten CLI

### The main application

The "main" application is a default application that is always implicitly used by Marten projects (which means that it does not appear in the [`installed_apps`](./reference/settings#installedapps) setting). This application is associated with the standard `src` folder: this means that models, migrations, assets, or templates defined in this folder will be associated with the main application by default. For example, models defined under a `src/models` folder would be associated with the main application.

:::info
The main application is associated with the `main` label. This means that models of the main application that do not define an explicit table name will have table names starting with `main_`.
:::

It should be noted that it is possible to create _explicitly defined_ applications whose structures live under the `src` folder as well: the abstractions (eg. models, migrations, etc) of these applications will be associated with them and _not_ with the main application. This is because abstractions are always associated with the closest application in the files and folders structure.

In the end, the main application provides a convenient way for starting projects and prototyping without requiring to spec out how projects will be organized in terms of applications upfront. That being said, as projects grow in size and scope, it is really encouraged to start thinking in terms of applications and how to split abstractions and features accross multiple apps depending on their intended responsibilities.

### Order of installed applications

You should note that the order in which installed applications are defined in the [`installed_apps`](./reference/settings#installedapps) setting can actually matter.

For example, a "foo" app might define a `test.html` template, and a similar template with the exact same name might be defined by a "bar" app. If the "foo" app appears before the "bar" app in the array of installed app, then requesting and rendering the `test.html` template will actually involve the "foo" app's template only. This is because template loaders associated with app directories iterate over applications in the order in which they are defined in the installed apps array.

This is why it is always important to _namespace_ abstractions, assets, templates, and locales when creating applications. Failing to do so exposes apps to conflicts with other applications' code. As such, in the previous example the "foo" app should've defined a `foo/test.html` template while the "bar" app should've defined a `bar/test.html` template to avoid possible conflicts.

## Creating applications

Creating applications can be done very easily through the use of the [`new`](./reference/management-commands#new) management command. For example:

```bash
marten new app blog src/blog
```

Running such command will usually create the following directory structure:

```
src/blog
├── handlers
├── migrations
├── models
├── schemas
├── templates
├── app.cr
└── cli.cr
```

These files and folders are described below:

| Path | Description |
| ----------- | ----------- |
| handlers/ | Empty directory where the request handlers of the application will be defined. |
| migrations/ | Empty directory that will store the migrations that will be generated for the models of the application. |
| models/ | Empty directory where the models of the application will be defined. |
| schemas/ | Empty directory where the schemas of the application will be defined. |
| templates/ | Empty directory where the templates of the application will be defined. |
| app.cr | Definition of the application configuration abstraction; this is also where application files requirements should be defined. |
| cli.cr | Requirements of CLI-related files, such as migrations for example. |

The most important file of an application is the `app.cr` one. This file usually includes all the app requirements and defines the application configuration class itself, which must be a subclass of the [`Marten::App`](pathname:///api/Marten/App.html) abstract class. This class allows mainly to define the "label" identifier of the application (through the use of the [`#label`](pathname:///api/Marten/Apps/Config.html#label(label%3AString|Symbol)-class-method) class method): this identifier must be unique across all the installed applications of a project and is used to generate things like model table names or migration classes.

Here is an example `app.cr` file content for an hypothetic "blog" app:

```crystal
require "./handlers/**"
require "./models/**"
require "./schemas/**"
module Blog
class App < Marten::App
label "blog"
end
end
```

:::info
_Where_ the `app.cr` file is located is important: the directory where this file is defined is also the directory where key folders like `models`, `migrations`, `templates`, etc, must be present. This is necessary to ensure that these files and abstractions are associated with the considered app.
:::

Another very important file is the `cli.cr` one: this file is there to define all the CLI-related requirements and will usually be required directly by your project's `manage.cr` file. _A minima_ the `cli.cr` file should require model migrations, but it could also require the management commands provided by the application. For example:

```crystal
require "./cli/**"
require "./migrations/**"
```
Loading

0 comments on commit faf59c5

Please sign in to comment.