<p align="center">
  <img src="https://github.com/campfire-previews/campfire-app/blob/main/src/assets/campfire.svg" width="500" height="auto" />
</p>

<h1 align="center">🔥 Campfire: open-source, self-hosted deploy previews for containerized, headless frontends</h1>

Campfire automates the creation and teardown of deploy previews for your application, and comes with an integrated feedback interface to make collaborative teamwork possible. We support serverless applications with a Dockerfile and provision resources on AWS.

To learn more, check out our [case study](https://campfire-previews.github.io/).

[![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)
[![GitHub license](https://img.shields.io/github/license/oclif/hello-world)](https://github.com/oclif/hello-world/blob/main/LICENSE)

---

# Table of Contents

- [Prerequisites](#prerequisites)
- [Application Requirements](#application-requirements)
- [Installation](#installation)
- [Configuring Campfire](#configuring-campfire)
- [Using Campfire with your Application](#using-campfire-with-your-application)
- [Commands](#commands)
- [FAQ](#faq)

# Prerequisites

- GitHub Account/Organization
- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) configured to your AWS account
- AWS IAM User with required permissions
- Node + NPM
- Domain Name

# Application Requirements

- Contains a Dockerfile
- Has a serverless architecture
- Configured to run on port `8080`
- Embedded Campfire SDK

# Installation

```sh-session
$ npm install -g campfire-cli
```

# Configuring Campfire

- Run `campfire setup`

- Input your AWS Region and domain for Campfire to use.

  - A configuration file will be created

- A server will be started at `localhost` on port `3000`. You will be directed to register Campfire's GitHub App by visting `localhost:3000` in your browser. You will be directed to GitHub where you will have to enter a unique name for the GitHub Application. This will be the name of the Campfire bot that posts comments on pull requests.

- Campfire will request an AWS SSL certificate. The certificate must be validated through DNS verification on your domain host.

  - Campfire will output 3 CNAME records that need to be added to your domain in order to verify the certificate. The `setup` process will not continue until the certificate is verified.
  - Keep your domain host window open for the last step.

- Once verified `setup` will proceed to provision all other AWS resources.

- Two additional CNAME records with hosts for `\*.campfire-preview` and `campfire` will be output. These records should also be added to your domain and be set to reference the application load balancer.

- It may take around 5 - 10 minutes for AWS to complete the stack build.

# Using Campfire with your application

> [!IMPORTANT]
>
> ### GitHub App Installation
>
> Make sure the Campfire GitHub App you registered during `setup` is installed and has access to the GitHub repository you are initializing. You have the option to install the GitHub App for all repositories or only selected repositories.
>
> User/Organization Settings > Developer Settings > Github Apps > Edit > Install App
>
> ##

### Embedding the Campfire SDK

In order for Campfire features to function properly, we require users to have the Campfire SDK embedded into their applications. There are two ways to embed the SDK:


#### 1. **Embed as an `npm` package**
Install the [Campfire SDK](https://www.npmjs.com/package/campfire-sdk) through your CLI:

```
npm install campfire-sdk
```

Create an instance of the Campfire SDK in a script:

```javascript
import CampfireSDK from 'campfire-sdk'

new CampfireSDK()
```

#### 2. **Embed through a CDN link**
Alternatively, import the SDK in a HTML file using our CDN:
```html
<script type="module">
  import CampfireSDK from 'https://cdn.jsdelivr.net/npm/campfire-sdk@1.0.0/+esm'
  new CampfireSDK();
</script>
```


For React applications, create the instance within a `useEffect` hook:

```javascript
import CampfireSDK from 'campfire-sdk'
import {useEffect} from 'react'

useEffect(() => {
  new CampfireSDK()
}, [])
```

### Generating Workflow Files

- Navigate to the root of your project repository.

- Run `campfire init`

- Enter the name of your application. The name you provide will correspond to the cluster created in AWS Elastic Container Service.

- Campfire will build the workflow files for your project and place them in a new `.github` directory.

- Commit and push the directory to your GitHub repository.

- Add the AWS Access Keys that are output to your project's Github repository as secrets. See [Environment Variables step 1](#environment-variables) below for instructions on creating GitHub secrets.

- All future pull requests made will now generate Campfire deploy previews.

> [!NOTE]
>
> ### Environment Variables
>
> If your application references environment variables that you don't want exposed in your GitHub repo, add them as GitHub Secrets.
>
> 1. Create GitHub Secrets
>
>    - Navigate to the main page of your repository
>
>    - Settings > Secrets > Actions > New repository secret
>
> 2. Add your environment variable(s)
>
>    - Go to `.github/workflows/create_preview.yml`.
>    - Add your environment variable as a GitHub Action `env` variable:
>
>      ```yaml
>      env:
>        MY_ENV_VAR: ${{ secrets.MY_ENV_VAR }}
>        # ...
>      ```
>
> 3. Reference in Task Definition
>
>    - Go to `.github/actions/deploy-preview/action.yml`.
>    - Go to line 52
>
>      ```yaml
>      'environment': []
>      ```
>
>    - Add JSON for your environemnt variable key/value pair to the `environment` array. The `'value'` corresponds to the name you gave your `env` variable in step 2.
>
>      ```yaml
>      'environment': [{'name': 'MY_ENV_VAR', 'value': $MY_ENV_VAR}]
>      ```
>
> #

# Commands

- [`campfire setup`](#campfire-setup-command)
- [`campfire init`](#campfire-init-command)
- [`campfire list`](#campfire-list-command)
- [`campfire destroy`](#campfire-destroy-command)
- [`campfire help [COMMAND]`](#campfire-help-command)

## `campfire setup`

Provisions the AWS resources required for Campfire.

This command creates the underlying AWS infrastructure to support future deploy previews. This includes the following:

 <table>
  <tr>
    <th colSpan=2>List of Resources</th>
  </tr>
  <tr>
    <td>IAM Roles (2)</td>
    <td>REST API Gateway</td>
  </tr>
  <tr>
    <td>IAM User (1)</td>
    <td>ECS Cluster</td>
  </tr>
  <tr>
    <td>Non-default VPC</td>
    <td>ECS Service</td>
  </tr>
  <tr>
    <td>Route Table</td>
    <td>ECS Task Definition</td>
  </tr>
  <tr>
    <td>Application Load Balancer (ALB)</td>
    <td>ECR Repositories</td>
  </tr>
  <tr>
    <td>ALB Listener</td>
    <td>Log Groups</td>
  </tr>
  <tr>
    <td>ALB Listener Rules</td>
    <td>EC2 Target Groups</td>
  </tr>
  <tr>
    <td>TLS/SSL Certificates</td>
    <td>Lambda Functions</td>
  </tr>
  <tr>
    <td>Internet Gateway</td>
    <td>Lambda Permissions</td>
  </tr>
  <tr>
    <td>Security Groups</td>
    <td>S3 Buckets</td>
  </tr>
  <tr>
    <td>Subnets</td>
    <td>Secrets Manager</td>
  </tr>
</table>

**NOTE: The IAM User configured with your AWS CLI must have write permissions for the resources above.**

See [Configuring Campfire](#configuring-campfire) above for more details on the `campfire setup` process

See [here](https://github.com/campfire-previews/campfire-cli/blob/main/templates/cloudformation/campfire.yml) for a complete list of resources provisioned.

See [src/commands/setup.js](https://github.com/campfire-previews/campfire-cli/blob/main/src/commands/setup.ts)

## `campfire init`

Initializes Campfire in your project repository

Run it from the root directory of your repository and follow the prompts for each step of the initialization process.

See [Using Campfire with your application](#using-campfire-with-your-application) above for more details on the `campfire init` process

See [src/commands/init.js](https://github.com/campfire-previews/campfire-cli/blob/main/src/commands/init.ts)

## `campfire list`

Lists all project repositories that have been initialized with Campfire. The names listed are all ECS Clusters that were created for each project during `campfire init`.

See [src/commands/init.js](https://github.com/campfire-previews/campfire-cli/blob/main/src/commands/init.ts)

## `campfire destroy`

Deletes all AWS resources provisioned from `campfire setup` and ECS clusters created in `campfire init`.

Run command after closing all open pull requests for initialized projects.

Users have the option to delete secrets created in AWS Secrets Manager.

- Deleting secrets will prevent your AWS from incurring charges for storing them.
- However, you will not be able to use Campfire (run `setup`) until these secrets are deleted. These secrets are scheduled to be deleted in seven days.

If you plan on using Campfire again in the near future, we advise not to delete the secrets.

See [src/commands/destroy.js](https://github.com/campfire-previews/campfire-cli/blob/main/src/commands/destroy.ts)

## `campfire help [COMMAND]`

Display usage and description for a Campfire command.

# FAQ

## How can I troubleshoot the `setup` command hanging at `Provisioning AWS Resources`?

Navigate to your [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/home). Click on the `campfire` stack created by the `setup` command and click on `Detect Root Cause`.

Any information or error logs relating to the CloudFormation stack can be found here.

If the stack creation rolled back due to `Insufficient IAM permissions`, it is likely that the IAM User configured with your AWS CLI does not have the specified permission. Navigate to the AWS IAM console and attach the appropriate permissions to your IAM User.

## Why is the "Create Preview App" action failing when I make a pull request?

Make sure the Campfire GitHub App has been installed to the repository. See [GitHub App Installation](#github-app-installation).

Verify that the repository contains your AWS Access Key and AWS Private Access Key as repository secrets. These credentials are output during `campfire init`.

---

<p align="center">🌲🌳🌲 ⛺💬🔥⛺ 🌲🌳🌲</p>
