Skip to main content

Monorepo CI/CD

A monorepo is a single repository that contains the code for multiple projects or services. Instead of having one repo per application, everything lives in the same repository — which simplifies code sharing and consistency between services.

Fransys supports deploying multiple applications from a single repository, with a bit of manual CI configuration. This guide walks you through step by step.

Scenario

We'll configure a monorepo on Fransys with GitHub Actions for CI/CD. The repository contains two applications — App A and App B — organized in subdirectories.

We'll create two Fransys application blocks (one per app) connected to the same GitHub repo, with a dedicated CI workflow for each.

tip

This guide uses GitHub, but the same logic applies to GitLab.

Monorepo structure

Let's use the repository tutorial-fransys/monorepo-example as an example:

monorepo-example/
└── apps/
├── app-a/
│ └── Dockerfile
└── app-b/
└── Dockerfile

Each subdirectory contains the source code and a Dockerfile. Fransys will deploy each app as a separate block via its own Dockerfile.

Step 1 — Create Block A in Fransys

  1. Log in to the Fransys dashboard and navigate to your project
  2. Add a new Docker block for App A
  3. Give it a clear name (e.g., "App A" or "app-a")

In the block configuration, choose GitHub as the source, select your monorepo repository and the desired branch.

Once the link is created, click Open merge request and go to GitHub.

Step 3 — Configure the CI workflow for App A

On your GitHub repository, two things to do:

Add the Dockerfile path variable

In your GitHub repo, go to Settings > Secrets and variables > Actions. Under "Repository variables", create a variable:

  • Name: DOCKERFILE_PATH_APP_A
  • Value: app-a/Dockerfile

This variable tells the workflow which Dockerfile to build for Block A.

Modify the CI workflow

Open the GitHub Actions workflow file generated by Fransys (e.g., .github/workflows/fransys.yml). Find the following snippet (around line 24):

run: |
if [[ -z "${{ vars.DOCKERFILE_PATH }}" ]]; then
echo "DOCKERFILE_PATH=Dockerfile" >> $GITHUB_OUTPUT
else
echo "DOCKERFILE_PATH=${{ vars.DOCKERFILE_PATH }}" >> $GITHUB_OUTPUT
fi

Replace DOCKERFILE_PATH with DOCKERFILE_PATH_APP_A:

run: |
if [[ -z "${{ vars.DOCKERFILE_PATH_APP_A }}" ]]; then
echo "DOCKERFILE_PATH=Dockerfile" >> $GITHUB_OUTPUT
else
echo "DOCKERFILE_PATH=${{ vars.DOCKERFILE_PATH_APP_A }}" >> $GITHUB_OUTPUT
fi

Rename the file to fransys_app_a.yml to distinguish it, then commit on the pull request branch.

Step 4 — Test the workflow

On GitHub, go to the Actions tab and verify that the build passes correctly.

If the build fails, check the logs — the most common causes are an incorrect Dockerfile path or missing permissions. Fix and rerun until the pipeline passes.

Step 5 — Verify Block A deployment

Once the GitHub Actions workflow succeeds, go back to Fransys. In Block A's details, you should see the latest commit from your repository. Fransys links each deployment to a Git commit — confirm that Block A is using the latest image.

App A is configured and deployed via CI/CD.

Step 6 — Repeat for Block B

Follow the same process for App B:

  1. Create Block B in Fransys — Add a new Docker block named "App B" or "app-b", linked to the same monorepo repository

  2. Add the variable DOCKERFILE_PATH_APP_B in the GitHub repo variables with the value app-b/Dockerfile

  3. Modify the CI workflow — Linking the block with GitHub will generate a new fransys.yml. Modify it to use DOCKERFILE_PATH_APP_B and rename it to fransys_app_b.yml

  4. Test and verify — Verify that the workflow passes in GitHub Actions, then confirm on Fransys that Block B detects the latest commit

Step 7 — Deploy

You now have two blocks correctly configured from the same repository. Deploy them on the cluster of your choice.

Tips

  • Check the paths — The DOCKERFILE_PATH_APP_A and DOCKERFILE_PATH_APP_B variables must exactly match the paths to your Dockerfiles. A typo = a failed build.
  • Monitor CI logs — With each push or pull request, check GitHub Actions logs to catch errors early.
  • Confirm on Fransys — After a successful build, verify that each block shows the latest commit and deployment timestamp.
  • Auto-deploy enabled by default — Both blocks are on auto-deploy: any change to the repo automatically deploys the new version if the block is already online.