Streamlining CI/CD for Monorepos with Serverless Framework Pro

ci/cd

Learn to efficiently deploy serverless applications from a monorepo using Serverless Framework Pro's CI/CD solution, covering setup, automated, selective, and dependency-based deployments.

This article was updated to reflect changes in the new dashboard at app.serverless.com.

When building serverless applications as a collection of Serverless services, deciding whether to push each service individually to your version control system or bundle them all together as a single repository is crucial. While this article won't delve into the pros and cons of each approach, previous examples often showcase services stored in individual repositories.

This guide will demonstrate how easily services can be deployed from within a single monorepo using Serverless Framework Pro's CI/CD solution.

Getting Started

Ensure that the services you are deploying are bundled together in a repository within separate subdirectories off the root. A simple example repository here illustrates this structure. The key point is that all services, along with any shared code, reside in separate subdirectories directly off the repository's root, simplifying later configuration.

Note: Serverless Framework Pro offers a generous free tier, so you can try this feature without needing a paid account.

Once your repository is set up (or you've cloned the sample repo), verify that each service in its subdirectory has the same app and org settings to connect to the dashboard, and that these changes are pushed to the repo.

The final preparatory step before configuring monorepo deployment is to ensure your connection to your AWS account is established, especially if you have a brand new dashboard account. This 2-minute video provides a quick guide on connecting to AWS using Providers.

With these prerequisites addressed, let's begin!

First Deploy

The best way to start is to perform an initial deployment to get all your services into AWS and registered within the dashboard. Follow these steps:

  1. Ensure you have CLI credentials to communicate with your Serverless account by running serverless login in your CLI and completing the login process.
  2. If the app property you've added to your services' serverless.yml files doesn't exist, click the create app button and choose to add an existing Serverless Framework project.
  3. During this process, you can create or select a new Provider.
  4. Once the app is created, return to your project on the CLI, cd into the first service's directory, and run serverless deploy --stage [stageyouwanthere]. The --stage flag is optional; it defaults to dev unless specified otherwise.
  5. Repeat step 4 by cding into each subsequent subdirectory and deploying each service to AWS.

Even if these services are already deployed, you can deploy them again. As long as only the org and app properties have changed, this new deployment simply adds these services to your dashboard account.

Connecting to GitHub or BitBucket

Now that everything is added to the dashboard, click the menu option to the right of one of your service names and select 'Settings':

In the settings menu, select 'CI/CD' to open the configuration. If this is your first time, you may need to connect to GitHub or BitBucket; simply click the connect option and follow the prompts.

After connecting, choose your monorepo from the dropdown list. Since it's a monorepo, the CI/CD settings will also prompt you to select the correct base directory for this specific service. Proceed with that selection.

Setting Up Automated Deployments

With the basic connection established, scroll down to the branch deploys section. Here, you can configure which repository branch deploys to which stage or environment. Typically, a main (or master) branch is mapped to the prod stage. You can also add a develop branch to deploy to the dev stage, as shown in the image:

Add any additional branch-to-stage mappings as needed. This configuration will automatically trigger a deployment whenever code changes are merged into the configured branch. For instance, if a developer creates a PR to the develop branch and it's merged, it will automatically deploy your service to the dev stage if configured as in the image above.

NOTE: You can use Providers to configure different AWS connections for each stage and Parameters to pass different configuration values for each stage at deployment time.

You will need to repeat this process for each subdirectory within your monorepo.

More Advanced Configuration

Selective Deployments

By default, if you have multiple services configured within a monorepo and merge a change anywhere in that repository, all services will redeploy as a precaution. The system cannot infer dependencies between services, so it cannot assume that only the service with the direct change needs redeploying. For example, if you have six services and make a change to just one, all six will undergo separate redeployments.

However, you can configure this differently. If you open the CI/CD settings for one of your services and expand the build settings section, you'll find various options to maximize your monorepo's CI/CD pipeline efficiency.

By default, the Only trigger builds on selected file changes option is not selected, meaning this service will always redeploy with any change to the Git repository, even if its own code hasn't changed. To ensure this service only redeploys when its code is edited, check the box, and you'll see something like this:

The current service's directory is automatically selected. From this point on, servicea will only be redeployed when its own code is edited.

Dependency Deployment

What if your services actually have dependencies on each other? For instance, with servicea, you could link it to serviceb and configure it so servicea always redeploys when serviceb is edited. By simply adding a reference to the correct service directory, you can ensure this happens:

You can apply this to any number of services that servicea depends on, and vice versa. What if servicea uses a shared folder? Since our configuration references a directory structure, you can point to any path in your monorepo to be watched for changes. In the example repo, there's a shared directory containing classes and functions reused by multiple services. If anything in shared changes, multiple services need to redeploy.

You can achieve this by simply adding the path to shared:

In the image above, servicea will be deployed on merges to GitHub if changes are detected in the servicea, serviceb, or shared directories. This allows for a highly flexible configuration, enabling you to deploy exactly what's needed under specific circumstances.

Monorepo deployments are significantly simpler to manage using Serverless Framework Pro CI/CD. For feedback or to share your thoughts, join our Slack channels or Forums. You can also DM on Twitter with any questions.

Try Serverless Console

Monitor, observe, and trace your serverless architectures. Real-time dev mode provides streaming logs from your AWS Lambda Functions. Get started for free.