Working with NX, Railway and CI/CD
Railway has first-party support for NX monorepos through Nixpacks, users may instead want to opt for GitHub Actions in order to only create deployments for the affected services whenever they push a change.
In this article we will walk you through deploying a sample project on Railway to achieve that exact workflow.
We will use the npm-libs repository by community member: IgnisDa as our sample project. Within this repository, we will deploy the remix-pagination-demo project.
You can start by forking that repository and deploying it within a project on Railway. Once you add the repository, go to the variables
section and set the NIXPACKS_NX_APP_NAME
variable to remix-pagination-demo
.
Configuring the NX app name
Next, we can head over to the service settings and disable the GitHub trigger as we will be using GitHub actions to automatically trigger deployments for our project.
Disabling the GitHub trigger on Railway
Next, create two separate environments. One for our main
branch and one for the dev
branch and head over to the project settings to create a project token for each environment.
Creating project tokens
Copy the project tokens from Railway and add them as repository secrets on GitHub. They should have the following naming scheme:
RAILWAY_TOKEN__<project_name>_<railway_environment>
Repository secrets on GitHub
Now, we need to set-up the workflow within GitHub to trigger a new deploy.
The GitHub action workflow will:
- Run on every commit to the
main
anddev
branches - Test if a particular project has been affected
- If it has, deploy it to the correct environment on Railway
name: Deploy affected projects
on:
push:
branches:
- main
- dev
env:
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: ./.github/actions/setup
name: Setup environment
- name: Set base commit hash
run: |
#!/usr/bin/env bash
commit=${{ github.event.before }}
if git branch --contains "$commit"; then
echo "No force push detected, continuing..."
else
# get the commit before this one
commit=$(git log --format="%H" -n 2 | tail -n 1)
fi
echo "BASE_COMMIT=$commit" >> $GITHUB_ENV
- name: Display base commit
run: echo "$BASE_COMMIT"
- name: Lint affected
run: pnpm nx affected --target=lint --parallel=6 --base=$BASE_COMMIT --head=HEAD
- name: Build affected
run: pnpm nx affected --target=build --parallel=6 --base=$BASE_COMMIT --head=HEAD
- name: Dump access secrets into file
run: |
mkdir -p ./dist
echo '${{ toJSON(secrets) }}' >> ./dist/secrets.json
- name: Deploy affected
run: ./deployment/railway-trigger.sh
The main steps to note here are the:
Dump access secrets to file
step which converts the secrets into json format and dumps them into a file. This can be a potentially exploitable step if used in public repositories, so please make sure you take the appropriate cautions.Deploy affected
step which triggers therailway-trigger.sh
script shared below.
#!/usr/bin/env bash
set -euo pipefail
RAILWAY_BINARY="/tmp/railway"
RAILWAY_VERSION="1.8.4"
# Install the Railway CLI
VERSION="$RAILWAY_VERSION" INSTALL_DIR="$RAILWAY_BINARY" sh -c "$(curl -sSL https://raw.githubusercontent.com/railwayapp/cli/master/install.sh)"
$RAILWAY_BINARY version
affected_projects=$(pnpm nx print-affected --base="$BASE_COMMIT" --head=HEAD --select=projects --type='app')
for project in ${affected_projects//,/ }
do
echo "Processing: '$project'..."
# convert hyphens to underscores
parameterized_name=$(echo $project | tr '-' '_')
branch_name="$(git branch --show-current)"
# this is the key by which the required token is present in the secrets file
env_variable=RAILWAY_TOKEN__"$parameterized_name"_"$branch_name"
# convert the whole thing to upper case
final_env_variable=$(echo "$env_variable" | awk '{print toupper($0)}')
# get the actual value of the token from the secrets file
railway_token="$(jq -r ."$final_env_variable" ./dist/secrets.json)"
# trigger the deploy
RAILWAY_TOKEN="$railway_token" $RAILWAY_BINARY up --detach --verbose
done
Now there is a lot going on above.
The above script:
RAILWAY_TOKEN
RAILWAY_TOKEN
environment variable--detach
flag is used here because building containers might take a lot of time which could eat up free Github Actions quota provided. You can remove it if your project allows it.With that, we have set up CI/CD to deploy an NX monorepo to Railway using GitHub actions. You should be able to use this as a reference to deploy your own NX monorepos. If you run into any issues, feel free to reach out to us on our Discord.
This post is a community post thanks to IgnisDa’s. This is based off of a post on their own blog. Click here to read the original post!