Monorepos are powerful, but when it comes to deploying them to platforms like Koyeb, Netlify, and Vercel, things can get messy fast.
In this article, Iβll walk you through a common issue with monorepo deployments and how I solved it using GitHub Actions, including how to disable auto-deployments and trigger deploys only when specific apps/packages change.
π§ The Problem
Modern deployment platforms listen to your repo and redeploy your app every time anything changes. This works fine for single-app projects.
But with monorepos? Not so much.
Imagine this:
- You have a monorepo with multiple packages or apps.
- You deploy only one package to a platform like Vercel.
- Then you change a file in another unrelated package.
- The platform still triggers a redeploy π©
Thatβs a waste of resources, time, and can cause unnecessary build failures.
We want this instead:
Only deploy when files relevant to the deployed app/package are changed.
ποΈ Example Project Structure
To demonstrate the solution, letβs use a simple monorepo setup like this:
monorepo/
βββ netlify-frontend/ # Deployed to Netlify
βββ vercel-nextjs-app/ # Deployed to Vercel
βββ koyeb-server/ # Deployed to Koyeb
βββ shared/ # Shared code across apps (not deployed directly)
π Generating Deployment Credentials
Before we disable auto-deploys, we need a way to trigger deploys manually β using webhooks or API keys.
Vercel β Deployment Webhook
- Navigate to your project page β Settings β Git β Deploy Hooks β Create Hook
Netlify β Build Hook
- Go to your site dashboard β Site Configuration β Build & Deploy β Build Hooks β Add Build Hook
Koyeb β API Key
Koyeb doesnβt use build hooks, but instead offers an API you can use to trigger deployments programmatically.
- Open your Koyeb dashboard β Settings β API β Create API Token
π« Disabling Auto-Deployments
Once we have the credentials, we can safely disable automatic deployments.
Netlify
- Go to your site dashboard β Deploys β Click Lock to stop auto publishing
Vercel
To prevent auto-deploys from Git integration:
- Navigate to your project page β Settings β Git β Ignored Build Step β Select "Don't build anything"
Koyeb
To disable Git auto-deploy:
- Go to your service page β Settings β Configure Deployment Source β Uncheck the Autodeploy checkbox
βοΈ Step 2: GitHub Actions Workflow
Now that auto-deploy is off, we take control.
Hereβs how the GitHub Actions workflow works:
- It checks what files or folders have changed in the commit.
- If the changed files are part of
netlify-frontend/
,vercel-nextjs-app/
, orkoyeb-server/
, it triggers the corresponding deployment via webhook/API.
Hereβs a sample workflow:
# .github/workflows/deploy.yml
name: Conditional Deploy
on:
push:
branches:
- master # Triggers workflow only on push to master branch
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
# Expose matched filters as outputs for use in other jobs
netlify_frontend_changed: ${{ steps.filter.outputs.netlify_frontend }}
vercel_nextjs_app_changed: ${{ steps.filter.outputs.vercel_nextjs_app }}
koyeb_server_changed: ${{ steps.filter.outputs.koyeb_server }}
shared_changed: ${{ steps.filter.outputs.shared }}
steps:
- uses: actions/checkout@v3 # Checkout the repository code
- name: Check for changes
id: filter
uses: dorny/paths-filter@v3 # Detect which paths have changed
with:
filters: |
netlify_frontend:
- 'netlify-frontend/**'
vercel_nextjs_app:
- 'vercel-nextjs-app/**'
koyeb_server:
- 'koyeb-server/**'
shared:
- 'shared/**'
deploy-netlify-frontend:
needs: detect-changes
if: needs.detect-changes.outputs.netlify_frontend_changed == 'true' || needs.detect-changes.outputs.shared_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Trigger Netlify Deploy
run: |
curl -X POST -d '{}' https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_FRONTEND_DEPLOY_KEY }}
# Uses Netlify build hook URL to trigger deploy
deploy-nextjs-app:
needs: detect-changes
if: needs.detect-changes.outputs.vercel_nextjs_app_changed == 'true' || needs.detect-changes.outputs.shared_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Trigger Vercel Deploy
run: |
curl -X POST -d '{}' https://api.vercel.com/v1/integrations/deploy/${{ secrets.VERCEL_APP_DEPLOY_KEY }}
# Uses Vercel deploy webhook to trigger a deploy
deploy-koyeb-server:
needs: detect-changes
if: needs.detect-changes.outputs.koyeb_server_changed == 'true' || needs.detect-changes.outputs.shared_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Install Koyeb CLI
run: |
curl -fsSL https://raw.githubusercontent.com/koyeb/koyeb-cli/master/install.sh | sh
echo "$HOME/.koyeb/bin" >> $GITHUB_PATH
# Installs the Koyeb CLI and adds it to the path
- name: Verify CLI
run: koyeb version
# Optional step to verify the CLI is working
- name: Trigger redeploy
run: |
koyeb service redeploy ${{ secrets.KOYEB_SERVICE_NAME }} \
--app ${{ secrets.KOYEB_APP_NAME }} \
--token ${{ secrets.KOYEB_API_TOKEN }}
# Redeploys the Koyeb service using the CLI and secret tokens
π― Final Thoughts
With this setup:
β
You stop wasting build minutes
β
You only deploy what's actually changed
β
You fully control the pipeline with GitHub Actions
Let your monorepo breathe β deploy smarter, not harder.
Top comments (1)
Absolutely splendid write-up! Incredibly interesting! π₯