Streamlining Node.js App Deployment with GitHub Actions and Railway
Tags: javascript, githubactions, node, railway
Published: 2023-07-17 08:44:00

Deploying Node.js applications efficiently and reliably is crucial for modern development workflows. Thankfully, the process has become much more streamlined with the advent of powerful automation tools and cloud platforms. 

By harnessing the capabilities of the combination of GitHub Actions and Railway, developers can not only streamline the deployment of their Node.js applications but also establish a seamless continuous delivery pipeline. 

This powerful combination can simplify and automate the deployment of Node.js applications, incorporating Continuous Integration/Continuous Delivery|Deployment (CI/CD) practices. In my last [article](https://dev.to/olumidenwosu/implementing-continuous-integration-for-nodejs-apps-with-github-actions-1ag2), I shed more light on Continuous Integration with GitHub Actions in Node.js apps. 

Continuous Delivery enables frequent and reliable releases by automating the entire software release process, from code changes to production deployment. Continuous Deployment takes it a step further by automatically deploying the changes to the production environment once they pass the necessary tests and checks.

In this article, we will walk through the step-by-step process of setting up GitHub Actions and Railway for our Node.js application deployments, covering everything from initial setup to defining the deployment workflow and ultimately, deploying our application seamlessly. 

Now, let's dive in and explore how GitHub Actions and Railway can help us spend more time on coding and less on infrastructure management.

## GitHub Actions: Automate GitHub workflows

GitHub Actions makes it easy to automate, customize, and execute our software development workflows right in our GitHub repositories. It allows developers to create custom workflows that automate various tasks, including building, testing, and deploying code changes. These workflows are defined in YAML files and can be triggered by events such as code pushes, pull requests, and issue comments.

Some of the key features of GitHub Actions include:

* Easy integration with GitHub repositories.
* Support for a wide range of programming languages and frameworks.
* Ability to run workflows on different operating systems and virtual environments.
* Support for custom actions and third-party integrations.
* Detailed logs and reporting to help diagnose issues and track progress.
    

## Railway: Deploy apps to production effortlessly

Railway is a powerful platform made to make managing and deploying applications easier. It is a platform that offers programmers a quick and effective way to ship their projects. It takes care of the hassles associated with infrastructure setup, freeing developers to concentrate on developing code. With just a few commands or configuration steps, developers may easily launch their apps using Railway. It provides one-click deployments, which makes it simple to distribute programs across various environments. Railway takes away the specifics of the infrastructure, making deployment simple. It seeks to give developers a simple method for quickly deploying their apps to the cloud without having to worry about complex infrastructure arrangements.

Here are a few standout features that make Railway the top choice for hosting applications:

* **Zero-downtime deploys:** Applications can be deployed without any downtime, or according to their [Home Page](https://railway.app/), +99% uptime.
* **Lightning-fast builds:** Railway uses Docker to build applications, so builds are lightning-fast. This means that new code can be shipped quickly and easily.
* **Real-time logs and metrics:** Railway provides real-time logs and metrics for applications, making it easy and quick to troubleshoot problems.
* **Config as Code:** Railway allows for automation of deployments and infrastructure management with code, improving consistency.
* **Secrets management**: Developers have the ability to maintain separate development, staging, and production environments while securely managing secrets.
* **Usage-based pricing**: Resource usage is billed based on actual usage, eliminating the need for over-provisioning and allowing for more efficient cost management.


## GitHub Actions + Railway: Control app deployments

Although it is possible to link a GitHub repository directly to a Railway project for automatic deployment whenever changes are pushed, making use of GitHub Actions provides several advantages, such as:

* **Customization**: GitHub Actions and a workflow file offer flexibility and customization options to tailor the CI/CD pipeline to specific requirements. For instance, a workflow could be set up for multiple branches, or different triggers(push or pull request).
* **Integration with Testing and Build Processes**: GitHub Actions seamlessly integrates with testing frameworks and build processes. We can incorporate automated tests, code quality checks, and build steps into our workflow. This integration ensures that all changes are thoroughly tested and validated before deployment.   
* **Extensive Ecosystem of Actions**: GitHub Actions has a vast ecosystem of pre-built actions that can be incorporated into workflows. These actions cover a wide range of functionalities, such as deploying to various platforms, running tests in different environments, and interacting with external services. Leveraging these actions simplifies the deployment process and extends the capabilities of our workflow.
    
## Prerequisites

To follow through in this article, the following have to be put in place:

* A [GitHub Account](https://github.com/signup)
* A Node.js Repository
* A [Railway Account](https://railway.app/login)
    

## Creating a Project on Railway

After creating a Railway account, we need to create a project.

* First, click on the **New Project** button.

![New Project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5yd443bbee65ve758y0.png)
    
* Next, create an empty template.
    
![Empty Template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i1zrynhvznhgr29q3c21.png)


## Getting an Authentication Token

After creating our project, we need to obtain a token with which will communicate to Railway from GitHub. To do that we need to follow these steps:

* Navigate to the project settings.
    ![Project Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d10r2b87zirm3ei4y92x.png)
    
* Click on the **Tokens** tab.
    ![Tokens Tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7v16n834jo1efoy9oyx.png)

* Create a new token. We can call it whatever we want. Here, it's called `GITHUB_TOKEN` .
    ![New Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5jf7qxv7ybejnbpyx74b.png)
    
* Copy the newly created token.
    ![Copy Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aqjnjyvs835xd5q27ta7.png)


## Adding Authentication Key to GitHub

For the purpose of this article, we will be making use of this repository: [gh-actions-demo](https://github.com/olumidayy/gh-actions-demo). This was the project that was used for this article: [Implementing Continuous Integration for Node.js Apps with GitHub Actions](https://olumidenwosu.hashnode.dev/implementing-continuous-integration-for-nodejs-apps-with-github-actions). We will also be adopting the workflow file of this project.

Now, to add the authentication token we got from the previous section to GitHUb we need to follow the following steps:

* Go over to the repository's settings.
    
* Click on **Secrets and variables**, and then on **Actions.**
    
* Next, click on the **New repository secret button.**
    ![New Secret](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0itii10lt4mlts6ei8q.png)
    
* Add the authentication token and set the name as **RAILWAY\_TOKEN.**
    ![Token Name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9vx7ac7hrn25pr91o4e.png)

It should show the newly added token as one of the repository's secrets.
![Repo Secrets](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0rpygfo81exdw9tacg2.png)

## Adding Our Workflow File

Now that we've put our Railway token in place, we can now create the workflow that triggers the deployment of changes to the server. Currently, our `main.yml` file looks like this:

### `main.yml`

```yaml
name: Node.js CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 14
      uses: actions/setup-node@v3
      with:
        node-version: 14
        cache: 'npm'

    - run: npm install
    - run: npm test
```

At this stage, all this workflow basically does is to install our app's dependencies and to test the app. To account for the deployment process as well, we'll be adding the following snippet to our workflow file:

```yaml
- name: Install Railway # 1
  run: npm i -g @railway/cli

- name: Deploy # 2
  run: railway up
  env:
    RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} # 3
```

1. The first command is responsible for installing the railway CLI which will be used to carry out the deployment.
    
2. The second command is the one that actually initiates the deployment.
    
3. For the whole deployment process, Railway needs to know that we have authorization and so it checks for the `RAILWAY_TOKEN` . This is why we needed to add it as a repository secret.
    

**NOTE:** Railway CLI works with Node.js 16+, so we'll be changing that as well.

After making these, our workflow file should now look like this:

### `main.yml`

```yaml
name: Node.js CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 16
      uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'

    - run: npm install
    - run: npm test

    - name: Install Railway
      run: npm i -g @railway/cli
    
    - name: Deploy
      run: railway up
      env:
        RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
```

Now we will commit these changes and push them to GitHub to trigger the deployment workflow. After pushing the changes, a green checkmark should be visible on the repository which denotes that our workflow ran successfully.
![Workflow Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tkoqhkmy7rol9pzfo4nw.png)

Similarly, when we navigate to our project on Railway, we should see that the deployment was successful.

![Railway Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nz50vbwdixt49d8qqjp0.png)


## Making our App Public

At this juncture, the app has been deployed but it is still not visible to everybody. This means that we need to generate a domain for it so that anybody with a link can visit our app. This can be done by following these steps:

* Click on **Settings** to go the project's settings.
    
* Click on **Generate Domain**.
   
![Generate domain](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k7ol6z9lqwu7ll5v9w2v.png)
    
A link should be generated.

![Domain link](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0asp8n5zxi4cvd0xrbz.png)

* Click on the link and it should return the expected response.

![Response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zye6r81qj5mwfm6b9cl4.png)

## Conclusion
In conclusion, the combination of GitHub Actions and Railway offers a powerful solution for streamlining the deployment of Node.js applications. By integrating these two platforms, developers can automate the entire CI/CD pipeline, reduce manual effort, and ensure consistent and reliable deployments.

With GitHub Actions, developers have the flexibility to define custom workflows, automate build and test processes, and seamlessly integrate with various tools and services.