This is the Evergreen UI monorepo containing two React applications for MongoDB's continuous integration system:
- Spruce (
apps/spruce) - The main CI/CD dashboard UI for Evergreen - Parsley (
apps/parsley) - Log viewer application for Evergreen
Tech Stack: React, TypeScript, Vite, pnpm workspaces, Apollo Client (GraphQL), Emotion (CSS-in-JS), LeafyGreen UI components. Refer to each app's package.json file to see what version is being used.
ui/
├── apps/
│ ├── spruce/ # Main CI/CD dashboard (port 3000)
│ └── parsley/ # Log viewer (port 5173)
├── packages/
│ ├── lib/ # Shared components, hooks, utilities
│ ├── eslint-config/ # Shared ESLint configuration
│ ├── deploy-utils/ # Deployment CLI utilities
│ ├── vite-utils/ # Shared Vite configuration
│ ├── storybook-addon/ # Custom Storybook addon
│ ├── fungi/ # AI/Chat components
│ ├── analytics-visualizer/
│ └── lint-staged/
└── scripts/
Within each app (apps/spruce/, apps/parsley/):
src/
├── components/ # Reusable UI components
├── pages/ # Route-level page components
├── hooks/ # Custom React hooks
├── gql/ # GraphQL queries, mutations, generated types
├── types/ # TypeScript type definitions
├── constants/ # App constants
├── context/ # React Context providers
├── analytics/ # Analytics tracking
├── utils/ # Utility functions
└── test_utils/ # Test helpers
pnpm install # Install all dependencies
pnpm clean # Remove all node_modules
pnpm codegen # Generate GraphQL types (all workspaces)
pnpm test # Run unit tests (all workspaces)
pnpm check-types # TypeScript type check (all workspaces)
pnpm eslint:strict # Strict linting (all workspaces)
pnpm eslint:fix # Auto-fix lint errors
pnpm storybook # Run combined Storybookpnpm dev # Start dev server (local Evergreen)
pnpm staging # Dev server against staging Evergreen (HTTPS)
pnpm prod # Dev server against production Evergreen (HTTPS)
pnpm test # Run Vitest unit tests
pnpm cy:open # Cypress interactive mode
pnpm cy:run # Cypress headless tests
pnpm codegen # Generate GraphQL types
pnpm storybook # Run Storybook
pnpm build # Production build
pnpm snapshot # Run snapshot testsCreate a symlink to the Evergreen GraphQL schema in each app:
ln -s <path_to_evergreen_repo>/graphql/schema sdlschemapnpm codegen # From app directory or root- Config file:
graphql.config.tsin each app - Input:
.graphqlfiles insrc/gql/queries/andsrc/gql/mutations/ - Output:
src/gql/generated/types.ts - Plugins:
typescript,typescript-operations - Custom scalars:
Duration→number,Time→Date,StringMap→{ [key: string]: any }
- Each query/mutation must have a unique name
- Queries should be declared with a name for type generation
- Run codegen after modifying
.graphqlfiles
// Use arrow functions with React.FC
export const ComponentName: React.FC<ComponentNameProps> = ({ prop1, prop2 }) => {
return <div>...</div>;
};
// Props interface
interface ComponentNameProps {
prop1: string;
prop2?: boolean;
onEvent: (value: string) => void;
}- Components are directory-based with
index.tsxas barrel export - Co-locate tests (
*.test.tsx), stories (*.stories.tsx), and types - Use named exports (not default exports)
import styled from "@emotion/styled";
import { size } from "constants/tokens";
const StyledWrapper = styled.div`
padding: ${size.xs};
margin-bottom: ${size.s};
`;- Components: PascalCase
- Hooks:
useprefix (useMyHook) - Constants: SCREAMING_SNAKE_CASE
- Files: Match export name (MyComponent.tsx, useMyHook.ts)
Comments should explain why the code does something, not what it does. The code should be self-explanatory through clear variable names, function names, and structure.
Good use of comments:
- Documentation for structs, functions, fields, methods
- Explaining why the code has to do something non-obvious
Avoid:
- Comments that restate what the code already says
- Comments that explain what the code is doing (let the code speak for itself)
- Redundant comments that add clutter or maintenance burden
Instead of adding explanatory comments, prefer making the code clearer through better naming and helper functions.
Requires local Evergreen server running on http://localhost:9090:
# In Evergreen repo
make local-evergreen
# In app directory
pnpm devOne-time setup (when first cloning the repo):
# Install mkcert
brew install mkcert nss
mkcert -install
# Generate certificates (run from app directory)
mkcert -key-file localhost-key.pem -cert-file localhost-cert.pem spruce-local.corp.mongodb.com
mkcert -key-file localhost-key.pem -cert-file localhost-cert.pem parsley-local.corp.mongodb.com
# Add to /etc/hosts
127.0.0.1 spruce-local.corp.mongodb.com
127.0.0.1 parsley-local.corp.mongodb.comRunning against remote servers:
pnpm staging # Run against staging Evergreen
pnpm prod # Run against production EvergreenURLs:
- Spruce (staging/prod):
https://spruce-local.corp.mongodb.com:8443 - Parsley (staging/prod):
https://parsley-local.corp.mongodb.com:8444
pnpm test # Watch mode
pnpm test run # Run once
pnpm test run <name> # Run specific testVitest globals (describe, it, expect, vi) do not need to be imported.
Use test utilities from @evg-ui/lib/test_utils:
import { render, screen, userEvent, waitFor, renderWithRouterMatch } from "@evg-ui/lib/test_utils";Requires local Evergreen server and built app:
pnpm build:local && pnpm serve # Build and serve
pnpm cy:open # Interactive mode
pnpm cy:run # Headless modeGenerated from Storybook stories:
pnpm snapshotpnpm update [package-name] --latest --recursive # Update dependency across workspacesHouses code shared between Spruce and Parsley:
- Reusable React components
- Custom hooks
- Test utilities
- Type definitions
- Analytics infrastructure
- External deps used only by lib: install in
packages/lib - External deps shared with apps: install in both lib and app
IMPORTANT: AI agents should NEVER run production deploy commands (pnpm deploy:prod). Production deployments must only be performed by humans.
Must be on main branch:
pnpm deploy:prod # Creates git tag, triggers build (HUMANS ONLY)Run corresponding deploy task in Evergreen patch.
Follow the template in .github/pull_request_template.md:
Title format:
- Prefix with Jira ticket:
DEVPROD-XXXX: Description of change - Include
[minor]or[major]for SemVer version bumps - Example:
DEVPROD-1234: Add user authentication [minor]
Labels:
- Add 🔵Spruce or 🟢Parsley label in the sidebar
Required sections:
- Description - Context, thought process, what changed
- Screenshots - For visible UI changes
- Testing - How you tested the changes
- Evergreen PR - Link to corresponding backend PR if applicable
Commits may fail due to lint or TypeScript errors. To fix:
Lint errors:
pnpm eslint:fix # Auto-fix what can be fixedThen manually fix any remaining errors shown in the output.
TypeScript errors:
pnpm check-types # Identify TypeScript errorsNote: check-types only identifies errors, it does not auto-fix them. Manually fix the errors shown.
pnpm clean # Remove all node_modules
pnpm install # Reinstall- Ensure
sdlschemasymlink exists and points to valid schema - Run
pnpm codegenafter modifying.graphqlfiles
- Regenerate certificate with
mkcert - Ensure hosts file entry exists