| name | turborepo-workflow |
| description | Expert guidance on Turborepo build orchestration and remote caching workflow. Use this skill when running build commands, troubleshooting caching issues, working with monorepo task execution, or investigating CI/CD pipeline problems. Covers the critical pattern of always using root-level pnpm scripts, understanding the turbo-wrapper.js authentication system, filter syntax for targeting packages, and remote cache configuration. |
Turborepo Workflow
This skill covers the build orchestration and remote caching patterns used in the Squareone monorepo.
Critical Rules
⚠️ ALWAYS use root-level pnpm scripts - Never run individual package scripts or call turbo directly (unless environment variables are pre-set in CI/CD).
Why This Matters
Only the root package.json scripts use the wrapper (scripts/turbo-wrapper.js) that enables remote caching with authentication.
Individual package.json scripts bypass the wrapper and remote caching, resulting in slower builds and missed cache hits.
Correct vs Incorrect Usage
✅ Correct
# Root script with filter (from repository root)
pnpm test --filter @lsst-sqre/squared
# Root scripts for all packages
pnpm build
pnpm lint
pnpm type-check
pnpm dev --filter squareone
❌ Wrong
# Individual package script (bypasses wrapper!)
cd packages/squared && pnpm test
# Direct turbo call without env vars (bypasses wrapper!)
turbo run test --filter @lsst-sqre/squared
# Running from package directory (bypasses wrapper!)
cd apps/squareone && pnpm dev
Exception: Direct Turbo Calls in CI/CD
Direct turbo calls are acceptable only when TURBO_API, TURBO_TOKEN, and TURBO_TEAM are already set as environment variables:
# In CI/CD pipelines with pre-set env vars
export TURBO_API="https://roundtable.lsst.cloud/turborepo-cache"
export TURBO_TOKEN="$SECRET_TOKEN"
export TURBO_TEAM="team_squareone"
turbo run build # OK in this context
In Docker builds or CI/CD where these env vars are injected, direct turbo calls work because the wrapper script detects them first (Priority 1).
Common Commands
Build Commands
# Build all packages and apps
pnpm build
# Build specific package
pnpm build --filter @lsst-sqre/squared
# Build specific app
pnpm build --filter squareone
# Build with increased memory (if needed)
NODE_OPTIONS="--max_old_space_size=4096" pnpm build
Development Commands
# Start all dev servers
pnpm dev
# Start specific app dev server
pnpm dev --filter squareone
# Start specific package dev server
pnpm dev --filter @lsst-sqre/squared
Testing Commands
# Run all tests
pnpm test
# Run tests for specific package
pnpm test --filter @lsst-sqre/squared
# Run Storybook tests
pnpm test-storybook
pnpm test-storybook:watch
pnpm test-storybook --filter @lsst-sqre/squared
Quality Commands
# Run ESLint
pnpm lint
pnpm lint --filter squareone
# Run TypeScript type checking
pnpm type-check
pnpm type-check --filter @lsst-sqre/squared
# Format code with Prettier
pnpm format
Storybook Commands
# Start Storybook for all packages
pnpm storybook
# Start Storybook for specific package
pnpm storybook --filter @lsst-sqre/squared
# Build Storybook static site
pnpm build-storybook --filter squared
Filter Syntax
Turborepo's filter syntax allows targeting specific packages:
# By package name
pnpm build --filter @lsst-sqre/squared
# By app name (no scope prefix for apps)
pnpm dev --filter squareone
# Multiple filters
pnpm test --filter @lsst-sqre/squared --filter squareone
# Dependents (packages that depend on this)
pnpm build --filter ...@lsst-sqre/squared
# Dependencies (packages this depends on)
pnpm build --filter @lsst-sqre/squared...
Remote Cache Authentication
The monorepo uses a custom Turborepo cache server at https://roundtable.lsst.cloud/turborepo-cache for faster builds through remote caching.
See the complete documentation at docs/dev/remote-cache.rst.
Authentication Methods
The turbo-wrapper.js script checks for authentication in priority order:
- Environment variables -
TURBO_API,TURBO_TOKEN,TURBO_TEAMall set (CI/CD) - 1Password -
.env.opfile +opCLI available (secure local development) - Plain .env file -
.envfile present (local development without 1Password) - No authentication - Local cache only (external contributors)
Authentication Messages
When running commands, you'll see:
- ✅
🔑 Using environment variables for Turborepo remote cache authentication - ✅
🔐 Using 1Password for Turborepo remote cache authentication - ✅
🔑 Using .env for Turborepo remote cache authentication - ℹ️
ℹ️ Running Turborepo without remote cache (local cache only)
Setting Up Authentication
For 1Password Users
Create
.env.opfile from template:cp .env.op.example .env.opEdit
.env.opto reference your 1Password vault itemsInstall 1Password CLI:
brew install 1password-cliSign in to 1Password:
op signin lsstit.1password.com
For Plain .env Users
Create
.envfile from template:cp .env.example .envAdd your credentials to
.env:TURBO_API=https://roundtable.lsst.cloud/turborepo-cache TURBO_TOKEN=your_token_here TURBO_TEAM=team_squareoneNever commit .env files - they're in
.gitignore
Obtaining Access Tokens
- Visit https://roundtable.lsst.cloud
- Log in with your credentials
- Navigate to the token management page
- Create a new token with the
write:turboreposcope - Store it securely in 1Password or
.envfile
Verifying Remote Cache
Cache Hit Messages
Look for these indicators in Turborepo output:
>>> FULL TURBO
>>> Remote caching enabled
@lsst-sqre/squared:build: cache hit, replaying output...
squareone:build: cache hit, replaying output...
Debug Mode
For detailed caching information:
TURBO_LOG_LEVEL=debug pnpm build
Troubleshooting
Remote Cache Not Working
Symptoms: No "Remote caching enabled" message, slow builds
Solutions:
- Verify authentication message shows up
- Check network connectivity to https://roundtable.lsst.cloud
- Ensure token hasn't expired
- Verify token has the
write:turboreposcope - Try with
TURBO_LOG_LEVEL=debugto see detailed logs - Verify credentials are correct in
.envor.env.op
1Password CLI Not Found
Symptoms: Warning message about 1Password CLI not available
Solutions:
# Verify installation
op --version
# Install if needed
brew install 1password-cli
# Sign in
op signin lsstit.1password.com
Cache Poisoning / Stale Cache
Symptoms: Build failures or incorrect behavior despite clean checkout
Solutions:
# Force rebuild (ignore cache)
pnpm build --force
# Clear local turbo cache
rm -rf node_modules/.cache/turbo
# Clear all node_modules and reinstall
pnpm clean && pnpm install
Build Errors in Monorepo
Symptoms: Build fails with mysterious errors
Solutions:
- Ensure you're using root-level scripts (not running from package directories)
- Check that all dependencies are installed:
pnpm install - Try a clean build:
pnpm clean && pnpm build - Verify turbo.json configuration is correct
- Check for circular dependencies
Package Not Building
Symptoms: Specific package fails to build or isn't found
Solutions:
# Verify package name is correct
ls packages/
# Check turbo.json for correct package name
cat turbo.json
# Try building just that package
pnpm build --filter @lsst-sqre/package-name
# Check package.json for valid build script
cat packages/package-name/package.json
Temporarily Disabling Remote Cache
Sometimes useful for testing local-only builds:
# Rename config files
mv .env .env.backup
mv .env.op .env.op.backup
# Or use build:local script (if available)
pnpm build:local
# Or call turbo directly (bypasses wrapper)
npx turbo build
Turborepo Configuration
The monorepo's build pipeline is configured in turbo.json:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**", "build/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"lint": {},
"type-check": {}
}
}
Understanding Pipeline
build- Depends on dependencies' builds (^build), caches outputstest- Depends on build, caches coveragelint- No dependencies, can run in paralleltype-check- No dependencies, can run in parallel
Cache Outputs
Turborepo caches specified output directories:
.next/**- Next.js build outputdist/**- Package build outputbuild/**- Other build artifactscoverage/**- Test coverage reports
Package Dependencies
The monorepo has these package relationships:
@lsst-sqre/squared (component library)
├── @lsst-sqre/global-css (styles)
│ └── @lsst-sqre/rubin-style-dictionary (tokens)
├── @lsst-sqre/eslint-config
└── @lsst-sqre/tsconfig
squareone (Next.js app)
├── @lsst-sqre/squared
├── @lsst-sqre/global-css
└── @lsst-sqre/eslint-config
Building squared automatically builds its dependencies (global-css, rubin-style-dictionary).
CI/CD Integration
In CI/CD pipelines:
# GitHub Actions example
env:
TURBO_API: ${{ secrets.TURBO_API }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
steps:
- run: pnpm install
- run: pnpm build # Uses environment variables for remote cache
- run: pnpm test
Environment variables take priority, so the wrapper automatically uses them without needing .env files.
Best Practices
- Always run from repository root with filters
- Use root-level pnpm scripts for all Turborepo commands
- Never commit .env or .env.op files (in .gitignore)
- Verify remote cache is working via authentication messages
- Use filters to target specific packages for faster iteration
- Check turbo.json when adding new scripts or packages
- Clean caches if experiencing unexplained build issues
- Document new scripts in root package.json with clear names
Performance Tips
# Increase Node.js memory for large builds
NODE_OPTIONS="--max_old_space_size=4096" pnpm build
# Parallel execution is automatic via Turborepo
# No need to manually parallelize
# Use filters to avoid unnecessary work
pnpm test --filter @lsst-sqre/squared # Only test one package
# Remote cache dramatically speeds up CI/CD
# and switching branches
Common Patterns
After Pulling Changes
pnpm install # Update dependencies
pnpm build # Rebuild (uses remote cache if possible)
Before Committing
pnpm lint # Check code style
pnpm type-check # Check TypeScript
pnpm test # Run tests
Adding New Package
- Create package in
packages/orapps/ - Add to
pnpm-workspace.yaml(usually automatic) - Add scripts to package's
package.json - Update
turbo.jsonif needed - Run
pnpm installfrom root
Debugging Build Issues
# 1. Clean everything
pnpm clean
# 2. Reinstall dependencies
pnpm install
# 3. Build with debug logging
TURBO_LOG_LEVEL=debug pnpm build --force
# 4. Check specific package
pnpm build --filter @lsst-sqre/package-name --force
Related Documentation
docs/dev/remote-cache.rst- Complete remote cache documentationscripts/turbo-wrapper.js- Wrapper script source codeturbo.json- Pipeline configurationpnpm-workspace.yaml- Workspace configuration
Infrastructure
The Turborepo cache server is deployed as part of the Rubin Science Platform:
- URL: https://roundtable.lsst.cloud/turborepo-cache
- Authentication: Gafaelfawr tokens with
write:turboreposcope - Storage: Google Cloud Storage
- Documentation: See Phalanx turborepo-cache application docs
Components:
turborepo-cache-proxy- Exchanges Gafaelfawr token for cache authenticationturborepo-remote-cache- Cache server implementation- Google Cloud Storage - Backend storage for artifacts