Ctrl K
ComunidadGuías…

CONTRIBUTING.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Contributing to Ciaren

Thank you for your interest in Ciaren! We're excited to have you help build a local-first visual builder for data and ML workflows that exports clean Python.

This document explains how to contribute — whether you're fixing bugs, adding features, improving docs, or helping with design.

---

## ✨ What We Need

### Project Philosophy

Ciaren is an **open-core** project with a deliberately small built-in surface.
The core should stay lightweight, local-first, and easy to understand. It will
include a focused set of broadly useful connectors and transformations, but it
is not meant to collect every database, SaaS API, proprietary storage system, or
organization-specific integration.

Use the public Plugin API/SDK for long-tail integrations. If you need a niche
connector, a product-specific node, or a company-specific workflow, the expected
path is to build and maintain it as a plugin. Core changes are reserved for
capabilities that benefit many users, improve the SDK, fix bugs, or unblock
plugin authors.

### Code Contributions

- **New transformation nodes** — filters, aggregations, joins, reshaping operations
- **Bug fixes** — we track these in [Issues](https://github.com/ciaren-labs/Ciaren/issues)
- **Performance improvements** — especially in the execution engine and preview system
- **Frontend improvements** — better UX, accessibility, responsive design
- **Backend improvements** — better error handling, validation, API design
- **Plugin SDK improvements** — extension points, docs, tests, and examples that
  make community plugins easier to build

### Non-Code Contributions

- **Documentation** — tutorials, examples, troubleshooting guides
- **Testing** — try Ciaren with real datasets, report edge cases
- **Design feedback** — UI/UX improvements, workflow suggestions
- **Community** — answer questions in discussions, mentor new contributors

---

## 🌿 Branching Strategy

Ciaren uses **trunk-based development**, the same model as scikit-learn,
Apache Airflow, and MLflow: one long-lived branch, kept releasable at all
times by CI.

```
main            ← stable, continuously integrated; always releasable
  └── feature/your-feature   ← your work

release/x.y     ← cut from a released tag to backport fixes once main has
                  moved past that version (maintainers, only when needed)
```

| Branch | Purpose | Who pushes | Lives on GitHub as |
|---|---|---|---|
| `main` | What users install; every merge runs the full CI suite | Merged via PR only, from `feature/*`/`fix/*`/etc. | Protected |
| `release/x.y` | Backport bugfixes to an already-shipped minor version after `main` has moved on | Maintainers, via PR | Protected, long-lived per supported version |
| `feature/*`, `fix/*`, `docs/*`, `chore/*` | Your daily work | You (freely, usually from your fork) | Unprotected |

**The flow for most contributions:**
1. Branch off `main`
2. Open a PR targeting `main` — the full CI suite runs (cross-platform matrix, Docker, connector integration tests)
3. Once it's green and reviewed, it merges straight into `main`. `main` is
   tagged directly for releases — there's no separate integration branch to
   promote through first.

There is no `development` branch and no bugfix-only staging period before a
merge lands on `main` — CI on `main` is the gate. `release/x.y` branches only
get created later, and only if an older shipped version needs a patch after
`main` has already moved forward (the same pattern Airflow's `vX-Y-stable` and
MLflow's `branch-2.x` follow). You won't normally create one yourself.
Maintainer responsibilities and branch protection rules are documented in
[MAINTAINERS.md](MAINTAINERS.md#branch-protection).

---

## 🚀 Getting Started

Before starting work, check existing issues and PRs to avoid duplicate effort.
For questions, setup help, or early design ideas, use
[GitHub Discussions](https://github.com/ciaren-labs/Ciaren/discussions)
instead of opening a free-form issue.

### 1. Fork & Clone

```bash
git clone https://github.com/YOUR_USERNAME/Ciaren.git
cd Ciaren
```

### 2. Set Up Development Environment

#### Backend

```bash
cd backend

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Start server
uvicorn app.main:app --reload
```

#### Frontend

```bash
cd frontend

# Install dependencies
npm install

# Start dev server (runs on port 5173)
npm run dev

# Run linting
npm run lint

# Build for production
npm run build
```

### 3. Create a Branch

Branch from `main`:

```bash
git checkout main
git pull origin main
git checkout -b feature/your-feature-name
```

Use descriptive branch names:
- `feature/add-pivot-transformation`
- `fix/null-handling-bug`
- `docs/setup-guide`

---

## 📝 Code Standards

### Product and Architecture Guardrails

- Ciaren is local-first visual ETL for small and medium datasets.
- Keep the core lightweight; it is not an Airflow, dbt, Spark, or SaaS replacement.
- Keep built-in connectors selective. New database, SaaS, API, or storage
  integrations should usually be plugins unless maintainers explicitly accept
  the integration as core.
- Prefer improving the Plugin API/SDK over adding long-tail integrations to the
  open core.
- The backend is the source of truth for validation, execution, persistence, and code export.
- Every visual node should map to one clear dataframe operation.
- Generated Python must be readable and runnable outside Ciaren.
- Do not document, demo, or claim a feature unless it is implemented in code.
- Avoid enterprise-only scope creep such as multi-tenant permissions, cloud sync, distributed execution, or real-time collaboration unless maintainers have accepted the proposal first.

Authoritative places to check:

- Transformations: `backend/app/engine/registry.py`
- I/O node kinds: `backend/app/engine/node_kinds.py`
- API routes: `backend/app/api/routes/`
- Frontend features: `frontend/src/features/`
- Backend architecture: `backend/app/README.md`

### Backend (Python)

- **Type hints required** — use them everywhere (`def transform(data: pd.DataFrame) -> pd.DataFrame`)
- **Follow PEP 8** — we use [Black](https://github.com/psf/black) for formatting
- **Tests for new code** — especially transformations and services
- **Pydantic schemas for API inputs/outputs** — no raw dicts
- **Keep route handlers thin** — put logic in services
- **No pandas directly in routes** — encapsulate in `app/engine`

#### Example:

```python
from pydantic import BaseModel, Field

class RenameColumnsConfig(BaseModel):
    mapping: dict[str, str] = Field(..., description="Old name -> New name")

def rename_columns(df: pd.DataFrame, config: RenameColumnsConfig) -> pd.DataFrame:
    return df.rename(columns=config.mapping)
```

### Frontend (TypeScript/React)

- **TypeScript always** — no `any` without a comment explaining why
- **Feature-based folder structure** — components grouped by feature, not type
- **Use TanStack Query for server state** — centralized cache management
- **Use Zustand for UI state only** — lightweight, local UI state
- **shadcn/ui for components** — consistent design system
- **Zod for form validation** — same validation as backend when possible
- **No inline styles** — use Tailwind CSS classes

### Documentation

- Keep documentation user-focused, concrete, and example-driven.
- Update docs in the same PR as user-facing behavior changes.
- For UI changes, check whether screenshots in `docs/public/screenshots/` are stale.
- Use active voice, clear headings, and tested examples.
- Every new transformation should include or update its docs page under `docs/transformations/`.
- Do not copy internal notes or tool-specific agent instructions into public docs.

#### Example:

```typescript
// features/flows/hooks/useFlowQuery.ts
import { useQuery } from '@tanstack/react-query';
import { getFlow } from '@/lib/api';

export function useFlowQuery(flowId: string) {
  return useQuery({
    queryKey: ['flows', flowId],
    queryFn: () => getFlow(flowId),
  });
}
```

---

## ✅ Testing

### Backend Tests

```bash
cd backend

# Run all tests
pytest

# Run specific test file
pytest tests/test_flows.py

# Run with coverage
pytest --cov=app
```

**Guidelines:**
- Test new transformations with real data edge cases
- Test API endpoints with integration tests (use SQLite for speed)
- Test graph validation and topological sorting
- Aim for >80% coverage on critical paths

### Connector Integration Tests

The default `pytest` run is **infra-free**: the cloud/database connector tests
self-skip unless their service is reachable, so a normal test run never needs
Docker. They live in `backend/tests/integration/` under the `connectors` marker
and exercise the real driver I/O paths against local emulators. CI runs them in
the **Connectors Integration** workflow
(`.github/workflows/connectors-integration.yml`).

To run one locally: start its emulator, install the matching extra, set the
service's env var(s), then run the marked tests.

| Connector  | Emulator        | Extra   | Activating env var             |
|------------|-----------------|---------|--------------------------------|
| S3         | MinIO           | `s3`    | `CIAREN_TEST_S3_ENDPOINT`   |
| MongoDB    | `mongo`         | `mongo` | `CIAREN_TEST_MONGO_HOST`    |
| Azure Blob | Azurite         | `azure` | `CIAREN_TEST_AZURE_ENDPOINT`|
| GCS        | fake-gcs-server | `gcs`   | `STORAGE_EMULATOR_HOST`        |

```bash
cd backend
pip install -e ".[dev,s3,mongo,azure,gcs]"   # or just the extra you need
```

**S3 (MinIO):**

```bash
docker run -d -p 9000:9000 -e MINIO_ROOT_USER=minioadmin \
  -e MINIO_ROOT_PASSWORD=minioadmin minio/minio server /data
CIAREN_TEST_S3_ENDPOINT=http://127.0.0.1:9000 \
CIAREN_TEST_S3_ACCESS_KEY=minioadmin \
CIAREN_TEST_S3_SECRET_KEY=minioadmin \
  pytest tests/integration/test_s3_connector.py -m connectors
```

**MongoDB:**

```bash
docker run -d -p 27017:27017 mongo:7
CIAREN_TEST_MONGO_HOST=127.0.0.1 \
  pytest tests/integration/test_mongo_connector.py -m connectors
```

**Azure Blob (Azurite):**

```bash
docker run -d -p 10000:10000 mcr.microsoft.com/azure-storage/azurite \
  azurite-blob --blobHost 0.0.0.0 --skipApiVersionCheck
CIAREN_TEST_AZURE_ENDPOINT=http://127.0.0.1:10000/devstoreaccount1 \
  pytest tests/integration/test_azure_connector.py -m connectors
```

**GCS (fake-gcs-server):**

```bash
docker run -d -p 4443:4443 fsouza/fake-gcs-server \
  -scheme http -port 4443 -public-host 127.0.0.1:4443
STORAGE_EMULATOR_HOST=http://127.0.0.1:4443 \
  pytest tests/integration/test_gcs_connector.py -m connectors
```

To run every suite at once, start all four emulators, export all the env vars,
then `pytest -m connectors`.

**Notes:**
- Azurite needs `--skipApiVersionCheck` — the SDK speaks a newer API version than the emulator pins.
- The endpoints and Azurite credentials shown are the emulators' well-known defaults, not secrets.
- On **Windows PowerShell**, the inline `VAR=value cmd` prefix doesn't work — set each variable first with `$env:VAR = "value"`, then run `pytest`.
- Coverage from these tests lands in the merged Codecov report (the `connectors-integration` flag), not the infra-free `--cov-fail-under` gate.

### Frontend Tests

```bash
cd frontend

# Vitest (component/hook tests)
npm run test

# E2E tests (Playwright)
npm run test:e2e
```

**Guidelines:**
- Test form validation and error states
- Test flow editor interactions
- Test API error handling and retries

---

## 🔄 Submitting a Pull Request

### Before You Start

1. **Check existing issues/PRs** — search [open issues](https://github.com/ciaren-labs/Ciaren/issues) to avoid duplicate work
2. **Open an issue first for big features** — [start a discussion](https://github.com/ciaren-labs/Ciaren/discussions) before coding
3. **Use plugins for niche integrations** — if your idea is a new connector or
   product-specific integration, start with the Plugin SDK docs and open a
   discussion if the SDK blocks you
4. **Keep PRs focused** — one feature or fix per PR, not multiple unrelated changes

### Commit Messages

Use clear, descriptive commit messages:

```
feat: add pivot table transformation

- Implement pivot transformation node
- Add Pydantic schema validation
- Add 8 tests covering edge cases
- Update docs with pivot example
```

Format:
- `feat:` — new feature
- `fix:` — bug fix
- `refactor:` — code restructuring (no behavior change)
- `docs:` — documentation only
- `test:` — tests only
- `chore:` — dependencies, config, tooling

### Licensing of contributions

By opening a pull request, you agree that your contribution is licensed under
the license of the files you change: AGPL-3.0-only for the core and Apache-2.0
for the public Plugin API/SDK in `backend/app/plugin_api/` (see
[Licensing](README.md#licensing)). Only submit code you have the right to
contribute. No sign-off or CLA is required.

### Create the PR

1. Push your branch to your fork
2. Open a PR targeting **`main`**
3. Fill out the PR template (auto-generated)
4. Reference any related issues

**Good PR description:**
```
## Summary
Add pivot table transformation to enable reshaping data by column values.

## Changes
- New `PivotTransformation` class in `app/engine/transformations/reshape.py`
- API endpoint: `POST /api/transformations/preview` supports `pivot` type
- 8 tests covering 1D pivot, aggregation, margins

## Testing
- Tested with real-world sales data (1M rows)
- Verified null handling and data type preservation
- No performance regression (< 500ms for typical use)

## Checklist
- [x] Tests pass
- [x] Type hints on all functions
- [x] Updated architecture or docs if behavior changed
- [x] No new security warnings
```

### Review Process

- A maintainer will review as soon as possible — Ciaren currently has a single
  maintainer, so please allow up to a week for a first review
- Address feedback in new commits (don't force-push)
- Re-request review when you've made changes

---

## 🎯 Good First Issues

New to the project? Check out [issues labeled `good-first-issue`](https://github.com/ciaren-labs/Ciaren/labels/good-first-issue) or [`help-wanted`](https://github.com/ciaren-labs/Ciaren/labels/help-wanted):

- Adding a new transformation node (self-contained)
- Improving error messages
- Adding missing type hints
- Writing tests for untested code
- Documentation improvements

---

## 🐛 Reporting Bugs

1. **Check if it's already reported** — [search existing issues](https://github.com/ciaren-labs/Ciaren/issues)
2. **Include reproduction steps** — exactly how to trigger the bug
3. **Share your environment** — OS, Python version, browser, etc.
4. **Attach sample data** — anonymized CSV/Excel if possible
5. **Expected vs actual behavior** — what should happen vs what did

**Example:**
```
## Description
Null values not properly filled when using the "Fill Nulls" node with mean strategy.

## Steps to Reproduce
1. Upload attached `sales.csv` (100 rows, 3 columns)
2. Create flow with single "Fill Nulls" node
3. Set column to "amount", strategy to "mean"
4. Click Preview
5. Notice "amount" column still has NaN values

## Expected
All null values in "amount" should be replaced with column mean.

## Actual
Nulls remain unchanged.

## Environment
- OS: macOS 14.2
- Python: 3.12.4
- Browser: Chrome 121
```

---

## ✍️ Improving Documentation

Documentation lives in:
- **[backend/app/README.md](backend/app/README.md)** — backend architecture and layering rules
- **[README.md](README.md)** — project overview and quick start
- **[docs/](docs/)** — user guides, API reference, examples, and plugin docs
- **Code comments** — explain the "why", not the "what"

Help by:
- Writing tutorials for new transformations
- Clarifying ambiguous explanations
- Adding examples to docstrings
- Fixing typos and broken links
- Creating troubleshooting guides

---

## ⚠️ Important Notes

### About AI-Generated Code

This project includes code generated or assisted by AI. When contributing:

1. **Review all code carefully** — even AI-generated code needs human verification
2. **Test edge cases** — AI tools can miss subtle bugs
3. **Comment non-obvious logic** — especially if you had to fix AI-generated code
4. **Don't blindly trust generated tests** — validate they actually test the behavior

### Security & Performance

- **Security first** — validate all user inputs at system boundaries
- **Test with real data** — sample data doesn't catch edge cases
- **Consider performance** — test with larger datasets before merging
- **No secrets in code** — use environment variables for credentials

---

## 🚫 What We Won't Accept

- PRs that add **enterprise features** such as multi-tenant auth, cloud sync, distributed execution, or real-time collaboration without prior maintainer agreement
- PRs that add **long-tail connectors or product-specific integrations to core**
  without prior maintainer agreement. Build these as plugins instead, or propose
  an SDK improvement if the plugin path is blocked.
- **Breaking changes** without discussion — file an issue first
- **Unmaintained code** — if you add a feature, help maintain it
- **Security vulnerabilities** — see [SECURITY.md](SECURITY.md) for responsible disclosure

---

## 💬 Questions?

- **Setup issues?** Open a discussion in [GitHub Discussions](https://github.com/ciaren-labs/Ciaren/discussions)
- **Design questions?** [Open an issue](https://github.com/ciaren-labs/Ciaren/issues) or [discussion](https://github.com/ciaren-labs/Ciaren/discussions) — we love early feedback
- **Stuck on a PR?** Ask in comments — we're here to help

---

## 🙏 Thank You

Whether it's a one-line docs fix or a major feature, every contribution matters. You're helping build a tool that makes data work simpler for thousands of people.

**Welcome to Ciaren! 🚀**