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.
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
- Log in to the Fransys dashboard and navigate to your project
- Add a new Docker block for App A
- Give it a clear name (e.g., "App A" or "app-a")
Step 2 — Link the GitHub repository to Block 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:
-
Create Block B in Fransys — Add a new Docker block named "App B" or "app-b", linked to the same monorepo repository
-
Add the variable
DOCKERFILE_PATH_APP_Bin the GitHub repo variables with the valueapp-b/Dockerfile -
Modify the CI workflow — Linking the block with GitHub will generate a new
fransys.yml. Modify it to useDOCKERFILE_PATH_APP_Band rename it tofransys_app_b.yml -
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_AandDOCKERFILE_PATH_APP_Bvariables 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.