Enterprise Submodule Setup
Use this skill when making changes to the enterprise submodule (.source/) or enterprise packages (enterprise/packages/*), or when the enterprise submodule needs to be initialized/updated.
Overview
Novu uses a git submodule at .source pointing to git@github.com:novuhq/packages-enterprise.git. The enterprise packages in enterprise/packages/ have their src directories symlinked to .source/<package>/src.
Initial Setup
Configure git for submodule recursion:
git config --global submodule.recurse trueInitialize the submodule:
git submodule update --init --recursiveIf SSH is unavailable (e.g., in cloud environments), configure HTTPS fallback:
git config --global url."https://github.com/".insteadOf "git@github.com:" gh auth setup-gitAdd enterprise env vars to
apps/api/src/.envandapps/worker/src/.env:NOVU_ENTERPRISE=trueInstall and build with enterprise:
pnpm install:with-ee pnpm buildinstall:with-eerunspnpm installthenpnpm symlink:submoduleswhich symlinkssrcdirs from.source/intoenterprise/packages/.
Pulling Changes
git pullin the main repository (withsubmodule.recurse=true, submodule changes are fetched but NOT merged).- For development in the submodule:
cd .source && git checkout <branch> && git pull
Making Changes in the Submodule
- Pull latest from both repos.
- Create branches in both the main repo and submodule using the same Conventional Commits name (e.g.,
feat/scope-description-fixes-NOV-123). Start from a branch in the submodule, not a detached HEAD. - Implement changes.
- Commit in the submodule first, then the main repo.
- Push the submodule branch from inside
.source/:git push - Create the enterprise PR from the workspace root (do NOT
cdinto the submodule):
If this fails due to permissions, give the user this link instead:gh pr create --repo novuhq/packages-enterprise --head <branch-name> --base next --title "..." --body "..."https://github.com/novuhq/packages-enterprise/compare/next...<branch-name> - Push the main repo branch and create its PR with
gh pr create. - Cross-link both PRs: each PR body links the other (monorepo ↔ enterprise);
gh pr editthe earlier one once the second URL exists. - Merge the submodule PR first, then the main repo PR (to avoid broken builds for teammates).
Troubleshooting
fatal: could not get a repository handle for submodule '.source':- Delete
.git/modules/contents - Run
git submodule update --init --recursive
- Delete
Untracked working tree files error on checkout:
git submodule deinit -f enterprise- Checkout to branch and pull
git submodule update --init --recursive
Nuclear option:
pnpm run clean rm -rf node_modules pnpm i pnpm run symlink:submodules pnpm nx run-many --target=build --all --skip-nx-cache
Key Points
- The
.sourcedirectory contains the actual enterprise source code (private repo). enterprise/packages/*/srcare symlinks to.source/*/src.- Enterprise packages:
@novu/ee-auth,@novu/ee-api,@novu/ee-dal,@novu/ee-billing,@novu/ee-translation,@novu/ee-shared-services. - The
check-ee.mjsscript in each enterprise package only builds if thesrcfolder exists (graceful degradation for OSS contributors).