mirror of
https://github.com/apache/superset.git
synced 2026-04-30 05:24:31 +00:00
Compare commits
387 Commits
standardiz
...
playwright
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
482bef1507 | ||
|
|
20c04a4663 | ||
|
|
782f5eab16 | ||
|
|
1234533c67 | ||
|
|
7f0c0aea94 | ||
|
|
d9dcbb68b7 | ||
|
|
98fba1eefe | ||
|
|
bad03b1e76 | ||
|
|
fcfafebb29 | ||
|
|
47e82b02ed | ||
|
|
a463d66c80 | ||
|
|
337da13ba7 | ||
|
|
4a3453999a | ||
|
|
58758de93d | ||
|
|
b4a8acc584 | ||
|
|
08f89690e9 | ||
|
|
f02899d38d | ||
|
|
86583f1121 | ||
|
|
26cbd71099 | ||
|
|
500ce7a02a | ||
|
|
6d8ceed10e | ||
|
|
68d65f727f | ||
|
|
f165785003 | ||
|
|
8e31c93119 | ||
|
|
4974c08f7d | ||
|
|
fa90ba976c | ||
|
|
35c3d8dfbc | ||
|
|
ee23815aff | ||
|
|
7c946ae3db | ||
|
|
3926f5c55c | ||
|
|
fdc03d4bf3 | ||
|
|
24f0aed8a7 | ||
|
|
00d2f577df | ||
|
|
c35fc71bc5 | ||
|
|
1b6d57c3f3 | ||
|
|
d089a96163 | ||
|
|
0b3fe3d60c | ||
|
|
0eeb184b6a | ||
|
|
8e7edce616 | ||
|
|
754201b3d0 | ||
|
|
925401b4e1 | ||
|
|
8368ea4094 | ||
|
|
e8a6fb24ae | ||
|
|
311b7a72dc | ||
|
|
aa496def53 | ||
|
|
aea4375255 | ||
|
|
9ab0a0179d | ||
|
|
3db613dab5 | ||
|
|
de5ca79805 | ||
|
|
aede3bb5ba | ||
|
|
408f84aea6 | ||
|
|
92c07aaf54 | ||
|
|
f405174fcf | ||
|
|
8c125d2553 | ||
|
|
fb8fca4c64 | ||
|
|
dc0c055518 | ||
|
|
09349cb1e7 | ||
|
|
ca29adb0cb | ||
|
|
1617bbbe71 | ||
|
|
de1dd53186 | ||
|
|
58672dfab6 | ||
|
|
4b5629d1c8 | ||
|
|
4ddc3f14ed | ||
|
|
400a8aec89 | ||
|
|
51489a75ce | ||
|
|
09772eeda0 | ||
|
|
78907d08cd | ||
|
|
d0a0d280a1 | ||
|
|
5d77ed3677 | ||
|
|
f68ee6ba67 | ||
|
|
a01560cfa1 | ||
|
|
7e06ce8eeb | ||
|
|
ccc0e3dbb2 | ||
|
|
bd48e87eeb | ||
|
|
e6bd03fe98 | ||
|
|
9252d835b8 | ||
|
|
35b5f8dcdc | ||
|
|
97518544ee | ||
|
|
1c934b474a | ||
|
|
9d1d396a9b | ||
|
|
c38ba1daa8 | ||
|
|
8727d321f3 | ||
|
|
9918f8868e | ||
|
|
3dcf85caef | ||
|
|
e437ae1f2f | ||
|
|
17ebbdd966 | ||
|
|
de0bd37a66 | ||
|
|
412587ad41 | ||
|
|
941907ed4e | ||
|
|
91fbc64327 | ||
|
|
79ff093b30 | ||
|
|
ff80d4f406 | ||
|
|
c846cd187c | ||
|
|
9a43a47e6a | ||
|
|
9f2fead651 | ||
|
|
5a15c632ad | ||
|
|
3acc9aba8b | ||
|
|
8a61cdf4f2 | ||
|
|
ed47ceb1e4 | ||
|
|
4dbdb1811b | ||
|
|
d921f6d2b4 | ||
|
|
9d3fab8e4d | ||
|
|
a9630f3ec7 | ||
|
|
c2120f62cf | ||
|
|
19cf645224 | ||
|
|
6b1c058436 | ||
|
|
54b4056eb3 | ||
|
|
82e4763588 | ||
|
|
831a9a8a57 | ||
|
|
aa54da6d67 | ||
|
|
930736bdb0 | ||
|
|
668dcf4799 | ||
|
|
50a5854b25 | ||
|
|
441e043bff | ||
|
|
d383b2bf3c | ||
|
|
d7903631f5 | ||
|
|
10cb964c96 | ||
|
|
c519094313 | ||
|
|
e32c2d82a5 | ||
|
|
f7b9d7a64b | ||
|
|
89932fa0b2 | ||
|
|
a90928766b | ||
|
|
9d50f1b8a2 | ||
|
|
72464afb2e | ||
|
|
64af516dfd | ||
|
|
70cd4dd9d9 | ||
|
|
b7266e647c | ||
|
|
77c3146829 | ||
|
|
4545d55d30 | ||
|
|
a7b158c7fa | ||
|
|
d39c55e941 | ||
|
|
821173f6c4 | ||
|
|
635b7a6a4d | ||
|
|
04b1a45416 | ||
|
|
d23006ce03 | ||
|
|
8bb911bc91 | ||
|
|
249733c768 | ||
|
|
d83a938870 | ||
|
|
593e376cf2 | ||
|
|
fd4fe2c2ad | ||
|
|
281fa67b8e | ||
|
|
a8fd27aec3 | ||
|
|
139b5ae20c | ||
|
|
891f826143 | ||
|
|
0e2fb1d1a3 | ||
|
|
96170e43c0 | ||
|
|
8fde970b6b | ||
|
|
38cb577fc6 | ||
|
|
8ebe045846 | ||
|
|
62dc5c0306 | ||
|
|
6ad8d29fcd | ||
|
|
d83a88d5d9 | ||
|
|
a7cc48dcda | ||
|
|
e2a7dc9256 | ||
|
|
0364933e8b | ||
|
|
3202ff4b3f | ||
|
|
553204e613 | ||
|
|
fe8348c03a | ||
|
|
30021f8ede | ||
|
|
f3349388d0 | ||
|
|
449a89c214 | ||
|
|
5428376662 | ||
|
|
5493e2c96d | ||
|
|
2f8657f122 | ||
|
|
aa97d2fe03 | ||
|
|
28389de93e | ||
|
|
7c415c7cd9 | ||
|
|
f6b2abee81 | ||
|
|
2ef7232959 | ||
|
|
2991f60368 | ||
|
|
85ec3b1901 | ||
|
|
0c639abe17 | ||
|
|
50ed9b9e0e | ||
|
|
13a164dd63 | ||
|
|
6b0b13e4e7 | ||
|
|
c188952de2 | ||
|
|
a3b91f924d | ||
|
|
d8688cf8b1 | ||
|
|
40378afbf8 | ||
|
|
84e21434b3 | ||
|
|
d27210794c | ||
|
|
5a90a84685 | ||
|
|
6fbbc85df7 | ||
|
|
a66c230058 | ||
|
|
19db0353a9 | ||
|
|
88e5581d04 | ||
|
|
bf88d9bb1c | ||
|
|
d51b35f61b | ||
|
|
220480b627 | ||
|
|
ef78d2af06 | ||
|
|
7deed00def | ||
|
|
4e093a8e2a | ||
|
|
0b73b4842f | ||
|
|
90f281f585 | ||
|
|
d62249d13f | ||
|
|
ff102aadb3 | ||
|
|
82e2bc6181 | ||
|
|
784ff82847 | ||
|
|
027b25e6b8 | ||
|
|
b652fab042 | ||
|
|
77a5969dc1 | ||
|
|
fb9032c05c | ||
|
|
7a9dbfe879 | ||
|
|
0de78d8203 | ||
|
|
abc2d46fed | ||
|
|
927cc1cda1 | ||
|
|
7f3840557a | ||
|
|
0defcb604b | ||
|
|
94686ddfbe | ||
|
|
ec322dfd8d | ||
|
|
cb88d886c7 | ||
|
|
608e3baf43 | ||
|
|
b6f6b75348 | ||
|
|
a5ad1d186c | ||
|
|
db88d80b3f | ||
|
|
4b71adaa9c | ||
|
|
5fbda3af40 | ||
|
|
bc0c40c80e | ||
|
|
f030d658c5 | ||
|
|
e85337c543 | ||
|
|
fe7f8062f3 | ||
|
|
dce74014da | ||
|
|
619b341cad | ||
|
|
9b6876be62 | ||
|
|
c601341520 | ||
|
|
78faaee685 | ||
|
|
4027bad1d6 | ||
|
|
ce55cc7dd7 | ||
|
|
48e1b1ff2c | ||
|
|
5ec8f9d886 | ||
|
|
ecb3ac68ff | ||
|
|
076e477fd4 | ||
|
|
1e4bc6ee78 | ||
|
|
db178cf527 | ||
|
|
5901320933 | ||
|
|
23bb4f88c0 | ||
|
|
4130b92966 | ||
|
|
38297edc6b | ||
|
|
0c8f326258 | ||
|
|
127f6b3d66 | ||
|
|
ea519a77b5 | ||
|
|
6cb3ef9f5d | ||
|
|
a889ae75fc | ||
|
|
b60be9655f | ||
|
|
fd6da21ce0 | ||
|
|
1bf112a57a | ||
|
|
1f530d45cb | ||
|
|
1187902e68 | ||
|
|
ad3eff9e90 | ||
|
|
3e554674ff | ||
|
|
dced2f8564 | ||
|
|
05c6a1bf20 | ||
|
|
c193d6d6a1 | ||
|
|
fb840b8e71 | ||
|
|
d0cc6f115b | ||
|
|
966e231f94 | ||
|
|
a66737cb05 | ||
|
|
bc6859a99d | ||
|
|
133e686224 | ||
|
|
7d0a472d1e | ||
|
|
c2534f9155 | ||
|
|
088ecdd0bf | ||
|
|
e1a2e4843a | ||
|
|
15e8ffee1e | ||
|
|
19ddcb7e5c | ||
|
|
36daa2dc3f | ||
|
|
7fd5a7668b | ||
|
|
95333e34b1 | ||
|
|
a9fb853e3e | ||
|
|
dea9068647 | ||
|
|
3416bd1479 | ||
|
|
e729b2dbb4 | ||
|
|
06261f262b | ||
|
|
454ed1883f | ||
|
|
b42060c880 | ||
|
|
7bf16d805d | ||
|
|
529adebe1b | ||
|
|
eb4351af83 | ||
|
|
5a2411fa64 | ||
|
|
078c1701f4 | ||
|
|
a7d349a5c6 | ||
|
|
7a20a65a4d | ||
|
|
912ed2ba80 | ||
|
|
fedb3ca941 | ||
|
|
42b15b6840 | ||
|
|
2f64343186 | ||
|
|
65376c7baf | ||
|
|
4c2b27e7f0 | ||
|
|
15e4e8df94 | ||
|
|
c5f220a9ff | ||
|
|
b05def1a8a | ||
|
|
da7f6efea8 | ||
|
|
1c2b9db4f0 | ||
|
|
0fce5ecfa5 | ||
|
|
385471c34d | ||
|
|
bef1f4d045 | ||
|
|
5a3182ce21 | ||
|
|
9efb80dbf4 | ||
|
|
a20b236809 | ||
|
|
4e969d19d1 | ||
|
|
876257fb94 | ||
|
|
472e599f91 | ||
|
|
d826e90395 | ||
|
|
c65cb284e6 | ||
|
|
bc54b7970a | ||
|
|
ce74ae095d | ||
|
|
9424538bb1 | ||
|
|
031fb4b5a8 | ||
|
|
7fb7ac8bef | ||
|
|
569a7b33a5 | ||
|
|
59df0d6f15 | ||
|
|
2e4ccffc11 | ||
|
|
2e51d02806 | ||
|
|
8406a827dd | ||
|
|
ea0a77daaf | ||
|
|
e5e3ddb24e | ||
|
|
7320ad9a0a | ||
|
|
3dbe593a4a | ||
|
|
61f359d565 | ||
|
|
e77ff267a1 | ||
|
|
c426723275 | ||
|
|
d2a1d86561 | ||
|
|
0cd0b37983 | ||
|
|
a6b4ff9847 | ||
|
|
a81282adeb | ||
|
|
3ba3c09c47 | ||
|
|
3081c7fb62 | ||
|
|
fa5b0d7281 | ||
|
|
1444ef36b9 | ||
|
|
15d2f22eb4 | ||
|
|
355d7e1ee5 | ||
|
|
448a28545b | ||
|
|
cefd046ea0 | ||
|
|
b0d3f0f0d4 | ||
|
|
b7a193d53e | ||
|
|
0a75bac2a1 | ||
|
|
0de5b28716 | ||
|
|
b5ae402c12 | ||
|
|
682cdcc3e0 | ||
|
|
5dba59b6a4 | ||
|
|
71242dc6dd | ||
|
|
b2f8803486 | ||
|
|
744fa1f54c | ||
|
|
f0ff972f0e | ||
|
|
ba838b6aeb | ||
|
|
6a4b1df3a2 | ||
|
|
0a76f84142 | ||
|
|
9bcc62f210 | ||
|
|
322442d5be | ||
|
|
92879e6b32 | ||
|
|
fad3cb3162 | ||
|
|
4d040006b6 | ||
|
|
6e7cb521ba | ||
|
|
bc9ec6ac63 | ||
|
|
b9cbf2e766 | ||
|
|
d183969744 | ||
|
|
4695be5cc5 | ||
|
|
c1a3606774 | ||
|
|
175835138c | ||
|
|
077724c2d2 | ||
|
|
6b69dc42dc | ||
|
|
c5a84c0985 | ||
|
|
dc7a8844eb | ||
|
|
54f071138c | ||
|
|
812374b31b | ||
|
|
e463743fcf | ||
|
|
1d9e17df14 | ||
|
|
bcf156c969 | ||
|
|
ebfb14c353 | ||
|
|
7946ec003f | ||
|
|
665a11f821 | ||
|
|
5566eb8dd6 | ||
|
|
836540e8c9 | ||
|
|
b558b34faf | ||
|
|
30c72ba0a3 | ||
|
|
d8a3d29ad9 | ||
|
|
53ce530a46 | ||
|
|
06264f07fb | ||
|
|
ce3b93d8a0 | ||
|
|
b74a244950 | ||
|
|
ab58b0a8a3 | ||
|
|
659db162d6 | ||
|
|
cb24737825 | ||
|
|
97b35a4640 | ||
|
|
54af1cb2c8 | ||
|
|
b8c2f7db47 | ||
|
|
4701e78f1f |
10
.claude/commands/js-to-ts.md
Normal file
10
.claude/commands/js-to-ts.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# JavaScript to TypeScript Migration Command
|
||||
|
||||
## Usage
|
||||
```
|
||||
/js-to-ts <core-filename>
|
||||
```
|
||||
- `<core-filename>` - Path to CORE file relative to `superset-frontend/` (e.g., `src/utils/common.js`, `src/middleware/loggerMiddleware.js`)
|
||||
|
||||
## Agent Instructions
|
||||
**See:** [../projects/js-to-ts/AGENT.md](../projects/js-to-ts/AGENT.md) for complete migration guide.
|
||||
684
.claude/projects/js-to-ts/AGENT.md
Normal file
684
.claude/projects/js-to-ts/AGENT.md
Normal file
@@ -0,0 +1,684 @@
|
||||
# JavaScript to TypeScript Migration Agent Guide
|
||||
|
||||
**Complete technical reference for converting JavaScript/JSX files to TypeScript/TSX in Apache Superset frontend.**
|
||||
|
||||
**Agent Role:** Atomic migration unit - migrate the core file + ALL related tests/mocks as one cohesive unit. Use `git mv` to preserve history, NO `git commit`. NO global import changes. Report results upon completion.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Migration Principles
|
||||
|
||||
1. **Atomic migration units** - Core file + all related tests/mocks migrate together
|
||||
2. **Zero `any` types** - Use proper TypeScript throughout
|
||||
3. **Leverage existing types** - Reuse established definitions
|
||||
4. **Type inheritance** - Derivatives extend base component types
|
||||
5. **Strategic placement** - File types for maximum discoverability
|
||||
6. **Surgical improvements** - Enhance existing types during migration
|
||||
|
||||
---
|
||||
|
||||
## Step 0: Dependency Check (MANDATORY)
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
grep -E "from '\.\./.*\.jsx?'|from '\./.*\.jsx?'|from 'src/.*\.jsx?'" superset-frontend/{filename}
|
||||
```
|
||||
|
||||
**Decision:**
|
||||
- ✅ No matches → Proceed with atomic migration (core + tests + mocks)
|
||||
- ❌ Matches found → EXIT with dependency report (see format below)
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Identify Related Files (REQUIRED)
|
||||
|
||||
**Atomic Migration Scope:**
|
||||
For core file `src/utils/example.js`, also migrate:
|
||||
- `src/utils/example.test.js` / `src/utils/example.test.jsx`
|
||||
- `src/utils/example.spec.js` / `src/utils/example.spec.jsx`
|
||||
- `src/utils/__mocks__/example.js`
|
||||
- Any other related test/mock files found by pattern matching
|
||||
|
||||
**Find all related test and mock files:**
|
||||
```bash
|
||||
# Pattern-based search for related files
|
||||
basename=$(basename {filename} .js)
|
||||
dirname=$(dirname superset-frontend/{filename})
|
||||
|
||||
# Find test files
|
||||
find "$dirname" -name "${basename}.test.js" -o -name "${basename}.test.jsx"
|
||||
find "$dirname" -name "${basename}.spec.js" -o -name "${basename}.spec.jsx"
|
||||
|
||||
# Find mock files
|
||||
find "$dirname" -name "__mocks__/${basename}.js"
|
||||
find "$dirname" -name "${basename}.mock.js"
|
||||
```
|
||||
|
||||
**Migration Requirement:** All discovered related files MUST be migrated together as one atomic unit.
|
||||
|
||||
**Test File Creation:** If NO test files exist for the core file, CREATE a minimal test file using the following pattern:
|
||||
- Location: Same directory as core file
|
||||
- Name: `{basename}.test.ts` (e.g., `DebouncedMessageQueue.test.ts`)
|
||||
- Content: Basic test structure importing and testing the main functionality
|
||||
- Use proper TypeScript types in test file
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ Type Reference Map
|
||||
|
||||
### From `@superset-ui/core`
|
||||
```typescript
|
||||
// Data & Query
|
||||
QueryFormData, QueryData, JsonObject, AnnotationData, AdhocMetric
|
||||
LatestQueryFormData, GenericDataType, DatasourceType, ExtraFormData
|
||||
DataMaskStateWithId, NativeFilterScope, NativeFiltersState, NativeFilterTarget
|
||||
|
||||
// UI & Theme
|
||||
FeatureFlagMap, LanguagePack, ColorSchemeConfig, SequentialSchemeConfig
|
||||
```
|
||||
|
||||
### From `@superset-ui/chart-controls`
|
||||
```typescript
|
||||
Dataset, ColumnMeta, ControlStateMapping
|
||||
```
|
||||
|
||||
### From Local Types (`src/types/`)
|
||||
```typescript
|
||||
// Authentication
|
||||
User, UserWithPermissionsAndRoles, BootstrapUser, PermissionsAndRoles
|
||||
|
||||
// Dashboard
|
||||
Dashboard, DashboardState, DashboardInfo, DashboardLayout, LayoutItem
|
||||
ComponentType, ChartConfiguration, ActiveFilters
|
||||
|
||||
// Charts
|
||||
Chart, ChartState, ChartStatus, ChartLinkedDashboard, Slice, SaveActionType
|
||||
|
||||
// Data
|
||||
Datasource, Database, Owner, Role
|
||||
|
||||
// UI Components
|
||||
TagType, FavoriteStatus, Filter, ImportResourceName
|
||||
```
|
||||
|
||||
### From Domain Types
|
||||
```typescript
|
||||
// src/dashboard/types.ts
|
||||
RootState, ChartsState, DatasourcesState, FilterBarOrientation
|
||||
ChartCrossFiltersConfig, ActiveTabs, MenuKeys
|
||||
|
||||
// src/explore/types.ts
|
||||
ExplorePageInitialData, ExplorePageState, ExploreResponsePayload, OptionSortType
|
||||
|
||||
// src/SqlLab/types.ts
|
||||
[SQL Lab specific types]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Type Organization Strategy
|
||||
|
||||
### Type Placement Hierarchy
|
||||
|
||||
1. **Component-Colocated** (90% of cases)
|
||||
```typescript
|
||||
// Same file as component
|
||||
interface MyComponentProps {
|
||||
title: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
2. **Feature-Shared**
|
||||
```typescript
|
||||
// src/[domain]/components/[Feature]/types.ts
|
||||
export interface FilterConfiguration {
|
||||
filterId: string;
|
||||
targets: NativeFilterTarget[];
|
||||
}
|
||||
```
|
||||
|
||||
3. **Domain-Wide**
|
||||
```typescript
|
||||
// src/[domain]/types.ts
|
||||
export interface ExploreFormData extends QueryFormData {
|
||||
viz_type: string;
|
||||
}
|
||||
```
|
||||
|
||||
4. **Global**
|
||||
```typescript
|
||||
// src/types/[TypeName].ts
|
||||
export interface ApiResponse<T> {
|
||||
result: T;
|
||||
count?: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Type Discovery Commands
|
||||
```bash
|
||||
# Search existing types before creating
|
||||
find superset-frontend/src -name "types.ts" -exec grep -l "[TypeConcept]" {} \;
|
||||
grep -r "interface.*Props\|type.*Props" superset-frontend/src/
|
||||
```
|
||||
|
||||
### Derivative Component Patterns
|
||||
|
||||
**Rule:** Components that extend others should extend their type interfaces.
|
||||
|
||||
```typescript
|
||||
// ✅ Base component type
|
||||
interface SelectProps {
|
||||
value: string | number;
|
||||
options: SelectOption[];
|
||||
onChange: (value: string | number) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
// ✅ Derivative extends base
|
||||
interface ChartSelectProps extends SelectProps {
|
||||
charts: Chart[];
|
||||
onChartSelect: (chart: Chart) => void;
|
||||
}
|
||||
|
||||
// ✅ Derivative with modified props
|
||||
interface DatabaseSelectProps extends Omit<SelectProps, 'value' | 'onChange'> {
|
||||
value: number; // Narrowed type
|
||||
onChange: (databaseId: number) => void; // Specific signature
|
||||
}
|
||||
```
|
||||
|
||||
**Common Patterns:**
|
||||
- **Extension:** `extends BaseProps` - adds new props
|
||||
- **Omission:** `Omit<BaseProps, 'prop'>` - removes props
|
||||
- **Modification:** `Omit<BaseProps, 'prop'> & { prop: NewType }` - changes prop type
|
||||
- **Restriction:** Override with narrower types (union → specific)
|
||||
|
||||
---
|
||||
|
||||
## 📋 Migration Recipe
|
||||
|
||||
### Step 2: File Conversion
|
||||
```bash
|
||||
# Use git mv to preserve history
|
||||
git mv component.js component.ts
|
||||
git mv Component.jsx Component.tsx
|
||||
```
|
||||
|
||||
### Step 3: Import & Type Setup
|
||||
```typescript
|
||||
// Import order (enforced by linting)
|
||||
import { FC, ReactNode } from 'react';
|
||||
import { JsonObject, QueryFormData } from '@superset-ui/core';
|
||||
import { Dataset } from '@superset-ui/chart-controls';
|
||||
import type { Dashboard } from 'src/types/Dashboard';
|
||||
```
|
||||
|
||||
### Step 4: Function & Component Typing
|
||||
```typescript
|
||||
// Functions with proper parameter/return types
|
||||
export function processData(
|
||||
data: Dataset[],
|
||||
config: JsonObject
|
||||
): ProcessedData[] {
|
||||
// implementation
|
||||
}
|
||||
|
||||
// Component props with inheritance
|
||||
interface ComponentProps extends BaseProps {
|
||||
data: Chart[];
|
||||
onSelect: (id: number) => void;
|
||||
}
|
||||
|
||||
const Component: FC<ComponentProps> = ({ data, onSelect }) => {
|
||||
// implementation
|
||||
};
|
||||
```
|
||||
|
||||
### Step 5: State & Redux Typing
|
||||
```typescript
|
||||
// Hooks with specific types
|
||||
const [data, setData] = useState<Chart[]>([]);
|
||||
const [selected, setSelected] = useState<number | null>(null);
|
||||
|
||||
// Redux with existing RootState
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
charts: state.charts,
|
||||
user: state.user,
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Type Debugging Strategies (Real-World Learnings)
|
||||
|
||||
### The Evolution of Type Approaches
|
||||
When you hit type errors, follow this debugging evolution:
|
||||
|
||||
#### 1. ❌ Idealized Union Types (First Attempt)
|
||||
```typescript
|
||||
// Looks clean but doesn't match reality
|
||||
type DatasourceInput = Datasource | QueryEditor;
|
||||
```
|
||||
**Problem**: Real calling sites pass variations, not exact types.
|
||||
|
||||
#### 2. ❌ Overly Precise Types (Second Attempt)
|
||||
```typescript
|
||||
// Tried to match exact calling signatures
|
||||
type DatasourceInput =
|
||||
| IDatasource // From DatasourcePanel
|
||||
| (QueryEditor & { columns: ColumnMeta[] }); // From SaveQuery
|
||||
```
|
||||
**Problem**: Too rigid, doesn't handle legacy variations.
|
||||
|
||||
#### 3. ✅ Flexible Interface (Final Solution)
|
||||
```typescript
|
||||
// Captures what the function actually needs
|
||||
interface DatasourceInput {
|
||||
name?: string | null; // Allow null for compatibility
|
||||
datasource_name?: string | null; // Legacy variations
|
||||
columns?: any[]; // Multiple column types accepted
|
||||
database?: { id?: number };
|
||||
// ... other optional properties
|
||||
}
|
||||
```
|
||||
**Success**: Works with all calling sites, focuses on function needs.
|
||||
|
||||
### Type Debugging Process
|
||||
1. **Start with compilation errors** - they show exact mismatches
|
||||
2. **Examine actual usage** - look at calling sites, not idealized types
|
||||
3. **Build flexible interfaces** - capture what functions need, not rigid contracts
|
||||
4. **Iterate based on downstream validation** - let calling sites guide your types
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Anti-Patterns to Avoid
|
||||
|
||||
```typescript
|
||||
// ❌ Never use any
|
||||
const obj: any = {};
|
||||
|
||||
// ✅ Use proper types
|
||||
const obj: Record<string, JsonObject> = {};
|
||||
|
||||
// ❌ Don't recreate base component props
|
||||
interface ChartSelectProps {
|
||||
value: string; // Duplicated from SelectProps
|
||||
onChange: () => void; // Duplicated from SelectProps
|
||||
charts: Chart[]; // New prop
|
||||
}
|
||||
|
||||
// ✅ Inherit and extend
|
||||
interface ChartSelectProps extends SelectProps {
|
||||
charts: Chart[]; // Only new props
|
||||
}
|
||||
|
||||
// ❌ Don't create ad-hoc type variations
|
||||
interface UserInfo {
|
||||
name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
// ✅ Extend existing types (DRY principle)
|
||||
import { User } from 'src/types/bootstrapTypes';
|
||||
type UserDisplayInfo = Pick<User, 'firstName' | 'lastName' | 'email'>;
|
||||
|
||||
// ❌ Don't create overly rigid unions
|
||||
type StrictInput = ExactTypeA | ExactTypeB;
|
||||
|
||||
// ✅ Create flexible interfaces for function parameters
|
||||
interface FlexibleInput {
|
||||
// Focus on what the function actually needs
|
||||
commonProperty: string;
|
||||
optionalVariations?: any; // Allow for legacy variations
|
||||
}
|
||||
```
|
||||
|
||||
## 📍 DRY Type Guidelines (WHERE TYPES BELONG)
|
||||
|
||||
### Type Placement Rules
|
||||
**CRITICAL**: Type variations must live close to where they belong, not scattered across files.
|
||||
|
||||
#### ✅ Proper Type Organization
|
||||
```typescript
|
||||
// ❌ Don't create one-off interfaces in utility files
|
||||
// src/utils/datasourceUtils.ts
|
||||
interface DatasourceInput { /* custom interface */ } // Wrong!
|
||||
|
||||
// ✅ Use existing types or extend them in their proper domain
|
||||
// src/utils/datasourceUtils.ts
|
||||
import { IDatasource } from 'src/explore/components/DatasourcePanel';
|
||||
import { QueryEditor } from 'src/SqlLab/types';
|
||||
|
||||
// Create flexible interface that references existing types
|
||||
interface FlexibleDatasourceInput {
|
||||
// Properties that actually exist across variations
|
||||
}
|
||||
```
|
||||
|
||||
#### Type Location Hierarchy
|
||||
1. **Domain Types**: `src/{domain}/types.ts` (dashboard, explore, SqlLab)
|
||||
2. **Component Types**: Co-located with components
|
||||
3. **Global Types**: `src/types/` directory
|
||||
4. **Utility Types**: Only when they truly don't belong elsewhere
|
||||
|
||||
#### ✅ DRY Type Patterns
|
||||
```typescript
|
||||
// ✅ Extend existing domain types
|
||||
interface SaveQueryData extends Pick<QueryEditor, 'sql' | 'dbId' | 'catalog'> {
|
||||
columns: ColumnMeta[]; // Add what's needed
|
||||
}
|
||||
|
||||
// ✅ Create flexible interfaces for cross-domain utilities
|
||||
interface CrossDomainInput {
|
||||
// Common properties that exist across different source types
|
||||
name?: string | null; // Accommodate legacy null values
|
||||
// Only include properties the function actually uses
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 PropTypes Auto-Generation (Elegant Approach)
|
||||
|
||||
**IMPORTANT**: Superset has `babel-plugin-typescript-to-proptypes` configured to automatically generate PropTypes from TypeScript interfaces. Use this instead of manual PropTypes duplication!
|
||||
|
||||
### ❌ Manual PropTypes Duplication (Avoid This)
|
||||
```typescript
|
||||
export interface MyComponentProps {
|
||||
title: string;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
// 8+ lines of manual PropTypes duplication 😱
|
||||
const propTypes = PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
count: PropTypes.number,
|
||||
});
|
||||
|
||||
export default propTypes;
|
||||
```
|
||||
|
||||
### ✅ Auto-Generated PropTypes (Use This)
|
||||
```typescript
|
||||
import { InferProps } from 'prop-types';
|
||||
|
||||
export interface MyComponentProps {
|
||||
title: string;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
// Single validator function - babel plugin auto-generates PropTypes! ✨
|
||||
export default function MyComponentValidator(props: MyComponentProps) {
|
||||
return null; // PropTypes auto-assigned by babel-plugin-typescript-to-proptypes
|
||||
}
|
||||
|
||||
// Optional: For consumers needing PropTypes type inference
|
||||
export type MyComponentPropsInferred = InferProps<typeof MyComponentValidator>;
|
||||
```
|
||||
|
||||
### Migration Pattern for Type-Only Files
|
||||
|
||||
**When migrating type-only files with manual PropTypes:**
|
||||
|
||||
1. **Keep the TypeScript interfaces** (single source of truth)
|
||||
2. **Replace manual PropTypes** with validator function
|
||||
3. **Remove PropTypes imports** and manual shape definitions
|
||||
4. **Add InferProps import** if type inference needed
|
||||
|
||||
**Example Migration:**
|
||||
```typescript
|
||||
// Before: 25+ lines with manual PropTypes duplication
|
||||
export interface AdhocFilterType { /* ... */ }
|
||||
const adhocFilterTypePropTypes = PropTypes.oneOfType([...]);
|
||||
|
||||
// After: 3 lines with auto-generation
|
||||
export interface AdhocFilterType { /* ... */ }
|
||||
export default function AdhocFilterValidator(props: { filter: AdhocFilterType }) {
|
||||
return null; // Auto-generated PropTypes by babel plugin
|
||||
}
|
||||
```
|
||||
|
||||
### Component PropTypes Pattern
|
||||
|
||||
**For React components, the babel plugin works automatically:**
|
||||
|
||||
```typescript
|
||||
interface ComponentProps {
|
||||
title: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const MyComponent: FC<ComponentProps> = ({ title, onClick }) => {
|
||||
// Component implementation
|
||||
};
|
||||
|
||||
// PropTypes automatically generated by babel plugin - no manual work needed!
|
||||
export default MyComponent;
|
||||
```
|
||||
|
||||
### Auto-Generation Benefits
|
||||
|
||||
- ✅ **Single source of truth**: TypeScript interfaces drive PropTypes
|
||||
- ✅ **No duplication**: Eliminate 15-20 lines of manual PropTypes code
|
||||
- ✅ **Automatic updates**: Changes to TypeScript automatically update PropTypes
|
||||
- ✅ **Type safety**: Compile-time checking ensures PropTypes match interfaces
|
||||
- ✅ **Backward compatibility**: Existing JavaScript components continue working
|
||||
|
||||
### Babel Plugin Configuration
|
||||
|
||||
The plugin is already configured in `babel.config.js`:
|
||||
```javascript
|
||||
['babel-plugin-typescript-to-proptypes', { loose: true }]
|
||||
```
|
||||
|
||||
**No additional setup required** - just use TypeScript interfaces and the plugin handles the rest!
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test File Migration Patterns
|
||||
|
||||
### Test File Priority
|
||||
- **Always migrate test files** alongside production files
|
||||
- **Test files are often leaf nodes** - good starting candidates
|
||||
- **Create tests if missing** - Leverage new TypeScript types for better test coverage
|
||||
|
||||
### Test-Specific Type Patterns
|
||||
```typescript
|
||||
// Mock interfaces for testing
|
||||
interface MockStore {
|
||||
getState: () => Partial<RootState>; // Partial allows minimal mocking
|
||||
}
|
||||
|
||||
// Type-safe mocking for complex objects
|
||||
const mockDashboardInfo: Partial<DashboardInfo> as DashboardInfo = {
|
||||
id: 123,
|
||||
json_metadata: '{}',
|
||||
};
|
||||
|
||||
// Sinon stub typing
|
||||
let postStub: sinon.SinonStub;
|
||||
beforeEach(() => {
|
||||
postStub = sinon.stub(SupersetClient, 'post');
|
||||
});
|
||||
|
||||
// Use stub reference instead of original method
|
||||
expect(postStub.callCount).toBe(1);
|
||||
expect(postStub.getCall(0).args[0].endpoint).toMatch('/api/');
|
||||
```
|
||||
|
||||
### Test Migration Recipe
|
||||
1. **Migrate production file first** (if both need migration)
|
||||
2. **Update test imports** to point to `.ts/.tsx` files
|
||||
3. **Add proper mock typing** using `Partial<T> as T` pattern
|
||||
4. **Fix stub typing** - Use stub references, not original methods
|
||||
5. **Verify all tests pass** with TypeScript compilation
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Type Conflict Resolution
|
||||
|
||||
### Multiple Type Definitions Issue
|
||||
**Problem**: Same type name defined in multiple files causes compilation errors.
|
||||
|
||||
**Example**: `DashboardInfo` defined in both:
|
||||
- `src/dashboard/reducers/types.ts` (minimal)
|
||||
- `src/dashboard/components/Header/types.ts` (different shape)
|
||||
- `src/dashboard/types.ts` (complete - used by RootState)
|
||||
|
||||
### Resolution Strategy
|
||||
1. **Identify the authoritative type**:
|
||||
```bash
|
||||
# Find which type is used by RootState/main interfaces
|
||||
grep -r "DashboardInfo" src/dashboard/types.ts
|
||||
```
|
||||
|
||||
2. **Use import from authoritative source**:
|
||||
```typescript
|
||||
// ✅ Import from main domain types
|
||||
import { RootState, DashboardInfo } from 'src/dashboard/types';
|
||||
|
||||
// ❌ Don't import from component-specific files
|
||||
import { DashboardInfo } from 'src/dashboard/components/Header/types';
|
||||
```
|
||||
|
||||
3. **Mock complex types in tests**:
|
||||
```typescript
|
||||
// For testing - provide minimal required fields
|
||||
const mockInfo: Partial<DashboardInfo> as DashboardInfo = {
|
||||
id: 123,
|
||||
json_metadata: '{}',
|
||||
// Only provide fields actually used in test
|
||||
};
|
||||
```
|
||||
|
||||
### Type Hierarchy Discovery Commands
|
||||
```bash
|
||||
# Find all definitions of a type
|
||||
grep -r "interface.*TypeName\|type.*TypeName" src/
|
||||
|
||||
# Find import usage patterns
|
||||
grep -r "import.*TypeName" src/
|
||||
|
||||
# Check what RootState uses
|
||||
grep -A 10 -B 10 "TypeName" src/*/types.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Agent Constraints (CRITICAL)
|
||||
|
||||
1. **Use git mv** - Run `git mv file.js file.ts` to preserve git history, but NO `git commit`
|
||||
2. **NO global import changes** - Don't update imports across codebase
|
||||
3. **Type files OK** - Can modify existing type files to improve/align types
|
||||
4. **Single-File TypeScript Validation** (CRITICAL) - tsc has known issues with multi-file compilation:
|
||||
- **Core Issue**: TypeScript's `tsc` has documented problems validating multiple files simultaneously in complex projects
|
||||
- **Solution**: ALWAYS validate files one at a time using individual `tsc` calls
|
||||
- **Command Pattern**: `cd superset-frontend && npx tscw --noEmit --allowJs --composite false --project tsconfig.json {single-file-path}`
|
||||
- **Why**: Multi-file validation can produce false positives, miss real errors, and conflict during parallel agent execution
|
||||
5. **Downstream Impact Validation** (CRITICAL) - Your migration affects calling sites:
|
||||
- **Find downstream files**: `find superset-frontend/src -name "*.tsx" -o -name "*.ts" | xargs grep -l "your-core-filename" 2>/dev/null || echo "No files found"`
|
||||
- **Validate each downstream file individually**: `cd superset-frontend && npx tscw --noEmit --allowJs --composite false --project tsconfig.json {each-downstream-file}`
|
||||
- **Fix type mismatches** you introduced in calling sites
|
||||
- **NEVER ignore downstream errors** - they indicate your types don't match reality
|
||||
6. **Avoid Project-Wide Validation During Migration**:
|
||||
- **NEVER use `npm run type`** during parallel agent execution - produces unreliable results
|
||||
- **Single-file validation is authoritative** - trust individual file checks over project-wide scans
|
||||
6. **ESLint validation** - Run `npm run eslint -- --fix {file}` for each migrated file to auto-fix formatting/linting issues
|
||||
6. Zero `any` types - use proper TypeScript types
|
||||
7. Search existing types before creating new ones
|
||||
8. Follow patterns from this guide
|
||||
|
||||
---
|
||||
|
||||
## Success Report Format
|
||||
|
||||
```
|
||||
SUCCESS: Atomic Migration of {core-filename}
|
||||
|
||||
## Files Migrated (Atomic Unit)
|
||||
- Core: {core-filename} → {core-filename.ts/tsx}
|
||||
- Tests: {list-of-test-files} → {list-of-test-files.ts/tsx} OR "CREATED: {basename}.test.ts"
|
||||
- Mocks: {list-of-mock-files} → {list-of-mock-files.ts}
|
||||
- Type files modified: {list-of-type-files}
|
||||
|
||||
## Types Created/Improved
|
||||
- {TypeName}: {location} ({scope}) - {rationale}
|
||||
- {ExistingType}: enhanced in {location} - {improvement-description}
|
||||
|
||||
## Documentation Recommendations
|
||||
- ADD_TO_DIRECTORY: {TypeName} - {reason}
|
||||
- NO_DOCUMENTATION: {TypeName} - {reason}
|
||||
|
||||
## Quality Validation
|
||||
- **Single-File TypeScript Validation**: ✅ PASS - Core files individually validated
|
||||
- Core file: `npx tscw --noEmit --allowJs --composite false --project tsconfig.json {core-file}`
|
||||
- Test files: `npx tscw --noEmit --allowJs --composite false --project tsconfig.json {test-file}` (if exists)
|
||||
- **Downstream Impact Check**: ✅ PASS - Found {N} files importing this module, all validate individually
|
||||
- Downstream files: {list-of-files-that-import-your-module}
|
||||
- Individual validation: `npx tscw --noEmit --allowJs --composite false --project tsconfig.json {each-downstream-file}`
|
||||
- **ESLint validation**: ✅ PASS (using `npm run eslint -- --fix {files}` to auto-fix formatting)
|
||||
- **Zero any types**: ✅ PASS
|
||||
- **Local imports resolved**: ✅ PASS
|
||||
- **Functionality preserved**: ✅ PASS
|
||||
- **Tests pass** (if test file): ✅ PASS
|
||||
- **Follow-up action required**: {YES/NO}
|
||||
|
||||
## Validation Strategy Notes
|
||||
- **Single-file approach used**: Avoided multi-file tsc validation due to known TypeScript compilation issues
|
||||
- **Project-wide validation skipped**: `npm run type` not used during parallel migration to prevent false positives
|
||||
|
||||
## Migration Learnings
|
||||
- Type conflicts encountered: {describe any multiple type definitions}
|
||||
- Mock patterns used: {describe test mocking approaches}
|
||||
- Import hierarchy decisions: {note authoritative type sources used}
|
||||
- PropTypes strategy: {AUTO_GENERATED via babel plugin | MANUAL_DUPLICATION_REMOVED | N/A}
|
||||
|
||||
## Improvement Suggestions for Documentation
|
||||
- AGENT.md enhancement: {suggest additions to migration guide}
|
||||
- Common pattern identified: {note reusable patterns for future migrations}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependency Block Report Format
|
||||
|
||||
```
|
||||
DEPENDENCY_BLOCK: Cannot migrate {filename}
|
||||
|
||||
## Blocking Dependencies
|
||||
- {path}: {type} - {usage} - {priority}
|
||||
|
||||
## Impact Analysis
|
||||
- Estimated types: {number}
|
||||
- Expected locations: {list}
|
||||
- Cross-domain: {YES/NO}
|
||||
|
||||
## Recommended Order
|
||||
{ordered-list}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Quick Reference
|
||||
|
||||
**Type Utilities:**
|
||||
- `Record<K, V>` - Object with specific key/value types
|
||||
- `Partial<T>` - All properties optional
|
||||
- `Pick<T, K>` - Subset of properties
|
||||
- `Omit<T, K>` - Exclude specific properties
|
||||
- `NonNullable<T>` - Exclude null/undefined
|
||||
|
||||
**Event Types:**
|
||||
- `MouseEvent<HTMLButtonElement>`
|
||||
- `ChangeEvent<HTMLInputElement>`
|
||||
- `FormEvent<HTMLFormElement>`
|
||||
|
||||
**React Types:**
|
||||
- `FC<Props>` - Functional component
|
||||
- `ReactNode` - Any renderable content
|
||||
- `CSSProperties` - Style objects
|
||||
|
||||
---
|
||||
|
||||
**Remember:** Every type should add value and clarity. The goal is meaningful type safety that catches bugs and improves developer experience.
|
||||
199
.claude/projects/js-to-ts/COORDINATOR.md
Normal file
199
.claude/projects/js-to-ts/COORDINATOR.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# JS-to-TS Coordinator Workflow
|
||||
|
||||
**Role:** Strategic migration coordination - select leaf-node files, trigger agents, review results, handle integration, manage dependencies.
|
||||
|
||||
---
|
||||
|
||||
## 1. Core File Selection Strategy
|
||||
|
||||
**Target ONLY Core Files**: Coordinators identify core files (production code), agents handle related tests/mocks atomically.
|
||||
|
||||
**File Analysis Commands**:
|
||||
```bash
|
||||
# Find CORE files with no JS/JSX dependencies (exclude tests/mocks) - SIZE PRIORITIZED
|
||||
find superset-frontend/src -name "*.js" -o -name "*.jsx" | grep -v "test\|spec\|mock" | xargs wc -l | sort -n | head -20
|
||||
|
||||
# Alternative: Get file sizes in lines with paths
|
||||
find superset-frontend/src -name "*.js" -o -name "*.jsx" | grep -v "test\|spec\|mock" | while read file; do
|
||||
lines=$(wc -l < "$file")
|
||||
echo "$lines $file"
|
||||
done | sort -n | head -20
|
||||
|
||||
# Check dependencies for core files only (start with smallest)
|
||||
for file in <core-files-sorted-by-size>; do
|
||||
echo "=== $file ($(wc -l < "$file") lines) ==="
|
||||
grep -E "from '\.\./.*\.jsx?'|from '\./.*\.jsx?'|from 'src/.*\.jsx?'" "$file" || echo "✅ LEAF CANDIDATE"
|
||||
done
|
||||
|
||||
# Identify heavily imported files (migrate last)
|
||||
grep -r "from.*utils/common" superset-frontend/src/ | wc -l
|
||||
|
||||
# Quick leaf analysis with size priority
|
||||
find superset-frontend/src -name "*.js" -o -name "*.jsx" | grep -v "test\|spec\|mock" | head -30 | while read file; do
|
||||
deps=$(grep -E "from '\.\./.*\.jsx?'|from '\./.*\.jsx?'|from 'src/.*\.jsx?'" "$file" | wc -l)
|
||||
lines=$(wc -l < "$file")
|
||||
if [ "$deps" -eq 0 ]; then
|
||||
echo "✅ LEAF: $lines lines - $file"
|
||||
fi
|
||||
done | sort -n
|
||||
```
|
||||
|
||||
**Priority Order** (Smallest files first for easier wins):
|
||||
1. **Small leaf files** (<50 lines) - No JS/JSX imports, quick TypeScript conversion
|
||||
2. **Medium leaf files** (50-200 lines) - Self-contained utilities and helpers
|
||||
3. **Small dependency files** (<100 lines) - Import only already-migrated files
|
||||
4. **Larger components** (200+ lines) - Complex but well-contained functionality
|
||||
5. **Core foundational files** (utils/common.js, controls.jsx) - migrate last regardless of size
|
||||
|
||||
**Size-First Benefits**:
|
||||
- Faster completion builds momentum
|
||||
- Earlier validation of migration patterns
|
||||
- Easier rollback if issues arise
|
||||
- Better success rate for agent learning
|
||||
|
||||
**Migration Unit**: Each agent call migrates:
|
||||
- 1 core file (primary target)
|
||||
- All related `*.test.js/jsx` files
|
||||
- All related `*.mock.js` files
|
||||
- All related `__mocks__/` files
|
||||
|
||||
---
|
||||
|
||||
## 2. Task Creation & Agent Control
|
||||
|
||||
### Task Triggering
|
||||
When triggering the `/js-to-ts` command:
|
||||
- **Task Title**: Use the core filename as the task title (e.g., "DebouncedMessageQueue.js migration", "hostNamesConfig.js migration")
|
||||
- **Task Description**: Include the full relative path to help agent locate the file
|
||||
- **Reference**: Point agent to [AGENT.md](./AGENT.md) for technical instructions
|
||||
|
||||
### Post-Processing Workflow
|
||||
After each agent completes:
|
||||
|
||||
1. **Review Agent Report**: Always read and analyze the complete agent report
|
||||
2. **Share Summary**: Provide user with key highlights from agent's work:
|
||||
- Files migrated (core + tests/mocks)
|
||||
- Types created or improved
|
||||
- Any validation issues or coordinator actions needed
|
||||
3. **Quality Assessment**: Evaluate agent's TypeScript implementation against criteria:
|
||||
- ✅ **Type Usage**: Proper types used, no `any` types
|
||||
- ✅ **Type Filing**: Types placed in correct hierarchy (component → feature → domain → global)
|
||||
- ✅ **Side Effects**: No unintended changes to other files
|
||||
- ✅ **Import Alignment**: Proper .ts/.tsx import extensions
|
||||
4. **Integration Decision**:
|
||||
- **COMMIT**: If agent work is complete and high quality
|
||||
- **FIX & COMMIT**: If minor issues need coordinator fixes
|
||||
- **ROLLBACK**: If major issues require complete rework
|
||||
5. **Next Action**: Ask user preference - commit this work or trigger next migration
|
||||
|
||||
---
|
||||
|
||||
## 3. Integration Decision Framework
|
||||
|
||||
**Automatic Integration** ✅:
|
||||
- `npm run type` passes without errors
|
||||
- Agent created clean TypeScript with proper types
|
||||
- Types appropriately filed in hierarchy
|
||||
|
||||
**Coordinator Integration** (Fix Side-Effects) 🔧:
|
||||
- `npm run type` fails BUT agent's work is high quality
|
||||
- Good type usage, proper patterns, well-organized
|
||||
- Side-effects are manageable TypeScript compilation errors
|
||||
- **Coordinator Action**: Integrate the change, then fix global compilation issues
|
||||
|
||||
**Rollback Only** ❌:
|
||||
- Agent introduced `any` types or poor type choices
|
||||
- Types poorly organized or conflicting with existing patterns
|
||||
- Fundamental approach issues requiring complete rework
|
||||
|
||||
**Integration Process**:
|
||||
1. **Review**: Agent already used `git mv` to preserve history
|
||||
2. **Fix Side-Effects**: Update dependent files with proper import extensions
|
||||
3. **Resolve Types**: Fix any cascading type issues across codebase
|
||||
4. **Validate**: Ensure `npm run type` passes after fixes
|
||||
|
||||
---
|
||||
|
||||
## 4. Common Integration Patterns
|
||||
|
||||
**Common Side-Effects (Expect These)**:
|
||||
- **Type import conflicts**: Multiple definitions of same type name
|
||||
- **Mock object typing**: Tests need complete type satisfaction
|
||||
- **Stub method references**: Use stub vars instead of original methods
|
||||
|
||||
**Coordinator Fixes (Standard Process)**:
|
||||
1. **Import Resolution**:
|
||||
```bash
|
||||
# Find authoritative type source
|
||||
grep -r "TypeName" src/*/types.ts
|
||||
# Import from domain types (src/dashboard/types.ts) not component types
|
||||
```
|
||||
|
||||
2. **Test Mock Completion**:
|
||||
```typescript
|
||||
// Use Partial<T> as T pattern for minimal mocking
|
||||
const mockDashboard: Partial<DashboardInfo> as DashboardInfo = {
|
||||
id: 123,
|
||||
json_metadata: '{}',
|
||||
};
|
||||
```
|
||||
|
||||
3. **Stub Reference Fixes**:
|
||||
```typescript
|
||||
// ✅ Use stub variable
|
||||
expect(postStub.callCount).toBe(1);
|
||||
// ❌ Don't use original method
|
||||
expect(SupersetClient.post.callCount).toBe(1);
|
||||
```
|
||||
|
||||
4. **Validation Commands**:
|
||||
```bash
|
||||
npm run type # TypeScript compilation
|
||||
npm test -- filename # Test functionality
|
||||
git status # Should show rename, not add/delete
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. File Categories for Planning
|
||||
|
||||
### Leaf Files (Start Here)
|
||||
**Self-contained files with minimal JS/JSX dependencies**:
|
||||
- Test files (80 files) - Usually only import the file being tested
|
||||
- Utility files without internal dependencies
|
||||
- Components importing only external libraries
|
||||
|
||||
### Heavily Imported Files (Migrate Last)
|
||||
**Core files that many others depend on**:
|
||||
- `utils/common.js` - Core utility functions
|
||||
- `utils/reducerUtils.js` - Redux helpers
|
||||
- `@superset-ui/core` equivalent files
|
||||
- Major state management files (`explore/store.js`, `dashboard/actions/`)
|
||||
|
||||
### Complex Components (Middle Priority)
|
||||
**Large files requiring careful type analysis**:
|
||||
- `components/Datasource/DatasourceEditor.jsx` (1,809 lines)
|
||||
- `explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx` (1,031 lines)
|
||||
- `explore/components/ExploreViewContainer/index.jsx` (911 lines)
|
||||
|
||||
---
|
||||
|
||||
## 6. Success Metrics & Continuous Improvement
|
||||
|
||||
**Per-File Gates**:
|
||||
- ✅ `npm run type` passes after each migration
|
||||
- ✅ Zero `any` types introduced
|
||||
- ✅ All imports properly typed
|
||||
- ✅ Types filed in correct hierarchy
|
||||
|
||||
**Linear Scheduling**:
|
||||
When agents report `DEPENDENCY_BLOCK`:
|
||||
- Queue dependencies in linear order
|
||||
- Process one file at a time to avoid conflicts
|
||||
- Handle cascading type changes between files
|
||||
|
||||
**After Each Migration**:
|
||||
1. **Update guides** with new patterns discovered
|
||||
2. **Document coordinator fixes** that become common
|
||||
3. **Enhance agent instructions** based on recurring issues
|
||||
4. **Track success metrics** - automatic vs coordinator integration rates
|
||||
76
.claude/projects/js-to-ts/PROJECT.md
Normal file
76
.claude/projects/js-to-ts/PROJECT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# JavaScript to TypeScript Migration Project
|
||||
|
||||
Progressive migration of 219 JS/JSX files to TypeScript in Apache Superset frontend.
|
||||
|
||||
## 📁 Project Documentation
|
||||
|
||||
- **[AGENT.md](./AGENT.md)** - Complete technical migration guide for agents (includes type reference, patterns, validation)
|
||||
- **[COORDINATOR.md](./COORDINATOR.md)** - Strategic workflow for coordinators (file selection, task management, integration)
|
||||
|
||||
## 🎯 Quick Start
|
||||
|
||||
**For Agents:** Read [AGENT.md](./AGENT.md) for complete migration instructions
|
||||
**For Coordinators:** Read [COORDINATOR.md](./COORDINATOR.md) for workflow and [AGENT.md](./AGENT.md) for supervision
|
||||
|
||||
**Command:** `/js-to-ts <filename>` - See [../../commands/js-to-ts.md](../../commands/js-to-ts.md)
|
||||
|
||||
## 📊 Migration Progress
|
||||
|
||||
**Scope**: 219 files total (112 JS + 107 JSX)
|
||||
- Production files: 139 (63%)
|
||||
- Test files: 80 (37%)
|
||||
|
||||
**Strategy**: Leaf-first migration with dependency-aware coordination
|
||||
|
||||
### Completed Migrations ✅
|
||||
|
||||
1. **roundDecimal** - `plugins/legacy-plugin-chart-map-box/src/utils/roundDecimal.js`
|
||||
- Migrated core + test files
|
||||
- Added proper TypeScript function signature with optional precision parameter
|
||||
- All tests pass
|
||||
|
||||
2. **timeGrainSqlaAnimationOverrides** - `src/explore/controlPanels/timeGrainSqlaAnimationOverrides.js`
|
||||
- Migrated to TypeScript with ControlPanelState and Dataset types
|
||||
- Added TimeGrainOverrideState interface for return type
|
||||
- Used type guards for safe property access
|
||||
|
||||
3. **DebouncedMessageQueue** - `src/utils/DebouncedMessageQueue.js`
|
||||
- Migrated to TypeScript with proper generics
|
||||
- Created DebouncedMessageQueueOptions interface
|
||||
- **CREATED test file** with 4 comprehensive test cases
|
||||
- Excellent class property typing with private/readonly modifiers
|
||||
|
||||
**Files Migrated**: 3/219 (1.4%)
|
||||
**Tests Created**: 2 (roundDecimal had existing, DebouncedMessageQueue created)
|
||||
|
||||
### Next Candidates (Leaf Nodes) 🎯
|
||||
|
||||
**Identified leaf files with no JS/JSX dependencies:**
|
||||
- `src/utils/hostNamesConfig.js` - Domain configuration utility
|
||||
- `src/explore/controlPanels/Separator.js` - Control panel configuration
|
||||
- `src/middleware/loggerMiddleware.js` - Logging middleware
|
||||
|
||||
**Migration Quality**: All completed migrations have:
|
||||
- ✅ Zero `any` types
|
||||
- ✅ Proper TypeScript compilation
|
||||
- ✅ ESLint validation passed
|
||||
- ✅ Test coverage (created where missing)
|
||||
|
||||
---
|
||||
|
||||
## 📈 Success Metrics
|
||||
|
||||
**Per-File Gates**:
|
||||
- ✅ `npm run type` passes after each migration
|
||||
- ✅ Zero `any` types introduced
|
||||
- ✅ All imports properly typed
|
||||
- ✅ Types filed in correct hierarchy
|
||||
|
||||
**Overall Progress**:
|
||||
- **Automatic Integration Rate**: 100% (3/3 migrations required no coordinator fixes)
|
||||
- **Test Coverage**: Improved (1 new test file created)
|
||||
- **Type Safety**: Enhanced with proper interfaces and generics
|
||||
|
||||
---
|
||||
|
||||
*This is a claudette-managed progressive refactor. All documentation and coordination resources are organized under `.claude/projects/js-to-ts/`*
|
||||
@@ -1,5 +1,5 @@
|
||||
# Keep this in sync with the base image in the main Dockerfile (ARG PY_VER)
|
||||
FROM python:3.11.13-bookworm AS base
|
||||
FROM python:3.11.13-trixie AS base
|
||||
|
||||
# Install system dependencies that Superset needs
|
||||
# This layer will be cached across Codespace sessions
|
||||
|
||||
16
.github/CODEOWNERS
vendored
16
.github/CODEOWNERS
vendored
@@ -20,7 +20,7 @@
|
||||
|
||||
# Notify PMC members of changes to GitHub Actions
|
||||
|
||||
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar
|
||||
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @sadpandajoe
|
||||
|
||||
# Notify PMC members of changes to required GitHub Actions
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
|
||||
# Notify PMC members of changes to extension-related files
|
||||
|
||||
/superset-core/ @michael-s-molina @villebro
|
||||
/superset-cli/ @michael-s-molina @villebro
|
||||
/superset/core/ @michael-s-molina @villebro
|
||||
/superset/extensions/ @michael-s-molina @villebro
|
||||
/superset-frontend/src/packages/superset-core/ @michael-s-molina @villebro
|
||||
/superset-frontend/src/core/ @michael-s-molina @villebro
|
||||
/superset-frontend/src/extensions/ @michael-s-molina @villebro
|
||||
/superset-core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-extensions-cli/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset/core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset/extensions/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-frontend/src/packages/superset-core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-frontend/src/core/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
/superset-frontend/src/extensions/ @michael-s-molina @villebro @geido @eschutho @rusackas @kgabryje
|
||||
|
||||
6
.github/actions/change-detector/action.yml
vendored
6
.github/actions/change-detector/action.yml
vendored
@@ -17,9 +17,9 @@ outputs:
|
||||
docs:
|
||||
description: Whether docs-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.docs }}
|
||||
superset-cli:
|
||||
description: Whether superset-cli package-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.superset-cli }}
|
||||
superset-extensions-cli:
|
||||
description: Whether superset-extensions-cli package-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.superset-extensions-cli }}
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
|
||||
2
.github/copilot-instructions.md
vendored
2
.github/copilot-instructions.md
vendored
@@ -1 +1 @@
|
||||
../LLMS.md
|
||||
../AGENTS.md
|
||||
70
.github/dependabot.yml
vendored
70
.github/dependabot.yml
vendored
@@ -5,7 +5,7 @@ updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
ignore:
|
||||
@@ -18,7 +18,7 @@ updates:
|
||||
- dependency-name: "jest-environment-jsdom"
|
||||
directory: "/superset-frontend/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -40,21 +40,21 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: ".github/actions"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: increase
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/docs/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: increase
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-websocket/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -63,7 +63,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-websocket/utils/client-ws-app/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -75,7 +75,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-calendar/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -85,7 +85,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-histogram/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -95,7 +95,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-partition/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -105,7 +105,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-world-map/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -115,7 +115,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-pivot-table/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -125,7 +125,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-chord/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -135,7 +135,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-horizon/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -145,7 +145,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-rose/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -155,7 +155,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-preset-chart-deckgl/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -165,7 +165,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-table/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -175,7 +175,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-country-map/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -185,7 +185,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-map-box/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -195,7 +195,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-sankey/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -205,7 +205,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-preset-chart-nvd3/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -215,7 +215,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-word-cloud/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -225,7 +225,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-event-flow/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -235,7 +235,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -245,7 +245,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -255,7 +255,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-echarts/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -265,7 +265,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/preset-chart-xy/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -275,7 +275,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-heatmap/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -285,7 +285,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -295,7 +295,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-sunburst/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -305,7 +305,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-handlebars/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -315,7 +315,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/generator-superset/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -325,7 +325,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-chart-controls/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -339,7 +339,7 @@ updates:
|
||||
- dependency-name: "react-markdown"
|
||||
- dependency-name: "remark-gfm"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -349,7 +349,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-demo/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -359,7 +359,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-switchboard/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
|
||||
70
.github/workflows/bashlib.sh
vendored
70
.github/workflows/bashlib.sh
vendored
@@ -182,6 +182,76 @@ cypress-run-all() {
|
||||
kill $flaskProcessId
|
||||
}
|
||||
|
||||
playwright-install() {
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||
|
||||
say "::group::Install Playwright browsers"
|
||||
npx playwright install --with-deps chromium
|
||||
# Create output directories for test results and debugging
|
||||
mkdir -p playwright-results
|
||||
mkdir -p test-results
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
playwright-run() {
|
||||
local APP_ROOT=$1
|
||||
|
||||
# Start Flask from the project root (same as Cypress)
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
local flasklog="${HOME}/flask-playwright.log"
|
||||
local port=8081
|
||||
PLAYWRIGHT_BASE_URL="http://localhost:${port}"
|
||||
if [ -n "$APP_ROOT" ]; then
|
||||
export SUPERSET_APP_ROOT=$APP_ROOT
|
||||
PLAYWRIGHT_BASE_URL=${PLAYWRIGHT_BASE_URL}${APP_ROOT}/
|
||||
fi
|
||||
export PLAYWRIGHT_BASE_URL
|
||||
|
||||
nohup flask run --no-debugger -p $port >"$flasklog" 2>&1 </dev/null &
|
||||
local flaskProcessId=$!
|
||||
|
||||
# Ensure cleanup on exit
|
||||
trap "kill $flaskProcessId 2>/dev/null || true" EXIT
|
||||
|
||||
# Wait for server to be ready with health check
|
||||
local timeout=60
|
||||
say "Waiting for Flask server to start on port $port..."
|
||||
while [ $timeout -gt 0 ]; do
|
||||
if curl -f ${PLAYWRIGHT_BASE_URL}/health >/dev/null 2>&1; then
|
||||
say "Flask server is ready"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
timeout=$((timeout - 1))
|
||||
done
|
||||
|
||||
if [ $timeout -eq 0 ]; then
|
||||
echo "::error::Flask server failed to start within 60 seconds"
|
||||
echo "::group::Flask startup log"
|
||||
cat "$flasklog"
|
||||
echo "::endgroup::"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Change to frontend directory for Playwright execution
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||
|
||||
say "::group::Run Playwright tests"
|
||||
echo "Running Playwright with baseURL: ${PLAYWRIGHT_BASE_URL}"
|
||||
npx playwright test auth/login --reporter=github --output=playwright-results
|
||||
local status=$?
|
||||
say "::endgroup::"
|
||||
|
||||
# After job is done, print out Flask log for debugging
|
||||
echo "::group::Flask log for Playwright run"
|
||||
cat "$flasklog"
|
||||
echo "::endgroup::"
|
||||
# make sure the program exits
|
||||
kill $flaskProcessId
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
eyes-storybook-dependencies() {
|
||||
say "::group::install eyes-storyook dependencies"
|
||||
sudo apt-get update -y && sudo apt-get -y install gconf-service ca-certificates libxshmfence-dev fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libgconf-2-4 libglib2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libnss3 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release xdg-utils libappindicator1
|
||||
|
||||
4
.github/workflows/bump-python-package.yml
vendored
4
.github/workflows/bump-python-package.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: true
|
||||
ref: master
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
uses: ./.github/actions/setup-supersetbot/
|
||||
|
||||
- name: Set up Python ${{ inputs.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
|
||||
2
.github/workflows/cancel_duplicates.yml
vendored
2
.github/workflows/cancel_duplicates.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
if: steps.check_queued.outputs.count >= 20
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Cancel duplicate workflow runs
|
||||
if: steps.check_queued.outputs.count >= 20
|
||||
|
||||
2
.github/workflows/check-python-deps.yml
vendored
2
.github/workflows/check-python-deps.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -25,9 +25,9 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Check and notify
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
script: |
|
||||
|
||||
4
.github/workflows/claude.yml
vendored
4
.github/workflows/claude.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Comment access denied
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const message = `👋 Hi @${{ github.event.comment.user.login || github.event.review.user.login || github.event.issue.user.login }}!
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -53,6 +53,6 @@ jobs:
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
4
.github/workflows/dependency-review.yml
vendored
4
.github/workflows/dependency-review.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: "Dependency Review"
|
||||
uses: actions/dependency-review-action@v4
|
||||
continue-on-error: true
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
|
||||
6
.github/workflows/docker.yml
vendored
6
.github/workflows/docker.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
steps:
|
||||
- id: set_matrix
|
||||
run: |
|
||||
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311"]'; fi)
|
||||
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]'; fi)
|
||||
echo "matrix_config=${MATRIX_CONFIG}" >> $GITHUB_OUTPUT
|
||||
echo $GITHUB_OUTPUT
|
||||
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Check for file changes
|
||||
|
||||
4
.github/workflows/embedded-sdk-release.yml
vendored
4
.github/workflows/embedded-sdk-release.yml
vendored
@@ -28,8 +28,8 @@ jobs:
|
||||
run:
|
||||
working-directory: superset-embedded-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-embedded-sdk/.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
4
.github/workflows/embedded-sdk-test.yml
vendored
4
.github/workflows/embedded-sdk-test.yml
vendored
@@ -18,8 +18,8 @@ jobs:
|
||||
run:
|
||||
working-directory: superset-embedded-sdk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-embedded-sdk/.nvmrc'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
14
.github/workflows/ephemeral-env-pr-close.yml
vendored
14
.github/workflows/ephemeral-env-pr-close.yml
vendored
@@ -1,4 +1,10 @@
|
||||
name: Cleanup ephemeral envs (PR close)
|
||||
name: Cleanup ephemeral envs (PR close) [DEPRECATED]
|
||||
|
||||
# ⚠️ DEPRECATION NOTICE ⚠️
|
||||
# This workflow is deprecated and will be removed in a future version.
|
||||
# The new Superset Showtime workflow handles cleanup automatically.
|
||||
# See .github/workflows/showtime.yml and showtime-cleanup.yml for replacements.
|
||||
# Migration guide: https://github.com/mistercrunch/superset-showtime
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
@@ -27,7 +33,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -63,7 +69,7 @@ jobs:
|
||||
|
||||
- name: Comment (success)
|
||||
if: steps.describe-services.outputs.active == 'true'
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
@@ -71,5 +77,5 @@ jobs:
|
||||
issue_number: ${{ github.event.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: 'Ephemeral environment shutdown and build artifacts deleted.'
|
||||
body: '⚠️ **DEPRECATED WORKFLOW** - Ephemeral environment shutdown and build artifacts deleted. Please migrate to the new Superset Showtime system for future PRs.'
|
||||
})
|
||||
|
||||
37
.github/workflows/ephemeral-env.yml
vendored
37
.github/workflows/ephemeral-env.yml
vendored
@@ -1,4 +1,12 @@
|
||||
name: Ephemeral env workflow
|
||||
name: Ephemeral env workflow [DEPRECATED]
|
||||
|
||||
# ⚠️ DEPRECATION NOTICE ⚠️
|
||||
# This workflow is deprecated and will be removed in a future version.
|
||||
# Please use the new Superset Showtime workflow instead:
|
||||
# - Use label "🎪 trigger-start" instead of "testenv-up"
|
||||
# - Showtime provides better reliability and easier management
|
||||
# - See .github/workflows/showtime.yml for the replacement
|
||||
# - Migration guide: https://github.com/mistercrunch/superset-showtime
|
||||
|
||||
# Example manual trigger:
|
||||
# gh workflow run ephemeral-env.yml --ref fix_ephemerals --field label_name="testenv-up" --field issue_number=666
|
||||
@@ -55,7 +63,7 @@ jobs:
|
||||
- name: Get event SHA
|
||||
id: get-sha
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
@@ -86,7 +94,7 @@ jobs:
|
||||
core.setOutput("sha", prSha);
|
||||
|
||||
- name: Looking for feature flags in PR description
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
id: eval-feature-flags
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
with:
|
||||
@@ -108,7 +116,7 @@ jobs:
|
||||
return results;
|
||||
|
||||
- name: Reply with confirmation comment
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -126,8 +134,11 @@ jobs:
|
||||
throw new Error("Issue number is not available.");
|
||||
}
|
||||
|
||||
const body = `@${user} Processing your ephemeral environment request [here](${workflowUrl}).` +
|
||||
` Action: **${action}**.` +
|
||||
const body = `⚠️ **DEPRECATED WORKFLOW** ⚠️\n\n@${user} This workflow is deprecated! Please use the new **Superset Showtime** system instead:\n\n` +
|
||||
`- Replace "testenv-up" label with "🎪 trigger-start"\n` +
|
||||
`- Better reliability and easier management\n` +
|
||||
`- See https://github.com/mistercrunch/superset-showtime for details\n\n` +
|
||||
`Processing your ephemeral environment request [here](${workflowUrl}). Action: **${action}**.` +
|
||||
` More information on [how to use or configure ephemeral environments]` +
|
||||
`(https://superset.apache.org/docs/contributing/howtos/#github-ephemeral-environments)`;
|
||||
|
||||
@@ -149,7 +160,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ needs.ephemeral-env-label.outputs.sha }} : ${{steps.get-sha.outputs.sha}} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
|
||||
persist-credentials: false
|
||||
@@ -178,7 +189,7 @@ jobs:
|
||||
--extra-flags "--build-arg INCLUDE_CHROMIUM=false"
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -209,12 +220,12 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -237,7 +248,7 @@ jobs:
|
||||
|
||||
- name: Fail on missing container image
|
||||
if: steps.check-image.outcome == 'failure'
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
script: |
|
||||
@@ -307,7 +318,7 @@ jobs:
|
||||
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
|
||||
- name: Comment (success)
|
||||
if: ${{ success() }}
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
@@ -320,7 +331,7 @@ jobs:
|
||||
});
|
||||
- name: Comment (failure)
|
||||
if: ${{ failure() }}
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
|
||||
4
.github/workflows/generate-FOSSA-report.yml
vendored
4
.github/workflows/generate-FOSSA-report.yml
vendored
@@ -27,12 +27,12 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "11"
|
||||
|
||||
@@ -14,10 +14,10 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
|
||||
2
.github/workflows/issue_creation.yml
vendored
2
.github/workflows/issue_creation.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
- uses: actions/labeler@v6
|
||||
with:
|
||||
sync-labels: true
|
||||
|
||||
|
||||
2
.github/workflows/latest-release-tag.yml
vendored
2
.github/workflows/latest-release-tag.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
4
.github/workflows/license-check.yml
vendored
4
.github/workflows/license-check.yml
vendored
@@ -15,12 +15,12 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
|
||||
2
.github/workflows/no-hold-label.yml
vendored
2
.github/workflows/no-hold-label.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Check for 'hold' label
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
|
||||
2
.github/workflows/pr-lint.yml
vendored
2
.github/workflows/pr-lint.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
4
.github/workflows/pre-commit.yml
vendored
4
.github/workflows/pre-commit.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
python-version: ["current", "previous", "next"]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >>"${GITHUB_ENV}"
|
||||
brew install norwoodj/tap/helm-docs
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
|
||||
2
.github/workflows/prefer-typescript.yml
vendored
2
.github/workflows/prefer-typescript.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
name: Bump version and publish package(s)
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
# pulls all commits (needed for lerna / semantic release to correctly version)
|
||||
fetch-depth: 0
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
|
||||
- name: Install Node.js
|
||||
if: env.HAS_TAGS
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
|
||||
|
||||
50
.github/workflows/showtime-cleanup.yml
vendored
Normal file
50
.github/workflows/showtime-cleanup.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: 🎪 Showtime Cleanup
|
||||
|
||||
# Scheduled cleanup of expired environments
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */6 * * *' # Every 6 hours
|
||||
|
||||
# Manual trigger for testing
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
max_age_hours:
|
||||
description: 'Maximum age in hours before cleanup'
|
||||
required: false
|
||||
default: '48'
|
||||
type: string
|
||||
|
||||
# Common environment variables
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: ${{ vars.AWS_REGION || 'us-west-2' }}
|
||||
GITHUB_ORG: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
|
||||
jobs:
|
||||
cleanup-expired:
|
||||
name: Clean up expired showtime environments
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Install Superset Showtime
|
||||
run: pip install superset-showtime
|
||||
|
||||
- name: Cleanup expired environments
|
||||
run: |
|
||||
MAX_AGE="${{ github.event.inputs.max_age_hours || '48' }}"
|
||||
|
||||
# Validate max_age is numeric
|
||||
if [[ ! "$MAX_AGE" =~ ^[0-9]+$ ]]; then
|
||||
echo "❌ Invalid max_age_hours format: $MAX_AGE (must be numeric)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Cleaning up environments older than ${MAX_AGE}h"
|
||||
python -m showtime cleanup --older-than "${MAX_AGE}h"
|
||||
179
.github/workflows/showtime-trigger.yml
vendored
Normal file
179
.github/workflows/showtime-trigger.yml
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
name: 🎪 Superset Showtime
|
||||
|
||||
# Ultra-simple: just sync on any PR state change
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, synchronize, closed]
|
||||
|
||||
# Manual testing
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to sync'
|
||||
required: true
|
||||
type: number
|
||||
sha:
|
||||
description: 'Specific SHA to deploy (optional, defaults to latest)'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
# Common environment variables for all jobs (non-sensitive only)
|
||||
env:
|
||||
AWS_REGION: us-west-2
|
||||
GITHUB_ORG: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
GITHUB_ACTOR: ${{ github.actor }}
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: 🎪 Sync PR to desired state
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Security Check - Authorize Maintainers Only
|
||||
id: auth
|
||||
uses: actions/github-script@v8
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
script: |
|
||||
const actor = context.actor;
|
||||
console.log(`🔍 Checking authorization for ${actor}`);
|
||||
|
||||
// Early exit for workflow_dispatch - assume authorized since it's manually triggered
|
||||
if (context.eventName === 'workflow_dispatch') {
|
||||
console.log(`✅ Workflow dispatch event - assuming authorized for ${actor}`);
|
||||
core.setOutput('authorized', 'true');
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
username: actor
|
||||
});
|
||||
|
||||
console.log(`📊 Permission level for ${actor}: ${permission.permission}`);
|
||||
const authorized = ['write', 'admin'].includes(permission.permission);
|
||||
|
||||
// If this is a synchronize event from unauthorized user, check if Showtime is active and set blocked label
|
||||
if (!authorized && context.eventName === 'pull_request_target' && context.payload.action === 'synchronize') {
|
||||
console.log(`🔒 Synchronize event detected - checking if Showtime is active`);
|
||||
|
||||
// Check if PR has any circus tent labels (Showtime is in use)
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number
|
||||
});
|
||||
|
||||
const hasCircusLabels = issue.labels.some(label => label.name.startsWith('🎪 '));
|
||||
|
||||
if (hasCircusLabels) {
|
||||
console.log(`🎪 Circus labels found - setting blocked label to prevent auto-deployment`);
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
labels: ['🎪 🔒 showtime-blocked']
|
||||
});
|
||||
|
||||
console.log(`✅ Blocked label set - Showtime will detect and skip operations`);
|
||||
} else {
|
||||
console.log(`ℹ️ No circus labels found - Showtime not in use, skipping block`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!authorized) {
|
||||
console.log(`🚨 Unauthorized user ${actor} - skipping all operations`);
|
||||
core.setOutput('authorized', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ Authorized maintainer: ${actor}`);
|
||||
core.setOutput('authorized', 'true');
|
||||
|
||||
- name: Install Superset Showtime
|
||||
if: steps.auth.outputs.authorized == 'true'
|
||||
run: |
|
||||
echo "::notice::Maintainer ${{ github.actor }} triggered deploy for PR ${{ github.event.pull_request.number || github.event.inputs.pr_number }}"
|
||||
pip install --upgrade superset-showtime
|
||||
showtime version
|
||||
|
||||
- name: Check what actions are needed
|
||||
if: steps.auth.outputs.authorized == 'true'
|
||||
id: check
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Bulletproof PR number extraction
|
||||
if [[ -n "${{ github.event.pull_request.number }}" ]]; then
|
||||
PR_NUM="${{ github.event.pull_request.number }}"
|
||||
elif [[ -n "${{ github.event.inputs.pr_number }}" ]]; then
|
||||
PR_NUM="${{ github.event.inputs.pr_number }}"
|
||||
else
|
||||
echo "❌ No PR number found in event or inputs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using PR number: $PR_NUM"
|
||||
|
||||
# Run sync check-only with optional SHA override
|
||||
if [[ -n "${{ github.event.inputs.sha }}" ]]; then
|
||||
OUTPUT=$(python -m showtime sync $PR_NUM --check-only --sha "${{ github.event.inputs.sha }}")
|
||||
else
|
||||
OUTPUT=$(python -m showtime sync $PR_NUM --check-only)
|
||||
fi
|
||||
echo "$OUTPUT"
|
||||
|
||||
# Extract the outputs we need for conditional steps
|
||||
BUILD=$(echo "$OUTPUT" | grep "build_needed=" | cut -d'=' -f2)
|
||||
SYNC=$(echo "$OUTPUT" | grep "sync_needed=" | cut -d'=' -f2)
|
||||
PR_NUM_OUT=$(echo "$OUTPUT" | grep "pr_number=" | cut -d'=' -f2)
|
||||
TARGET_SHA=$(echo "$OUTPUT" | grep "target_sha=" | cut -d'=' -f2)
|
||||
|
||||
echo "build_needed=$BUILD" >> $GITHUB_OUTPUT
|
||||
echo "sync_needed=$SYNC" >> $GITHUB_OUTPUT
|
||||
echo "pr_number=$PR_NUM_OUT" >> $GITHUB_OUTPUT
|
||||
echo "target_sha=$TARGET_SHA" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout PR code (only if build needed)
|
||||
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ steps.check.outputs.target_sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Docker Environment (only if build needed)
|
||||
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.build_needed == 'true'
|
||||
uses: ./.github/actions/setup-docker
|
||||
with:
|
||||
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
build: "true"
|
||||
install-docker-compose: "false"
|
||||
|
||||
- name: Execute sync (handles everything)
|
||||
if: steps.auth.outputs.authorized == 'true' && steps.check.outputs.sync_needed == 'true'
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
run: |
|
||||
PR_NUM="${{ steps.check.outputs.pr_number }}"
|
||||
TARGET_SHA="${{ steps.check.outputs.target_sha }}"
|
||||
if [[ -n "$TARGET_SHA" ]]; then
|
||||
python -m showtime sync $PR_NUM --sha "$TARGET_SHA"
|
||||
else
|
||||
python -m showtime sync $PR_NUM
|
||||
fi
|
||||
2
.github/workflows/superset-app-cli.yml
vendored
2
.github/workflows/superset-app-cli.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
|
||||
@@ -30,13 +30,13 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
ref: master
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install eyes-storybook dependencies
|
||||
|
||||
6
.github/workflows/superset-docs-deploy.yml
vendored
6
.github/workflows/superset-docs-deploy.yml
vendored
@@ -31,17 +31,17 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './docs/.nvmrc'
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '21'
|
||||
|
||||
26
.github/workflows/superset-docs-verify.yml
vendored
26
.github/workflows/superset-docs-verify.yml
vendored
@@ -18,15 +18,17 @@ jobs:
|
||||
name: Link Checking
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
# Do not bump this linkinator-action version without opening
|
||||
# an ASF Infra ticket to allow the new version first!
|
||||
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
||||
- uses: JustinBeckwith/linkinator-action@3d5ba091319fa7b0ac14703761eebb7d100e6f6d # v1.11.0
|
||||
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
||||
with:
|
||||
paths: "**/*.md, **/*.mdx, !superset-frontend/CHANGELOG.md"
|
||||
paths: "**/*.md, **/*.mdx"
|
||||
linksToSkip: >-
|
||||
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
||||
^https://github.com/apache/(superset|incubator-superset)/(pull|issues)/\d+,
|
||||
^https://github.com/apache/(superset|incubator-superset)/commit/[a-f0-9]+,
|
||||
superset-frontend/.*CHANGELOG\.md,
|
||||
http://localhost:8088/,
|
||||
http://127.0.0.1:3000/,
|
||||
http://localhost:9001/,
|
||||
@@ -41,12 +43,12 @@ jobs:
|
||||
http://theiconic.com.au/,
|
||||
https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html,
|
||||
^https://img\.shields\.io/.*,
|
||||
https://vkusvill.ru/
|
||||
https://www.linkedin.com/in/mark-thomas-b16751158/
|
||||
https://theiconic.com.au/
|
||||
https://wattbewerb.de/
|
||||
https://timbr.ai/
|
||||
https://opensource.org/license/apache-2-0
|
||||
https://vkusvill.ru/,
|
||||
https://www.linkedin.com/in/mark-thomas-b16751158/,
|
||||
https://theiconic.com.au/,
|
||||
https://wattbewerb.de/,
|
||||
https://timbr.ai/,
|
||||
https://opensource.org/license/apache-2-0,
|
||||
https://www.plaidcloud.com/
|
||||
build-deploy:
|
||||
name: Build & Deploy
|
||||
@@ -56,12 +58,12 @@ jobs:
|
||||
working-directory: docs
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './docs/.nvmrc'
|
||||
- name: yarn install
|
||||
|
||||
8
.github/workflows/superset-e2e.yml
vendored
8
.github/workflows/superset-e2e.yml
vendored
@@ -69,21 +69,21 @@ jobs:
|
||||
# Conditional checkout based on context
|
||||
- name: Checkout for push or pull_request event
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Checkout using ref (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
submodules: recursive
|
||||
- name: Checkout using PR ID (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Superset CLI Package Tests
|
||||
name: Superset Extensions CLI Package Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -14,17 +14,17 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-superset-cli-package:
|
||||
test-superset-extensions-cli-package:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["previous", "current", "next"]
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-cli
|
||||
working-directory: superset-extensions-cli
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -36,29 +36,29 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Python
|
||||
if: steps.check.outputs.superset-cli
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: ./.github/actions/setup-backend/
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
requirements-type: dev
|
||||
|
||||
- name: Run pytest with coverage
|
||||
if: steps.check.outputs.superset-cli
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
run: |
|
||||
pytest --cov=superset_cli --cov-report=xml --cov-report=term-missing --cov-report=html -v --tb=short
|
||||
pytest --cov=superset_extensions_cli --cov-report=xml --cov-report=term-missing --cov-report=html -v --tb=short
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
if: steps.check.outputs.superset-cli
|
||||
uses: codecov/codecov-action@v3
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: superset-cli
|
||||
name: superset-cli-coverage
|
||||
flags: superset-extensions-cli
|
||||
name: superset-extensions-cli-coverage
|
||||
fail_ci_if_error: false
|
||||
|
||||
- name: Upload HTML coverage report
|
||||
if: steps.check.outputs.superset-cli
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: superset-cli-coverage-html
|
||||
name: superset-extensions-cli-coverage-html
|
||||
path: htmlcov/
|
||||
14
.github/workflows/superset-frontend.yml
vendored
14
.github/workflows/superset-frontend.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
should-run: ${{ steps.check.outputs.frontend }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
git show -s --format=raw HEAD
|
||||
docker buildx build \
|
||||
-t $TAG \
|
||||
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-bookworm \
|
||||
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-trixie \
|
||||
--target superset-node-ci \
|
||||
.
|
||||
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Coverage Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
pattern: coverage-artifacts-*
|
||||
path: coverage/
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
@@ -143,7 +143,7 @@ jobs:
|
||||
- name: tsc
|
||||
run: |
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm run type"
|
||||
"npm run plugins:build && npm run type"
|
||||
|
||||
validate-frontend:
|
||||
needs: frontend-build
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
|
||||
2
.github/workflows/superset-helm-lint.yml
vendored
2
.github/workflows/superset-helm-lint.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
4
.github/workflows/superset-helm-release.yml
vendored
4
.github/workflows/superset-helm-release.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.ref || github.ref_name }}
|
||||
persist-credentials: true
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
CR_RELEASE_NAME_TEMPLATE: "superset-helm-chart-{{ .Version }}"
|
||||
|
||||
- name: Open Pull Request
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const branchName = '${{ env.branch_name }}';
|
||||
|
||||
141
.github/workflows/superset-playwright.yml
vendored
Normal file
141
.github/workflows/superset-playwright.yml
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
name: Playwright E2E Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'The branch or tag to checkout'
|
||||
required: false
|
||||
default: ''
|
||||
pr_id:
|
||||
description: 'The pull request ID to checkout'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
playwright-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
# Allow workflow to succeed even if tests fail during shadow mode
|
||||
continue-on-error: true
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: ["chromium"]
|
||||
app_root: ["", "/app/prefix"]
|
||||
env:
|
||||
SUPERSET_ENV: development
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
REDIS_PORT: 16379
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
ports:
|
||||
- 15432:5432
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- 16379:6379
|
||||
steps:
|
||||
# -------------------------------------------------------
|
||||
# Conditional checkout based on context (same as Cypress workflow)
|
||||
- name: Checkout for push or pull_request event
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Checkout using ref (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
submodules: recursive
|
||||
- name: Checkout using PR ID (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
|
||||
submodules: recursive
|
||||
# -------------------------------------------------------
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
- name: Setup postgres
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: Import test data
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: npm-install
|
||||
- name: Build javascript packages
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: build-instrumented-assets
|
||||
- name: Install Playwright
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: playwright-install
|
||||
- name: Run Playwright
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
with:
|
||||
run: playwright-run ${{ matrix.app_root }}
|
||||
- name: Set safe app root
|
||||
if: failure()
|
||||
id: set-safe-app-root
|
||||
run: |
|
||||
APP_ROOT="${{ matrix.app_root }}"
|
||||
SAFE_APP_ROOT=${APP_ROOT//\//_}
|
||||
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
|
||||
- name: Upload Playwright Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/superset-frontend/playwright-results/
|
||||
${{ github.workspace }}/superset-frontend/test-results/
|
||||
name: playwright-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
6
.github/workflows/superset-translations.yml
vendored
6
.github/workflows/superset-translations.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install dependencies
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
2
.github/workflows/superset-websocket.yml
vendored
2
.github/workflows/superset-websocket.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install dependencies
|
||||
|
||||
4
.github/workflows/supersetbot.yml
vendored
4
.github/workflows/supersetbot.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
steps:
|
||||
- name: Quickly add thumbs up!
|
||||
if: github.event_name == 'issue_comment' && contains(github.event.comment.body, '@supersetbot')
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
});
|
||||
|
||||
- name: "Checkout ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
10
.github/workflows/tag-release.yml
vendored
10
.github/workflows/tag-release.yml
vendored
@@ -42,12 +42,12 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311"]
|
||||
build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311", "py312"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
build: "true"
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
@@ -107,12 +107,12 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
|
||||
4
.github/workflows/tech-debt.yml
vendored
4
.github/workflows/tech-debt.yml
vendored
@@ -27,10 +27,10 @@ jobs:
|
||||
name: Generate Reports
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
|
||||
|
||||
2
.github/workflows/welcome-new-users.yml
vendored
2
.github/workflows/welcome-new-users.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Welcome Message
|
||||
uses: actions/first-interaction@v2
|
||||
uses: actions/first-interaction@v3
|
||||
continue-on-error: true
|
||||
with:
|
||||
repo-token: ${{ github.token }}
|
||||
|
||||
@@ -25,7 +25,7 @@ repos:
|
||||
- id: mypy
|
||||
name: mypy (main)
|
||||
args: [--check-untyped-defs]
|
||||
exclude: ^superset-cli/
|
||||
exclude: ^superset-extensions-cli/
|
||||
additional_dependencies: [
|
||||
types-simplejson,
|
||||
types-python-dateutil,
|
||||
@@ -41,9 +41,9 @@ repos:
|
||||
types-Markdown,
|
||||
]
|
||||
- id: mypy
|
||||
name: mypy (superset-cli)
|
||||
name: mypy (superset-extensions-cli)
|
||||
args: [--check-untyped-defs]
|
||||
files: ^superset-cli/
|
||||
files: ^superset-extensions-cli/
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
@@ -68,7 +68,7 @@ repos:
|
||||
files: ^superset-frontend/.*\.(js|jsx|ts|tsx)$
|
||||
- id: eslint-docs
|
||||
name: eslint (docs)
|
||||
entry: bash -c 'cd docs && FILES=$(echo "$@" | sed "s|docs/||g") && yarn eslint --fix --ext .js,.jsx,.ts,.tsx --quiet $FILES'
|
||||
entry: bash -c 'cd docs && FILES=$(echo "$@" | sed "s|docs/||g") && yarn eslint --fix --quiet $FILES'
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^docs/.*\.(js|jsx|ts|tsx)$
|
||||
|
||||
@@ -73,6 +73,7 @@ ibm-db2.svg
|
||||
postgresql.svg
|
||||
snowflake.svg
|
||||
ydb.svg
|
||||
loading.svg
|
||||
|
||||
# docs-related
|
||||
erd.puml
|
||||
@@ -81,6 +82,7 @@ intro_header.txt
|
||||
|
||||
# for LLMs
|
||||
llm-context.md
|
||||
AGENTS.md
|
||||
LLMS.md
|
||||
CLAUDE.md
|
||||
CURSOR.md
|
||||
|
||||
@@ -15,8 +15,9 @@ Apache Superset is a data visualization platform with Flask/Python backend and R
|
||||
|
||||
### Testing Strategy Migration
|
||||
- **Prefer unit tests** over integration tests
|
||||
- **Prefer integration tests** over Cypress end-to-end tests
|
||||
- **Cypress is last resort** - Actively moving away from Cypress
|
||||
- **Prefer integration tests** over end-to-end tests
|
||||
- **Use Playwright for E2E tests** - Migrating from Cypress
|
||||
- **Cypress is deprecated** - Will be removed once migration is completed
|
||||
- **Use Jest + React Testing Library** for component testing
|
||||
- **Use `test()` instead of `describe()`** - Follow [avoid nesting when testing](https://kentcdodds.com/blog/avoid-nesting-when-youre-testing) principles
|
||||
|
||||
@@ -67,7 +68,11 @@ superset/
|
||||
|
||||
### Apache License Headers
|
||||
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
|
||||
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
||||
- **LLM instruction files are excluded** - Files like AGENTS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
||||
|
||||
### Code Comments
|
||||
- **Avoid time-specific language** - Don't use words like "now", "currently", "today" in code comments as they become outdated
|
||||
- **Write timeless comments** - Comments should remain accurate regardless of when they're read
|
||||
|
||||
## Documentation Requirements
|
||||
|
||||
@@ -107,6 +112,18 @@ superset/
|
||||
npm run test # All tests
|
||||
npm run test -- filename.test.tsx # Single file
|
||||
|
||||
# E2E Tests (Playwright - NEW)
|
||||
npm run playwright:test # All Playwright tests
|
||||
npm run playwright:ui # Interactive UI mode
|
||||
npm run playwright:headed # See browser during tests
|
||||
npx playwright test tests/auth/login.spec.ts # Single file
|
||||
npm run playwright:debug tests/auth/login.spec.ts # Debug specific file
|
||||
|
||||
# E2E Tests (Cypress - DEPRECATED)
|
||||
cd superset-frontend/cypress-base
|
||||
npm run cypress-run-chrome # All Cypress tests (headless)
|
||||
npm run cypress-debug # Interactive Cypress UI
|
||||
|
||||
# Backend
|
||||
pytest # All tests
|
||||
pytest tests/unit_tests/specific_test.py # Single file
|
||||
@@ -136,6 +153,19 @@ curl -f http://localhost:8088/health || echo "❌ Setup required - see https://s
|
||||
- **Use negation operator**: `~Model.field` instead of `== False` to avoid ruff E712 errors
|
||||
- **Example**: `~Model.is_active` instead of `Model.is_active == False`
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
**When creating pull requests:**
|
||||
|
||||
1. **Read the current PR template**: Always check `.github/PULL_REQUEST_TEMPLATE.md` for the latest format
|
||||
2. **Use the template sections**: Include all sections from the template (SUMMARY, BEFORE/AFTER, TESTING INSTRUCTIONS, ADDITIONAL INFORMATION)
|
||||
3. **Follow PR title conventions**: Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
- Format: `type(scope): description`
|
||||
- Example: `fix(dashboard): load charts correctly`
|
||||
- Types: `fix`, `feat`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
|
||||
|
||||
**Important**: Always reference the actual template file at `.github/PULL_REQUEST_TEMPLATE.md` instead of using cached content, as the template may be updated over time.
|
||||
|
||||
## Pre-commit Validation
|
||||
|
||||
**Use pre-commit hooks for quality validation:**
|
||||
@@ -44,4 +44,8 @@ under the License.
|
||||
- [4.0.1](./CHANGELOG/4.0.1.md)
|
||||
- [4.0.2](./CHANGELOG/4.0.2.md)
|
||||
- [4.1.0](./CHANGELOG/4.1.0.md)
|
||||
- [4.1.1](./CHANGELOG/4.1.1.md)
|
||||
- [4.1.2](./CHANGELOG/4.1.2.md)
|
||||
- [4.1.3](./CHANGELOG/4.1.3.md)
|
||||
- [4.1.4](./CHANGELOG/4.1.4.md)
|
||||
- [5.0.0](./CHANGELOG/5.0.0.md)
|
||||
|
||||
33
CHANGELOG/4.1.4.md
Normal file
33
CHANGELOG/4.1.4.md
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
## Change Log
|
||||
|
||||
### 4.1.4 (Thu Jul 24 08:30:04 2025 -0300)
|
||||
|
||||
**Database Migrations**
|
||||
|
||||
**Features**
|
||||
|
||||
**Fixes**
|
||||
- [#34289](https://github.com/apache/superset/pull/34289) fix: Saved queries list break if one query can't be parsed (@michael-s-molina)
|
||||
- [#33059](https://github.com/apache/superset/pull/33059) fix: Adds missing __init__ file to commands/logs (@michael-s-molina)
|
||||
|
||||
**Others**
|
||||
- [#32236](https://github.com/apache/superset/pull/32236) chore(deps): bump cryptography from 43.0.3 to 44.0.1 (@dependabot[bot])
|
||||
@@ -5,7 +5,7 @@
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
@@ -16,9 +16,23 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
# Contributing to Apache Superset
|
||||
|
||||
Contributions are welcome and are greatly appreciated! Every
|
||||
little bit helps, and credit will always be given.
|
||||
|
||||
All matters related to contributions have moved to [this section of
|
||||
the official Superset documentation](https://superset.apache.org/docs/contributing/). Source for the documentation is
|
||||
[located here](https://github.com/apache/superset/tree/master/docs/docs).
|
||||
## Developer Portal
|
||||
|
||||
All developer and contribution documentation has moved to the Apache Superset Developer Portal:
|
||||
|
||||
**[📚 View the Developer Portal →](https://superset.apache.org/developer_portal/)**
|
||||
|
||||
The Developer Portal includes comprehensive guides for:
|
||||
- [Contributing Overview](https://superset.apache.org/developer_portal/contributing/overview)
|
||||
- [Development Setup](https://superset.apache.org/developer_portal/contributing/development-setup)
|
||||
- [Submitting Pull Requests](https://superset.apache.org/developer_portal/contributing/submitting-pr)
|
||||
- [Contribution Guidelines](https://superset.apache.org/developer_portal/contributing/guidelines)
|
||||
- [Code Review Process](https://superset.apache.org/developer_portal/contributing/code-review)
|
||||
- [Development How-tos](https://superset.apache.org/developer_portal/contributing/howtos)
|
||||
|
||||
Source for the Developer Portal documentation is [located here](https://github.com/apache/superset/tree/master/docs/developer_portal).
|
||||
|
||||
39
Dockerfile
39
Dockerfile
@@ -18,7 +18,7 @@
|
||||
######################################################################
|
||||
# Node stage to deal with static asset construction
|
||||
######################################################################
|
||||
ARG PY_VER=3.11.13-slim-bookworm
|
||||
ARG PY_VER=3.11.13-slim-trixie
|
||||
|
||||
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
|
||||
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
||||
@@ -26,10 +26,13 @@ ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
||||
# Include translations in the final build
|
||||
ARG BUILD_TRANSLATIONS="false"
|
||||
|
||||
# Build arg to pre-populate examples DuckDB file
|
||||
ARG LOAD_EXAMPLES_DUCKDB="false"
|
||||
|
||||
######################################################################
|
||||
# superset-node-ci used as a base for building frontend assets and CI
|
||||
######################################################################
|
||||
FROM --platform=${BUILDPLATFORM} node:20-bookworm-slim AS superset-node-ci
|
||||
FROM --platform=${BUILDPLATFORM} node:20-trixie-slim AS superset-node-ci
|
||||
ARG BUILD_TRANSLATIONS
|
||||
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
||||
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
||||
@@ -64,7 +67,7 @@ RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.j
|
||||
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/root/.npm \
|
||||
if [ "$DEV_MODE" = "false" ]; then \
|
||||
if [ "${DEV_MODE}" = "false" ]; then \
|
||||
npm ci; \
|
||||
else \
|
||||
echo "Skipping 'npm ci' in dev mode"; \
|
||||
@@ -80,7 +83,7 @@ FROM superset-node-ci AS superset-node
|
||||
|
||||
# Build the frontend if not in dev mode
|
||||
RUN --mount=type=cache,target=/root/.npm \
|
||||
if [ "$DEV_MODE" = "false" ]; then \
|
||||
if [ "${DEV_MODE}" = "false" ]; then \
|
||||
echo "Running 'npm run ${BUILD_CMD}'"; \
|
||||
npm run ${BUILD_CMD}; \
|
||||
else \
|
||||
@@ -91,11 +94,10 @@ RUN --mount=type=cache,target=/root/.npm \
|
||||
COPY superset/translations /app/superset/translations
|
||||
|
||||
# Build translations if enabled, then cleanup localization files
|
||||
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
|
||||
RUN if [ "${BUILD_TRANSLATIONS}" = "true" ]; then \
|
||||
npm run build-translation; \
|
||||
fi; \
|
||||
rm -rf /app/superset/translations/*/*/*.po; \
|
||||
rm -rf /app/superset/translations/*/*/*.mo;
|
||||
rm -rf /app/superset/translations/*/*/*.[po,mo];
|
||||
|
||||
|
||||
######################################################################
|
||||
@@ -106,10 +108,10 @@ FROM python:${PY_VER} AS python-base
|
||||
ARG SUPERSET_HOME="/app/superset_home"
|
||||
ENV SUPERSET_HOME=${SUPERSET_HOME}
|
||||
|
||||
RUN mkdir -p $SUPERSET_HOME
|
||||
RUN mkdir -p ${SUPERSET_HOME}
|
||||
RUN useradd --user-group -d ${SUPERSET_HOME} -m --no-log-init --shell /bin/bash superset \
|
||||
&& chmod -R 1777 $SUPERSET_HOME \
|
||||
&& chown -R superset:superset $SUPERSET_HOME
|
||||
&& chmod -R 1777 ${SUPERSET_HOME} \
|
||||
&& chown -R superset:superset ${SUPERSET_HOME}
|
||||
|
||||
# Some bash scripts needed throughout the layers
|
||||
COPY --chmod=755 docker/*.sh /app/docker/
|
||||
@@ -134,19 +136,18 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
. /app/.venv/bin/activate && /app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
|
||||
|
||||
COPY superset/translations/ /app/translations_mo/
|
||||
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
|
||||
RUN if [ "${BUILD_TRANSLATIONS}" = "true" ]; then \
|
||||
pybabel compile -d /app/translations_mo | true; \
|
||||
fi; \
|
||||
rm -f /app/translations_mo/*/*/*.po; \
|
||||
rm -f /app/translations_mo/*/*/*.json;
|
||||
rm -f /app/translations_mo/*/*/*.[po,json]
|
||||
|
||||
######################################################################
|
||||
# Python APP common layer
|
||||
######################################################################
|
||||
FROM python-base AS python-common
|
||||
|
||||
# Build arg to pre-populate examples DuckDB file
|
||||
ARG LOAD_EXAMPLES_DUCKDB="false"
|
||||
# Re-declare build arg to receive it in this stage
|
||||
ARG LOAD_EXAMPLES_DUCKDB
|
||||
|
||||
ENV SUPERSET_HOME="/app/superset_home" \
|
||||
HOME="/app/superset_home" \
|
||||
@@ -173,11 +174,11 @@ RUN mkdir -p \
|
||||
ARG INCLUDE_CHROMIUM="false"
|
||||
ARG INCLUDE_FIREFOX="false"
|
||||
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||
if [ "$INCLUDE_CHROMIUM" = "true" ] || [ "$INCLUDE_FIREFOX" = "true" ]; then \
|
||||
if [ "${INCLUDE_CHROMIUM}" = "true" ] || [ "${INCLUDE_FIREFOX}" = "true" ]; then \
|
||||
uv pip install playwright && \
|
||||
playwright install-deps && \
|
||||
if [ "$INCLUDE_CHROMIUM" = "true" ]; then playwright install chromium; fi && \
|
||||
if [ "$INCLUDE_FIREFOX" = "true" ]; then playwright install firefox; fi; \
|
||||
if [ "${INCLUDE_CHROMIUM}" = "true" ]; then playwright install chromium; fi && \
|
||||
if [ "${INCLUDE_FIREFOX}" = "true" ]; then playwright install firefox; fi; \
|
||||
else \
|
||||
echo "Skipping browser installation"; \
|
||||
fi
|
||||
@@ -263,7 +264,7 @@ COPY requirements/*.txt requirements/
|
||||
|
||||
# Copy local packages needed for editable installs in development.txt
|
||||
COPY superset-core superset-core
|
||||
COPY superset-cli superset-cli
|
||||
COPY superset-extensions-cli superset-extensions-cli
|
||||
|
||||
# Install Python dependencies using docker/pip-install.sh
|
||||
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||
|
||||
2
Makefile
2
Makefile
@@ -91,7 +91,7 @@ js-format:
|
||||
cd superset-frontend; npm run prettier
|
||||
|
||||
flask-app:
|
||||
flask run -p 8088 --with-threads --reload --debugger
|
||||
flask run -p 8088 --reload --debugger
|
||||
|
||||
node-app:
|
||||
cd superset-frontend; npm run dev-server
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.10-slim-bookworm
|
||||
FROM python:3.10-slim-trixie
|
||||
|
||||
RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.10-slim-bookworm
|
||||
FROM python:3.10-slim-trixie
|
||||
|
||||
RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.10-slim-bookworm
|
||||
FROM python:3.10-slim-trixie
|
||||
ARG VERSION
|
||||
|
||||
RUN git clone --depth 1 --branch ${VERSION} https://github.com/apache/superset.git /superset
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.10-slim-bookworm
|
||||
FROM python:3.10-slim-trixie
|
||||
|
||||
RUN apt-get update -y
|
||||
RUN apt-get install -y \
|
||||
|
||||
@@ -469,6 +469,10 @@ an account first if you don't have one, and reference your username
|
||||
while requesting access to push packages.
|
||||
|
||||
```bash
|
||||
# Run this first to make sure you are uploading the right version.
|
||||
# Pypi does not allow you to delete or retract once uplaoded.
|
||||
twine check dist/*
|
||||
|
||||
twine upload dist/*
|
||||
```
|
||||
|
||||
@@ -518,6 +522,8 @@ takes the version (ie `3.1.1`), the git reference (any SHA, tag or branch
|
||||
reference), and whether to force the `latest` Docker tag on the
|
||||
generated images.
|
||||
|
||||
**NOTE:** If the docker image isn't built, you'll need to run this [GH action](https://github.com/apache/superset/actions/workflows/tag-release.yml) where you provide it the tag sha.
|
||||
|
||||
### Npm Release
|
||||
|
||||
You might want to publish the latest @superset-ui release to npm
|
||||
|
||||
@@ -23,6 +23,9 @@ This file documents any backwards-incompatible changes in Superset and
|
||||
assists people when migrating to a new version.
|
||||
|
||||
## Next
|
||||
- [33055](https://github.com/apache/superset/pull/33055): Upgrades Flask-AppBuilder to 5.0.0. The AUTH_OID authentication type has been deprecated and is no longer available as an option in Flask-AppBuilder. OpenID (OID) is considered a deprecated authentication protocol - if you are using AUTH_OID, you will need to migrate to an alternative authentication method such as OAuth, LDAP, or database authentication before upgrading.
|
||||
- [35062](https://github.com/apache/superset/pull/35062): Changed the function signature of `setupExtensions` to `setupCodeOverrides` with options as arguments.
|
||||
- [34871](https://github.com/apache/superset/pull/34871): Fixed Jest test hanging issue from Ant Design v5 upgrade. MessageChannel is now mocked in test environment to prevent rc-overflow from causing Jest to hang. Test environment only - no production impact.
|
||||
- [34782](https://github.com/apache/superset/pull/34782): Dataset exports now include the dataset ID in their file name (similar to charts and dashboards). If managing assets as code, make sure to rename existing dataset YAMLs to include the ID (and avoid duplicated files).
|
||||
- [34536](https://github.com/apache/superset/pull/34536): The `ENVIRONMENT_TAG_CONFIG` color values have changed to support only Ant Design semantic colors. Update your `superset_config.py`:
|
||||
- Change `"error.base"` to just `"error"` after this PR
|
||||
|
||||
@@ -28,6 +28,7 @@ x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset
|
||||
x-superset-volumes:
|
||||
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||
- ./docker:/app/docker
|
||||
- ./superset-core:/app/superset-core
|
||||
- superset_home:/app/superset_home
|
||||
|
||||
services:
|
||||
|
||||
@@ -71,7 +71,7 @@ x-common-build: &common-build
|
||||
context: .
|
||||
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
|
||||
cache_from:
|
||||
- apache/superset-cache:3.10-slim-bookworm
|
||||
- apache/superset-cache:3.10-slim-trixie
|
||||
args:
|
||||
DEV_MODE: "true"
|
||||
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
|
||||
@@ -118,6 +118,8 @@ services:
|
||||
POSTGRES_DB: superset_light
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: "duckdb:////app/data/examples.duckdb"
|
||||
SUPERSET_CONFIG_PATH: /app/docker/pythonpath_dev/superset_config_docker_light.py
|
||||
GITHUB_HEAD_REF: ${GITHUB_HEAD_REF:-}
|
||||
GITHUB_SHA: ${GITHUB_SHA:-}
|
||||
|
||||
superset-init-light:
|
||||
build:
|
||||
@@ -160,8 +162,11 @@ services:
|
||||
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
|
||||
# configuring the dev-server to use the host.docker.internal to connect to the backend
|
||||
superset: "http://superset-light:8088"
|
||||
# Webpack dev server configuration
|
||||
WEBPACK_DEVSERVER_HOST: "${WEBPACK_DEVSERVER_HOST:-127.0.0.1}"
|
||||
WEBPACK_DEVSERVER_PORT: "${WEBPACK_DEVSERVER_PORT:-9000}"
|
||||
ports:
|
||||
- "127.0.0.1:${NODE_PORT:-9001}:9000" # Parameterized port
|
||||
- "${NODE_PORT:-9001}:9000" # Parameterized port, accessible on all interfaces
|
||||
command: ["/app/docker/docker-frontend.sh"]
|
||||
env_file:
|
||||
- path: docker/.env # default
|
||||
|
||||
@@ -33,7 +33,7 @@ x-common-build: &common-build
|
||||
context: .
|
||||
target: dev
|
||||
cache_from:
|
||||
- apache/superset-cache:3.10-slim-bookworm
|
||||
- apache/superset-cache:3.10-slim-trixie
|
||||
|
||||
services:
|
||||
redis:
|
||||
|
||||
@@ -29,14 +29,16 @@ x-superset-volumes: &superset-volumes
|
||||
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||
- ./docker:/app/docker
|
||||
- ./superset:/app/superset
|
||||
- ./superset-core:/app/superset-core
|
||||
- ./superset-frontend:/app/superset-frontend
|
||||
- superset_home:/app/superset_home
|
||||
- ./tests:/app/tests
|
||||
- superset_data:/app/data
|
||||
x-common-build: &common-build
|
||||
context: .
|
||||
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
|
||||
cache_from:
|
||||
- apache/superset-cache:3.10-slim-bookworm
|
||||
- apache/superset-cache:3.10-slim-trixie
|
||||
args:
|
||||
DEV_MODE: "true"
|
||||
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
|
||||
@@ -274,3 +276,5 @@ volumes:
|
||||
external: false
|
||||
redis:
|
||||
external: false
|
||||
superset_data:
|
||||
external: false
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
# Ensure this script is run as root
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
if [[ ${EUID} -ne 0 ]]; then
|
||||
echo "This script must be run as root" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -42,7 +42,7 @@ echo -e "${GREEN}Installing packages: $@${RESET}"
|
||||
apt-get install -yqq --no-install-recommends "$@"
|
||||
|
||||
echo -e "${GREEN}Autoremoving unnecessary packages...${RESET}"
|
||||
apt-get autoremove -y
|
||||
apt-get autoremove -yqq --purge
|
||||
|
||||
echo -e "${GREEN}Cleaning up package cache and metadata...${RESET}"
|
||||
apt-get clean
|
||||
|
||||
@@ -21,8 +21,15 @@ set -eo pipefail
|
||||
# Make python interactive
|
||||
if [ "$DEV_MODE" == "true" ]; then
|
||||
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
|
||||
echo "Reinstalling the app in editable mode"
|
||||
uv pip install -e .
|
||||
# Always ensure superset-core is available
|
||||
echo "Installing superset-core in editable mode"
|
||||
uv pip install --no-deps -e /app/superset-core
|
||||
|
||||
# Only reinstall the main app for non-worker processes
|
||||
if [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||
echo "Reinstalling the app in editable mode"
|
||||
uv pip install -e .
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
||||
@@ -34,7 +41,8 @@ if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
|
||||
PORT=8081
|
||||
fi
|
||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ]; then
|
||||
# Skip postgres requirements installation for workers to avoid conflicts
|
||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ] && [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||
# older images may not have the postgres dev requirements installed
|
||||
echo "Installing postgres requirements"
|
||||
if command -v uv > /dev/null 2>&1; then
|
||||
@@ -72,7 +80,7 @@ case "${1}" in
|
||||
;;
|
||||
app)
|
||||
echo "Starting web app (using development server)..."
|
||||
flask run -p $PORT --with-threads --reload --debugger --host=0.0.0.0
|
||||
flask run -p $PORT --reload --debugger --without-threads --host=0.0.0.0
|
||||
;;
|
||||
app-gunicorn)
|
||||
echo "Starting web app..."
|
||||
|
||||
@@ -38,14 +38,14 @@ for arg in "$@"; do
|
||||
done
|
||||
|
||||
# Install build-essential if required
|
||||
if $REQUIRES_BUILD_ESSENTIAL; then
|
||||
if ${REQUIRES_BUILD_ESSENTIAL}; then
|
||||
echo "Installing build-essential for package builds..."
|
||||
apt-get update -qq \
|
||||
&& apt-get install -yqq --no-install-recommends build-essential
|
||||
fi
|
||||
|
||||
# Choose whether to use pip cache
|
||||
if $USE_CACHE; then
|
||||
if ${USE_CACHE}; then
|
||||
echo "Using pip cache..."
|
||||
uv pip install "${ARGS[@]}"
|
||||
else
|
||||
@@ -54,7 +54,7 @@ else
|
||||
fi
|
||||
|
||||
# Remove build-essential if it was installed
|
||||
if $REQUIRES_BUILD_ESSENTIAL; then
|
||||
if ${REQUIRES_BUILD_ESSENTIAL}; then
|
||||
echo "Removing build-essential to keep the image lean..."
|
||||
apt-get autoremove -yqq --purge build-essential \
|
||||
&& apt-get clean \
|
||||
|
||||
@@ -138,7 +138,7 @@ try:
|
||||
from superset_config_docker import * # noqa: F403
|
||||
|
||||
logger.info(
|
||||
f"Loaded your Docker configuration at [{superset_config_docker.__file__}]"
|
||||
"Loaded your Docker configuration at [%s]", superset_config_docker.__file__
|
||||
)
|
||||
except ImportError:
|
||||
logger.info("Using default Docker config...")
|
||||
|
||||
642
docs/DOCS_CLAUDE.md
Normal file
642
docs/DOCS_CLAUDE.md
Normal file
@@ -0,0 +1,642 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# LLM Context Guide for Apache Superset Documentation
|
||||
|
||||
This guide helps LLMs work with the Apache Superset documentation site built with Docusaurus 3.
|
||||
|
||||
## 📍 Current Directory Context
|
||||
|
||||
You are currently in the `/docs` subdirectory of the Apache Superset repository. When referencing files from the main codebase, use `../` to access the parent directory.
|
||||
|
||||
```
|
||||
/Users/evan_1/GitHub/superset/ # Main repository root
|
||||
├── superset/ # Python backend code
|
||||
├── superset-frontend/ # React/TypeScript frontend
|
||||
└── docs/ # Documentation site (YOU ARE HERE)
|
||||
├── docs/ # Main documentation content
|
||||
├── developer_portal/ # Developer guides (currently disabled)
|
||||
├── components/ # Component playground (currently disabled)
|
||||
└── docusaurus.config.ts # Site configuration
|
||||
```
|
||||
|
||||
## 🚀 Quick Commands
|
||||
|
||||
```bash
|
||||
# Development
|
||||
yarn start # Start dev server on http://localhost:3000
|
||||
yarn stop # Stop running dev server
|
||||
yarn build # Build production site
|
||||
yarn serve # Serve built site locally
|
||||
|
||||
# Version Management (USE THESE, NOT docusaurus commands)
|
||||
yarn version:add:docs <version> # Add new docs version
|
||||
yarn version:add:developer_portal <version> # Add developer portal version
|
||||
yarn version:add:components <version> # Add components version
|
||||
yarn version:remove:docs <version> # Remove docs version
|
||||
yarn version:remove:developer_portal <version> # Remove developer portal version
|
||||
yarn version:remove:components <version> # Remove components version
|
||||
|
||||
# Quality Checks
|
||||
yarn typecheck # TypeScript validation
|
||||
yarn eslint # Lint TypeScript/JavaScript files
|
||||
```
|
||||
|
||||
## 📁 Documentation Structure
|
||||
|
||||
### Main Documentation (`/docs`)
|
||||
The primary documentation lives in `/docs` with this structure:
|
||||
|
||||
```
|
||||
docs/
|
||||
├── intro.md # Auto-generated from ../README.md
|
||||
├── quickstart.mdx # Getting started guide
|
||||
├── api.mdx # API reference with Swagger UI
|
||||
├── faq.mdx # Frequently asked questions
|
||||
├── installation/ # Installation guides
|
||||
│ ├── installation-methods.mdx
|
||||
│ ├── docker-compose.mdx
|
||||
│ ├── docker-builds.mdx
|
||||
│ ├── kubernetes.mdx
|
||||
│ ├── pypi.mdx
|
||||
│ └── architecture.mdx
|
||||
├── configuration/ # Configuration guides
|
||||
│ ├── configuring-superset.mdx
|
||||
│ ├── alerts-reports.mdx
|
||||
│ ├── caching.mdx
|
||||
│ ├── databases.mdx
|
||||
│ └── [more config docs]
|
||||
├── using-superset/ # User guides
|
||||
│ ├── creating-your-first-dashboard.md
|
||||
│ ├── exploring-data.mdx
|
||||
│ └── [more user docs]
|
||||
├── contributing/ # Contributor guides
|
||||
│ ├── development.mdx
|
||||
│ ├── testing-locally.mdx
|
||||
│ └── [more contributor docs]
|
||||
└── security/ # Security documentation
|
||||
├── security.mdx
|
||||
└── [security guides]
|
||||
```
|
||||
|
||||
### Developer Portal (`/developer_portal`) - Currently Disabled
|
||||
When enabled, contains developer-focused content:
|
||||
- API documentation
|
||||
- Architecture guides
|
||||
- CLI tools
|
||||
- Code examples
|
||||
|
||||
### Component Playground (`/components`) - Currently Disabled
|
||||
When enabled, provides interactive component examples for UI development.
|
||||
|
||||
## 📝 Documentation Standards
|
||||
|
||||
### File Types
|
||||
- **`.md` files**: Basic Markdown documents
|
||||
- **`.mdx` files**: Markdown with JSX - can include React components
|
||||
- **`.tsx` files in `/src`**: Custom React components and pages
|
||||
|
||||
### Frontmatter Structure
|
||||
Every documentation page should have frontmatter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Page Title
|
||||
description: Brief description for SEO
|
||||
sidebar_position: 1 # Optional: controls order in sidebar
|
||||
---
|
||||
```
|
||||
|
||||
### MDX Component Usage
|
||||
MDX files can import and use React components:
|
||||
|
||||
```mdx
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="npm" label="npm" default>
|
||||
```bash
|
||||
npm install superset
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="yarn" label="yarn">
|
||||
```bash
|
||||
yarn add superset
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### Code Blocks
|
||||
Use triple backticks with language identifiers:
|
||||
|
||||
````markdown
|
||||
```python
|
||||
def hello_world():
|
||||
print("Hello, Superset!")
|
||||
```
|
||||
|
||||
```sql title="Example Query"
|
||||
SELECT * FROM users WHERE active = true;
|
||||
```
|
||||
|
||||
```bash
|
||||
# Installation command
|
||||
pip install apache-superset
|
||||
```
|
||||
````
|
||||
|
||||
### Admonitions
|
||||
Docusaurus supports various admonition types:
|
||||
|
||||
```markdown
|
||||
:::note
|
||||
This is a note
|
||||
:::
|
||||
|
||||
:::tip
|
||||
This is a tip
|
||||
:::
|
||||
|
||||
:::warning
|
||||
This is a warning
|
||||
:::
|
||||
|
||||
:::danger
|
||||
This is a danger warning
|
||||
:::
|
||||
|
||||
:::info
|
||||
This is an info box
|
||||
:::
|
||||
```
|
||||
|
||||
## 🔄 Version Management
|
||||
|
||||
### Version Configuration
|
||||
Versions are managed through `versions-config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"docs": {
|
||||
"disabled": false,
|
||||
"lastVersion": "6.0.0", // Default version shown
|
||||
"includeCurrentVersion": true, // Show "Next" version
|
||||
"onlyIncludeVersions": ["current", "6.0.0"],
|
||||
"versions": {
|
||||
"current": {
|
||||
"label": "Next",
|
||||
"path": "",
|
||||
"banner": "unreleased" // Shows warning banner
|
||||
},
|
||||
"6.0.0": {
|
||||
"label": "6.0.0",
|
||||
"path": "6.0.0",
|
||||
"banner": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Creating New Versions
|
||||
**IMPORTANT**: Always use the custom scripts, NOT native Docusaurus commands:
|
||||
|
||||
```bash
|
||||
# ✅ CORRECT - Updates both Docusaurus and versions-config.json
|
||||
yarn version:add:docs 6.1.0
|
||||
|
||||
# ❌ WRONG - Only updates Docusaurus, breaks version dropdown
|
||||
yarn docusaurus docs:version 6.1.0
|
||||
```
|
||||
|
||||
### Version Files Created
|
||||
When versioning, these files are created:
|
||||
- `versioned_docs/version-X.X.X/` - Snapshot of current docs
|
||||
- `versioned_sidebars/version-X.X.X-sidebars.json` - Sidebar config
|
||||
- `versions.json` - List of all versions
|
||||
|
||||
## 🎨 Styling and Theming
|
||||
|
||||
### Custom CSS
|
||||
Add custom styles in `/src/css/custom.css`:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--ifm-color-primary: #20a7c9;
|
||||
--ifm-code-font-size: 95%;
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Components
|
||||
Create React components in `/src/components/`:
|
||||
|
||||
```tsx
|
||||
// src/components/FeatureCard.tsx
|
||||
import React from 'react';
|
||||
|
||||
export default function FeatureCard({title, description}) {
|
||||
return (
|
||||
<div className="card">
|
||||
<h3>{title}</h3>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Use in MDX:
|
||||
|
||||
```mdx
|
||||
import FeatureCard from '@site/src/components/FeatureCard';
|
||||
|
||||
<FeatureCard
|
||||
title="Fast"
|
||||
description="Lightning fast queries"
|
||||
/>
|
||||
```
|
||||
|
||||
## 📦 Key Dependencies
|
||||
|
||||
- **Docusaurus 3.8.1**: Static site generator
|
||||
- **React 18.3**: UI framework
|
||||
- **Ant Design 5.26**: Component library
|
||||
- **@superset-ui/core**: Superset UI components
|
||||
- **Swagger UI React**: API documentation
|
||||
- **Prism**: Syntax highlighting
|
||||
|
||||
## 🔗 Linking Strategies
|
||||
|
||||
### Internal Links
|
||||
Use relative paths for internal documentation:
|
||||
|
||||
```markdown
|
||||
[Installation Guide](./installation/docker-compose)
|
||||
[Configuration](../configuration/configuring-superset)
|
||||
```
|
||||
|
||||
### External Links
|
||||
Always use full URLs:
|
||||
|
||||
```markdown
|
||||
[Apache Superset GitHub](https://github.com/apache/superset)
|
||||
```
|
||||
|
||||
### Linking to Code
|
||||
Reference code in the main repository:
|
||||
|
||||
```markdown
|
||||
See the [main configuration file](https://github.com/apache/superset/blob/master/superset/config.py)
|
||||
```
|
||||
|
||||
## 🛠️ Common Documentation Tasks
|
||||
|
||||
### Adding a New Guide
|
||||
1. Create the `.mdx` file in the appropriate directory
|
||||
2. Add frontmatter with title and description
|
||||
3. Update sidebar if needed (for manual sidebar configs)
|
||||
|
||||
### Adding API Documentation
|
||||
The API docs use Swagger UI embedded in `/docs/api.mdx`:
|
||||
|
||||
```mdx
|
||||
import SwaggerUI from "swagger-ui-react";
|
||||
import "swagger-ui-react/swagger-ui.css";
|
||||
|
||||
<SwaggerUI url="/api/v1/openapi.json" />
|
||||
```
|
||||
|
||||
### Adding Interactive Examples
|
||||
Use MDX to create interactive documentation:
|
||||
|
||||
```mdx
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import MyComponentExample from '!!raw-loader!../examples/MyComponent.tsx';
|
||||
|
||||
<CodeBlock language="tsx">{MyComponentExample}</CodeBlock>
|
||||
```
|
||||
|
||||
## 📋 Documentation Checklist
|
||||
|
||||
When creating or updating documentation:
|
||||
|
||||
- [ ] Clear, descriptive title in frontmatter
|
||||
- [ ] Description for SEO in frontmatter
|
||||
- [ ] Proper heading hierarchy (h1 -> h2 -> h3)
|
||||
- [ ] Code examples with language identifiers
|
||||
- [ ] Links verified (internal and external)
|
||||
- [ ] Images have alt text
|
||||
- [ ] Admonitions used for important notes
|
||||
- [ ] Tested locally with `yarn start`
|
||||
- [ ] No broken links (check with `yarn build`)
|
||||
|
||||
## 🔍 Searching and Navigation
|
||||
|
||||
### Sidebar Configuration
|
||||
Sidebars are configured in `/sidebars.js`:
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
CustomSidebar: [
|
||||
{
|
||||
type: 'doc',
|
||||
label: 'Introduction',
|
||||
id: 'intro',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Installation',
|
||||
items: [
|
||||
{
|
||||
type: 'autogenerated',
|
||||
dirName: 'installation',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### Search
|
||||
Docusaurus includes Algolia DocSearch integration configured in `docusaurus.config.ts`.
|
||||
|
||||
## 🚫 Common Pitfalls to Avoid
|
||||
|
||||
1. **Never use `yarn docusaurus docs:version`** - Use `yarn version:add:docs` instead
|
||||
2. **Don't edit versioned docs directly** - Edit current docs and create new version
|
||||
3. **Avoid absolute paths in links** - Use relative paths for maintainability
|
||||
4. **Don't forget frontmatter** - Every doc needs title and description
|
||||
5. **Test builds locally** - Run `yarn build` before committing
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Dev Server Issues
|
||||
```bash
|
||||
yarn stop # Kill any running servers
|
||||
yarn clear # Clear cache
|
||||
yarn start # Restart
|
||||
```
|
||||
|
||||
### Build Failures
|
||||
```bash
|
||||
# Check for broken links
|
||||
yarn build
|
||||
|
||||
# TypeScript issues
|
||||
yarn typecheck
|
||||
|
||||
# Linting issues
|
||||
yarn eslint
|
||||
```
|
||||
|
||||
### Version Issues
|
||||
If versions don't appear in dropdown:
|
||||
1. Check `versions-config.json` includes the version
|
||||
2. Verify version files exist in `versioned_docs/`
|
||||
3. Restart dev server
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
- [Docusaurus Documentation](https://docusaurus.io/docs)
|
||||
- [MDX Documentation](https://mdxjs.com/)
|
||||
- [Superset Contributing Guide](../CONTRIBUTING.md)
|
||||
- [Main Superset Documentation](https://superset.apache.org/docs/intro)
|
||||
|
||||
## 📖 Real Examples and Patterns
|
||||
|
||||
### Example: Configuration Documentation Pattern
|
||||
From `docs/configuration/configuring-superset.mdx`:
|
||||
|
||||
```mdx
|
||||
---
|
||||
title: Configuring Superset
|
||||
hide_title: true
|
||||
sidebar_position: 1
|
||||
version: 1
|
||||
---
|
||||
|
||||
# Configuring Superset
|
||||
|
||||
## superset_config.py
|
||||
|
||||
Superset exposes hundreds of configurable parameters through its
|
||||
[config.py module](https://github.com/apache/superset/blob/master/superset/config.py).
|
||||
|
||||
```bash
|
||||
export SUPERSET_CONFIG_PATH=/app/superset_config.py
|
||||
```
|
||||
```
|
||||
|
||||
**Key patterns:**
|
||||
- Links to source code for reference
|
||||
- Code blocks with bash/python examples
|
||||
- Environment variable documentation
|
||||
- Step-by-step configuration instructions
|
||||
|
||||
### Example: Tutorial Documentation Pattern
|
||||
From `docs/using-superset/creating-your-first-dashboard.mdx`:
|
||||
|
||||
```mdx
|
||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||
|
||||
## Creating Your First Dashboard
|
||||
|
||||
:::tip
|
||||
In addition to this site, [Preset.io](http://preset.io/) maintains an updated set of end-user
|
||||
documentation at [docs.preset.io](https://docs.preset.io/).
|
||||
:::
|
||||
|
||||
### Connecting to a new database
|
||||
|
||||
<img src={useBaseUrl("/img/tutorial/tutorial_01_add_database_connection.png")} width="600" />
|
||||
```
|
||||
|
||||
**Key patterns:**
|
||||
- Import Docusaurus hooks for dynamic URLs
|
||||
- Use of admonitions (:::tip) for helpful information
|
||||
- Screenshots with useBaseUrl for proper path resolution
|
||||
- Clear section hierarchy with ### subheadings
|
||||
- Step-by-step visual guides
|
||||
|
||||
### Example: API Documentation Pattern
|
||||
From `docs/api.mdx`:
|
||||
|
||||
```mdx
|
||||
import SwaggerUI from "swagger-ui-react";
|
||||
import "swagger-ui-react/swagger-ui.css";
|
||||
|
||||
## API Documentation
|
||||
|
||||
<SwaggerUI url="/api/v1/openapi.json" />
|
||||
```
|
||||
|
||||
**Key patterns:**
|
||||
- Embedding interactive Swagger UI
|
||||
- Importing necessary CSS
|
||||
- Direct API spec integration
|
||||
|
||||
### Common Image Patterns
|
||||
|
||||
```mdx
|
||||
// For images in static folder
|
||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||
|
||||
<img src={useBaseUrl("/img/feature-screenshot.png")} width="600" />
|
||||
|
||||
// With caption
|
||||
<figure>
|
||||
<img src={useBaseUrl("/img/dashboard.png")} alt="Dashboard view" />
|
||||
<figcaption>Superset Dashboard Interface</figcaption>
|
||||
</figure>
|
||||
```
|
||||
|
||||
### Multi-Tab Code Examples
|
||||
|
||||
```mdx
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<Tabs
|
||||
defaultValue="docker"
|
||||
values={[
|
||||
{label: 'Docker', value: 'docker'},
|
||||
{label: 'Kubernetes', value: 'k8s'},
|
||||
{label: 'PyPI', value: 'pypi'},
|
||||
]}>
|
||||
<TabItem value="docker">
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="k8s">
|
||||
```bash
|
||||
kubectl apply -f superset.yaml
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="pypi">
|
||||
```bash
|
||||
pip install apache-superset
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### Configuration File Examples
|
||||
|
||||
```mdx
|
||||
```python title="superset_config.py"
|
||||
# Database connection example
|
||||
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password@localhost/superset'
|
||||
|
||||
# Security configuration
|
||||
SECRET_KEY = 'YOUR_SECRET_KEY_HERE'
|
||||
WTF_CSRF_ENABLED = True
|
||||
|
||||
# Feature flags
|
||||
FEATURE_FLAGS = {
|
||||
'ENABLE_TEMPLATE_PROCESSING': True,
|
||||
'DASHBOARD_NATIVE_FILTERS': True,
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### Cross-Referencing Pattern
|
||||
|
||||
```mdx
|
||||
For detailed configuration options, see:
|
||||
- [Configuring Superset](./configuration/configuring-superset)
|
||||
- [Database Connections](./configuration/databases)
|
||||
- [Security Settings](./security/security)
|
||||
|
||||
External resources:
|
||||
- [SQLAlchemy Documentation](https://docs.sqlalchemy.org/)
|
||||
- [Flask Configuration](https://flask.palletsprojects.com/config/)
|
||||
```
|
||||
|
||||
### Writing Installation Guides
|
||||
|
||||
```mdx
|
||||
## Prerequisites
|
||||
|
||||
:::warning
|
||||
Ensure you have Python 3.9+ and Node.js 16+ installed before proceeding.
|
||||
:::
|
||||
|
||||
## Installation Steps
|
||||
|
||||
1. **Clone the repository**
|
||||
```bash
|
||||
git clone https://github.com/apache/superset.git
|
||||
cd superset
|
||||
```
|
||||
|
||||
2. **Install Python dependencies**
|
||||
```bash
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
3. **Initialize the database**
|
||||
```bash
|
||||
superset db upgrade
|
||||
superset init
|
||||
```
|
||||
|
||||
:::tip Success Check
|
||||
Navigate to http://localhost:8088 and login with admin/admin
|
||||
:::
|
||||
```
|
||||
|
||||
### Documenting API Endpoints
|
||||
|
||||
```mdx
|
||||
## Chart API
|
||||
|
||||
### GET /api/v1/chart/
|
||||
|
||||
Returns a list of charts.
|
||||
|
||||
**Parameters:**
|
||||
- `page` (optional): Page number
|
||||
- `page_size` (optional): Number of items per page
|
||||
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl -X GET "http://localhost:8088/api/v1/chart/" \
|
||||
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
||||
```
|
||||
|
||||
**Example Response:**
|
||||
```json
|
||||
{
|
||||
"count": 42,
|
||||
"result": [
|
||||
{
|
||||
"id": 1,
|
||||
"slice_name": "Sales Dashboard",
|
||||
"viz_type": "line"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Note**: This documentation site serves as the primary resource for Superset users, administrators, and contributors. Always prioritize clarity, accuracy, and completeness when creating or updating documentation.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,348 +1,194 @@
|
||||
---
|
||||
title: Architecture Overview
|
||||
title: Extension Architecture
|
||||
sidebar_position: 1
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Extension Architecture Overview
|
||||
# Superset Extension Architecture
|
||||
|
||||
The Superset extension architecture is designed to be modular, secure, and performant. This document provides a comprehensive overview of how extensions work and interact with the Superset host application.
|
||||
Apache Superset's extension architecture enables developers to enhance and customize the platform without modifying the core codebase. Inspired by the successful VS Code Extensions model, this architecture provides well-defined, versioned APIs and clear contribution points that allow the community to build upon and extend Superset's functionality.
|
||||
|
||||
## Core Principles
|
||||
## Core Concepts
|
||||
|
||||
### 1. Lean Core
|
||||
Superset's core remains minimal, with features delegated to extensions wherever possible. Built-in features use the same APIs as external extensions, ensuring API quality through dogfooding.
|
||||
### Extensions vs Plugins
|
||||
|
||||
### 2. Explicit Contribution Points
|
||||
All extension points are clearly defined and documented. Extensions declare their capabilities in metadata files, enabling predictable lifecycle management.
|
||||
We use the term "extensions" rather than "plugins" to better convey the idea of enhancing and expanding Superset's core capabilities in a modular and integrated way. Extensions can add new features, modify existing behavior, and integrate deeply with the host application through well-defined APIs.
|
||||
|
||||
### 3. Versioned APIs
|
||||
Public interfaces follow semantic versioning, ensuring backward compatibility and safe evolution of the platform.
|
||||
### Lean Core Philosophy
|
||||
|
||||
### 4. Lazy Loading
|
||||
Extensions load only when needed, minimizing performance impact and resource consumption.
|
||||
Superset's core remains minimal, with many features delegated to extensions. Built-in features are implemented using the same APIs available to external extension authors, ensuring consistency and validating the extension architecture through real-world usage.
|
||||
|
||||
### 5. Composability
|
||||
Architecture patterns and APIs are reusable across different Superset modules, promoting consistency.
|
||||
## Architecture Overview
|
||||
|
||||
### 6. Community-Driven
|
||||
The system evolves based on real-world feedback, with new extension points added as needs emerge.
|
||||
|
||||
## System Architecture
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Superset Host Application"
|
||||
Core[Core Application]
|
||||
API[Extension APIs]
|
||||
Loader[Extension Loader]
|
||||
Manager[Extension Manager]
|
||||
end
|
||||
|
||||
subgraph "Core Packages"
|
||||
FrontendCore["@apache-superset/core<br/>(Frontend)"]
|
||||
BackendCore["apache-superset-core<br/>(Backend)"]
|
||||
CLI["apache-superset-extensions-cli"]
|
||||
end
|
||||
|
||||
subgraph "Extension"
|
||||
Metadata[extension.json]
|
||||
Frontend[Frontend Code]
|
||||
Backend[Backend Code]
|
||||
Bundle[.supx Bundle]
|
||||
end
|
||||
|
||||
Core --> API
|
||||
API --> FrontendCore
|
||||
API --> BackendCore
|
||||
Loader --> Manager
|
||||
Manager --> Bundle
|
||||
Frontend --> FrontendCore
|
||||
Backend --> BackendCore
|
||||
CLI --> Bundle
|
||||
```
|
||||
|
||||
## Key Components
|
||||
|
||||
### Host Application
|
||||
|
||||
The Superset host application provides:
|
||||
|
||||
- **Extension APIs**: Well-defined interfaces for extensions to interact with Superset
|
||||
- **Extension Manager**: Handles lifecycle, activation, and deactivation
|
||||
- **Module Loader**: Dynamically loads extension code using Webpack Module Federation
|
||||
- **Security Context**: Manages permissions and sandboxing for extensions
|
||||
The extension architecture consists of several key components:
|
||||
|
||||
### Core Packages
|
||||
|
||||
#### @apache-superset/core (Frontend)
|
||||
- Shared UI components and utilities
|
||||
- TypeScript type definitions
|
||||
- Frontend API implementations
|
||||
- Event system and command registry
|
||||
Provides essential building blocks for extensions:
|
||||
- Shared UI components
|
||||
- Utility functions
|
||||
- Type definitions
|
||||
- Frontend APIs for interacting with the host
|
||||
|
||||
#### apache-superset-core (Backend)
|
||||
- Python base classes and utilities
|
||||
Exposes backend functionality:
|
||||
- Database access APIs
|
||||
- Security and permission helpers
|
||||
- REST API registration
|
||||
- Security models
|
||||
- REST API extensions
|
||||
- SQLAlchemy models and utilities
|
||||
|
||||
#### apache-superset-extensions-cli
|
||||
- Project scaffolding
|
||||
- Build and bundling tools
|
||||
- Development server
|
||||
- Package management
|
||||
### Extension CLI
|
||||
|
||||
### Extension Structure
|
||||
The `apache-superset-extensions-cli` package provides commands for:
|
||||
- Scaffolding new extension projects
|
||||
- Building and bundling extensions
|
||||
- Development workflows with hot-reload
|
||||
- Packaging extensions for distribution
|
||||
|
||||
Each extension consists of:
|
||||
### Host Application
|
||||
|
||||
- **Metadata** (`extension.json`): Declares capabilities and requirements
|
||||
- **Frontend**: React components and TypeScript code
|
||||
- **Backend**: Python modules and API endpoints
|
||||
- **Assets**: Styles, images, and other resources
|
||||
- **Bundle** (`.supx`): Packaged distribution format
|
||||
Superset acts as the host, providing:
|
||||
- Extension registration and management
|
||||
- Dynamic loading of extension assets
|
||||
- API implementation for extensions
|
||||
- Lifecycle management (activation/deactivation)
|
||||
|
||||
## Module Federation
|
||||
## Extension Points
|
||||
|
||||
Extensions use Webpack Module Federation for dynamic loading:
|
||||
Extensions can contribute to various parts of Superset:
|
||||
|
||||
```javascript
|
||||
// Extension webpack.config.js
|
||||
new ModuleFederationPlugin({
|
||||
name: 'my_extension',
|
||||
filename: 'remoteEntry.[contenthash].js',
|
||||
exposes: {
|
||||
'./index': './src/index.tsx',
|
||||
},
|
||||
externals: {
|
||||
'@apache-superset/core': 'superset',
|
||||
},
|
||||
shared: {
|
||||
react: { singleton: true },
|
||||
'react-dom': { singleton: true },
|
||||
}
|
||||
})
|
||||
```
|
||||
### SQL Lab Extensions
|
||||
- Custom panels (left, right, bottom)
|
||||
- Editor enhancements
|
||||
- Query processors
|
||||
- Autocomplete providers
|
||||
- Execution plan visualizers
|
||||
|
||||
This allows:
|
||||
- **Independent builds**: Extensions compile separately from Superset
|
||||
- **Shared dependencies**: Common libraries like React aren't duplicated
|
||||
- **Dynamic loading**: Extensions load at runtime without rebuilding Superset
|
||||
- **Version compatibility**: Extensions declare compatible core versions
|
||||
### Dashboard Extensions (Future)
|
||||
- Custom widget types
|
||||
- Filter components
|
||||
- Interaction handlers
|
||||
|
||||
## Extension Lifecycle
|
||||
### Chart Extensions (Future)
|
||||
- New visualization types
|
||||
- Data transformers
|
||||
- Export formats
|
||||
|
||||
## Technical Foundation
|
||||
|
||||
### Module Federation
|
||||
|
||||
Frontend extensions leverage Webpack Module Federation for dynamic loading:
|
||||
- Extensions are built independently
|
||||
- Dependencies are shared with the host
|
||||
- No rebuild of Superset required
|
||||
- Runtime loading of extension assets
|
||||
|
||||
### API Versioning
|
||||
|
||||
All public APIs follow semantic versioning:
|
||||
- Breaking changes require major version bumps
|
||||
- Extensions declare compatibility requirements
|
||||
- Backward compatibility maintained within major versions
|
||||
|
||||
### Security Model
|
||||
|
||||
- Extensions disabled by default (require `ENABLE_EXTENSIONS` flag)
|
||||
- Built-in extensions follow same security standards as core
|
||||
- External extensions run in same context as host (sandboxing planned)
|
||||
- Administrators responsible for vetting third-party extensions
|
||||
|
||||
## Development Workflow
|
||||
|
||||
1. **Initialize**: Use CLI to scaffold new extension
|
||||
2. **Develop**: Work with hot-reload in development mode
|
||||
3. **Build**: Bundle frontend and backend assets
|
||||
4. **Package**: Create `.supx` distribution file
|
||||
5. **Deploy**: Upload through API or management UI
|
||||
|
||||
## Example: Dataset References Extension
|
||||
|
||||
A practical example demonstrating the architecture:
|
||||
|
||||
### 1. Registration
|
||||
```typescript
|
||||
// Extension registered with host
|
||||
extensionManager.register({
|
||||
name: 'my-extension',
|
||||
version: '1.0.0',
|
||||
manifest: manifestData
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Activation
|
||||
```typescript
|
||||
// activate() called when extension loads
|
||||
export function activate(context: ExtensionContext) {
|
||||
// Register contributions
|
||||
const disposables = [];
|
||||
|
||||
// Add panel
|
||||
disposables.push(
|
||||
context.core.registerView('my-panel', MyPanel)
|
||||
// Frontend activation
|
||||
export function activate(context) {
|
||||
// Register a new SQL Lab panel
|
||||
const panel = core.registerView('dataset_references.main',
|
||||
<DatasetReferencesPanel />
|
||||
);
|
||||
|
||||
// Register command
|
||||
disposables.push(
|
||||
context.commands.registerCommand('my-command', {
|
||||
execute: () => { /* ... */ }
|
||||
})
|
||||
);
|
||||
// Listen to query changes
|
||||
const listener = sqlLab.onDidQueryRun(editor => {
|
||||
// Analyze query and update panel
|
||||
});
|
||||
|
||||
// Store for cleanup
|
||||
context.subscriptions.push(...disposables);
|
||||
// Cleanup on deactivation
|
||||
context.subscriptions.push(panel, listener);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Runtime
|
||||
- Extension responds to events
|
||||
- Provides UI components when requested
|
||||
- Executes commands when triggered
|
||||
- Accesses APIs as needed
|
||||
|
||||
### 4. Deactivation
|
||||
```typescript
|
||||
// Automatic cleanup of registered items
|
||||
export function deactivate() {
|
||||
// context.subscriptions automatically disposed
|
||||
// Additional cleanup if needed
|
||||
}
|
||||
```
|
||||
|
||||
## Contribution Types
|
||||
|
||||
### Views
|
||||
Extensions can add panels and UI components:
|
||||
|
||||
```json
|
||||
{
|
||||
"views": {
|
||||
"sqllab.panels": [{
|
||||
"id": "my-panel",
|
||||
"name": "My Panel",
|
||||
"icon": "ToolOutlined"
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Commands
|
||||
Define executable actions:
|
||||
|
||||
```json
|
||||
{
|
||||
"commands": [{
|
||||
"command": "my-extension.run",
|
||||
"title": "Run Analysis",
|
||||
"icon": "PlayCircleOutlined"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Menus
|
||||
Add items to existing menus:
|
||||
|
||||
```json
|
||||
{
|
||||
"menus": {
|
||||
"sqllab.editor": {
|
||||
"primary": [{
|
||||
"command": "my-extension.run",
|
||||
"when": "editorHasSelection"
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
Register backend REST endpoints:
|
||||
|
||||
```python
|
||||
# Backend API extension
|
||||
from superset_core.api import rest_api
|
||||
from .api import DatasetReferencesAPI
|
||||
|
||||
@rest_api.route('/my-endpoint')
|
||||
def my_endpoint():
|
||||
return {'data': 'value'}
|
||||
# Register custom REST endpoints
|
||||
rest_api.add_extension_api(DatasetReferencesAPI)
|
||||
```
|
||||
|
||||
## Security Model
|
||||
|
||||
### Permissions
|
||||
- Extensions run with user's permissions
|
||||
- No elevation of privileges
|
||||
- Access controlled by Superset's RBAC
|
||||
|
||||
### Sandboxing
|
||||
- Frontend code runs in browser context
|
||||
- Backend code runs in Python process
|
||||
- Future: Optional sandboxed execution
|
||||
|
||||
### Validation
|
||||
- Manifest validation on upload
|
||||
- Signature verification (future)
|
||||
- Dependency scanning
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Lazy Loading
|
||||
- Extensions load only when features are accessed
|
||||
- Code splitting for large extensions
|
||||
- Cached after first load
|
||||
|
||||
### Bundle Optimization
|
||||
- Tree shaking removes unused code
|
||||
- Minification reduces size
|
||||
- Compression for network transfer
|
||||
|
||||
### Resource Management
|
||||
- Automatic cleanup on deactivation
|
||||
- Memory leak prevention
|
||||
- Event listener management
|
||||
|
||||
## Development vs Production
|
||||
|
||||
### Development Mode
|
||||
```python
|
||||
# superset_config.py
|
||||
ENABLE_EXTENSIONS = True
|
||||
LOCAL_EXTENSIONS = ['/path/to/extension']
|
||||
```
|
||||
- Hot reloading
|
||||
- Source maps
|
||||
- Debug logging
|
||||
|
||||
### Production Mode
|
||||
- Optimized bundles
|
||||
- Cached assets
|
||||
- Performance monitoring
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Planned Features
|
||||
- Enhanced sandboxing
|
||||
- Extension marketplace
|
||||
- Inter-extension communication
|
||||
- Theme contributions
|
||||
- Chart type extensions
|
||||
|
||||
### API Expansion
|
||||
- Dashboard extensions
|
||||
- Database connector API
|
||||
- Security provider interface
|
||||
- Workflow automation
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do's
|
||||
- ✅ Use TypeScript for type safety
|
||||
- ✅ Follow semantic versioning
|
||||
- ✅ Handle errors gracefully
|
||||
- ✅ Clean up resources properly
|
||||
- ✅ Document your extension
|
||||
### Extension Design
|
||||
- Keep extensions focused on specific functionality
|
||||
- Use versioned APIs for stability
|
||||
- Handle cleanup properly on deactivation
|
||||
- Follow Superset's coding standards
|
||||
|
||||
### Don'ts
|
||||
- ❌ Access private APIs
|
||||
- ❌ Modify global state directly
|
||||
- ❌ Block the main thread
|
||||
- ❌ Store sensitive data insecurely
|
||||
- ❌ Assume API stability in 0.x versions
|
||||
### Performance
|
||||
- Lazy load assets when possible
|
||||
- Minimize bundle sizes
|
||||
- Share dependencies with host
|
||||
- Cache expensive operations
|
||||
|
||||
## Learn More
|
||||
### Compatibility
|
||||
- Declare API version requirements
|
||||
- Test across Superset versions
|
||||
- Provide migration guides for breaking changes
|
||||
- Document compatibility clearly
|
||||
|
||||
- [API Reference](../api/frontend)
|
||||
- [Development Guide](../getting-started)
|
||||
- [Security Guidelines](./security)
|
||||
- [Performance Optimization](./performance)
|
||||
## Future Roadmap
|
||||
|
||||
Planned enhancements include:
|
||||
- JavaScript sandboxing for untrusted extensions
|
||||
- Extension marketplace and registry
|
||||
- Inter-extension communication
|
||||
- Advanced theming capabilities
|
||||
- Backend hot-reload without restart
|
||||
|
||||
## Getting Started
|
||||
|
||||
Ready to build your first extension? Check out:
|
||||
- [Extension Project Structure](/developer_portal/extensions/extension-project-structure)
|
||||
- [API Reference](/developer_portal/api/frontend)
|
||||
- [CLI Documentation](/developer_portal/cli/overview)
|
||||
- [Frontend Contribution Types](/developer_portal/extensions/frontend-contribution-types)
|
||||
|
||||
55
docs/developer_portal/capabilities/common-capabilities.md
Normal file
55
docs/developer_portal/capabilities/common-capabilities.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: Common Plugin Capabilities
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Common Plugin Capabilities
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Explore the shared functionality and common patterns available to all Superset plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Plugin lifecycle hooks (initialization, activation, deactivation)
|
||||
- Accessing Superset's core services and APIs
|
||||
- State management and data persistence
|
||||
- Event handling and plugin communication
|
||||
- Internationalization (i18n) support
|
||||
- Error handling and logging
|
||||
- Plugin configuration management
|
||||
- Accessing user context and permissions
|
||||
- Working with datasets and queries
|
||||
- Plugin metadata and manifests
|
||||
|
||||
## Core Services Available
|
||||
|
||||
- **API Client** - HTTP client for backend communication
|
||||
- **State Store** - Redux store access
|
||||
- **Theme Provider** - Access to current theme settings
|
||||
- **User Context** - Current user information and permissions
|
||||
- **Dataset Service** - Working with data sources
|
||||
- **Chart Service** - Chart rendering utilities
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
62
docs/developer_portal/capabilities/extending-workbench.md
Normal file
62
docs/developer_portal/capabilities/extending-workbench.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: Extending the Workbench
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Extending the Workbench
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Discover how to extend Superset's main interface and workbench with custom components and functionality.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Adding custom menu items and navigation
|
||||
- Creating custom dashboard components
|
||||
- Extending the SQL Lab interface
|
||||
- Adding custom sidebar panels
|
||||
- Creating floating panels and modals
|
||||
- Integrating with the command palette
|
||||
- Custom toolbar buttons and actions
|
||||
- Workspace state management
|
||||
- Plugin-specific keyboard shortcuts
|
||||
- Context menu extensions
|
||||
|
||||
## Extension Points
|
||||
|
||||
- **Main navigation** - Top-level menu items
|
||||
- **Dashboard builder** - Custom components and layouts
|
||||
- **SQL Lab** - Query editor extensions
|
||||
- **Chart explorer** - Visualization building tools
|
||||
- **Settings panels** - Configuration interfaces
|
||||
- **Data source explorer** - Database navigation
|
||||
|
||||
## UI Integration Patterns
|
||||
|
||||
- React component composition
|
||||
- Portal-based rendering
|
||||
- Event-driven UI updates
|
||||
- Responsive layout adaptation
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
53
docs/developer_portal/capabilities/overview.md
Normal file
53
docs/developer_portal/capabilities/overview.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: Plugin Capabilities Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Plugin Capabilities Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
This section provides a comprehensive overview of what Superset plugins can do and how they integrate with the core platform.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Plugin architecture and lifecycle
|
||||
- Available extension points
|
||||
- Core APIs and services
|
||||
- Plugin communication patterns
|
||||
- Configuration and settings management
|
||||
- Plugin permissions and security
|
||||
- Performance considerations
|
||||
- Best practices for plugin development
|
||||
|
||||
## Plugin Types
|
||||
|
||||
Superset supports several types of plugins:
|
||||
- **Visualization plugins** - Custom chart types and data visualizations
|
||||
- **Database connectors** - New data source integrations
|
||||
- **UI extensions** - Custom dashboard components and interfaces
|
||||
- **Theme plugins** - Custom styling and branding
|
||||
- **Filter plugins** - Custom filter components
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
61
docs/developer_portal/capabilities/theming.md
Normal file
61
docs/developer_portal/capabilities/theming.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Theming and Styling
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Theming and Styling
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Learn how to create custom themes and style your plugins to match Superset's design system.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Understanding Superset's theme architecture
|
||||
- Using the theme provider in plugins
|
||||
- Creating custom color palettes
|
||||
- Responsive design considerations
|
||||
- Dark mode and light mode support
|
||||
- Customizing chart colors and styling
|
||||
- Brand customization and white-labeling
|
||||
- CSS-in-JS best practices
|
||||
- Working with Ant Design components
|
||||
- Accessibility in custom themes
|
||||
|
||||
## Theme Structure
|
||||
|
||||
- **Color tokens** - Primary, secondary, and semantic colors
|
||||
- **Typography** - Font families, sizes, and weights
|
||||
- **Spacing** - Grid system and layout tokens
|
||||
- **Component styles** - Default component appearances
|
||||
- **Chart themes** - Color schemes for visualizations
|
||||
|
||||
## Supported Theming APIs
|
||||
|
||||
- Theme provider context
|
||||
- CSS custom properties
|
||||
- Emotion/styled-components integration
|
||||
- Chart color palette API
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
@@ -1,466 +1,578 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
---
|
||||
title: CLI Documentation
|
||||
title: Extension CLI
|
||||
sidebar_position: 1
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Superset Extensions CLI
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
The `apache-superset-extensions-cli` provides command-line tools for creating, developing, and packaging Superset extensions.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Superset Extension CLI
|
||||
|
||||
The `apache-superset-extensions-cli` package provides command-line tools for creating, developing, and packaging Apache Superset extensions. It streamlines the entire extension development workflow from initialization to deployment.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the CLI globally using pip:
|
||||
|
||||
```bash
|
||||
pip install apache-superset-extensions-cli
|
||||
```
|
||||
|
||||
## Commands
|
||||
Or install locally in your project:
|
||||
|
||||
```bash
|
||||
pip install --user apache-superset-extensions-cli
|
||||
```
|
||||
|
||||
Verify installation:
|
||||
|
||||
```bash
|
||||
superset-extensions --version
|
||||
# Output: apache-superset-extensions-cli version 1.0.0
|
||||
```
|
||||
|
||||
## Commands Overview
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `init` | Create a new extension project |
|
||||
| `dev` | Start development mode with hot reload |
|
||||
| `build` | Build extension assets for production |
|
||||
| `bundle` | Package extension into a .supx file |
|
||||
| `validate` | Validate extension metadata and structure |
|
||||
| `publish` | Publish extension to registry (future) |
|
||||
|
||||
## Command Reference
|
||||
|
||||
### init
|
||||
|
||||
Creates a new extension project with the standard folder structure.
|
||||
Creates a new extension project with the standard structure and boilerplate code.
|
||||
|
||||
```bash
|
||||
superset-extensions init <extension-name> [options]
|
||||
superset-extensions init [options] <extension-name>
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--template <template>`: Use a specific template (default: basic)
|
||||
- `--author <name>`: Set the author name
|
||||
- `--description <text>`: Set the extension description
|
||||
- `--with-backend`: Include backend code structure
|
||||
#### Options
|
||||
|
||||
- `--type, -t <type>` - Extension type: `full` (default), `frontend-only`, `backend-only`
|
||||
- `--template <template>` - Project template: `default`, `sql-lab`, `dashboard`, `chart`
|
||||
- `--author <name>` - Extension author name
|
||||
- `--description <desc>` - Extension description
|
||||
- `--license <license>` - License identifier (default: Apache-2.0)
|
||||
- `--superset-version <version>` - Minimum Superset version (default: 4.0.0)
|
||||
- `--skip-install` - Skip installing dependencies
|
||||
- `--use-typescript` - Use TypeScript for frontend (default: true)
|
||||
- `--use-npm` - Use npm instead of yarn
|
||||
|
||||
#### Examples
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
superset-extensions init my-extension \
|
||||
--author "John Doe" \
|
||||
--description "Adds custom analytics to SQL Lab" \
|
||||
--with-backend
|
||||
# Create a basic extension
|
||||
superset-extensions init my-extension
|
||||
|
||||
# Create a SQL Lab focused extension
|
||||
superset-extensions init query-optimizer --template sql-lab
|
||||
|
||||
# Create frontend-only extension
|
||||
superset-extensions init custom-viz --type frontend-only
|
||||
|
||||
# Create with metadata
|
||||
superset-extensions init data-quality \
|
||||
--author "Jane Doe" \
|
||||
--description "Data quality monitoring for SQL Lab"
|
||||
```
|
||||
|
||||
**Generated Structure:**
|
||||
#### Generated Structure
|
||||
|
||||
```
|
||||
my-extension/
|
||||
├── extension.json
|
||||
├── frontend/
|
||||
├── extension.json # Extension metadata
|
||||
├── frontend/ # Frontend source code
|
||||
│ ├── src/
|
||||
│ │ └── index.tsx
|
||||
│ │ ├── index.tsx # Main entry point
|
||||
│ │ └── components/ # React components
|
||||
│ ├── package.json
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── backend/
|
||||
├── backend/ # Backend source code
|
||||
│ ├── src/
|
||||
│ │ └── my_extension/
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── entrypoint.py
|
||||
│ │ └── api.py
|
||||
│ ├── tests/
|
||||
│ ├── pyproject.toml
|
||||
│ └── requirements.txt
|
||||
└── README.md
|
||||
├── README.md
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
### dev
|
||||
|
||||
Starts the development server with hot reloading.
|
||||
Starts development mode with automatic rebuilding and hot reload.
|
||||
|
||||
```bash
|
||||
superset-extensions dev [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--port <port>`: Development server port (default: 9001)
|
||||
- `--host <host>`: Development server host (default: localhost)
|
||||
- `--no-watch`: Disable file watching
|
||||
- `--verbose`: Show detailed output
|
||||
#### Options
|
||||
|
||||
- `--port, -p <port>` - Development server port (default: 9001)
|
||||
- `--host <host>` - Development server host (default: localhost)
|
||||
- `--watch-backend` - Also watch backend files (default: true)
|
||||
- `--watch-frontend` - Also watch frontend files (default: true)
|
||||
- `--no-open` - Don't open browser automatically
|
||||
- `--superset-url <url>` - Superset instance URL (default: http://localhost:8088)
|
||||
- `--verbose` - Enable verbose logging
|
||||
|
||||
#### Examples
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Start development server
|
||||
# Start development mode
|
||||
superset-extensions dev
|
||||
|
||||
# Output:
|
||||
⚙️ Building frontend assets...
|
||||
✅ Frontend rebuilt
|
||||
✅ Backend files synced
|
||||
✅ Manifest updated
|
||||
👀 Watching for changes...
|
||||
# Use custom port
|
||||
superset-extensions dev --port 9002
|
||||
|
||||
# Connect to remote Superset
|
||||
superset-extensions dev --superset-url https://superset.example.com
|
||||
```
|
||||
|
||||
#### Development Workflow
|
||||
|
||||
1. **Start the dev server:**
|
||||
```bash
|
||||
superset-extensions dev
|
||||
```
|
||||
|
||||
2. **Configure Superset** (`superset_config.py`):
|
||||
```python
|
||||
LOCAL_EXTENSIONS = [
|
||||
"/path/to/your/extension"
|
||||
]
|
||||
ENABLE_EXTENSIONS = True
|
||||
```
|
||||
|
||||
3. **Start Superset:**
|
||||
```bash
|
||||
superset run -p 8088 --with-threads --reload
|
||||
```
|
||||
|
||||
The extension will automatically reload when you make changes.
|
||||
|
||||
### build
|
||||
|
||||
Builds the extension for production.
|
||||
Builds extension assets for production deployment.
|
||||
|
||||
```bash
|
||||
superset-extensions build [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--mode <mode>`: Build mode (development | production)
|
||||
- `--analyze`: Generate bundle analysis
|
||||
- `--source-maps`: Include source maps
|
||||
#### Options
|
||||
|
||||
- `--mode <mode>` - Build mode: `production` (default), `development`
|
||||
- `--analyze` - Generate bundle analysis report
|
||||
- `--source-maps` - Generate source maps
|
||||
- `--minify` - Minify output (default: true in production)
|
||||
- `--output, -o <dir>` - Output directory (default: dist)
|
||||
- `--clean` - Clean output directory before build
|
||||
- `--parallel` - Build frontend and backend in parallel
|
||||
|
||||
#### Examples
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Production build
|
||||
superset-extensions build --mode production
|
||||
superset-extensions build
|
||||
|
||||
# With analysis
|
||||
# Development build with source maps
|
||||
superset-extensions build --mode development --source-maps
|
||||
|
||||
# Analyze bundle size
|
||||
superset-extensions build --analyze
|
||||
|
||||
# Custom output directory
|
||||
superset-extensions build --output build
|
||||
```
|
||||
|
||||
#### Build Output
|
||||
|
||||
```
|
||||
dist/
|
||||
├── manifest.json # Build manifest
|
||||
├── frontend/
|
||||
│ ├── remoteEntry.[hash].js
|
||||
│ ├── [name].[hash].js
|
||||
│ └── assets/
|
||||
└── backend/
|
||||
└── my_extension/
|
||||
├── __init__.py
|
||||
└── *.py
|
||||
```
|
||||
|
||||
### bundle
|
||||
|
||||
Creates a `.supx` package for distribution.
|
||||
Packages the built extension into a distributable `.supx` file.
|
||||
|
||||
```bash
|
||||
superset-extensions bundle [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--output <path>`: Output directory (default: current)
|
||||
- `--sign`: Sign the package (requires certificate)
|
||||
- `--compress`: Compression level (0-9, default: 6)
|
||||
#### Options
|
||||
|
||||
- `--output, -o <file>` - Output filename (default: `{name}-{version}.supx`)
|
||||
- `--sign` - Sign the bundle (requires configured keys)
|
||||
- `--compression <level>` - Compression level 0-9 (default: 6)
|
||||
- `--exclude <patterns>` - Files to exclude (comma-separated)
|
||||
- `--include-dev-deps` - Include development dependencies
|
||||
|
||||
#### Examples
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Create bundle
|
||||
superset-extensions bundle
|
||||
|
||||
# Creates: my-extension-1.0.0.supx
|
||||
# Custom output name
|
||||
superset-extensions bundle --output my-extension-latest.supx
|
||||
|
||||
# Signed bundle
|
||||
superset-extensions bundle --sign
|
||||
|
||||
# Exclude test files
|
||||
superset-extensions bundle --exclude "**/*.test.js,**/*.spec.ts"
|
||||
```
|
||||
|
||||
#### Bundle Structure
|
||||
|
||||
The `.supx` file is a ZIP archive containing:
|
||||
|
||||
```
|
||||
my-extension-1.0.0.supx
|
||||
├── manifest.json
|
||||
├── extension.json
|
||||
├── frontend/
|
||||
│ └── dist/
|
||||
└── backend/
|
||||
└── src/
|
||||
```
|
||||
|
||||
### validate
|
||||
|
||||
Validates extension configuration and structure.
|
||||
Validates extension structure, metadata, and compatibility.
|
||||
|
||||
```bash
|
||||
superset-extensions validate [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--fix`: Auto-fix common issues
|
||||
- `--strict`: Enable strict validation
|
||||
#### Options
|
||||
|
||||
**Checks:**
|
||||
- Valid extension.json syntax
|
||||
- Required files present
|
||||
- Dependency versions
|
||||
- Module exports
|
||||
- TypeScript configuration
|
||||
- `--strict` - Enable strict validation
|
||||
- `--fix` - Auto-fix correctable issues
|
||||
- `--check-deps` - Validate dependencies
|
||||
- `--check-security` - Run security checks
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
superset-extensions validate --strict
|
||||
|
||||
# Output:
|
||||
✅ extension.json valid
|
||||
✅ Frontend structure valid
|
||||
✅ Backend structure valid
|
||||
⚠️ Warning: Missing LICENSE file
|
||||
✅ Validation passed with warnings
|
||||
```
|
||||
|
||||
### test
|
||||
|
||||
Runs extension tests.
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
superset-extensions test [options]
|
||||
# Basic validation
|
||||
superset-extensions validate
|
||||
|
||||
# Strict mode with auto-fix
|
||||
superset-extensions validate --strict --fix
|
||||
|
||||
# Full validation
|
||||
superset-extensions validate --check-deps --check-security
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--coverage`: Generate coverage report
|
||||
- `--watch`: Run in watch mode
|
||||
- `--frontend-only`: Run only frontend tests
|
||||
- `--backend-only`: Run only backend tests
|
||||
#### Validation Checks
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
# Run all tests
|
||||
superset-extensions test --coverage
|
||||
- Extension metadata completeness
|
||||
- File structure conformity
|
||||
- API version compatibility
|
||||
- Dependency security vulnerabilities
|
||||
- Code quality standards
|
||||
- Bundle size limits
|
||||
|
||||
# Watch mode for frontend
|
||||
superset-extensions test --frontend-only --watch
|
||||
```
|
||||
## Configuration File
|
||||
|
||||
### publish
|
||||
|
||||
Publishes extension to a registry (future feature).
|
||||
|
||||
```bash
|
||||
superset-extensions publish [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--registry <url>`: Registry URL
|
||||
- `--token <token>`: Authentication token
|
||||
- `--dry-run`: Simulate publish
|
||||
|
||||
## Configuration
|
||||
|
||||
### Project Configuration
|
||||
|
||||
The CLI reads configuration from multiple sources:
|
||||
|
||||
1. **extension.json** - Extension metadata
|
||||
2. **package.json** - Frontend dependencies
|
||||
3. **pyproject.toml** - Backend configuration
|
||||
4. **.extensionrc** - CLI-specific settings
|
||||
|
||||
### .extensionrc Example
|
||||
Create `.superset-extension.json` for project-specific settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"mode": "production",
|
||||
"sourceMaps": true,
|
||||
"analyze": false,
|
||||
"parallel": true
|
||||
},
|
||||
"dev": {
|
||||
"port": 9001,
|
||||
"host": "localhost",
|
||||
"autoReload": true
|
||||
"autoOpen": true
|
||||
},
|
||||
"build": {
|
||||
"mode": "production",
|
||||
"sourceMaps": false,
|
||||
"optimization": true
|
||||
"bundle": {
|
||||
"compression": 6,
|
||||
"sign": false,
|
||||
"exclude": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*",
|
||||
"**/tests/**"
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"coverage": true,
|
||||
"threshold": {
|
||||
"statements": 80,
|
||||
"branches": 70,
|
||||
"functions": 80,
|
||||
"lines": 80
|
||||
}
|
||||
"validation": {
|
||||
"strict": true,
|
||||
"autoFix": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
### Available Templates
|
||||
|
||||
- **basic**: Simple extension with frontend only
|
||||
- **full-stack**: Frontend and backend components
|
||||
- **sql-panel**: SQL Lab panel extension
|
||||
- **api-only**: Backend API extension
|
||||
- **chart-plugin**: Custom chart visualization
|
||||
|
||||
### Using Templates
|
||||
|
||||
```bash
|
||||
# Use specific template
|
||||
superset-extensions init my-chart --template chart-plugin
|
||||
|
||||
# List available templates
|
||||
superset-extensions init --list-templates
|
||||
```
|
||||
|
||||
### Custom Templates
|
||||
|
||||
Create custom templates in `~/.superset-extensions/templates/`:
|
||||
|
||||
```
|
||||
~/.superset-extensions/templates/
|
||||
└── my-template/
|
||||
├── template.json
|
||||
└── files/
|
||||
└── ... template files ...
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### 1. Create Extension
|
||||
|
||||
```bash
|
||||
superset-extensions init awesome-feature
|
||||
cd awesome-feature
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
```bash
|
||||
# Frontend
|
||||
cd frontend && npm install
|
||||
|
||||
# Backend (if applicable)
|
||||
cd ../backend && pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 3. Configure Superset
|
||||
|
||||
```python
|
||||
# superset_config.py
|
||||
ENABLE_EXTENSIONS = True
|
||||
LOCAL_EXTENSIONS = [
|
||||
"/path/to/awesome-feature"
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Start Development
|
||||
|
||||
```bash
|
||||
# Terminal 1: Extension dev server
|
||||
superset-extensions dev
|
||||
|
||||
# Terminal 2: Superset
|
||||
superset run -p 8088 --reload
|
||||
```
|
||||
|
||||
### 5. Test Changes
|
||||
|
||||
Make changes to your code and see them reflected immediately in Superset.
|
||||
|
||||
### 6. Build and Package
|
||||
|
||||
```bash
|
||||
# Validate
|
||||
superset-extensions validate
|
||||
|
||||
# Test
|
||||
superset-extensions test
|
||||
|
||||
# Build
|
||||
superset-extensions build --mode production
|
||||
|
||||
# Bundle
|
||||
superset-extensions bundle
|
||||
```
|
||||
|
||||
### 7. Deploy
|
||||
|
||||
Upload the `.supx` file to your Superset instance.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The CLI respects these environment variables:
|
||||
|
||||
- `SUPERSET_EXTENSIONS_DEV_PORT`: Development server port
|
||||
- `SUPERSET_EXTENSIONS_DEV_HOST`: Development server host
|
||||
- `SUPERSET_BASE_URL`: Superset instance URL
|
||||
- `NODE_ENV`: Node environment (development/production)
|
||||
- `PYTHONPATH`: Python module search path
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Port Already in Use
|
||||
Configure CLI behavior using environment variables:
|
||||
|
||||
```bash
|
||||
# Use different port
|
||||
superset-extensions dev --port 9002
|
||||
# Superset connection
|
||||
export SUPERSET_URL=http://localhost:8088
|
||||
export SUPERSET_USERNAME=admin
|
||||
export SUPERSET_PASSWORD=admin
|
||||
|
||||
# Development settings
|
||||
export EXTENSION_DEV_PORT=9001
|
||||
export EXTENSION_DEV_HOST=localhost
|
||||
|
||||
# Build settings
|
||||
export EXTENSION_BUILD_MODE=production
|
||||
export EXTENSION_SOURCE_MAPS=true
|
||||
|
||||
# Registry settings (future)
|
||||
export EXTENSION_REGISTRY_URL=https://registry.superset.apache.org
|
||||
export EXTENSION_REGISTRY_TOKEN=your-token
|
||||
```
|
||||
|
||||
#### Module Federation Errors
|
||||
|
||||
```bash
|
||||
# Rebuild with clean cache
|
||||
rm -rf dist/ node_modules/.cache
|
||||
superset-extensions build
|
||||
```
|
||||
|
||||
#### Python Import Errors
|
||||
|
||||
```bash
|
||||
# Ensure virtual environment is activated
|
||||
source venv/bin/activate
|
||||
superset-extensions dev
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable verbose output for troubleshooting:
|
||||
|
||||
```bash
|
||||
# Verbose output
|
||||
superset-extensions dev --verbose
|
||||
|
||||
# Debug webpack
|
||||
DEBUG=webpack:* superset-extensions build
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Version Control**: Commit `extension.json` but not `dist/`
|
||||
2. **Dependencies**: Pin versions in package.json
|
||||
3. **Testing**: Write tests for critical functionality
|
||||
4. **Documentation**: Keep README.md updated
|
||||
5. **Validation**: Run validate before bundling
|
||||
6. **Semantic Versioning**: Follow semver for releases
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Webpack Configuration
|
||||
### Custom Templates
|
||||
|
||||
Extend the default webpack config:
|
||||
Create custom project templates:
|
||||
|
||||
```javascript
|
||||
// webpack.config.js
|
||||
const baseConfig = require('./webpack.base.config');
|
||||
```bash
|
||||
# Use custom template
|
||||
superset-extensions init my-ext --template https://github.com/user/template
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
// Custom modifications
|
||||
resolve: {
|
||||
...baseConfig.resolve,
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
};
|
||||
# Use local template
|
||||
superset-extensions init my-ext --template ./my-template
|
||||
```
|
||||
|
||||
### CI/CD Integration
|
||||
|
||||
#### GitHub Actions
|
||||
|
||||
```yaml
|
||||
# .github/workflows/extension.yml
|
||||
name: Extension CI
|
||||
name: Build Extension
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-python@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install CLI
|
||||
run: pip install apache-superset-extensions-cli
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm install --prefix frontend
|
||||
pip install -r backend/requirements.txt
|
||||
|
||||
- name: Validate
|
||||
run: superset-extensions validate --strict
|
||||
|
||||
- name: Test
|
||||
run: superset-extensions test --coverage
|
||||
|
||||
- name: Build
|
||||
run: superset-extensions build --mode production
|
||||
|
||||
- name: Bundle
|
||||
run: superset-extensions bundle
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: extension-bundle
|
||||
path: '*.supx'
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
### Automated Deployment
|
||||
|
||||
- **Documentation**: [Developer Portal](../)
|
||||
- **Examples**: [GitHub Repository](https://github.com/apache/superset/tree/master/extensions)
|
||||
- **Issues**: [GitHub Issues](https://github.com/apache/superset/issues)
|
||||
- **Community**: [Slack Channel](https://apache-superset.slack.com)
|
||||
Deploy extensions automatically:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# deploy.sh
|
||||
|
||||
# Build and bundle
|
||||
superset-extensions build --mode production
|
||||
superset-extensions bundle --sign
|
||||
|
||||
# Upload to Superset instance
|
||||
BUNDLE=$(ls *.supx | head -1)
|
||||
curl -X POST "$SUPERSET_URL/api/v1/extensions/import/" \
|
||||
-H "Authorization: Bearer $SUPERSET_TOKEN" \
|
||||
-F "bundle=@$BUNDLE"
|
||||
|
||||
# Verify deployment
|
||||
curl "$SUPERSET_URL/api/v1/extensions/" \
|
||||
-H "Authorization: Bearer $SUPERSET_TOKEN"
|
||||
```
|
||||
|
||||
### Multi-Extension Projects
|
||||
|
||||
Manage multiple extensions in one repository:
|
||||
|
||||
```bash
|
||||
# Initialize multiple extensions
|
||||
superset-extensions init extensions/viz-plugin --type frontend-only
|
||||
superset-extensions init extensions/sql-optimizer --template sql-lab
|
||||
superset-extensions init extensions/auth-provider --type backend-only
|
||||
|
||||
# Build all extensions
|
||||
for dir in extensions/*/; do
|
||||
(cd "$dir" && superset-extensions build)
|
||||
done
|
||||
|
||||
# Bundle all extensions
|
||||
for dir in extensions/*/; do
|
||||
(cd "$dir" && superset-extensions bundle)
|
||||
done
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Port already in use
|
||||
|
||||
```bash
|
||||
# Error: Port 9001 is already in use
|
||||
|
||||
# Solution: Use a different port
|
||||
superset-extensions dev --port 9002
|
||||
```
|
||||
|
||||
#### Module not found
|
||||
|
||||
```bash
|
||||
# Error: Cannot find module '@apache-superset/core'
|
||||
|
||||
# Solution: Ensure dependencies are installed
|
||||
npm install --prefix frontend
|
||||
```
|
||||
|
||||
#### Build failures
|
||||
|
||||
```bash
|
||||
# Check Node and Python versions
|
||||
node --version # Should be 16+
|
||||
python --version # Should be 3.9+
|
||||
|
||||
# Clear cache and rebuild
|
||||
rm -rf dist node_modules frontend/node_modules
|
||||
npm install --prefix frontend
|
||||
superset-extensions build --clean
|
||||
```
|
||||
|
||||
#### Bundle too large
|
||||
|
||||
```bash
|
||||
# Warning: Bundle size exceeds recommended limit
|
||||
|
||||
# Solution: Analyze and optimize
|
||||
superset-extensions build --analyze
|
||||
|
||||
# Exclude unnecessary files
|
||||
superset-extensions bundle --exclude "**/*.map,**/*.test.*"
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```bash
|
||||
# Set debug environment variable
|
||||
export DEBUG=superset-extensions:*
|
||||
|
||||
# Or use verbose flag
|
||||
superset-extensions dev --verbose
|
||||
superset-extensions build --verbose
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
```bash
|
||||
# General help
|
||||
superset-extensions --help
|
||||
|
||||
# Command-specific help
|
||||
superset-extensions init --help
|
||||
superset-extensions dev --help
|
||||
|
||||
# Version information
|
||||
superset-extensions --version
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Development
|
||||
|
||||
1. **Use TypeScript** for type safety
|
||||
2. **Follow the style guide** for consistency
|
||||
3. **Write tests** for critical functionality
|
||||
4. **Document your code** with JSDoc/docstrings
|
||||
5. **Use development mode** for rapid iteration
|
||||
|
||||
### Building
|
||||
|
||||
1. **Optimize bundle size** - analyze and tree-shake
|
||||
2. **Generate source maps** for debugging
|
||||
3. **Validate before building** to catch issues early
|
||||
4. **Use production mode** for final builds
|
||||
5. **Clean build directory** to avoid stale files
|
||||
|
||||
### Deployment
|
||||
|
||||
1. **Sign your bundles** for security
|
||||
2. **Version properly** using semantic versioning
|
||||
3. **Test in staging** before production deployment
|
||||
4. **Document breaking changes** in CHANGELOG
|
||||
5. **Provide migration guides** for major updates
|
||||
|
||||
## Resources
|
||||
|
||||
- [Extension Architecture](/developer_portal/architecture/overview)
|
||||
- [API Reference](/developer_portal/api/frontend)
|
||||
- [Frontend Contribution Types](/developer_portal/extensions/frontend-contribution-types)
|
||||
- [GitHub Repository](https://github.com/apache/superset)
|
||||
- [Community Forum](https://github.com/apache/superset/discussions)
|
||||
|
||||
44
docs/developer_portal/coding-guidelines/overview.md
Normal file
44
docs/developer_portal/coding-guidelines/overview.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Coding Guidelines Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Coding Guidelines Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Best practices and coding standards for Apache Superset development.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- General coding principles
|
||||
- Code organization
|
||||
- Error handling
|
||||
- Performance considerations
|
||||
- Security best practices
|
||||
- Testing requirements
|
||||
- Documentation standards
|
||||
- Commit message conventions
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
339
docs/developer_portal/contributing/code-review.md
Normal file
339
docs/developer_portal/contributing/code-review.md
Normal file
@@ -0,0 +1,339 @@
|
||||
---
|
||||
title: Code Review Process
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Code Review Process
|
||||
|
||||
Understand how code reviews work in Apache Superset and how to participate effectively.
|
||||
|
||||
## Overview
|
||||
|
||||
Code review is a critical part of maintaining code quality and sharing knowledge across the team. Every change to Superset goes through peer review before merging.
|
||||
|
||||
## For Authors
|
||||
|
||||
### Preparing for Review
|
||||
|
||||
#### Before Requesting Review
|
||||
- [ ] Self-review your changes
|
||||
- [ ] Ensure CI checks pass
|
||||
- [ ] Add comprehensive tests
|
||||
- [ ] Update documentation
|
||||
- [ ] Fill out PR template completely
|
||||
- [ ] Add screenshots for UI changes
|
||||
|
||||
#### Self-Review Checklist
|
||||
```bash
|
||||
# View your changes
|
||||
git diff upstream/master
|
||||
|
||||
# Check for common issues:
|
||||
# - Commented out code
|
||||
# - Debug statements (console.log, print)
|
||||
# - TODO comments that should be addressed
|
||||
# - Hardcoded values that should be configurable
|
||||
# - Missing error handling
|
||||
# - Performance implications
|
||||
```
|
||||
|
||||
### Requesting Review
|
||||
|
||||
#### Auto-Assignment
|
||||
GitHub will automatically request reviews based on CODEOWNERS file.
|
||||
|
||||
#### Manual Assignment
|
||||
For specific expertise, request additional reviewers:
|
||||
- Frontend changes: Tag frontend experts
|
||||
- Backend changes: Tag backend experts
|
||||
- Security changes: Tag security team
|
||||
- Database changes: Tag database experts
|
||||
|
||||
#### Review Request Message
|
||||
```markdown
|
||||
@reviewer This PR implements [feature]. Could you please review:
|
||||
1. The approach taken in [file]
|
||||
2. Performance implications of [change]
|
||||
3. Security considerations for [feature]
|
||||
|
||||
Thanks!
|
||||
```
|
||||
|
||||
### Responding to Feedback
|
||||
|
||||
#### Best Practices
|
||||
- **Be receptive**: Reviews improve code quality
|
||||
- **Ask questions**: Clarify if feedback is unclear
|
||||
- **Explain decisions**: Share context for your choices
|
||||
- **Update promptly**: Address feedback in timely manner
|
||||
|
||||
#### Comment Responses
|
||||
```markdown
|
||||
# Acknowledging
|
||||
"Good catch! Fixed in [commit hash]"
|
||||
|
||||
# Explaining
|
||||
"I chose this approach because [reason]. Would you prefer [alternative]?"
|
||||
|
||||
# Questioning
|
||||
"Could you elaborate on [concern]? I'm not sure I understand the issue."
|
||||
|
||||
# Disagreeing respectfully
|
||||
"I see your point, but I think [current approach] because [reason]. What do you think?"
|
||||
```
|
||||
|
||||
## For Reviewers
|
||||
|
||||
### Review Responsibilities
|
||||
|
||||
#### What to Review
|
||||
1. **Correctness**: Does the code do what it claims?
|
||||
2. **Design**: Is the approach appropriate?
|
||||
3. **Clarity**: Is the code readable and maintainable?
|
||||
4. **Testing**: Are tests comprehensive?
|
||||
5. **Performance**: Any performance concerns?
|
||||
6. **Security**: Any security issues?
|
||||
7. **Documentation**: Is it well documented?
|
||||
|
||||
### Review Checklist
|
||||
|
||||
#### Functionality
|
||||
- [ ] Feature works as described
|
||||
- [ ] Edge cases are handled
|
||||
- [ ] Error handling is appropriate
|
||||
- [ ] Backwards compatibility maintained
|
||||
|
||||
#### Code Quality
|
||||
- [ ] Follows project conventions
|
||||
- [ ] No code duplication
|
||||
- [ ] Clear variable/function names
|
||||
- [ ] Appropriate abstraction levels
|
||||
- [ ] SOLID principles followed
|
||||
|
||||
#### Testing
|
||||
- [ ] Unit tests for business logic
|
||||
- [ ] Integration tests for APIs
|
||||
- [ ] E2E tests for critical paths
|
||||
- [ ] Tests are maintainable
|
||||
- [ ] Good test coverage
|
||||
|
||||
#### Security
|
||||
- [ ] Input validation
|
||||
- [ ] SQL injection prevention
|
||||
- [ ] XSS prevention
|
||||
- [ ] CSRF protection
|
||||
- [ ] Authentication/authorization checks
|
||||
- [ ] No sensitive data in logs
|
||||
|
||||
#### Performance
|
||||
- [ ] Database queries optimized
|
||||
- [ ] No N+1 queries
|
||||
- [ ] Appropriate caching
|
||||
- [ ] Frontend bundle size impact
|
||||
- [ ] Memory usage considerations
|
||||
|
||||
### Providing Feedback
|
||||
|
||||
#### Effective Comments
|
||||
|
||||
```python
|
||||
# ✅ Good: Specific and actionable
|
||||
"This query could cause N+1 problems. Consider using
|
||||
`select_related('user')` to fetch users in a single query."
|
||||
|
||||
# ❌ Bad: Vague
|
||||
"This doesn't look right."
|
||||
```
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Suggests improvement
|
||||
"Consider using useMemo here to prevent unnecessary
|
||||
re-renders when dependencies haven't changed."
|
||||
|
||||
// ❌ Bad: Just criticism
|
||||
"This is inefficient."
|
||||
```
|
||||
|
||||
#### Comment Types
|
||||
|
||||
**Use GitHub's comment types:**
|
||||
- **Comment**: General feedback or questions
|
||||
- **Approve**: Changes look good
|
||||
- **Request Changes**: Must be addressed before merge
|
||||
|
||||
**Prefix conventions:**
|
||||
- `nit:` Minor issue (non-blocking)
|
||||
- `suggestion:` Recommended improvement
|
||||
- `question:` Seeking clarification
|
||||
- `blocker:` Must be fixed
|
||||
- `praise:` Highlighting good work
|
||||
|
||||
#### Examples
|
||||
|
||||
```markdown
|
||||
nit: Consider renaming `getData` to `fetchUserData` for clarity
|
||||
|
||||
suggestion: This could be simplified using Array.reduce()
|
||||
|
||||
question: Is this intentionally not handling the error case?
|
||||
|
||||
blocker: This SQL is vulnerable to injection. Please use parameterized queries.
|
||||
|
||||
praise: Excellent test coverage! 👍
|
||||
```
|
||||
|
||||
## Review Process
|
||||
|
||||
### Timeline
|
||||
|
||||
#### Expected Response Times
|
||||
- **Initial review**: Within 2-3 business days
|
||||
- **Follow-up review**: Within 1-2 business days
|
||||
- **Critical fixes**: ASAP (tag in Slack)
|
||||
|
||||
#### Escalation
|
||||
If no response after 3 days:
|
||||
1. Ping reviewer in PR comments
|
||||
2. Ask in #development Slack channel
|
||||
3. Tag @apache/superset-committers
|
||||
|
||||
### Approval Requirements
|
||||
|
||||
#### Minimum Requirements
|
||||
- **1 approval** from a committer for minor changes
|
||||
- **2 approvals** for significant features
|
||||
- **3 approvals** for breaking changes
|
||||
|
||||
#### Special Cases
|
||||
- **Security changes**: Require security team review
|
||||
- **API changes**: Require API team review
|
||||
- **Database migrations**: Require database expert review
|
||||
- **UI/UX changes**: Require design review
|
||||
|
||||
### Merge Process
|
||||
|
||||
#### Who Can Merge
|
||||
- Committers with write access
|
||||
- After all requirements met
|
||||
- CI checks must pass
|
||||
|
||||
#### Merge Methods
|
||||
- **Squash and merge**: Default for feature PRs
|
||||
- **Rebase and merge**: For clean history
|
||||
- **Create merge commit**: Rarely used
|
||||
|
||||
#### Merge Checklist
|
||||
- [ ] All CI checks green
|
||||
- [ ] Required approvals obtained
|
||||
- [ ] No unresolved conversations
|
||||
- [ ] PR title follows conventions
|
||||
- [ ] Milestone set (if applicable)
|
||||
|
||||
## Review Etiquette
|
||||
|
||||
### Do's
|
||||
- ✅ Be kind and constructive
|
||||
- ✅ Acknowledge time and effort
|
||||
- ✅ Provide specific examples
|
||||
- ✅ Suggest solutions
|
||||
- ✅ Praise good work
|
||||
- ✅ Consider cultural differences
|
||||
- ✅ Focus on the code, not the person
|
||||
|
||||
### Don'ts
|
||||
- ❌ Use harsh or dismissive language
|
||||
- ❌ Bikeshed on minor preferences
|
||||
- ❌ Review when tired or frustrated
|
||||
- ❌ Make personal attacks
|
||||
- ❌ Ignore the PR description
|
||||
- ❌ Demand perfection
|
||||
|
||||
## Becoming a Reviewer
|
||||
|
||||
### Path to Reviewer
|
||||
1. **Contribute regularly**: Submit quality PRs
|
||||
2. **Participate in discussions**: Share knowledge
|
||||
3. **Review others' code**: Start with comments
|
||||
4. **Build expertise**: Focus on specific areas
|
||||
5. **Get nominated**: By existing committers
|
||||
|
||||
### Reviewer Expectations
|
||||
- Review PRs in your area of expertise
|
||||
- Respond within reasonable time
|
||||
- Mentor new contributors
|
||||
- Maintain high standards
|
||||
- Stay current with best practices
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
### Reviewing Large PRs
|
||||
|
||||
#### Strategy
|
||||
1. **Request splitting**: Ask to break into smaller PRs
|
||||
2. **Review in phases**:
|
||||
- Architecture/approach first
|
||||
- Implementation details second
|
||||
- Tests and docs last
|
||||
3. **Use draft reviews**: Save comments and submit together
|
||||
|
||||
### Cross-Team Reviews
|
||||
|
||||
#### When Needed
|
||||
- Changes affecting multiple teams
|
||||
- Shared components/libraries
|
||||
- API contract changes
|
||||
- Database schema changes
|
||||
|
||||
### Performance Reviews
|
||||
|
||||
#### Tools
|
||||
```python
|
||||
# Backend performance
|
||||
import cProfile
|
||||
import pstats
|
||||
|
||||
# Profile the code
|
||||
cProfile.run('function_to_profile()', 'stats.prof')
|
||||
stats = pstats.Stats('stats.prof')
|
||||
stats.sort_stats('cumulative').print_stats(10)
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Frontend performance
|
||||
// Use React DevTools Profiler
|
||||
// Chrome DevTools Performance tab
|
||||
// Lighthouse audits
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Internal
|
||||
- [Coding Guidelines](../coding-guidelines/overview)
|
||||
- [Testing Guide](../testing/overview)
|
||||
- [Architecture Overview](../architecture/overview)
|
||||
|
||||
### External
|
||||
- [Google's Code Review Guide](https://google.github.io/eng-practices/review/)
|
||||
- [Best Practices for Code Review](https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/)
|
||||
- [The Art of Readable Code](https://www.oreilly.com/library/view/the-art-of/9781449318482/)
|
||||
|
||||
Next: [Reporting issues effectively](./issue-reporting)
|
||||
1108
docs/developer_portal/contributing/development-setup.md
Normal file
1108
docs/developer_portal/contributing/development-setup.md
Normal file
File diff suppressed because it is too large
Load Diff
415
docs/developer_portal/contributing/guidelines.md
Normal file
415
docs/developer_portal/contributing/guidelines.md
Normal file
@@ -0,0 +1,415 @@
|
||||
---
|
||||
title: Contribution Guidelines
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Contribution Guidelines
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
A philosophy we would like to strongly encourage is
|
||||
|
||||
> Before creating a PR, create an issue.
|
||||
|
||||
The purpose is to separate problem from possible solutions.
|
||||
|
||||
**Bug fixes:** If you're only fixing a small bug, it's fine to submit a pull request right away but we highly recommend filing an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue. Please keep in mind that the project maintainers reserve the rights to accept or reject incoming PRs, so it is better to separate the issue and the code to fix it from each other. In some cases, project maintainers may request you to create a separate issue from PR before proceeding.
|
||||
|
||||
**Refactor:** For small refactors, it can be a standalone PR itself detailing what you are refactoring and why. If there are concerns, project maintainers may request you to create a `#SIP` for the PR before proceeding.
|
||||
|
||||
**Feature/Large changes:** If you intend to change the public API, or make any non-trivial changes to the implementation, we require you to file a new issue as `#SIP` (Superset Improvement Proposal). This lets us reach an agreement on your proposal before you put significant effort into it. You are welcome to submit a PR along with the SIP (sometimes necessary for demonstration), but we will not review/merge the code until the SIP is approved.
|
||||
|
||||
In general, small PRs are always easier to review than large PRs. The best practice is to break your work into smaller independent PRs and refer to the same issue. This will greatly reduce turnaround time.
|
||||
|
||||
If you wish to share your work which is not ready to merge yet, create a [Draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/). This will enable maintainers and the CI runner to prioritize mature PR's.
|
||||
|
||||
Finally, never submit a PR that will put master branch in broken state. If the PR is part of multiple PRs to complete a large feature and cannot work on its own, you can create a feature branch and merge all related PRs into the feature branch before creating a PR from feature branch to master.
|
||||
|
||||
### Protocol
|
||||
|
||||
#### Authoring
|
||||
|
||||
- Fill in all sections of the PR template.
|
||||
- Title the PR with one of the following semantic prefixes (inspired by [Karma](http://karma-runner.github.io/0.10/dev/git-commit-msg.html])):
|
||||
|
||||
- `feat` (new feature)
|
||||
- `fix` (bug fix)
|
||||
- `docs` (changes to the documentation)
|
||||
- `style` (formatting, missing semi colons, etc; no application logic change)
|
||||
- `refactor` (refactoring code)
|
||||
- `test` (adding missing tests, refactoring tests; no application logic change)
|
||||
- `chore` (updating tasks etc; no application logic change)
|
||||
- `perf` (performance-related change)
|
||||
- `build` (build tooling, Docker configuration change)
|
||||
- `ci` (test runner, GitHub Actions workflow changes)
|
||||
- `other` (changes that don't correspond to the above -- should be rare!)
|
||||
- Examples:
|
||||
- `feat: export charts as ZIP files`
|
||||
- `perf(api): improve API info performance`
|
||||
- `fix(chart-api): cached-indicator always shows value is cached`
|
||||
|
||||
- Add prefix `[WIP]` to title if not ready for review (WIP = work-in-progress). We recommend creating a PR with `[WIP]` first and remove it once you have passed CI test and read through your code changes at least once.
|
||||
- If you believe your PR contributes a potentially breaking change, put a `!` after the semantic prefix but before the colon in the PR title, like so: `feat!: Added foo functionality to bar`
|
||||
- **Screenshots/GIFs:** Changes to user interface require before/after screenshots, or GIF for interactions
|
||||
- Recommended capture tools ([Kap](https://getkap.co/), [LICEcap](https://www.cockos.com/licecap/), [Skitch](https://download.cnet.com/Skitch/3000-13455_4-189876.html))
|
||||
- If no screenshot is provided, the committers will mark the PR with `need:screenshot` label and will not review until screenshot is provided.
|
||||
- **Dependencies:** Be careful about adding new dependency and avoid unnecessary dependencies.
|
||||
- For Python, include it in `pyproject.toml` denoting any specific restrictions and
|
||||
in `requirements.txt` pinned to a specific version which ensures that the application
|
||||
build is deterministic.
|
||||
- For TypeScript/JavaScript, include new libraries in `package.json`
|
||||
- **Tests:** The pull request should include tests, either as doctests, unit tests, or both. Make sure to resolve all errors and test failures. See [Testing](./howtos#testing) for how to run tests.
|
||||
- **Documentation:** If the pull request adds functionality, the docs should be updated as part of the same PR.
|
||||
- **CI:** Reviewers will not review the code until all CI tests are passed. Sometimes there can be flaky tests. You can close and open PR to re-run CI test. Please report if the issue persists. After the CI fix has been deployed to `master`, please rebase your PR.
|
||||
- **Code coverage:** Please ensure that code coverage does not decrease.
|
||||
- Remove `[WIP]` when ready for review. Please note that it may be merged soon after approved so please make sure the PR is ready to merge and do not expect more time for post-approval edits.
|
||||
- If the PR was not ready for review and inactive for > 30 days, we will close it due to inactivity. The author is welcome to re-open and update.
|
||||
|
||||
#### Reviewing
|
||||
|
||||
- Use constructive tone when writing reviews.
|
||||
- If there are changes required, state clearly what needs to be done before the PR can be approved.
|
||||
- If you are asked to update your pull request with some changes there's no need to create a new one. Push your changes to the same branch.
|
||||
- The committers reserve the right to reject any PR and in some cases may request the author to file an issue.
|
||||
|
||||
#### Test Environments
|
||||
|
||||
- Members of the Apache GitHub org can launch an ephemeral test environment directly on a pull request by creating a comment containing (only) the command `/testenv up`.
|
||||
- Note that org membership must be public in order for this validation to function properly.
|
||||
- Feature flags may be set for a test environment by specifying the flag name (prefixed with `FEATURE_`) and value after the command.
|
||||
- Format: `/testenv up FEATURE_<feature flag name>=true|false`
|
||||
- Example: `/testenv up FEATURE_DASHBOARD_NATIVE_FILTERS=true`
|
||||
- Multiple feature flags may be set in single command, separated by whitespace
|
||||
- A comment will be created by the workflow script with the address and login information for the ephemeral environment.
|
||||
- Test environments may be created once the Docker build CI workflow for the PR has completed successfully.
|
||||
- Test environments do not currently update automatically when new commits are added to a pull request.
|
||||
- Test environments do not currently support async workers, though this is planned.
|
||||
- Running test environments will be shutdown upon closing the pull request.
|
||||
|
||||
You can also access per-PR ephemeral environment directly using the following URL pattern:
|
||||
`https://pr-{PR_NUMBER}.superset.apache.org`
|
||||
|
||||
#### Merging
|
||||
|
||||
- At least one approval is required for merging a PR.
|
||||
- PR is usually left open for at least 24 hours before merging.
|
||||
- After the PR is merged, [close the corresponding issue(s)](https://help.github.com/articles/closing-issues-using-keywords/).
|
||||
|
||||
#### Post-merge Responsibility
|
||||
|
||||
- Project maintainers may contact the PR author if new issues are introduced by the PR.
|
||||
- Project maintainers may revert your changes if a critical issue is found, such as breaking master branch CI.
|
||||
|
||||
## Managing Issues and PRs
|
||||
|
||||
To handle issues and PRs that are coming in, committers read issues/PRs and flag them with labels to categorize and help contributors spot where to take actions, as contributors usually have different expertises.
|
||||
|
||||
Triaging goals
|
||||
|
||||
- **For issues:** Categorize, screen issues, flag required actions from authors.
|
||||
- **For PRs:** Categorize, flag required actions from authors. If PR is ready for review, flag required actions from reviewers.
|
||||
|
||||
First, add **Category labels (a.k.a. hash labels)**. Every issue/PR must have one hash label (except spam entry). Labels that begin with `#` defines issue/PR type:
|
||||
|
||||
| Label | for Issue | for PR |
|
||||
| --------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `#bug` | Bug report | Bug fix |
|
||||
| `#code-quality` | Describe problem with code, architecture or productivity | Refactor, tests, tooling |
|
||||
| `#feature` | New feature request | New feature implementation |
|
||||
| `#refine` | Propose improvement such as adjusting padding or refining UI style, excluding new features, bug fixes, and refactoring. | Implementation of improvement such as adjusting padding or refining UI style, excluding new features, bug fixes, and refactoring. |
|
||||
| `#doc` | Documentation | Documentation |
|
||||
| `#question` | Troubleshooting: Installation, Running locally, Ask how to do something. Can be changed to `#bug` later. | N/A |
|
||||
| `#SIP` | Superset Improvement Proposal | N/A |
|
||||
| `#ASF` | Tasks related to Apache Software Foundation policy | Tasks related to Apache Software Foundation policy |
|
||||
|
||||
Then add other types of labels as appropriate.
|
||||
|
||||
- **Descriptive labels (a.k.a. dot labels):** These labels that begin with `.` describe the details of the issue/PR, such as `.ui`, `.js`, `.install`, `.backend`, etc. Each issue/PR can have zero or more dot labels.
|
||||
- **Need labels:** These labels have pattern `need:xxx`, which describe the work required to progress, such as `need:rebase`, `need:update`, `need:screenshot`.
|
||||
- **Risk labels:** These labels have pattern `risk:xxx`, which describe the potential risk on adopting the work, such as `risk:db-migration`. The intention was to better understand the impact and create awareness for PRs that need more rigorous testing.
|
||||
- **Status labels:** These labels describe the status (`abandoned`, `wontfix`, `cant-reproduce`, etc.) Issue/PRs that are rejected or closed without completion should have one or more status labels.
|
||||
- **Version labels:** These have the pattern `vx.x` such as `v0.28`. Version labels on issues describe the version the bug was reported on. Version labels on PR describe the first release that will include the PR.
|
||||
|
||||
Committers may also update title to reflect the issue/PR content if the author-provided title is not descriptive enough.
|
||||
|
||||
If the PR passes CI tests and does not have any `need:` labels, it is ready for review, add label `review` and/or `design-review`.
|
||||
|
||||
If an issue/PR has been inactive for at least 30 days, it will be closed. If it does not have any status label, add `inactive`.
|
||||
|
||||
When creating a PR, if you're aiming to have it included in a specific release, please tag it with the version label. For example, to have a PR considered for inclusion in Superset 1.1 use the label `v1.1`.
|
||||
|
||||
## Revert Guidelines
|
||||
|
||||
Reverting changes that are causing issues in the master branch is a normal and expected part of the development process. In an open source community, the ramifications of a change cannot always be fully understood. With that in mind, here are some considerations to keep in mind when considering a revert:
|
||||
|
||||
- **Availability of the PR author:** If the original PR author or the engineer who merged the code is highly available and can provide a fix in a reasonable time frame, this would counter-indicate reverting.
|
||||
- **Severity of the issue:** How severe is the problem on master? Is it keeping the project from moving forward? Is there user impact? What percentage of users will experience a problem?
|
||||
- **Size of the change being reverted:** Reverting a single small PR is a much lower-risk proposition than reverting a massive, multi-PR change.
|
||||
- **Age of the change being reverted:** Reverting a recently-merged PR will be more acceptable than reverting an older PR. A bug discovered in an older PR is unlikely to be causing widespread serious issues.
|
||||
- **Risk inherent in reverting:** Will the reversion break critical functionality? Is the medicine more dangerous than the disease?
|
||||
- **Difficulty of crafting a fix:** In the case of issues with a clear solution, it may be preferable to implement and merge a fix rather than a revert.
|
||||
|
||||
Should you decide that reverting is desirable, it is the responsibility of the Contributor performing the revert to:
|
||||
|
||||
- **Contact the interested parties:** The PR's author and the engineer who merged the work should both be contacted and informed of the revert.
|
||||
- **Provide concise reproduction steps:** Ensure that the issue can be clearly understood and duplicated by the original author of the PR.
|
||||
- **Put the revert through code review:** The revert must be approved by another committer.
|
||||
|
||||
**Revert liberally to keep `master` stable**:
|
||||
- Build failures
|
||||
- Test failures
|
||||
- Critical bugs in production
|
||||
- Security vulnerabilities
|
||||
|
||||
**How to revert**:
|
||||
1. Use GitHub's revert button when possible
|
||||
2. Create a PR with clear explanation
|
||||
3. Tag the original author
|
||||
4. Work with them on a fix
|
||||
|
||||
## Design Guidelines
|
||||
|
||||
### Capitalization Guidelines
|
||||
|
||||
#### Sentence case
|
||||
|
||||
Use sentence-case capitalization for everything in the UI (except these **).
|
||||
|
||||
Sentence case is predominantly lowercase. Capitalize only the initial character of the first word, and other words that require capitalization, like:
|
||||
|
||||
- **Proper nouns.** Objects in the product _are not_ considered proper nouns e.g. dashboards, charts, saved queries etc. Proprietary feature names eg. SQL Lab, Preset Manager _are_ considered proper nouns
|
||||
- **Acronyms** (e.g. CSS, HTML)
|
||||
- When referring to **UI labels that are themselves capitalized** from sentence case (e.g. page titles - Dashboards page, Charts page, Saved queries page, etc.)
|
||||
- User input that is reflected in the UI. E.g. a user-named a dashboard tab
|
||||
|
||||
**Sentence case vs. Title case:**
|
||||
Title case: "A Dog Takes a Walk in Paris"
|
||||
Sentence case: "A dog takes a walk in Paris"
|
||||
|
||||
**Why sentence case?**
|
||||
|
||||
- It's generally accepted as the quickest to read
|
||||
- It's the easiest form to distinguish between common and proper nouns
|
||||
|
||||
**Good examples:**
|
||||
- "Select a database"
|
||||
- "Create new chart"
|
||||
- "View all dashboards"
|
||||
|
||||
**Bad examples:**
|
||||
- "Select a Database"
|
||||
- "Create New Chart"
|
||||
- "View All Dashboards"
|
||||
|
||||
#### How to refer to UI elements
|
||||
|
||||
When writing about a UI element, use the same capitalization as used in the UI.
|
||||
|
||||
For example, if an input field is labeled "Name" then you refer to this as the "Name input field". Similarly, if a button has the label "Save" in it, then it is correct to refer to the "Save button".
|
||||
|
||||
Where a product page is titled "Settings", you refer to this in writing as follows:
|
||||
"Edit your personal information on the Settings page".
|
||||
|
||||
Often a product page will have the same title as the objects it contains. In this case, refer to the page as it appears in the UI, and the objects as common nouns:
|
||||
|
||||
- Upload a dashboard on the Dashboards page
|
||||
- Go to Dashboards
|
||||
- View dashboard
|
||||
- View all dashboards
|
||||
- Upload CSS templates on the CSS templates page
|
||||
- Queries that you save will appear on the Saved queries page
|
||||
- Create custom queries in SQL Lab then create dashboards
|
||||
|
||||
When writing about UI elements:
|
||||
- Use **bold** for clickable elements: "Click **Save**"
|
||||
- Use quotes for text fields: 'Enter "My Dashboard" in the name field'
|
||||
- Be specific about element types: button, link, dropdown, etc.
|
||||
|
||||
#### **Exceptions to sentence case
|
||||
|
||||
Only use title case for:
|
||||
- Product names (Apache Superset)
|
||||
- Proper nouns
|
||||
- Acronyms (SQL, API, CSV)
|
||||
- Input labels, buttons and UI tabs are all caps
|
||||
- User input values (e.g. column names, SQL Lab tab names) should be in their original case
|
||||
|
||||
## Programming Language Conventions
|
||||
|
||||
### Python
|
||||
|
||||
We use:
|
||||
- **[Ruff](https://docs.astral.sh/ruff/)** for linting and formatting
|
||||
- **[Mypy](http://mypy-lang.org/)** for type checking
|
||||
|
||||
Python code should:
|
||||
- Follow PEP 8
|
||||
- Use type hints for all new code
|
||||
- Use descriptive variable names
|
||||
- Include docstrings for modules, classes, and functions
|
||||
- Handle exceptions appropriately
|
||||
- Avoid global variables
|
||||
|
||||
Parameters in the `config.py` (which are accessible via the Flask app.config dictionary) are
|
||||
assumed to always be defined and thus should be accessed directly via,
|
||||
|
||||
```python
|
||||
blueprints = app.config["BLUEPRINTS"]
|
||||
```
|
||||
|
||||
rather than,
|
||||
|
||||
```python
|
||||
blueprints = app.config.get("BLUEPRINTS")
|
||||
```
|
||||
|
||||
or similar as the later will cause typing issues. The former is of type `List[Callable]`
|
||||
whereas the later is of type `Optional[List[Callable]]`.
|
||||
|
||||
#### Typing / Type Hints
|
||||
|
||||
All new Python code should include type hints:
|
||||
|
||||
To ensure clarity, consistency, all readability, _all_ new functions should use
|
||||
[type hints](https://docs.python.org/3/library/typing.html) and include a
|
||||
docstring.
|
||||
|
||||
Note per [PEP-484](https://www.python.org/dev/peps/pep-0484/#exceptions) no
|
||||
syntax for listing explicitly raised exceptions is proposed and thus the
|
||||
recommendation is to put this information in a docstring, i.e.,
|
||||
|
||||
```python
|
||||
import math
|
||||
from typing import List, Optional, Dict, Any, Union
|
||||
|
||||
|
||||
def sqrt(x: Union[float, int]) -> Union[float, int]:
|
||||
"""
|
||||
Return the square root of x.
|
||||
|
||||
:param x: A number
|
||||
:returns: The square root of the given number
|
||||
:raises ValueError: If the number is negative
|
||||
"""
|
||||
|
||||
return math.sqrt(x)
|
||||
|
||||
|
||||
def process_data(
|
||||
data: List[Dict[str, Any]],
|
||||
filter_empty: bool = True
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Process a list of data dictionaries.
|
||||
|
||||
Args:
|
||||
data: List of dictionaries containing data
|
||||
filter_empty: Whether to filter empty entries
|
||||
|
||||
Returns:
|
||||
Processed data dictionary or None if no valid data
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
# Process data...
|
||||
return processed_data
|
||||
```
|
||||
|
||||
Use `mypy` to check types:
|
||||
```bash
|
||||
mypy superset
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
We use:
|
||||
- **ESLint** for linting
|
||||
- **Prettier** for formatting
|
||||
- **TypeScript** strict mode
|
||||
|
||||
TypeScript is fully supported and is the recommended language for writing all new frontend
|
||||
components. When modifying existing functions/components, migrating to TypeScript is
|
||||
appreciated, but not required. Examples of migrating functions/components to TypeScript can be
|
||||
found in [#9162](https://github.com/apache/superset/pull/9162) and [#9180](https://github.com/apache/superset/pull/9180).
|
||||
|
||||
TypeScript code should:
|
||||
- Avoid `any` types - use proper TypeScript types
|
||||
- Use functional components with hooks for React
|
||||
- Include JSDoc comments for complex functions
|
||||
- Use consistent naming conventions
|
||||
- Handle errors appropriately
|
||||
|
||||
Example:
|
||||
```typescript
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
export function processUser(user: User): string {
|
||||
// Avoid using 'any'
|
||||
const { name, email } = user;
|
||||
return email ? `${name} <${email}>` : name;
|
||||
}
|
||||
```
|
||||
|
||||
## Additional Guidelines
|
||||
|
||||
### Commit Messages
|
||||
|
||||
- Use clear, descriptive commit messages
|
||||
- Start with a verb in imperative mood
|
||||
- Reference issue numbers when applicable
|
||||
|
||||
Good: "Fix dashboard filter bug when dataset is deleted"
|
||||
Bad: "Fixed stuff"
|
||||
|
||||
### Code Review Etiquette
|
||||
|
||||
- Be respectful and constructive
|
||||
- Focus on the code, not the person
|
||||
- Provide specific suggestions for improvement
|
||||
- Acknowledge good work
|
||||
- Be open to different approaches
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update docs for any user-facing changes
|
||||
- Include code examples where helpful
|
||||
- Keep language clear and concise
|
||||
- Test documentation changes locally
|
||||
|
||||
### Security
|
||||
|
||||
- Never commit secrets or credentials
|
||||
- Validate all user input
|
||||
- Use parameterized queries for SQL
|
||||
- Follow OWASP guidelines
|
||||
- Report security issues privately to private@superset.apache.org
|
||||
|
||||
## Questions?
|
||||
|
||||
If you have questions about these guidelines, ask in:
|
||||
- [Slack #development](https://apache-superset.slack.com)
|
||||
- [GitHub Discussions](https://github.com/apache/superset/discussions)
|
||||
528
docs/developer_portal/contributing/howtos.md
Normal file
528
docs/developer_portal/contributing/howtos.md
Normal file
@@ -0,0 +1,528 @@
|
||||
---
|
||||
title: Development How-tos
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Development How-tos
|
||||
|
||||
This guide contains specific instructions for common development tasks in Superset.
|
||||
|
||||
## Contributing to Documentation
|
||||
|
||||
The documentation site is built using [Docusaurus](https://docusaurus.io/). All documentation lives in the `docs` folder, written in Markdown format.
|
||||
|
||||
### Local Development
|
||||
|
||||
To set up your local environment for documentation development:
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
npm install
|
||||
npm run start
|
||||
```
|
||||
|
||||
The site will be available at http://localhost:3000
|
||||
|
||||
### Build
|
||||
|
||||
To create a production build:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run serve # Test the build locally
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
Documentation is automatically deployed when changes are merged to master.
|
||||
|
||||
## Creating Visualization Plugins
|
||||
|
||||
Visualization plugins allow you to add custom chart types to Superset. They are built as npm packages that integrate with the Superset frontend.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+
|
||||
- npm or yarn
|
||||
- A local Superset development environment
|
||||
|
||||
### Creating a simple Hello World viz plugin
|
||||
|
||||
1. **Install the Superset Yeoman generator**:
|
||||
```bash
|
||||
npm install -g @superset-ui/generator-superset
|
||||
```
|
||||
|
||||
2. **Create a new plugin**:
|
||||
```bash
|
||||
mkdir superset-plugin-chart-hello-world
|
||||
cd superset-plugin-chart-hello-world
|
||||
yo @superset-ui/superset
|
||||
```
|
||||
|
||||
3. **Follow the prompts**:
|
||||
- Package name: `superset-plugin-chart-hello-world`
|
||||
- Chart type: Choose your preferred type
|
||||
- Include storybook: Yes (recommended for development)
|
||||
|
||||
4. **Develop your plugin**:
|
||||
The generator creates a complete plugin structure with TypeScript, React components, and build configuration.
|
||||
|
||||
5. **Test your plugin locally**:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
6. **Link to your local Superset**:
|
||||
```bash
|
||||
npm link
|
||||
# In your Superset frontend directory:
|
||||
npm link superset-plugin-chart-hello-world
|
||||
```
|
||||
|
||||
7. **Import and register in Superset**:
|
||||
Edit `superset-frontend/src/visualizations/presets/MainPreset.js` to include your plugin.
|
||||
|
||||
## Testing
|
||||
|
||||
### Python Testing
|
||||
|
||||
Run Python tests using pytest:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Run specific test file
|
||||
pytest tests/unit_tests/test_specific.py
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov=superset
|
||||
|
||||
# Run only unit tests
|
||||
pytest tests/unit_tests
|
||||
|
||||
# Run only integration tests
|
||||
pytest tests/integration_tests
|
||||
```
|
||||
|
||||
#### Testing with local Presto connections
|
||||
|
||||
To test against Presto:
|
||||
|
||||
```bash
|
||||
# Start Presto locally using Docker
|
||||
docker run -p 8080:8080 \
|
||||
--name presto \
|
||||
-d prestodb/presto
|
||||
|
||||
# Configure in superset_config.py
|
||||
SQLALCHEMY_DATABASE_URI = 'presto://localhost:8080/hive/default'
|
||||
```
|
||||
|
||||
### Frontend Testing
|
||||
|
||||
Run frontend tests using Jest:
|
||||
|
||||
```bash
|
||||
cd superset-frontend
|
||||
|
||||
# Run all tests
|
||||
npm run test
|
||||
|
||||
# Run with coverage
|
||||
npm run test -- --coverage
|
||||
|
||||
# Run in watch mode
|
||||
npm run test -- --watch
|
||||
|
||||
# Run specific test file
|
||||
npm run test -- MyComponent.test.tsx
|
||||
```
|
||||
|
||||
### E2E Integration Testing
|
||||
|
||||
We support both Playwright (recommended) and Cypress for end-to-end testing.
|
||||
|
||||
#### Playwright (Recommended - NEW)
|
||||
|
||||
Playwright is our new E2E testing framework, gradually replacing Cypress.
|
||||
|
||||
```bash
|
||||
# Navigate to frontend directory
|
||||
cd superset-frontend
|
||||
|
||||
# Run all Playwright tests
|
||||
npm run playwright:test
|
||||
# or: npx playwright test
|
||||
|
||||
# Run with interactive UI for debugging
|
||||
npm run playwright:ui
|
||||
# or: npx playwright test --ui
|
||||
|
||||
# Run in headed mode (see browser)
|
||||
npm run playwright:headed
|
||||
# or: npx playwright test --headed
|
||||
|
||||
# Run specific test file
|
||||
npx playwright test tests/auth/login.spec.ts
|
||||
|
||||
# Run with debug mode (step through tests)
|
||||
npm run playwright:debug tests/auth/login.spec.ts
|
||||
# or: npx playwright test --debug tests/auth/login.spec.ts
|
||||
|
||||
# Generate test report
|
||||
npm run playwright:report
|
||||
```
|
||||
|
||||
#### Cypress (DEPRECATED - will be removed)
|
||||
|
||||
Cypress is being phased out in favor of Playwright but is still available:
|
||||
|
||||
```bash
|
||||
# Set base URL for Cypress
|
||||
export CYPRESS_BASE_URL='http://localhost:8088'
|
||||
export CYPRESS_DATABASE=test
|
||||
export CYPRESS_USERNAME=admin
|
||||
export CYPRESS_PASSWORD=admin
|
||||
|
||||
# Navigate to Cypress directory
|
||||
cd superset-frontend/cypress-base
|
||||
|
||||
# Run interactively
|
||||
npm run cypress-debug
|
||||
|
||||
# Run headless (like CI)
|
||||
npm run cypress-run-chrome
|
||||
|
||||
# Run specific file
|
||||
npm run cypress-run-chrome -- --spec "cypress/e2e/dashboard/dashboard.test.ts"
|
||||
```
|
||||
|
||||
### Debugging Server App
|
||||
|
||||
For debugging the Flask backend:
|
||||
|
||||
#### Using PyCharm/IntelliJ
|
||||
|
||||
1. Create a new Python configuration
|
||||
2. Set script path to `superset/app.py`
|
||||
3. Set environment variables:
|
||||
- `FLASK_ENV=development`
|
||||
- `SUPERSET_CONFIG_PATH=/path/to/superset_config.py`
|
||||
4. Set breakpoints and run in debug mode
|
||||
|
||||
#### Using VS Code
|
||||
|
||||
1. Add to `.vscode/launch.json`:
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python: Flask",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "flask",
|
||||
"env": {
|
||||
"FLASK_APP": "superset/app.py",
|
||||
"FLASK_ENV": "development"
|
||||
},
|
||||
"args": ["run", "--no-debugger", "--no-reload"],
|
||||
"jinja": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
2. Set breakpoints and press F5 to debug
|
||||
|
||||
### Storybook
|
||||
|
||||
Storybook is used for developing and testing UI components in isolation:
|
||||
|
||||
```bash
|
||||
cd superset-frontend
|
||||
|
||||
# Start Storybook
|
||||
npm run storybook
|
||||
|
||||
# Build static Storybook
|
||||
npm run build-storybook
|
||||
```
|
||||
|
||||
Access Storybook at http://localhost:6006
|
||||
|
||||
## Contributing Translations
|
||||
|
||||
Superset uses Flask-Babel for internationalization.
|
||||
|
||||
### Enabling language selection
|
||||
|
||||
Edit `superset_config.py`:
|
||||
|
||||
```python
|
||||
LANGUAGES = {
|
||||
'en': {'flag': 'us', 'name': 'English'},
|
||||
'fr': {'flag': 'fr', 'name': 'French'},
|
||||
'zh': {'flag': 'cn', 'name': 'Chinese'},
|
||||
}
|
||||
```
|
||||
|
||||
### Creating a new language dictionary
|
||||
|
||||
```bash
|
||||
# Initialize a new language
|
||||
pybabel init -i superset/translations/messages.pot -d superset/translations -l de
|
||||
```
|
||||
|
||||
### Extracting new strings for translation
|
||||
|
||||
```bash
|
||||
# Extract Python strings
|
||||
pybabel extract -F babel.cfg -o superset/translations/messages.pot -k lazy_gettext superset
|
||||
|
||||
# Extract JavaScript strings
|
||||
npm run build-translation
|
||||
```
|
||||
|
||||
### Updating language files
|
||||
|
||||
```bash
|
||||
# Update all language files with new strings
|
||||
pybabel update -i superset/translations/messages.pot -d superset/translations
|
||||
```
|
||||
|
||||
### Applying translations
|
||||
|
||||
```bash
|
||||
# Frontend
|
||||
cd superset-frontend
|
||||
npm run build-translation
|
||||
|
||||
# Backend
|
||||
pybabel compile -d superset/translations
|
||||
```
|
||||
|
||||
## Linting
|
||||
|
||||
### Python
|
||||
|
||||
We use Ruff for Python linting and formatting:
|
||||
|
||||
```bash
|
||||
# Auto-format using ruff
|
||||
ruff format .
|
||||
|
||||
# Lint check with ruff
|
||||
ruff check .
|
||||
|
||||
# Lint fix with ruff
|
||||
ruff check --fix .
|
||||
```
|
||||
|
||||
Pre-commit hooks run automatically on `git commit` if installed.
|
||||
|
||||
### TypeScript
|
||||
|
||||
We use ESLint and Prettier for TypeScript:
|
||||
|
||||
```bash
|
||||
cd superset-frontend
|
||||
|
||||
# Run eslint checks
|
||||
npm run lint
|
||||
|
||||
# Run tsc (typescript) checks
|
||||
npm run type
|
||||
|
||||
# Fix lint issues
|
||||
npm run lint-fix
|
||||
|
||||
# Format with Prettier
|
||||
npm run prettier
|
||||
```
|
||||
|
||||
## GitHub Ephemeral Environments
|
||||
|
||||
For every PR, an ephemeral environment is automatically deployed for testing.
|
||||
|
||||
Access pattern: `https://pr-{PR_NUMBER}.superset.apache.org`
|
||||
|
||||
Features:
|
||||
- Automatically deployed on PR creation/update
|
||||
- Includes sample data
|
||||
- Destroyed when PR is closed
|
||||
- Useful for UI/UX review
|
||||
|
||||
## Tips and Tricks
|
||||
|
||||
### Using Docker for Development
|
||||
|
||||
```bash
|
||||
# Rebuild specific service
|
||||
docker compose build superset
|
||||
|
||||
# View logs
|
||||
docker compose logs -f superset
|
||||
|
||||
# Execute commands in container
|
||||
docker compose exec superset bash
|
||||
|
||||
# Reset database
|
||||
docker compose down -v
|
||||
docker compose up
|
||||
```
|
||||
|
||||
### Hot Reloading
|
||||
|
||||
**Frontend**: Webpack dev server provides hot module replacement automatically.
|
||||
|
||||
**Backend**: Use Flask debug mode:
|
||||
```bash
|
||||
FLASK_ENV=development superset run -p 8088 --with-threads --reload
|
||||
```
|
||||
|
||||
### Performance Profiling
|
||||
|
||||
For Python profiling:
|
||||
```python
|
||||
# In superset_config.py
|
||||
PROFILING = True
|
||||
```
|
||||
|
||||
For React profiling:
|
||||
- Use React DevTools Profiler
|
||||
- Enable performance marks in Chrome DevTools
|
||||
|
||||
### Database Migrations
|
||||
|
||||
```bash
|
||||
# Create a new migration
|
||||
superset db migrate -m "Description of changes"
|
||||
|
||||
# Apply migrations
|
||||
superset db upgrade
|
||||
|
||||
# Downgrade
|
||||
superset db downgrade
|
||||
```
|
||||
|
||||
### Useful Aliases
|
||||
|
||||
Add to your shell profile:
|
||||
|
||||
```bash
|
||||
alias sdev='FLASK_ENV=development superset run -p 8088 --with-threads --reload'
|
||||
alias stest='pytest tests/unit_tests'
|
||||
alias slint='pre-commit run --all-files'
|
||||
alias sfront='cd superset-frontend && npm run dev-server'
|
||||
```
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Node/npm Issues
|
||||
|
||||
```bash
|
||||
# Clear npm cache
|
||||
npm cache clean --force
|
||||
|
||||
# Reinstall dependencies
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install
|
||||
```
|
||||
|
||||
### Python Environment Issues
|
||||
|
||||
```bash
|
||||
# Recreate virtual environment
|
||||
deactivate
|
||||
rm -rf venv
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements/development.txt
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
### Database Issues
|
||||
|
||||
```bash
|
||||
# Reset local database
|
||||
superset db downgrade -r base
|
||||
superset db upgrade
|
||||
superset init
|
||||
```
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Find process using port
|
||||
lsof -i :8088
|
||||
# Kill process
|
||||
kill -9 [PID]
|
||||
```
|
||||
|
||||
## Reporting Security Vulnerabilities
|
||||
|
||||
Please report security vulnerabilities to **private@superset.apache.org**.
|
||||
|
||||
In the event a community member discovers a security flaw in Superset, it is important to follow the [Apache Security Guidelines](https://www.apache.org/security/committers.html) and release a fix as quickly as possible before public disclosure. Reporting security vulnerabilities through the usual GitHub Issues channel is not ideal as it will publicize the flaw before a fix can be applied.
|
||||
|
||||
## SQL Lab Async Configuration
|
||||
|
||||
It's possible to configure a local database to operate in `async` mode, to work on `async` related features.
|
||||
|
||||
To do this, you'll need to:
|
||||
|
||||
- Add an additional database entry. We recommend you copy the connection string from the database labeled `main`, and then enable `SQL Lab` and the features you want to use. Don't forget to check the `Async` box
|
||||
- Configure a results backend, here's a local `FileSystemCache` example, not recommended for production, but perfect for testing (stores cache in `/tmp`)
|
||||
|
||||
```python
|
||||
from flask_caching.backends.filesystemcache import FileSystemCache
|
||||
RESULTS_BACKEND = FileSystemCache('/tmp/sqllab')
|
||||
```
|
||||
|
||||
- Start up a celery worker
|
||||
|
||||
```bash
|
||||
celery --app=superset.tasks.celery_app:app worker -O fair
|
||||
```
|
||||
|
||||
Note that:
|
||||
- for changes that affect the worker logic, you'll have to restart the `celery worker` process for the changes to be reflected.
|
||||
- The message queue used is a `sqlite` database using the `SQLAlchemy` experimental broker. Ok for testing, but not recommended in production
|
||||
- In some cases, you may want to create a context that is more aligned to your production environment, and use the similar broker as well as results backend configuration
|
||||
|
||||
## Async Chart Queries
|
||||
|
||||
It's possible to configure database queries for charts to operate in `async` mode. This is especially useful for dashboards with many charts that may otherwise be affected by browser connection limits. To enable async queries for dashboards and Explore, the following dependencies are required:
|
||||
|
||||
- Redis 5.0+ (the feature utilizes [Redis Streams](https://redis.io/topics/streams-intro))
|
||||
- Cache backends enabled via the `CACHE_CONFIG` and `DATA_CACHE_CONFIG` config settings
|
||||
- Celery workers configured and running to process async tasks
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check the [FAQ](https://superset.apache.org/docs/frequently-asked-questions)
|
||||
- Ask in [Slack](https://apache-superset.slack.com)
|
||||
- Search [GitHub Issues](https://github.com/apache/superset/issues)
|
||||
- Post in [GitHub Discussions](https://github.com/apache/superset/discussions)
|
||||
418
docs/developer_portal/contributing/issue-reporting.md
Normal file
418
docs/developer_portal/contributing/issue-reporting.md
Normal file
@@ -0,0 +1,418 @@
|
||||
---
|
||||
title: Issue Reporting
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Issue Reporting
|
||||
|
||||
Learn how to effectively report bugs and request features for Apache Superset.
|
||||
|
||||
## Before Opening an Issue
|
||||
|
||||
### Pre-Issue Checklist
|
||||
|
||||
1. **Search Existing Issues**
|
||||
```
|
||||
Search: https://github.com/apache/superset/issues
|
||||
- Use keywords from your error message
|
||||
- Check both open and closed issues
|
||||
- Look for similar problems
|
||||
```
|
||||
|
||||
2. **Check Documentation**
|
||||
- [User Documentation](https://superset.apache.org/docs/intro)
|
||||
- [FAQ](https://superset.apache.org/docs/frequently-asked-questions)
|
||||
- [Configuration Guide](https://superset.apache.org/docs/configuration/configuring-superset)
|
||||
|
||||
3. **Verify Version**
|
||||
```bash
|
||||
# Check Superset version
|
||||
superset version
|
||||
|
||||
# Try latest version
|
||||
pip install --upgrade apache-superset
|
||||
```
|
||||
|
||||
4. **Reproduce Consistently**
|
||||
- Can you reproduce the issue?
|
||||
- Does it happen every time?
|
||||
- What specific actions trigger it?
|
||||
|
||||
## Bug Reports
|
||||
|
||||
### Bug Report Template
|
||||
|
||||
```markdown
|
||||
### Bug Description
|
||||
A clear and concise description of the bug.
|
||||
|
||||
### How to Reproduce
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
|
||||
### Expected Behavior
|
||||
What you expected to happen.
|
||||
|
||||
### Actual Behavior
|
||||
What actually happened. Include error messages.
|
||||
|
||||
### Screenshots/Videos
|
||||
If applicable, add screenshots or recordings.
|
||||
|
||||
### Environment
|
||||
- Superset version: [e.g., 3.0.0]
|
||||
- Python version: [e.g., 3.9.7]
|
||||
- Node version: [e.g., 18.17.0]
|
||||
- Database: [e.g., PostgreSQL 14]
|
||||
- Browser: [e.g., Chrome 120]
|
||||
- OS: [e.g., Ubuntu 22.04]
|
||||
|
||||
### Additional Context
|
||||
- Using Docker: Yes/No
|
||||
- Configuration overrides:
|
||||
- Feature flags enabled:
|
||||
- Authentication method:
|
||||
```
|
||||
|
||||
### What Makes a Good Bug Report
|
||||
|
||||
#### ✅ Good Example
|
||||
```markdown
|
||||
### Bug Description
|
||||
When filtering a dashboard with a date range filter, charts using
|
||||
SQL Lab datasets don't update, while charts using regular datasets do.
|
||||
|
||||
### How to Reproduce
|
||||
1. Create a dashboard with 2 charts:
|
||||
- Chart A: Uses a SQL Lab virtual dataset
|
||||
- Chart B: Uses a regular table dataset
|
||||
2. Add a date range filter (last 30 days)
|
||||
3. Apply the filter
|
||||
4. Chart B updates, Chart A shows no change
|
||||
|
||||
### Expected Behavior
|
||||
Both charts should filter to show last 30 days of data.
|
||||
|
||||
### Actual Behavior
|
||||
Only Chart B updates. Chart A still shows all data.
|
||||
No error messages in browser console or server logs.
|
||||
|
||||
### Screenshots
|
||||
[Dashboard before filter]: attachment1.png
|
||||
[Dashboard after filter]: attachment2.png
|
||||
[Network tab showing requests]: attachment3.png
|
||||
|
||||
### Environment
|
||||
- Superset version: 3.0.0
|
||||
- Python version: 3.9.16
|
||||
- Database: PostgreSQL 14.9
|
||||
- Browser: Chrome 120.0.6099.71
|
||||
- OS: macOS 14.2
|
||||
```
|
||||
|
||||
#### ❌ Poor Example
|
||||
```markdown
|
||||
Dashboard filters don't work. Please fix.
|
||||
```
|
||||
|
||||
### Required Information
|
||||
|
||||
#### Error Messages
|
||||
```python
|
||||
# Include full error traceback
|
||||
Traceback (most recent call last):
|
||||
File "...", line X, in function
|
||||
error details
|
||||
SupersetException: Detailed error message
|
||||
```
|
||||
|
||||
#### Logs
|
||||
```bash
|
||||
# Backend logs
|
||||
docker logs superset_app 2>&1 | tail -100
|
||||
|
||||
# Or from development
|
||||
tail -f ~/.superset/superset.log
|
||||
```
|
||||
|
||||
#### Browser Console
|
||||
```javascript
|
||||
// Include JavaScript errors
|
||||
// Chrome: F12 → Console tab
|
||||
// Include network errors
|
||||
// Chrome: F12 → Network tab
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
```python
|
||||
# Relevant config from superset_config.py
|
||||
FEATURE_FLAGS = {
|
||||
"ENABLE_TEMPLATE_PROCESSING": True,
|
||||
# ... other flags
|
||||
}
|
||||
```
|
||||
|
||||
## Feature Requests
|
||||
|
||||
### Feature Request Template
|
||||
|
||||
```markdown
|
||||
### Is your feature request related to a problem?
|
||||
A clear description of the problem you're trying to solve.
|
||||
|
||||
### Describe the solution you'd like
|
||||
A clear description of what you want to happen.
|
||||
|
||||
### Describe alternatives you've considered
|
||||
Other solutions or features you've considered.
|
||||
|
||||
### Additional context
|
||||
Any other context, mockups, or examples.
|
||||
|
||||
### Are you willing to contribute?
|
||||
- [ ] Yes, I can implement this feature
|
||||
- [ ] Yes, I can help test
|
||||
- [ ] No, but I can provide feedback
|
||||
```
|
||||
|
||||
### Good Feature Requests Include
|
||||
|
||||
1. **Clear Use Case**
|
||||
```markdown
|
||||
As a [type of user], I want [feature] so that [benefit].
|
||||
|
||||
Example:
|
||||
As a data analyst, I want to schedule dashboard screenshots
|
||||
so that I can automatically send reports to stakeholders.
|
||||
```
|
||||
|
||||
2. **Mockups/Designs**
|
||||
- UI mockups
|
||||
- Workflow diagrams
|
||||
- API specifications
|
||||
|
||||
3. **Impact Analysis**
|
||||
- Who benefits?
|
||||
- How many users affected?
|
||||
- Performance implications?
|
||||
|
||||
## Security Issues
|
||||
|
||||
### 🔴 IMPORTANT: Security Vulnerabilities
|
||||
|
||||
**DO NOT** create public issues for security vulnerabilities!
|
||||
|
||||
Instead:
|
||||
1. Email: security@apache.org
|
||||
2. Subject: `[Superset] Security Vulnerability`
|
||||
3. Include:
|
||||
- Description of vulnerability
|
||||
- Steps to reproduce
|
||||
- Potential impact
|
||||
- Suggested fix (if any)
|
||||
|
||||
### Security Issue Template
|
||||
|
||||
```markdown
|
||||
Send to: security@apache.org
|
||||
|
||||
### Vulnerability Description
|
||||
[Describe the security issue]
|
||||
|
||||
### Type
|
||||
- [ ] SQL Injection
|
||||
- [ ] XSS
|
||||
- [ ] CSRF
|
||||
- [ ] Authentication Bypass
|
||||
- [ ] Information Disclosure
|
||||
- [ ] Other: [specify]
|
||||
|
||||
### Affected Versions
|
||||
[List affected versions]
|
||||
|
||||
### Steps to Reproduce
|
||||
[Detailed steps - be specific]
|
||||
|
||||
### Impact
|
||||
[What can an attacker do?]
|
||||
|
||||
### Suggested Fix
|
||||
[If you have suggestions]
|
||||
```
|
||||
|
||||
## Issue Labels
|
||||
|
||||
### Priority Labels
|
||||
- `P0`: Critical - System unusable
|
||||
- `P1`: High - Major feature broken
|
||||
- `P2`: Medium - Important but workaround exists
|
||||
- `P3`: Low - Nice to have
|
||||
|
||||
### Type Labels
|
||||
- `bug`: Something isn't working
|
||||
- `feature`: New feature request
|
||||
- `enhancement`: Improvement to existing feature
|
||||
- `documentation`: Documentation improvements
|
||||
- `question`: Question about usage
|
||||
|
||||
### Component Labels
|
||||
- `dashboard`: Dashboard functionality
|
||||
- `sqllab`: SQL Lab
|
||||
- `explore`: Chart builder
|
||||
- `visualization`: Chart types
|
||||
- `api`: REST API
|
||||
- `security`: Security related
|
||||
|
||||
### Status Labels
|
||||
- `needs-triage`: Awaiting review
|
||||
- `confirmed`: Bug confirmed
|
||||
- `in-progress`: Being worked on
|
||||
- `blocked`: Blocked by dependency
|
||||
- `stale`: No activity for 30+ days
|
||||
|
||||
## Issue Lifecycle
|
||||
|
||||
### 1. Creation
|
||||
- User creates issue with template
|
||||
- Auto-labeled as `needs-triage`
|
||||
|
||||
### 2. Triage
|
||||
- Maintainer reviews within 7 days
|
||||
- Labels applied (priority, type, component)
|
||||
- Questions asked if needed
|
||||
|
||||
### 3. Confirmation
|
||||
- Bug reproduced or feature discussed
|
||||
- Label changed to `confirmed`
|
||||
- Assigned to milestone if applicable
|
||||
|
||||
### 4. Development
|
||||
- Contributor claims issue
|
||||
- Label changed to `in-progress`
|
||||
- PR linked to issue
|
||||
|
||||
### 5. Resolution
|
||||
- PR merged
|
||||
- Issue auto-closed
|
||||
- Or manually closed with explanation
|
||||
|
||||
## Following Up
|
||||
|
||||
### If No Response
|
||||
|
||||
After 7 days without response:
|
||||
```markdown
|
||||
@apache/superset-committers This issue hasn't been triaged yet.
|
||||
Could someone please take a look?
|
||||
```
|
||||
|
||||
### Providing Updates
|
||||
|
||||
```markdown
|
||||
Update: I found that this only happens when [condition].
|
||||
Here's additional debugging information: [details]
|
||||
```
|
||||
|
||||
### Issue Staleness
|
||||
|
||||
- Bot marks stale after 30 days of inactivity
|
||||
- Closes after 7 more days without activity
|
||||
- To keep open: Comment with updates
|
||||
|
||||
## Tips for Success
|
||||
|
||||
### Do's
|
||||
- ✅ Search before creating
|
||||
- ✅ Use templates
|
||||
- ✅ Provide complete information
|
||||
- ✅ Include screenshots/videos
|
||||
- ✅ Be responsive to questions
|
||||
- ✅ Test with latest version
|
||||
- ✅ One issue per report
|
||||
|
||||
### Don'ts
|
||||
- ❌ "+1" or "me too" comments (use reactions)
|
||||
- ❌ Multiple issues in one report
|
||||
- ❌ Vague descriptions
|
||||
- ❌ Screenshots of text (copy/paste instead)
|
||||
- ❌ Private/sensitive data in reports
|
||||
- ❌ Demanding immediate fixes
|
||||
|
||||
## Useful Commands
|
||||
|
||||
### Gathering System Info
|
||||
|
||||
```bash
|
||||
# Full environment info
|
||||
python -c "
|
||||
import sys
|
||||
import superset
|
||||
import sqlalchemy
|
||||
import pandas
|
||||
import numpy
|
||||
|
||||
print(f'Python: {sys.version}')
|
||||
print(f'Superset: {superset.__version__}')
|
||||
print(f'SQLAlchemy: {sqlalchemy.__version__}')
|
||||
print(f'Pandas: {pandas.__version__}')
|
||||
print(f'NumPy: {numpy.__version__}')
|
||||
"
|
||||
|
||||
# Database versions
|
||||
superset shell
|
||||
>>> from superset import db
|
||||
>>> print(db.engine.dialect.server_version_info)
|
||||
```
|
||||
|
||||
### Creating Minimal Reproductions
|
||||
|
||||
```python
|
||||
# Create test script
|
||||
# minimal_repro.py
|
||||
from superset import create_app
|
||||
|
||||
app = create_app()
|
||||
with app.app_context():
|
||||
# Your reproduction code here
|
||||
pass
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Before Creating an Issue
|
||||
|
||||
1. **Slack**: Ask in #troubleshooting
|
||||
2. **GitHub Discussions**: Search/ask questions
|
||||
3. **Stack Overflow**: Tag `apache-superset`
|
||||
4. **Mailing List**: user@superset.apache.org
|
||||
|
||||
### Issue Not a Bug?
|
||||
|
||||
Consider:
|
||||
- **Feature Request**: Use feature request template
|
||||
- **Question**: Use GitHub Discussions
|
||||
- **Configuration Help**: Ask in Slack
|
||||
- **Development Help**: See [Contributing Guide](./overview)
|
||||
|
||||
Next: [Understanding the release process](./release-process)
|
||||
166
docs/developer_portal/contributing/overview.md
Normal file
166
docs/developer_portal/contributing/overview.md
Normal file
@@ -0,0 +1,166 @@
|
||||
---
|
||||
title: Contributing Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Contributing to Apache Superset
|
||||
|
||||
Superset is an [Apache Software foundation](https://www.apache.org/theapacheway/index.html) project.
|
||||
The core contributors (or committers) to Superset communicate primarily in the following channels (which can be joined by anyone):
|
||||
|
||||
- [Mailing list](https://lists.apache.org/list.html?dev@superset.apache.org)
|
||||
- [Apache Superset Slack community](http://bit.ly/join-superset-slack)
|
||||
- [GitHub issues](https://github.com/apache/superset/issues)
|
||||
- [GitHub pull requests](https://github.com/apache/superset/pulls)
|
||||
- [GitHub discussions](https://github.com/apache/superset/discussions)
|
||||
- [Superset Community Calendar](https://superset.apache.org/community)
|
||||
|
||||
More references:
|
||||
|
||||
- [Superset Wiki (code guidelines and additional resources)](https://github.com/apache/superset/wiki)
|
||||
|
||||
## Orientation
|
||||
|
||||
Here's a list of repositories that contain Superset-related packages:
|
||||
|
||||
- [apache/superset](https://github.com/apache/superset)
|
||||
is the main repository containing the `apache_superset` Python package
|
||||
distributed on
|
||||
[pypi](https://pypi.org/project/apache_superset/). This repository
|
||||
also includes Superset's main TypeScript/JavaScript bundles and react apps under
|
||||
the [superset-frontend](https://github.com/apache/superset/tree/master/superset-frontend)
|
||||
folder.
|
||||
- [github.com/apache-superset](https://github.com/apache-superset) is the
|
||||
GitHub organization under which we manage Superset-related
|
||||
small tools, forks and Superset-related experimental ideas.
|
||||
|
||||
## Types of Contributions
|
||||
|
||||
### Report Bug
|
||||
|
||||
The best way to report a bug is to file an issue on GitHub. Please include:
|
||||
|
||||
- Your operating system name and version.
|
||||
- Superset version.
|
||||
- Detailed steps to reproduce the bug.
|
||||
- Any details about your local setup that might be helpful in troubleshooting.
|
||||
|
||||
When posting Python stack traces, please quote them using
|
||||
[Markdown blocks](https://help.github.com/articles/creating-and-highlighting-code-blocks/).
|
||||
|
||||
_Please note that feature requests opened as GitHub Issues will be moved to Discussions._
|
||||
|
||||
### Submit Ideas or Feature Requests
|
||||
|
||||
The best way is to start an ["Ideas" Discussion thread](https://github.com/apache/superset/discussions/categories/ideas) on GitHub:
|
||||
|
||||
- Explain in detail how it would work.
|
||||
- Keep the scope as narrow as possible, to make it easier to implement.
|
||||
- Remember that this is a volunteer-driven project, and that your contributions are as welcome as anyone's :)
|
||||
|
||||
To propose large features or major changes to codebase, and help usher in those changes, please create a **Superset Improvement Proposal (SIP)**. See template from [SIP-0](https://github.com/apache/superset/issues/5602)
|
||||
|
||||
### Fix Bugs
|
||||
|
||||
Look through the GitHub issues. Issues tagged with `#bug` are
|
||||
open to whoever wants to implement them.
|
||||
|
||||
### Implement Features
|
||||
|
||||
Look through the GitHub issues. Issues tagged with
|
||||
`#feature` are open to whoever wants to implement them.
|
||||
|
||||
### Improve Documentation
|
||||
|
||||
Superset could always use better documentation,
|
||||
whether as part of the official Superset docs,
|
||||
in docstrings, `docs/*.rst` or even on the web as blog posts or
|
||||
articles. See [Documentation](./howtos#contributing-to-documentation) for more details.
|
||||
|
||||
### Add Translations
|
||||
|
||||
If you are proficient in a non-English language, you can help translate
|
||||
text strings from Superset's UI. You can jump into the existing
|
||||
language dictionaries at
|
||||
`superset/translations/<language_code>/LC_MESSAGES/messages.po`, or
|
||||
even create a dictionary for a new language altogether.
|
||||
See [Translating](./howtos#contributing-translations) for more details.
|
||||
|
||||
### Ask Questions
|
||||
|
||||
There is a dedicated [`apache-superset` tag](https://stackoverflow.com/questions/tagged/apache-superset) on [StackOverflow](https://stackoverflow.com/). Please use it when asking questions.
|
||||
|
||||
## Types of Contributors
|
||||
|
||||
Following the project governance model of the Apache Software Foundation (ASF), Apache Superset has a specific set of contributor roles:
|
||||
|
||||
### PMC Member
|
||||
|
||||
A Project Management Committee (PMC) member is a person who has been elected by the PMC to help manage the project. PMC members are responsible for the overall health of the project, including community development, release management, and project governance. PMC members are also responsible for the technical direction of the project.
|
||||
|
||||
For more information about Apache Project PMCs, please refer to https://www.apache.org/foundation/governance/pmcs.html
|
||||
|
||||
### Committer
|
||||
|
||||
A committer is a person who has been elected by the PMC to have write access (commit access) to the code repository. They can modify the code, documentation, and website and accept contributions from others.
|
||||
|
||||
The official list of committers and PMC members can be found [here](https://projects.apache.org/committee.html?superset).
|
||||
|
||||
### Contributor
|
||||
|
||||
A contributor is a person who has contributed to the project in any way, including but not limited to code, tests, documentation, issues, and discussions.
|
||||
|
||||
> You can also review the Superset project's guidelines for PMC member promotion here: https://github.com/apache/superset/wiki/Guidelines-for-promoting-Superset-Committers-to-the-Superset-PMC
|
||||
|
||||
### Security Team
|
||||
|
||||
The security team is a selected subset of PMC members, committers and non-committers who are responsible for handling security issues.
|
||||
|
||||
New members of the security team are selected by the PMC members in a vote. You can request to be added to the team by sending a message to private@superset.apache.org. However, the team should be small and focused on solving security issues, so the requests will be evaluated on a case-by-case basis and the team size will be kept relatively small, limited to only actively security-focused contributors.
|
||||
|
||||
This security team must follow the [ASF vulnerability handling process](https://apache.org/security/committers.html#asf-project-security-for-committers).
|
||||
|
||||
Each new security issue is tracked as a JIRA ticket on the [ASF's JIRA Superset security project](https://issues.apache.org/jira/secure/RapidBoard.jspa?rapidView=588&projectKey=SUPERSETSEC)
|
||||
|
||||
Security team members must:
|
||||
|
||||
- Have an [ICLA](https://www.apache.org/licenses/contributor-agreements.html) signed with Apache Software Foundation.
|
||||
- Not reveal information about pending and unfixed security issues to anyone (including their employers) unless specifically authorised by the security team members, e.g., if the security team agrees that diagnosing and solving an issue requires the involvement of external experts.
|
||||
|
||||
A release manager, the contributor overseeing the release of a specific version of Apache Superset, is by default a member of the security team. However, they are not expected to be active in assessing, discussing, and fixing security issues.
|
||||
|
||||
Security team members should also follow these general expectations:
|
||||
|
||||
- Actively participate in assessing, discussing, fixing, and releasing security issues in Superset.
|
||||
- Avoid discussing security fixes in public forums. Pull request (PR) descriptions should not contain any information about security issues. The corresponding JIRA ticket should contain a link to the PR.
|
||||
- Security team members who contribute to a fix may be listed as remediation developers in the CVE report, along with their job affiliation (if they choose to include it).
|
||||
|
||||
## Getting Started
|
||||
|
||||
Ready to contribute? Here's how to get started:
|
||||
|
||||
1. **[Set up your environment](./development-setup)** - Get Superset running locally
|
||||
2. **[Find something to work on](#types-of-contributions)** - Pick an issue or feature
|
||||
3. **[Submit your contribution](./submitting-pr)** - Create a pull request
|
||||
4. **[Follow guidelines](./guidelines)** - Ensure code quality
|
||||
|
||||
Welcome to the Apache Superset community! 🚀
|
||||
469
docs/developer_portal/contributing/release-process.md
Normal file
469
docs/developer_portal/contributing/release-process.md
Normal file
@@ -0,0 +1,469 @@
|
||||
---
|
||||
title: Release Process
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Release Process
|
||||
|
||||
Understand Apache Superset's release process, versioning strategy, and how to participate.
|
||||
|
||||
## Release Cadence
|
||||
|
||||
### Schedule
|
||||
- **Major releases (X.0.0)**: Annually (approximately)
|
||||
- **Minor releases (X.Y.0)**: Quarterly
|
||||
- **Patch releases (X.Y.Z)**: As needed for critical fixes
|
||||
|
||||
### Version Numbering
|
||||
|
||||
Superset follows [Semantic Versioning](https://semver.org/):
|
||||
|
||||
```
|
||||
MAJOR.MINOR.PATCH
|
||||
↓ ↓ ↓
|
||||
│ │ └── Bug fixes, security patches
|
||||
│ └────── New features, backwards compatible
|
||||
└──────────── Breaking changes
|
||||
```
|
||||
|
||||
### Examples
|
||||
- `3.0.0`: Major release with breaking changes
|
||||
- `3.1.0`: Minor release with new features
|
||||
- `3.1.1`: Patch release with bug fixes
|
||||
|
||||
## Release Types
|
||||
|
||||
### Major Releases (X.0.0)
|
||||
|
||||
#### Includes
|
||||
- Breaking API changes
|
||||
- Deprecated feature removals
|
||||
- Major architectural changes
|
||||
- Database migration requirements
|
||||
|
||||
#### Process
|
||||
- 2-3 month preparation period
|
||||
- Multiple release candidates (RC)
|
||||
- Extensive testing period
|
||||
- Migration guides required
|
||||
|
||||
### Minor Releases (X.Y.0)
|
||||
|
||||
#### Includes
|
||||
- New features
|
||||
- Performance improvements
|
||||
- Non-breaking API additions
|
||||
- Minor UI/UX updates
|
||||
|
||||
#### Process
|
||||
- 1 month preparation
|
||||
- 1-2 release candidates
|
||||
- Standard testing period
|
||||
|
||||
### Patch Releases (X.Y.Z)
|
||||
|
||||
#### Includes
|
||||
- Bug fixes
|
||||
- Security patches
|
||||
- Documentation fixes
|
||||
- Dependency updates (security)
|
||||
|
||||
#### Process
|
||||
- Fast track for critical issues
|
||||
- May skip RC for urgent security fixes
|
||||
- Minimal testing requirements
|
||||
|
||||
## Release Process (For Release Managers)
|
||||
|
||||
### 1. Pre-Release Preparation
|
||||
|
||||
#### Feature Freeze
|
||||
```bash
|
||||
# Create release branch
|
||||
git checkout -b release-X.Y
|
||||
git push upstream release-X.Y
|
||||
|
||||
# Update version
|
||||
# Edit setup.py and package.json
|
||||
VERSION = "X.Y.0rc1"
|
||||
```
|
||||
|
||||
#### Update Documentation
|
||||
- CHANGELOG.md
|
||||
- UPDATING.md (for breaking changes)
|
||||
- Documentation version
|
||||
|
||||
#### Release Notes Template
|
||||
```markdown
|
||||
# Apache Superset X.Y.0
|
||||
|
||||
## 🎉 Highlights
|
||||
- Major feature 1
|
||||
- Major feature 2
|
||||
|
||||
## 🚀 New Features
|
||||
- Feature 1 (#PR)
|
||||
- Feature 2 (#PR)
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
- Fix 1 (#PR)
|
||||
- Fix 2 (#PR)
|
||||
|
||||
## ⚠️ Breaking Changes
|
||||
- Breaking change 1
|
||||
- Migration required for X
|
||||
|
||||
## 📝 Documentation
|
||||
- Doc update 1 (#PR)
|
||||
|
||||
## 🙏 Thank You
|
||||
Thanks to all contributors!
|
||||
```
|
||||
|
||||
### 2. Create Release Candidate
|
||||
|
||||
#### Build RC
|
||||
```bash
|
||||
# Tag release candidate
|
||||
git tag -a vX.Y.Zrc1 -m "Apache Superset X.Y.Z RC1"
|
||||
git push upstream vX.Y.Zrc1
|
||||
|
||||
# Build source distribution
|
||||
python setup.py sdist
|
||||
|
||||
# Build wheel
|
||||
python setup.py bdist_wheel
|
||||
|
||||
# Sign artifacts
|
||||
gpg --armor --detach-sig dist/apache-superset-X.Y.Zrc1.tar.gz
|
||||
```
|
||||
|
||||
#### Upload to staging
|
||||
```bash
|
||||
# Upload to Apache staging
|
||||
svn co https://dist.apache.org/repos/dist/dev/superset
|
||||
cd superset
|
||||
mkdir X.Y.Zrc1
|
||||
cp /path/to/dist/* X.Y.Zrc1/
|
||||
svn add X.Y.Zrc1
|
||||
svn commit -m "Add Apache Superset X.Y.Z RC1"
|
||||
```
|
||||
|
||||
### 3. Voting Process
|
||||
|
||||
#### Call for Vote Email
|
||||
|
||||
Send to dev@superset.apache.org:
|
||||
|
||||
```
|
||||
Subject: [VOTE] Release Apache Superset X.Y.Z RC1
|
||||
|
||||
Hi all,
|
||||
|
||||
I'd like to call a vote to release Apache Superset version X.Y.Z RC1.
|
||||
|
||||
The release candidate:
|
||||
- Git tag: vX.Y.Zrc1
|
||||
- Git hash: abc123def456
|
||||
- Source: https://dist.apache.org/repos/dist/dev/superset/X.Y.Zrc1/
|
||||
|
||||
Resources:
|
||||
- Release notes: [link]
|
||||
- CHANGELOG: [link]
|
||||
- PR list: [link]
|
||||
|
||||
The vote will be open for at least 72 hours.
|
||||
|
||||
[ ] +1 approve
|
||||
[ ] +0 no opinion
|
||||
[ ] -1 disapprove (and reason why)
|
||||
|
||||
Thanks,
|
||||
[Your name]
|
||||
```
|
||||
|
||||
#### Voting Rules
|
||||
- **Duration**: Minimum 72 hours
|
||||
- **Required**: 3 +1 votes from PMC members
|
||||
- **Veto**: Any -1 vote must be addressed
|
||||
|
||||
#### Testing Checklist
|
||||
```markdown
|
||||
- [ ] Source builds successfully
|
||||
- [ ] Docker image builds
|
||||
- [ ] Basic functionality works
|
||||
- [ ] No critical bugs
|
||||
- [ ] License check passes
|
||||
- [ ] Security scan clean
|
||||
```
|
||||
|
||||
### 4. Release Approval
|
||||
|
||||
#### Tally Votes
|
||||
```
|
||||
Subject: [RESULT][VOTE] Release Apache Superset X.Y.Z RC1
|
||||
|
||||
The vote to release Apache Superset X.Y.Z RC1 has passed.
|
||||
|
||||
+1 votes (binding):
|
||||
- PMC Member 1
|
||||
- PMC Member 2
|
||||
- PMC Member 3
|
||||
|
||||
+1 votes (non-binding):
|
||||
- Contributor 1
|
||||
- Contributor 2
|
||||
|
||||
0 votes:
|
||||
- None
|
||||
|
||||
-1 votes:
|
||||
- None
|
||||
|
||||
Thank you to everyone who tested and voted!
|
||||
```
|
||||
|
||||
### 5. Perform Release
|
||||
|
||||
#### Promote RC to Release
|
||||
```bash
|
||||
# Tag final release
|
||||
git tag -a vX.Y.Z -m "Apache Superset X.Y.Z"
|
||||
git push upstream vX.Y.Z
|
||||
|
||||
# Move from dev to release
|
||||
svn mv https://dist.apache.org/repos/dist/dev/superset/X.Y.Zrc1 \
|
||||
https://dist.apache.org/repos/dist/release/superset/X.Y.Z
|
||||
```
|
||||
|
||||
#### Publish to PyPI
|
||||
```bash
|
||||
# Upload to PyPI
|
||||
python -m twine upload dist/*X.Y.Z*
|
||||
```
|
||||
|
||||
#### Build Docker Images
|
||||
```bash
|
||||
# Build and push Docker images
|
||||
docker build -t apache/superset:X.Y.Z .
|
||||
docker push apache/superset:X.Y.Z
|
||||
docker tag apache/superset:X.Y.Z apache/superset:latest
|
||||
docker push apache/superset:latest
|
||||
```
|
||||
|
||||
### 6. Post-Release Tasks
|
||||
|
||||
#### Update Documentation
|
||||
```bash
|
||||
# Update docs version
|
||||
cd docs
|
||||
# Update docusaurus.config.js with new version
|
||||
npm run build
|
||||
```
|
||||
|
||||
#### Announcement Email
|
||||
|
||||
Send to announce@apache.org, dev@superset.apache.org:
|
||||
|
||||
```
|
||||
Subject: [ANNOUNCE] Apache Superset X.Y.Z Released
|
||||
|
||||
The Apache Superset team is pleased to announce the release of
|
||||
Apache Superset X.Y.Z.
|
||||
|
||||
Apache Superset is a modern data exploration and visualization platform.
|
||||
|
||||
This release includes [number] commits from [number] contributors.
|
||||
|
||||
Highlights:
|
||||
- Feature 1
|
||||
- Feature 2
|
||||
- Bug fixes and improvements
|
||||
|
||||
Download: https://superset.apache.org/docs/installation/
|
||||
Release Notes: https://github.com/apache/superset/releases/tag/vX.Y.Z
|
||||
PyPI: https://pypi.org/project/apache-superset/
|
||||
Docker: docker pull apache/superset:X.Y.Z
|
||||
|
||||
Thanks to all contributors who made this release possible!
|
||||
|
||||
The Apache Superset Team
|
||||
```
|
||||
|
||||
#### Update GitHub Release
|
||||
```bash
|
||||
# Create GitHub release
|
||||
gh release create vX.Y.Z \
|
||||
--title "Apache Superset X.Y.Z" \
|
||||
--notes-file RELEASE_NOTES.md
|
||||
```
|
||||
|
||||
## For Contributors
|
||||
|
||||
### During Feature Freeze
|
||||
|
||||
#### What's Allowed
|
||||
- ✅ Bug fixes
|
||||
- ✅ Documentation updates
|
||||
- ✅ Test improvements
|
||||
- ✅ Security fixes
|
||||
|
||||
#### What's Not Allowed
|
||||
- ❌ New features
|
||||
- ❌ Major refactoring
|
||||
- ❌ Breaking changes
|
||||
- ❌ Risky changes
|
||||
|
||||
### Testing RCs
|
||||
|
||||
#### How to Test
|
||||
```bash
|
||||
# Install RC from staging
|
||||
pip install https://dist.apache.org/repos/dist/dev/superset/X.Y.Zrc1/apache-superset-X.Y.Zrc1.tar.gz
|
||||
|
||||
# Or use Docker
|
||||
docker pull apache/superset:X.Y.Zrc1
|
||||
```
|
||||
|
||||
#### What to Test
|
||||
- Your use cases
|
||||
- New features mentioned in release notes
|
||||
- Upgrade from previous version
|
||||
- Database migrations
|
||||
- Critical workflows
|
||||
|
||||
#### Reporting Issues
|
||||
```markdown
|
||||
Found issue in RC1:
|
||||
- Description: [what's wrong]
|
||||
- Steps to reproduce: [how to trigger]
|
||||
- Impact: [blocker/major/minor]
|
||||
- Suggested fix: [if known]
|
||||
```
|
||||
|
||||
### CHANGELOG Maintenance
|
||||
|
||||
#### Format
|
||||
```markdown
|
||||
## X.Y.Z (YYYY-MM-DD)
|
||||
|
||||
### Features
|
||||
- feat: Description (#PR_NUMBER)
|
||||
|
||||
### Fixes
|
||||
- fix: Description (#PR_NUMBER)
|
||||
|
||||
### Breaking Changes
|
||||
- BREAKING: Description (#PR_NUMBER)
|
||||
Migration: Steps to migrate
|
||||
```
|
||||
|
||||
#### Generating CHANGELOG
|
||||
```bash
|
||||
# Use git log to generate initial list
|
||||
git log --oneline vX.Y-1.Z..vX.Y.Z | grep -E "^[a-f0-9]+ (feat|fix|perf|refactor|docs)"
|
||||
|
||||
# Group by type and format
|
||||
```
|
||||
|
||||
## Breaking Changes Process
|
||||
|
||||
### Documentation Required
|
||||
|
||||
#### UPDATING.md Entry
|
||||
```markdown
|
||||
# X.Y.Z
|
||||
|
||||
## Breaking Change: [Title]
|
||||
|
||||
### Description
|
||||
What changed and why.
|
||||
|
||||
### Before
|
||||
```python
|
||||
# Old way
|
||||
old_function(param1, param2)
|
||||
```
|
||||
|
||||
### After
|
||||
```python
|
||||
# New way
|
||||
new_function(param1, param2, param3)
|
||||
```
|
||||
|
||||
### Migration Steps
|
||||
1. Update your code to...
|
||||
2. Run migration script...
|
||||
3. Test that...
|
||||
```
|
||||
|
||||
### Deprecation Process
|
||||
|
||||
1. **Version N**: Mark as deprecated
|
||||
```python
|
||||
@deprecated(version="3.0.0", remove_in="4.0.0")
|
||||
def old_function():
|
||||
warnings.warn("Use new_function instead", DeprecationWarning)
|
||||
```
|
||||
|
||||
2. **Version N+1**: Keep deprecated with warnings
|
||||
|
||||
3. **Version N+2**: Remove completely
|
||||
|
||||
## Security Releases
|
||||
|
||||
### Expedited Process
|
||||
- No RC required for critical security fixes
|
||||
- Coordinate with security@apache.org
|
||||
- Embargo period may apply
|
||||
- CVE assignment through ASF security team
|
||||
|
||||
### Security Advisory Template
|
||||
```markdown
|
||||
CVE-YYYY-XXXXX: [Title]
|
||||
|
||||
Severity: [Critical/High/Medium/Low]
|
||||
Affected Versions: < X.Y.Z
|
||||
Fixed Version: X.Y.Z
|
||||
|
||||
Description:
|
||||
[Vulnerability description]
|
||||
|
||||
Mitigation:
|
||||
[How to fix or work around]
|
||||
|
||||
Credit:
|
||||
[Reporter name/organization]
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Internal
|
||||
- [Apache Release Policy](https://www.apache.org/legal/release-policy.html)
|
||||
- [Superset Release History](https://github.com/apache/superset/releases)
|
||||
- [Version Strategy Discussion](https://github.com/apache/superset/discussions)
|
||||
|
||||
### Tools
|
||||
- [Release Scripts](https://github.com/apache/superset/tree/master/scripts/release)
|
||||
- [Superset Repository Scripts](https://github.com/apache/superset/tree/master/scripts)
|
||||
|
||||
Next: Return to [Contributing Overview](./overview)
|
||||
133
docs/developer_portal/contributing/resources.md
Normal file
133
docs/developer_portal/contributing/resources.md
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
title: Resources
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Resources
|
||||
|
||||
## High Level Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
|
||||
%% Top Level
|
||||
LB["<b>Load Balancer(s)</b><br/>(optional)"]
|
||||
LB -.-> WebServers
|
||||
|
||||
%% Web Servers
|
||||
subgraph WebServers ["<b>Web Server(s)</b>"]
|
||||
WS1["<b>Frontend</b><br/>(React, AntD, ECharts, AGGrid)"]
|
||||
WS2["<b>Backend</b><br/>(Python, Flask, SQLAlchemy, Pandas, ...)"]
|
||||
end
|
||||
|
||||
%% Infra
|
||||
subgraph InfraServices ["<b>Infra</b>"]
|
||||
DB[("<b>Metadata Database</b><br/>(Postgres / MySQL)")]
|
||||
|
||||
subgraph Caching ["<b>Caching Subservices<br/></b>(Redis, memcache, S3, ...)"]
|
||||
direction LR
|
||||
DummySpace[" "]:::invisible
|
||||
QueryCache["<b>Query Results Cache</b><br/>(Accelerated Dashboards)"]
|
||||
CsvCache["<b>CSV Exports Cache</b>"]
|
||||
ThumbnailCache["<b>Thumbnails Cache</b>"]
|
||||
AlertImageCache["<b>Alert/Report Images Cache</b>"]
|
||||
QueryCache -- " " --> CsvCache
|
||||
linkStyle 1 stroke:transparent;
|
||||
ThumbnailCache -- " " --> AlertImageCache
|
||||
linkStyle 2 stroke:transparent;
|
||||
end
|
||||
|
||||
Broker(("<b>Message Queue</b><br/>(Redis / RabbitMQ / SQS)"))
|
||||
end
|
||||
|
||||
AsyncBackend["<b>Async Workers (Celery)</b><br>required for Alerts & Reports, thumbnails, CSV exports, long-running workloads, ..."]
|
||||
|
||||
%% External DBs
|
||||
subgraph ExternalDatabases ["<b>Analytics Databases</b>"]
|
||||
direction LR
|
||||
BigQuery[(BigQuery)]
|
||||
Snowflake[(Snowflake)]
|
||||
Redshift[(Redshift)]
|
||||
Postgres[(Postgres)]
|
||||
Postgres[(... any ...)]
|
||||
end
|
||||
|
||||
%% Connections
|
||||
LB -.-> WebServers
|
||||
WebServers --> DB
|
||||
WebServers -.-> Caching
|
||||
WebServers -.-> Broker
|
||||
WebServers -.-> ExternalDatabases
|
||||
|
||||
Broker -.-> AsyncBackend
|
||||
|
||||
AsyncBackend -.-> ExternalDatabases
|
||||
AsyncBackend -.-> Caching
|
||||
|
||||
|
||||
|
||||
%% Legend styling
|
||||
classDef requiredNode stroke-width:2px,stroke:black;
|
||||
class Required requiredNode;
|
||||
class Optional optionalNode;
|
||||
|
||||
%% Hide real arrow
|
||||
linkStyle 0 stroke:transparent;
|
||||
|
||||
%% Styling
|
||||
classDef optionalNode stroke-dasharray: 5 5, opacity:0.9;
|
||||
class LB optionalNode;
|
||||
class Caching optionalNode;
|
||||
class AsyncBackend optionalNode;
|
||||
class Broker optionalNode;
|
||||
class QueryCache optionalNode;
|
||||
class CsvCache optionalNode;
|
||||
class ThumbnailCache optionalNode;
|
||||
class AlertImageCache optionalNode;
|
||||
class Celery optionalNode;
|
||||
|
||||
classDef invisible fill:transparent,stroke:transparent;
|
||||
```
|
||||
|
||||
## Entity-Relationship Diagram
|
||||
|
||||
For the full interactive Entity-Relationship Diagram, please visit the [main documentation](https://superset.apache.org/docs/contributing/resources).
|
||||
|
||||
You can also [download the .svg](https://github.com/apache/superset/tree/master/docs/static/img/erd.svg) directly from GitHub.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
### Official Documentation
|
||||
- [Apache Superset Documentation](https://superset.apache.org/docs/intro)
|
||||
- [API Documentation](https://superset.apache.org/docs/api)
|
||||
- [Configuration Guide](https://superset.apache.org/docs/installation/configuring-superset)
|
||||
|
||||
### Community Resources
|
||||
- [Apache Superset Blog](https://preset.io/blog/)
|
||||
- [YouTube Channel](https://www.youtube.com/channel/UCMuwrvBsg_jjI2gLcm04R0g)
|
||||
- [Twitter/X](https://twitter.com/ApacheSuperset)
|
||||
|
||||
### Development Tools
|
||||
- [GitHub Repository](https://github.com/apache/superset)
|
||||
- [PyPI Package](https://pypi.org/project/apache-superset/)
|
||||
- [Docker Hub](https://hub.docker.com/r/apache/superset)
|
||||
- [npm Packages](https://www.npmjs.com/search?q=%40superset-ui)
|
||||
321
docs/developer_portal/contributing/submitting-pr.md
Normal file
321
docs/developer_portal/contributing/submitting-pr.md
Normal file
@@ -0,0 +1,321 @@
|
||||
---
|
||||
title: Submitting Pull Requests
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Submitting Pull Requests
|
||||
|
||||
Learn how to create and submit high-quality pull requests to Apache Superset.
|
||||
|
||||
## Before You Start
|
||||
|
||||
### Prerequisites
|
||||
- [ ] Development environment is set up
|
||||
- [ ] You've forked and cloned the repository
|
||||
- [ ] You've read the [contributing overview](./overview)
|
||||
- [ ] You've found or created an issue to work on
|
||||
|
||||
### PR Readiness Checklist
|
||||
- [ ] Code follows [coding guidelines](../coding-guidelines/overview)
|
||||
- [ ] Tests are passing locally
|
||||
- [ ] Linting passes (`pre-commit run --all-files`)
|
||||
- [ ] Documentation is updated if needed
|
||||
|
||||
## Creating Your Pull Request
|
||||
|
||||
### 1. Create a Feature Branch
|
||||
|
||||
```bash
|
||||
# Update your fork
|
||||
git fetch upstream
|
||||
git checkout master
|
||||
git merge upstream/master
|
||||
git push origin master
|
||||
|
||||
# Create feature branch
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
### 2. Make Your Changes
|
||||
|
||||
```bash
|
||||
# Make changes
|
||||
edit files...
|
||||
|
||||
# Run tests
|
||||
pytest tests/unit_tests/
|
||||
cd superset-frontend && npm run test
|
||||
|
||||
# Run linting
|
||||
pre-commit run --all-files
|
||||
|
||||
# Commit with conventional format
|
||||
git add .
|
||||
git commit -m "feat(dashboard): add new filter component"
|
||||
```
|
||||
|
||||
### 3. PR Title Format
|
||||
|
||||
Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
```
|
||||
type(scope): description
|
||||
```
|
||||
|
||||
**Types:**
|
||||
- `feat`: New feature
|
||||
- `fix`: Bug fix
|
||||
- `docs`: Documentation only
|
||||
- `style`: Code style (formatting, semicolons, etc.)
|
||||
- `refactor`: Code refactoring
|
||||
- `perf`: Performance improvement
|
||||
- `test`: Adding tests
|
||||
- `chore`: Maintenance tasks
|
||||
- `ci`: CI/CD changes
|
||||
- `build`: Build system changes
|
||||
- `revert`: Reverting changes
|
||||
|
||||
**Scopes:**
|
||||
- `dashboard`: Dashboard functionality
|
||||
- `sqllab`: SQL Lab features
|
||||
- `explore`: Chart explorer
|
||||
- `chart`: Visualization components
|
||||
- `api`: REST API endpoints
|
||||
- `db`: Database connections
|
||||
- `security`: Security features
|
||||
- `config`: Configuration
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
feat(sqllab): add query cost estimation
|
||||
fix(dashboard): resolve filter cascading issue
|
||||
docs(api): update REST endpoint documentation
|
||||
refactor(explore): simplify chart controls logic
|
||||
perf(dashboard): optimize chart loading
|
||||
```
|
||||
|
||||
### 4. PR Description Template
|
||||
|
||||
Use the template from `.github/PULL_REQUEST_TEMPLATE.md`:
|
||||
|
||||
```markdown
|
||||
### SUMMARY
|
||||
Brief description of changes and motivation.
|
||||
|
||||
### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
|
||||
[Required for UI changes]
|
||||
|
||||
### TESTING INSTRUCTIONS
|
||||
1. Step-by-step instructions
|
||||
2. How to verify the fix/feature
|
||||
3. Any specific test scenarios
|
||||
|
||||
### ADDITIONAL INFORMATION
|
||||
- [ ] Has associated issue: #12345
|
||||
- [ ] Required feature flags:
|
||||
- [ ] API changes:
|
||||
- [ ] DB migration required:
|
||||
|
||||
### CHECKLIST
|
||||
- [ ] CI checks pass
|
||||
- [ ] Tests added/updated
|
||||
- [ ] Documentation updated
|
||||
- [ ] PR title follows conventions
|
||||
```
|
||||
|
||||
### 5. Submit the PR
|
||||
|
||||
```bash
|
||||
# Push to your fork
|
||||
git push origin feature/your-feature-name
|
||||
|
||||
# Create PR via GitHub CLI
|
||||
gh pr create --title "feat(sqllab): add query cost estimation" \
|
||||
--body-file .github/PULL_REQUEST_TEMPLATE.md
|
||||
|
||||
# Or use the GitHub web interface
|
||||
```
|
||||
|
||||
## PR Best Practices
|
||||
|
||||
### Keep PRs Focused
|
||||
- One feature/fix per PR
|
||||
- Break large changes into smaller PRs
|
||||
- Separate refactoring from feature changes
|
||||
|
||||
### Write Good Commit Messages
|
||||
```bash
|
||||
# Good
|
||||
git commit -m "fix(dashboard): prevent duplicate API calls when filters change"
|
||||
|
||||
# Bad
|
||||
git commit -m "fix bug"
|
||||
git commit -m "updates"
|
||||
```
|
||||
|
||||
### Include Tests
|
||||
```python
|
||||
# Backend test example
|
||||
def test_new_feature():
|
||||
"""Test that new feature works correctly."""
|
||||
result = new_feature_function()
|
||||
assert result == expected_value
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Frontend test example
|
||||
test('renders new component', () => {
|
||||
const { getByText } = render(<NewComponent />);
|
||||
expect(getByText('Expected Text')).toBeInTheDocument();
|
||||
});
|
||||
```
|
||||
|
||||
### Add Screenshots for UI Changes
|
||||
```markdown
|
||||
### Before
|
||||

|
||||
|
||||
### After
|
||||

|
||||
```
|
||||
|
||||
### Update Documentation
|
||||
- Update relevant docs in `/docs` directory
|
||||
- Add docstrings to new functions/classes
|
||||
- Update UPDATING.md for breaking changes
|
||||
|
||||
## CI Checks
|
||||
|
||||
### Required Checks
|
||||
All PRs must pass:
|
||||
- `Python Tests` - Backend unit/integration tests
|
||||
- `Frontend Tests` - JavaScript/TypeScript tests
|
||||
- `Linting` - Code style checks
|
||||
- `Type Checking` - MyPy and TypeScript
|
||||
- `License Check` - Apache license headers
|
||||
- `Documentation Build` - Docs compile successfully
|
||||
|
||||
### Common CI Failures
|
||||
|
||||
#### Python Test Failures
|
||||
```bash
|
||||
# Run locally to debug
|
||||
pytest tests/unit_tests/ -v
|
||||
pytest tests/integration_tests/ -v
|
||||
```
|
||||
|
||||
#### Frontend Test Failures
|
||||
```bash
|
||||
cd superset-frontend
|
||||
npm run test -- --coverage
|
||||
```
|
||||
|
||||
#### Linting Failures
|
||||
```bash
|
||||
# Auto-fix many issues
|
||||
pre-commit run --all-files
|
||||
|
||||
# Manual fixes may be needed for:
|
||||
# - MyPy type errors
|
||||
# - Complex ESLint issues
|
||||
# - License headers
|
||||
```
|
||||
|
||||
## Responding to Reviews
|
||||
|
||||
### Address Feedback Promptly
|
||||
```bash
|
||||
# Make requested changes
|
||||
edit files...
|
||||
|
||||
# Add commits (don't amend during review)
|
||||
git add .
|
||||
git commit -m "fix: address review feedback"
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
### Request Re-review
|
||||
- Click "Re-request review" after addressing feedback
|
||||
- Comment on resolved discussions
|
||||
- Thank reviewers for their time
|
||||
|
||||
### Handling Conflicts
|
||||
```bash
|
||||
# Update your branch
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
|
||||
# Resolve conflicts
|
||||
edit conflicted files...
|
||||
git add .
|
||||
git rebase --continue
|
||||
|
||||
# Force push (only to your feature branch!)
|
||||
git push --force-with-lease origin feature/your-feature-name
|
||||
```
|
||||
|
||||
## After Merge
|
||||
|
||||
### Clean Up
|
||||
```bash
|
||||
# Delete local branch
|
||||
git checkout master
|
||||
git branch -d feature/your-feature-name
|
||||
|
||||
# Delete remote branch
|
||||
git push origin --delete feature/your-feature-name
|
||||
|
||||
# Update your fork
|
||||
git fetch upstream
|
||||
git merge upstream/master
|
||||
git push origin master
|
||||
```
|
||||
|
||||
### Follow Up
|
||||
- Monitor for any issues reported
|
||||
- Help with documentation if needed
|
||||
- Consider related improvements
|
||||
|
||||
## Tips for Success
|
||||
|
||||
### Do
|
||||
- ✅ Keep PRs small and focused
|
||||
- ✅ Write descriptive PR titles and descriptions
|
||||
- ✅ Include tests for new functionality
|
||||
- ✅ Respond to feedback constructively
|
||||
- ✅ Update documentation
|
||||
- ✅ Be patient with the review process
|
||||
|
||||
### Don't
|
||||
- ❌ Submit PRs with failing tests
|
||||
- ❌ Include unrelated changes
|
||||
- ❌ Force push to master
|
||||
- ❌ Ignore CI failures
|
||||
- ❌ Skip the PR template
|
||||
|
||||
## Getting Help
|
||||
|
||||
- **Slack**: Ask in #development or #beginners
|
||||
- **GitHub**: Tag @apache/superset-committers for attention
|
||||
- **Mailing List**: dev@superset.apache.org
|
||||
|
||||
Next: [Understanding code review process](./code-review)
|
||||
@@ -1,464 +0,0 @@
|
||||
---
|
||||
title: Extension Examples
|
||||
sidebar_position: 1
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Extension Examples
|
||||
|
||||
Learn from real-world extension implementations that showcase different capabilities of the Superset extension system.
|
||||
|
||||
## Dataset References Panel
|
||||
|
||||
A SQL Lab panel that analyzes queries and displays information about referenced tables.
|
||||
|
||||
### Features
|
||||
- Parses SQL to extract table references
|
||||
- Shows table owners and permissions
|
||||
- Displays last partition information
|
||||
- Provides row count estimates
|
||||
|
||||
### Key Implementation
|
||||
|
||||
```typescript
|
||||
// Parse SQL and extract tables
|
||||
function extractTables(sql: string): TableReference[] {
|
||||
const tables = [];
|
||||
const tableRegex = /FROM\s+(\w+\.?\w+)/gi;
|
||||
let match;
|
||||
|
||||
while ((match = tableRegex.exec(sql)) !== null) {
|
||||
tables.push({
|
||||
schema: match[1].split('.')[0],
|
||||
table: match[1].split('.')[1] || match[1],
|
||||
});
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
// Register panel
|
||||
export function activate(context: ExtensionContext) {
|
||||
const panel = context.core.registerView('dataset-references.panel', () => (
|
||||
<DatasetReferencesPanel />
|
||||
));
|
||||
|
||||
// Listen for query changes
|
||||
const listener = context.sqlLab.onDidChangeEditorContent((content) => {
|
||||
const tables = extractTables(content);
|
||||
updatePanelWithTables(tables);
|
||||
});
|
||||
|
||||
context.subscriptions.push(panel, listener);
|
||||
}
|
||||
```
|
||||
|
||||
### Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "dataset-references",
|
||||
"contributions": {
|
||||
"views": {
|
||||
"sqllab.panels": [{
|
||||
"id": "dataset-references.panel",
|
||||
"name": "Dataset References",
|
||||
"icon": "DatabaseOutlined",
|
||||
"location": "right"
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Query Optimizer
|
||||
|
||||
Analyzes SQL queries and suggests optimizations.
|
||||
|
||||
### Features
|
||||
- Detects missing indexes
|
||||
- Suggests query rewrites
|
||||
- Identifies expensive operations
|
||||
- Provides execution plan analysis
|
||||
|
||||
### Implementation Highlights
|
||||
|
||||
```typescript
|
||||
// Register optimization command
|
||||
const optimizeCommand = context.commands.registerCommand('query-optimizer.analyze', {
|
||||
title: 'Analyze Query Performance',
|
||||
icon: 'ThunderboltOutlined',
|
||||
execute: async () => {
|
||||
const query = context.sqlLab.getCurrentQuery();
|
||||
const database = context.sqlLab.getCurrentDatabase();
|
||||
|
||||
// Get execution plan
|
||||
const plan = await getExecutionPlan(database.id, query);
|
||||
|
||||
// Analyze and suggest improvements
|
||||
const suggestions = analyzeExecutionPlan(plan);
|
||||
|
||||
// Show results in panel
|
||||
showOptimizationResults(suggestions);
|
||||
}
|
||||
});
|
||||
|
||||
// Add to editor menu
|
||||
"menus": {
|
||||
"sqllab.editor": {
|
||||
"primary": [{
|
||||
"command": "query-optimizer.analyze",
|
||||
"when": "editorHasContent"
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Natural Language to SQL
|
||||
|
||||
Converts natural language questions to SQL queries using LLM integration.
|
||||
|
||||
### Features
|
||||
- Natural language input
|
||||
- Context-aware SQL generation
|
||||
- Query validation
|
||||
- History tracking
|
||||
|
||||
### Key Components
|
||||
|
||||
```typescript
|
||||
// Backend API endpoint
|
||||
@rest_api.route('/nl2sql/generate')
|
||||
def generate_sql(prompt: str, context: dict):
|
||||
# Use LLM to generate SQL
|
||||
sql = llm_client.generate(
|
||||
prompt=prompt,
|
||||
schema=context['schema'],
|
||||
examples=context['examples']
|
||||
)
|
||||
|
||||
# Validate generated SQL
|
||||
validation = validate_sql(sql)
|
||||
|
||||
return {
|
||||
'sql': sql,
|
||||
'valid': validation.is_valid,
|
||||
'errors': validation.errors
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Frontend integration
|
||||
function NL2SQLPanel() {
|
||||
const [prompt, setPrompt] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const generateSQL = async () => {
|
||||
setLoading(true);
|
||||
|
||||
const response = await context.network.api.post('/extensions/nl2sql/generate', {
|
||||
prompt,
|
||||
context: {
|
||||
database: context.sqlLab.getCurrentDatabase(),
|
||||
schema: await context.sqlLab.getCurrentSchema(),
|
||||
}
|
||||
});
|
||||
|
||||
if (response.valid) {
|
||||
// Insert SQL into editor
|
||||
context.sqlLab.insertText(response.sql);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input.TextArea
|
||||
value={prompt}
|
||||
onChange={(e) => setPrompt(e.target.value)}
|
||||
placeholder="Describe what data you want..."
|
||||
/>
|
||||
<Button onClick={generateSQL} loading={loading}>
|
||||
Generate SQL
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Schema Visualizer
|
||||
|
||||
Interactive database schema visualization.
|
||||
|
||||
### Features
|
||||
- Visual ERD diagram
|
||||
- Table relationships
|
||||
- Column details on hover
|
||||
- Export to image
|
||||
|
||||
### Implementation
|
||||
|
||||
```typescript
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
function SchemaVisualizer() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [graph, setGraph] = useState<Graph>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const g = new Graph({
|
||||
container: containerRef.current,
|
||||
layout: {
|
||||
type: 'dagre',
|
||||
rankdir: 'LR',
|
||||
},
|
||||
defaultNode: {
|
||||
type: 'sql-table-node',
|
||||
},
|
||||
defaultEdge: {
|
||||
type: 'sql-relation-edge',
|
||||
},
|
||||
});
|
||||
|
||||
setGraph(g);
|
||||
loadSchemaData(g);
|
||||
|
||||
return () => g.destroy();
|
||||
}, []);
|
||||
|
||||
const loadSchemaData = async (g: Graph) => {
|
||||
const tables = await context.sqlLab.getTables();
|
||||
const nodes = tables.map(table => ({
|
||||
id: table.name,
|
||||
label: table.name,
|
||||
columns: table.columns,
|
||||
}));
|
||||
|
||||
const edges = extractRelationships(tables);
|
||||
|
||||
g.data({ nodes, edges });
|
||||
g.render();
|
||||
};
|
||||
|
||||
return <div ref={containerRef} style={{ height: '100%' }} />;
|
||||
}
|
||||
```
|
||||
|
||||
## SQL Formatter
|
||||
|
||||
Formats and beautifies SQL code with customizable rules.
|
||||
|
||||
### Features
|
||||
- Multiple formatting styles
|
||||
- Custom rule configuration
|
||||
- Batch formatting
|
||||
- Format on save
|
||||
|
||||
### Simple Implementation
|
||||
|
||||
```typescript
|
||||
import { format } from 'sql-formatter';
|
||||
|
||||
const formatCommand = context.commands.registerCommand('sql-formatter.format', {
|
||||
title: 'Format SQL',
|
||||
execute: () => {
|
||||
const sql = context.sqlLab.getCurrentQuery();
|
||||
|
||||
const formatted = format(sql, {
|
||||
language: 'sql',
|
||||
indent: ' ',
|
||||
uppercase: true,
|
||||
linesBetweenQueries: 2,
|
||||
});
|
||||
|
||||
context.sqlLab.replaceQuery(formatted);
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-format on save
|
||||
context.sqlLab.onWillSaveQuery((event) => {
|
||||
if (context.storage.local.get('autoFormat')) {
|
||||
const formatted = format(event.query);
|
||||
event.waitUntil(Promise.resolve(formatted));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Query History Search
|
||||
|
||||
Enhanced query history with advanced search and filtering.
|
||||
|
||||
### Features
|
||||
- Full-text search
|
||||
- Filter by date, user, database
|
||||
- Query statistics
|
||||
- Export capabilities
|
||||
|
||||
### UI Component
|
||||
|
||||
```typescript
|
||||
function QueryHistoryPanel() {
|
||||
const [queries, setQueries] = useState<Query[]>([]);
|
||||
const [filters, setFilters] = useState<Filters>({});
|
||||
|
||||
useEffect(() => {
|
||||
loadQueries();
|
||||
}, [filters]);
|
||||
|
||||
const loadQueries = async () => {
|
||||
const history = await context.network.api.get('/api/v1/query', {
|
||||
params: {
|
||||
...filters,
|
||||
page_size: 100,
|
||||
}
|
||||
});
|
||||
|
||||
setQueries(history.result);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SearchFilters onChange={setFilters} />
|
||||
<Table
|
||||
dataSource={queries}
|
||||
columns={[
|
||||
{ title: 'Query', dataIndex: 'sql', ellipsis: true },
|
||||
{ title: 'Database', dataIndex: 'database' },
|
||||
{ title: 'Status', dataIndex: 'status' },
|
||||
{ title: 'Duration', dataIndex: 'duration' },
|
||||
{ title: 'User', dataIndex: 'user' },
|
||||
{
|
||||
title: 'Actions',
|
||||
render: (query) => (
|
||||
<Button
|
||||
icon={<CopyOutlined />}
|
||||
onClick={() => context.sqlLab.insertText(query.sql)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Git Integration
|
||||
|
||||
Version control for SQL queries and dashboards.
|
||||
|
||||
### Features
|
||||
- Save queries to Git
|
||||
- Track changes
|
||||
- Collaborative editing
|
||||
- Branch management
|
||||
|
||||
### Backend Integration
|
||||
|
||||
```python
|
||||
from git import Repo
|
||||
|
||||
class GitExtension:
|
||||
def __init__(self, repo_path):
|
||||
self.repo = Repo(repo_path)
|
||||
|
||||
def save_query(self, query, message):
|
||||
# Save query to file
|
||||
path = f"queries/{query.name}.sql"
|
||||
with open(path, 'w') as f:
|
||||
f.write(query.sql)
|
||||
|
||||
# Commit to Git
|
||||
self.repo.index.add([path])
|
||||
self.repo.index.commit(message)
|
||||
|
||||
return {
|
||||
'status': 'success',
|
||||
'commit': self.repo.head.commit.hexsha
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices from Examples
|
||||
|
||||
### 1. User Experience
|
||||
- Provide clear feedback for async operations
|
||||
- Handle errors gracefully
|
||||
- Include loading states
|
||||
- Add keyboard shortcuts
|
||||
|
||||
### 2. Performance
|
||||
- Debounce expensive operations
|
||||
- Cache API responses
|
||||
- Use virtual scrolling for large lists
|
||||
- Lazy load heavy components
|
||||
|
||||
### 3. Integration
|
||||
- Respect Superset's theme
|
||||
- Use provided UI components
|
||||
- Follow existing UX patterns
|
||||
- Integrate with existing menus
|
||||
|
||||
### 4. Code Organization
|
||||
```
|
||||
extension/
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── components/ # UI components
|
||||
│ │ ├── hooks/ # Custom hooks
|
||||
│ │ ├── services/ # API services
|
||||
│ │ ├── utils/ # Utilities
|
||||
│ │ └── index.tsx # Entry point
|
||||
│ └── tests/
|
||||
├── backend/
|
||||
│ ├── src/
|
||||
│ │ ├── api/ # REST endpoints
|
||||
│ │ ├── models/ # Data models
|
||||
│ │ ├── services/ # Business logic
|
||||
│ │ └── entrypoint.py
|
||||
│ └── tests/
|
||||
```
|
||||
|
||||
### 5. Testing
|
||||
```typescript
|
||||
// Test example
|
||||
describe('DatasetReferences', () => {
|
||||
it('should extract tables from SQL', () => {
|
||||
const sql = 'SELECT * FROM users JOIN orders ON users.id = orders.user_id';
|
||||
const tables = extractTables(sql);
|
||||
|
||||
expect(tables).toEqual([
|
||||
{ schema: 'public', table: 'users' },
|
||||
{ schema: 'public', table: 'orders' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Learn More
|
||||
|
||||
- [API Reference](../api/frontend)
|
||||
- [Architecture Overview](../architecture/overview)
|
||||
- [Getting Started Guide](../getting-started)
|
||||
- [CLI Documentation](../cli/overview)
|
||||
36
docs/developer_portal/extensions/architectural-principles.md
Normal file
36
docs/developer_portal/extensions/architectural-principles.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Architectural Principles
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Architectural Principles
|
||||
|
||||
Realizing this vision requires a strong architectural foundation. To ensure the resulting system is robust, maintainable, and adaptable, we have defined a set of architectural principles that will guide the design and implementation of the changes. These principles serve as the basis for all technical decisions and help create an environment where extensions can be developed safely and predictably, while minimizing technical debt and fragmentation.
|
||||
|
||||
The architectural principles guiding this proposal include:
|
||||
|
||||
1. **Lean core**: Superset's core should remain as minimal as possible, with many features and capabilities delegated to extensions. Wherever possible, built-in features should be implemented using the same APIs and extension mechanisms available to external extension authors. This approach reduces maintenance burden and complexity in the core application, encourages modularity, and allows the community to innovate and iterate on features independently of the main codebase.
|
||||
2. **Explicit contribution points**: All extension points must be clearly defined and documented, so extension authors know exactly where and how they can interact with the host system. Each extension must also declare its capabilities in a metadata file, enabling the host to manage the extension lifecycle and provide a consistent user experience.
|
||||
3. **Versioned and stable APIs**: Public interfaces for extensions should be versioned and follow semantic versioning, allowing for safe evolution and backward compatibility.
|
||||
4. **Lazy loading and activation**: Extensions should be loaded and activated only when needed, minimizing performance overhead and resource consumption.
|
||||
5. **Composability and reuse**: The architecture should encourage the reuse of extension points and patterns across different modules, promoting consistency and reducing duplication.
|
||||
6. **Community-driven evolution**: The system should be designed to evolve based on real-world feedback and contributions, allowing new extension points and capabilities to be added as needs emerge.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user