Skip to content

202511071816 Turborepo As A Multi-language Monorepo Orchestrator

Recently I’ve migrated over my deployment configuration and authored manifests for my k3s cluster and my Terraform code into a single consolidated codebase. After dropping Tanka in favour of a GitOps implementation via Flux 202510041935 Deploying Via FluxCD, it became clear to me that I GitOps-y approach could benefit greatly from a consolidated codebase.

Firstly, I already had a monorepo tooling in the repo. This was achieved through using Turborepo, which this website (built with Starlight + Obsidian) was housed under. The initial goal was to well, use it purely for applications. However, it also occurred to me that I did not intend to only write applications in JavaScript or TypeScript. So what would happen if I wrote an application in Rust or Go?

Thankfully, Turborepo can indeed be multi-language. As pnpm scripts are scripts for the package manager and the node runtime to run, it can be used to wrap other command line interactions such as docker run or even terraform init.

With Turborepo acting as a lightweight wrapper around pnpm and its ecosystem, with the turbo.json file in the monorepo acting as the script index, it supercharges the node ecosystem, by providing mechanisms such as caching, persistent runs and orchestration.

What this meant was that for each terraform module, a package.json could be housed within each module and the terraform helper scripts be executed through wrapper scripts.

And the magic in this monorepo tooling? The --affected flag which only finds runs tasks which changes.

  1. Convenience.
    1. I wouldn’t need to write scripts at a per project level. Instead, I could orchestrate through the pnpm package manager alongside workspace specific package.json fields regardless if its a JS/TS project.
  2. Consolidation reduces Cognitive Overhead
    1. I get a consolidated overview of all things related for my homelab, from my Terraform state to the applications I am currently working on.
    2. Managing the projects themselves are done through a standardised package.json in each module root. This meant the “root” folder which resides in .forge/kubernetes has a package.json representing a few CLI related things that could be executed to check for diffs.
  3. A single unified CICD
    1. I can run all the wrapper scripts with the --affected flag to determine what gets run. It exits cleanly, without producing any built artifacts if there are no code changes, be it a Kubernetes manifest or a Terraform module.
  4. Environment Parity
    1. Although one of the goals of a portable homelab 202501111134 A Portable Homelab was to achieve infrastructure portability, one think I felt keen to further explore was to achieve environment parity. If the repo could install the tooling needed to build and test the applications, it would be ideal if the repo could also provide the tooling needed to run it against the infrastructure it would be hosted in.

Based on these priniciples (or opinions regarding conveniences, if you wish) - it became clear that moving both terraform projects and kubernetes projects into forge became even more sensible.

So I did.