Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 0 additions & 135 deletions .cursor/rules/coding-guidelines.mdc

This file was deleted.

64 changes: 1 addition & 63 deletions .junie/guidelines.md
Original file line number Diff line number Diff line change
@@ -1,63 +1 @@
# Guidelines for Junie

This document provides guidelines for contributing to the OpenOps project, focusing on pull requests and commit practices.

## Pull Request Guidelines

### Size and Scope

- **Prefer small PRs**: Keep pull requests focused on a single feature, bug fix, or improvement.
- **Small commits**: Break down your work into logical, small commits that each represent a complete change.
- **One change per PR**: The PR should only contain changes related to the issue, with no unrelated modifications.

### Naming and Formatting

- **Use imperative mood** for PR titles and commit messages (e.g., "Add feature" not "Added feature" or "Adding feature").
- **PR title requirements** (as defined in `.github/prlint.json`):
- Must start with a capital letter and a real word (e.g., "Add GO support")
- Must have at least three words
- Must use imperative mood (e.g., "Fix bug" not "Fixed bug" or "Fixing bug")

### Creating Pull Requests

1. **Use GitHub CLI to create a draft PR**:
```bash
# Create a draft PR
gh pr create --draft --title "Add feature name" --body "Fixes #12345"
```

2. **Reference issues**:
- Reference a GitHub issue in the PR body (e.g., "Fixes #12345")
- Reference a Linear issue if one was mentioned (e.g., "Fixes OPS-1234")
- If no relevant issue exists, create a GitHub issue first:
```bash
# Create a GitHub issue
gh issue create --title "Issue title" --body "Issue description"
```

3. **Follow the PR template**:
- Provide a clear description of the changes
- Complete the testing checklist
- Include visual changes if applicable

## Commit Guidelines

- **Use imperative mood** in commit messages (e.g., "Fix bug" not "Fixed bug")
- **Keep commits small and focused** on a single change
- **Write descriptive commit messages** that explain what the change does and why
- **Follow this format** for commit messages:
```
Short summary in imperative mood (under 50 chars)
More detailed explanation if necessary. Wrap at around 72
characters. Explain what and why, not how (the code shows that).
Fixes #issue_number
```
## Additional Resources
- [CONTRIBUTING.md](../CONTRIBUTING.md): General contribution guidelines
- [.github/pull_request_template.md](../.github/pull_request_template.md): PR template
- [.github/prlint.json](../.github/prlint.json): PR linting rules
- [docs.openops.com](https://docs.openops.com): Official OpenOps documentation
See AGENTS.md in root folder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need the same for claude code
anthropics/claude-code#6235

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's unfortunate

169 changes: 169 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
## General Principles

- Follow existing code style and patterns in the repository
- Write clear, self-documenting code with descriptive variable and function names
- Include comments for complex logic or non-obvious behavior
- Always write tests for new functionality and changes
- Update documentation for user-facing changes
- Do not introduce new dependencies without discussion


## Structure

The repository is using nx, with the source code under the "packages" directory.
Use nx to run tests (e.g. npx nx test server-shared).
Run "npx nx lint" before committing.

## Code Style

### Formatting

- **Indentation:** 2 spaces (TypeScript/JavaScript, shell scripts)
- **Line length:** 100–120 characters preferred
- **Braces:** Required for all control blocks, even single-line
- **Spacing:**
- One space between keywords and parentheses: `if (condition) {`
- No trailing whitespace
- Newline at end of file
- **Linting:** Use ESLint as configured in each package
- **Formatting:** Follow Prettier rules if configured
- Respect `.editorconfig`, `.eslintrc`, `.prettierrc`, and other config files

### Naming Conventions

- **Variables/Functions:** `camelCase`
- **Classes/Types:** `PascalCase`
- **Constants:** `UPPER_SNAKE_CASE`
- **Files:** Lowercase with hyphens (e.g., `user-profile.ts`)

### Comments

- Explain _why_ something is done, not _what_ (the code should be self-explanatory)
- Use `TODO:` for actionable technical debt
- Document public functions, classes, and modules

## TypeScript/JavaScript

### General Guidelines

- Use types and interfaces where appropriate
- Prefer `const` over `let` or `var`
- Prefer arrow functions for callbacks and functional components
- Use explicit return types for exported functions

### Example

```typescript
export function getUserProfile(userId: string): UserProfile {
if (!userId) {
throw new Error('User ID required');
}
// TODO: Replace with real data source
return { id: userId, name: 'Sample User' };
}
```

## Frontend Guidelines

### Project Structure

- Use the `react-ui` package for main application logic
- Place pure, reusable components in the `ui-components` package, documented in Storybook
- Place and write tests in a separate `tests` folder

### Tech Stack

- **React 18**
- **Zustand** for state management
- **react-query v5** for data fetching
- **shadcn** for UI components
- **Axios** (use existing wrapper in `api.ts`), use `qs` package for query strings

### Best Practices

- Follow best practices for React hooks
- Prefer small, composable components
- Extract helper functions where possible
- Do not make breaking changes to existing code interfaces (component props, names) without discussion
- Ensure compliance with strict linter setups (including Sonar)
- Use `cn` utility to group Tailwind classnames:

```tsx
<div
className={cn(
'absolute bottom-[-20px] left-1/2 -translate-x-1/2',
'w-[118px] h-[24px] flex items-center justify-center',
'font-satoshi font-medium text-xs text-blueAccent-500',
'border border-solid border-blueAccent-500 rounded-[4px]',
'bg-background-800',
{
'pt-2': !someVar
}
)}
>
{t('Sample output data')}
</div>
```

## Testing

- Use Jest for testing
- Place unit tests in a `tests` folder alongside the code
- Run tests using Nx commands:

```bash
nx test react-ui
nx test ui-components
nx test-unit server-api
nx test engine
nx lint react-ui
```

## Git Workflow

### Commits

- Use imperative mood (e.g., "Fix bug" not "Fixed bug" or "Fixing bug")
- Keep commits small and focused on a single change
- Write descriptive commit messages that explain what and why, not how

**Commit message format:**

```
Short summary in imperative mood (under 50 chars)
More detailed explanation if necessary. Wrap at around 72
characters. Explain what and why, not how (the code shows that).
Fixes #issue_number
```

### Pull Requests

#### Size and Scope

- Keep PRs focused on a single feature, bug fix, or improvement
- Break down work into logical, small commits
- Only include changes related to the issue, no unrelated modifications

#### Title Requirements

- Must start with a capital letter and a real word
- Must have at least three words
- Must use imperative mood (e.g., "Add GO support" not "Added GO support")

#### Reference an issue

All PRs must reference a linear issue in their body.

Examples:
- Fixes OPS-100.
- Resolves OPS-101.
- Part of CI-102.

## Additional Resources

- [CONTRIBUTING.md](./CONTRIBUTING.md) - General contribution guidelines
- [.github/pull_request_template.md](./.github/pull_request_template.md) - PR template
- [.github/prlint.json](./.github/prlint.json) - PR linting rules
- [docs.openops.com](https://docs.openops.com) - Official OpenOps documentation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some better prompt, generated by Claude Code:

CLAUDE.md

Common Development Commands

Running the Application

# Start all services (Frontend + API + Engine)
npm run dev

# Start backend only (API + Engine)
npm run dev:backend

# Start frontend only
npm run dev:frontend

# Full start with Docker dependencies
npm start

Building

# Build frontend
npm run build:frontend

# Build all blocks
npm run build:blocks

# Build server worker
npm run build:server-worker

Testing

# Run tests for specific packages
nx test react-ui
nx test ui-components
nx test-unit server-api
nx test engine

# Run linting
nx lint react-ui
nx lint server-api

Block Development

# Create new block
npm run create-block

# Create new action in existing block
npm run create-action

# Create new trigger in existing block
npm run create-trigger

# Sync block metadata to database
npm run sync-blocks

# Publish block to npm
npm run publish-block

Database Migrations

# Create new migration
nx db-migration server-api --name MigrationName

# Migrations run automatically on app startup

Architecture Overview

Monorepo Structure (Nx)

OpenOps uses Nx as a monorepo build system with the following key packages:

  • packages/server/api - Main Fastify-based API server (port 3000)
  • packages/server/worker - BullMQ background job processor
  • packages/server/shared - Shared server utilities (logging, caching, encryption)
  • packages/engine - Isolated workflow execution engine (runs as separate service or AWS Lambda)
  • packages/react-ui - React frontend application (Vite + TailwindCSS)
  • packages/shared - Shared types and utilities across frontend/backend
  • packages/blocks/ - 50+ integration blocks (AWS, Azure, GCP, Slack, etc.)
  • packages/blocks/framework - Base framework for creating blocks/actions/triggers
  • packages/cli - CLI tools for block/action/trigger development
  • packages/ui-components - Reusable UI component library (documented in Storybook)

Three-Tier Architecture

  1. React UI (Frontend)

    • Built with React 18, Zustand, react-query v5, shadcn
    • Communicates with API server via Axios
    • Receives real-time updates via Socket.io
  2. API Server (Fastify)

    • RESTful API endpoints for workflow management
    • WebSocket support (Socket.io) for real-time updates
    • JWT-based authentication, multi-tenancy support
    • Health checks and telemetry (OpenTelemetry)
  3. Engine (Executor)

    • Isolated execution environment for workflows
    • Deploys as Node.js process (dev) or AWS Lambda (production)
    • Executes flows step-by-step with isolated sandboxes
    • Reports progress via WebSocket

Supporting Components

  • Worker: BullMQ-based job processor with three queue types:
    • ONE_TIME: Single workflow executions
    • SCHEDULED: Cron-based recurring workflows
    • WEBHOOK: Event-driven workflow triggers
  • PostgreSQL: Primary database (SQLite3 for development)
  • Redis: Queue backing and Socket.io adapter

Workflow Execution Model

Flow Structure (Graph-based)

Flows are defined as a directed graph:

  • Trigger (entry point) → Actions (linked list with branches)
  • Action types:
    • BLOCK: Execute a plugin action
    • CODE: Execute custom TypeScript code
    • BRANCH: Conditional logic (if/else)
    • LOOP_ON_ITEMS: Iteration
    • SPLIT: Parallel execution

Execution Flow

  1. Trigger receives event/payload
  2. Engine walks through action chain sequentially
  3. Each action produces output stored in execution context
  4. Context accessible to subsequent steps via variable interpolation: {{step.output.field}}
  5. Loop/branch steps can alter execution path
  6. Progress updates sent via WebSocket during execution
  7. Results stored in database with logs

Variable Resolution System

Variables use mustache-style syntax:

  • {{step.output.field}} - Access step outputs
  • {{connections.aws.accessKey}} - Access connection credentials
  • {{store.key}} - Access workflow key-value store
  • {{trigger.payload}} - Access trigger event data

Custom parser in packages/engine/src/lib/resolve-variable.ts handles resolution.

Blocks/Actions/Triggers Plugin System

Block Definition

Blocks are defined in packages/blocks/[block-name]/index.ts:

createBlock({
  displayName: "AWS",
  logoUrl: "...",
  auth: amazonAuth,  // Authentication strategy
  actions: [...],    // Array of actions
  triggers: [...],   // Array of triggers
  categories: [...]
})

Action Definition

createAction({
  name: 'ec2_stop_instance',
  displayName: 'Stop EC2 Instance',
  props: {
    /* input properties */
  },
  run: async (ctx) => {
    /* execution logic */
  },
  requireAuth: true,
  isWriteAction: true,
  riskLevel: RiskLevel.HIGH,
});

Key Patterns

  • Property System: Dynamic properties with validation (dropdowns, text, JSON)
  • Authentication: Pluggable auth providers (OAuth2, API Key, Basic)
  • Context Injection: ActionContext provides auth, props, files, connections
  • Type Safety: Full TypeScript with @sinclair/typebox schemas
  • Block Loading: Dynamic loading from npm packages or file system

Block Development Workflow

  1. Run npm run create-block to scaffold
  2. Define block with actions/triggers
  3. Implement action runners (async functions)
  4. Define properties with validation
  5. Test locally by running npm run dev
  6. Publish to npm (@openops/blocks-* scope)
  7. Sync to database via npm run sync-blocks

Each block package structure:

packages/blocks/[block-name]/
├── index.ts              # Block definition and exports
├── lib/
│   ├── actions/          # Action implementations
│   └── triggers/         # Trigger implementations
└── package.json

Database Architecture (TypeORM)

Primary Entities

  • Flow - Workflow definition (belongs to Project)
  • FlowVersion - Versioned workflow configuration (stores trigger graph as JSON)
  • FlowRun - Execution instance with status/logs
  • AppConnection - Stored credentials for integrations
  • Project - Multi-tenancy isolation
  • User / Organization - Authentication entities
  • TriggerEvent - Webhook events queue
  • StoreEntry - Key-value store for workflows

Database Configuration

  • Production: PostgreSQL 14+ (JSONB for complex data)
  • Development: SQLite3
  • Migrations: TypeORM migrations in packages/server/api/src/app/database/migrations/
  • Connection: Single databaseConnection() singleton with automatic dialect switching

Migrations

  • Located in packages/server/api/src/app/database/migrations/
  • Naming: Timestamp + description (e.g., 1740463047000-InitializePostgresSchema.ts)
  • Run automatically on app startup
  • Idempotent migrations with rollback capabilities

Code Execution Sandbox

  • Engine Mode: Uses isolated-vm package (v8 isolates)
  • Lambda Mode: Separate Lambda invocation
  • Security: No direct filesystem/network access from code steps
  • Dependencies: TypeScript + @types/node available
  • Timeout: Configurable per execution

Real-time Updates (Socket.io)

  • Redis adapter for horizontal scaling
  • Rooms per flow run ID
  • Progress service publishes step completion events
  • Frontend subscribes to specific run IDs
  • WebSocket events for live workflow execution updates

Multi-tenancy

  • Project-based: All resources scoped to Project
  • Enterprise: Additional Organization entity (feature-flagged)
  • Row-level filtering: All queries filtered by projectId
  • Connection isolation: Credentials stored per project

Error Handling Patterns

  • Retry Logic: Exponential backoff for transient failures
  • Continue on Failure: Optional per-step setting
  • Global Timeout: Workflow-level timeout (default 5 minutes)
  • Execution Limits: Max tasks per run to prevent infinite loops
  • Error Context: Detailed error messages with step context

Frontend Guidelines

  • Use the react-ui package for main application logic
  • Place pure, reusable components in the ui-components package, documented in Storybook
  • Tech stack:
    • React 18
    • Zustand (state management)
    • react-query v5 (server state)
    • shadcn (UI components)
    • Axios (we already have a wrapper in api.ts), use qs package for query strings
  • Place and write tests in a separate tests folder
  • Follow best practices for React hooks
  • Prefer small, composable components
  • Use cn utility to group tailwind classnames:
<div
  className={cn(
    'absolute bottom-[-20px] left-1/2 -translate-x-1/2',
    'w-[118px] h-[24px] flex items-center justify-center',
    'font-satoshi font-medium text-xs text-blueAccent-500',
    'border border-solid border-blueAccent-500 rounded-[4px]',
    'bg-background-800',
    {
      'pt-2': !someVar,
    },
  )}
>
  {t('Sample output data')}
</div>

Code Style

  • Indentation: 2 spaces (TypeScript/JavaScript)
  • Line length: 100–120 characters preferred
  • Braces: Required for all control blocks
  • Naming:
    • Variables/Functions: camelCase
    • Classes/Types: PascalCase
    • Constants: UPPER_SNAKE_CASE
    • Files: lowercase with hyphens (e.g., user-profile.ts)
  • TypeScript:
    • Use types and interfaces
    • Prefer const over let or var
    • Use explicit return types for exported functions
  • Tests: Place unit tests alongside code in a tests folder, use Jest
  • Comments: Explain why something is done, not what

Docker Compose (Development)

The compose.yaml file provides:

  • PostgreSQL (port 5432)
  • Redis (port 6379)
  • OpenOps Tables (Baserow fork, port 3001)
  • OpenOps Analytics (Superset fork, port 8088)

Environment Configuration

Configuration managed via .env file with 50+ options. See .env.template for reference.
System properties abstraction layer in @openops/server-shared/system.

Deployment

Docker Images

  • Main App: Dockerfile - API server + Nginx serving React UI
  • Engine: engine.Dockerfile - Lambda-ready with AWS/Azure/GCP CLIs
  • Multi-architecture: Supports AMD64 and ARM64

Production Services

  1. API Server (Fastify app)
  2. Engine (AWS Lambda or standalone process)
  3. Worker (Background job processor)
  4. PostgreSQL (Primary database)
  5. Redis (Queue and caching)
  6. OpenOps Tables (Built-in database UI)
  7. OpenOps Analytics (Built-in BI tool)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit bloated don't you think? A lot of information that might not be relevant. By the way, do you allow the agent to start the application (npm start)? Is there a real use for it?

Loading