turbo-daemon

Tool to idempotently run a local turborepo server.

MIT License

Downloads
27.4K
Stars
1

Turbo Daemon

A tool for running turbo locally as a demon that can be integrated with monorepo scripts.

Features

  • no money paid to Vercel
    (they do good work tho, It's just that I'm cheap)
  • doesn't use pm2
    (turbo-daemon is released under the MIT license)
  • wrapper around the highly tried and tested turborepo-remote-cache server
  • idempotent
    (call as many times as you want, only one server will run)
  • automatically shuts down after inactivity
  • CLI available for debugging

Installation

pnpm add turbo-daemon

Or from git: In your package.json:

"devDependencies": {
    "turbo-daemon": "github:NullVoxPopuli/turbo-daemon"
}

To test out a specific branch / tag:

"devDependencies": {
    "turbo-daemon": "github:NullVoxPopuli/turbo-daemon#branch-name"
}

Usage

In your tooling that wraps turbo commands, add a function that determines what the turbo environment variables should be.

For example:

import { execa } from 'execa';
import { createDaemon, TURBO_TOKEN } from 'turbo-daemon';
import ci from 'ci-info';

const daemon = createDaemon();
const TURBO_TEAM = 'team_your_team_name_here';

async function getServer() {
	if (ci.isCI) {
		return {
			TURBO_API: 'https://turborepo.your-domain-here.com',
			TURBO_TEAM,
			TURBO_TOKEN: process.env['TURBO_TOKEN'],
		}
	}

    /**
     * Environment variables from 
     * https://ducktors.github.io/turborepo-remote-cache/environment-variables.html
     *
     * These environment variables are required for the daemon to have 
     * access to remote storage.
     * If these are omitted, turbo will still work, but fallback to local, in-repo cache.
     */
    Object.assign(process.env, {
      TURBO_TEAM,
      /* ... */
    });

	await daemon.ensureStarted();
	return {
		TURBO_API: `http://localhost:${daemon.info.data.port}`,
		TURBO_TEAM,
		TURBO_TOKEN,
	}
}

/**
 * have your package.json scripts call this instead of turbo directly
 */
export async function wrappedTurbo(args) {
	const connectionInfo = await getServer();

	await execa(`pnpm`, [`turbo`, ...args], {
		env: {
			...connectionInfo,
		}
	})
}

Debugging

This project stores files in <git root>/node_modules/.turbo-daemon/

Start

pnpm turbo-daemon start

or when working in this project:

pnpm cli start

Restart

pnpm turbo-daemon restart

or when working in this project:

pnpm cli restart

Stop

pnpm turbo-daemon stop

or when working in this project:

pnpm cli stop

Status

pnpm turbo-daemon status

or when working in this project:

pnpm cli status

Logs

pnpm turbo-daemon logs

or when working in this project:

pnpm logs

Watching for the pid file:

watch -n 2 "cat node_modules/.turbo-daemon/.turbo.pid"

Debugging why the daemon isn't starting from other tools

in this project, run:

node ./src/run-turbo.js

and observe the output, logs, and pidfile.

If that's fine, try the daemonized version:

pnpm cli start

Debugging what is in the turbo daemon folder

ls -la node_modules/.turbo-daemon/**

This may require

shopt -s globstar

and to watch for changes:

watch -n 2 "ls -la node_modules/.turbo-daemon/**"

Clearing local cache to test remote speed

find . -name '.turbo' -type d -prune -exec rm -rf '{}' +

.turbo folders are in each package's node_modules directory.

Debugging S3 Access

Testing access to the cache bucket

To see if your local credentials have access to the s3 bucket, run:

 aws s3 ls $NAME_OF_BUCKET
# output doesn't matter
 echo $?
0 # this is what you're looking for