mirror of
https://github.com/apache/superset.git
synced 2026-04-30 21:44:40 +00:00
Compare commits
11 Commits
playwright
...
default_ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a82c2015c | ||
|
|
489d8a4b83 | ||
|
|
cb993639ce | ||
|
|
031938edb8 | ||
|
|
6e735d40a8 | ||
|
|
377bccd464 | ||
|
|
8bdb41674c | ||
|
|
51b887901f | ||
|
|
46924ad89e | ||
|
|
1d3c186fec | ||
|
|
03ba5b6949 |
@@ -1,10 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,684 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,199 +0,0 @@
|
||||
# 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
|
||||
@@ -1,76 +0,0 @@
|
||||
# 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-trixie AS base
|
||||
FROM python:3.11.13-bookworm AS base
|
||||
|
||||
# Install system dependencies that Superset needs
|
||||
# This layer will be cached across Codespace sessions
|
||||
|
||||
12
.github/CODEOWNERS
vendored
12
.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 @sadpandajoe
|
||||
/.github/ @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar
|
||||
|
||||
# Notify PMC members of changes to required GitHub Actions
|
||||
|
||||
@@ -30,13 +30,3 @@
|
||||
|
||||
**/*.geojson @villebro @rusackas
|
||||
/superset-frontend/plugins/legacy-plugin-chart-country-map/ @villebro @rusackas
|
||||
|
||||
# Notify PMC members of changes to extension-related files
|
||||
|
||||
/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
|
||||
|
||||
19
.github/actions/change-detector/action.yml
vendored
19
.github/actions/change-detector/action.yml
vendored
@@ -1,27 +1,24 @@
|
||||
name: Change Detector
|
||||
description: Detects file changes for pull request and push events
|
||||
name: 'Change Detector'
|
||||
description: 'Detects file changes for pull request and push events'
|
||||
inputs:
|
||||
token:
|
||||
description: GitHub token for authentication
|
||||
description: 'GitHub token for authentication'
|
||||
required: true
|
||||
outputs:
|
||||
python:
|
||||
description: Whether Python-related files were changed
|
||||
description: 'Whether Python-related files were changed'
|
||||
value: ${{ steps.change-detector.outputs.python }}
|
||||
frontend:
|
||||
description: Whether frontend-related files were changed
|
||||
description: 'Whether frontend-related files were changed'
|
||||
value: ${{ steps.change-detector.outputs.frontend }}
|
||||
docker:
|
||||
description: Whether docker-related files were changed
|
||||
description: 'Whether docker-related files were changed'
|
||||
value: ${{ steps.change-detector.outputs.docker }}
|
||||
docs:
|
||||
description: Whether docs-related files were changed
|
||||
description: 'Whether docs-related files were changed'
|
||||
value: ${{ steps.change-detector.outputs.docs }}
|
||||
superset-extensions-cli:
|
||||
description: Whether superset-extensions-cli package-related files were changed
|
||||
value: ${{ steps.change-detector.outputs.superset-extensions-cli }}
|
||||
runs:
|
||||
using: composite
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Detect file changes
|
||||
id: change-detector
|
||||
|
||||
2
.github/copilot-instructions.md
vendored
2
.github/copilot-instructions.md
vendored
@@ -1 +1 @@
|
||||
../AGENTS.md
|
||||
../LLMS.md
|
||||
70
.github/dependabot.yml
vendored
70
.github/dependabot.yml
vendored
@@ -5,7 +5,7 @@ updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
ignore:
|
||||
@@ -18,7 +18,7 @@ updates:
|
||||
- dependency-name: "jest-environment-jsdom"
|
||||
directory: "/superset-frontend/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -40,21 +40,21 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: ".github/actions"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: increase
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/docs/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
versioning-strategy: increase
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-websocket/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -63,7 +63,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-websocket/utils/client-ws-app/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -75,7 +75,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-calendar/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -85,7 +85,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-histogram/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -95,7 +95,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-partition/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -105,7 +105,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-world-map/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -115,7 +115,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-pivot-table/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -125,7 +125,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-chord/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -135,7 +135,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-horizon/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -145,7 +145,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-rose/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -155,7 +155,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-preset-chart-deckgl/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -165,7 +165,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-table/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -175,7 +175,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-country-map/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -185,7 +185,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-map-box/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -195,7 +195,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-sankey/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -205,7 +205,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-preset-chart-nvd3/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -215,7 +215,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-word-cloud/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -225,7 +225,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-event-flow/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -235,7 +235,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-paired-t-test/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -245,7 +245,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -255,7 +255,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-echarts/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -265,7 +265,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/preset-chart-xy/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -275,7 +275,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-heatmap/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -285,7 +285,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -295,7 +295,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/legacy-plugin-chart-sunburst/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -305,7 +305,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/plugins/plugin-chart-handlebars/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -315,7 +315,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/generator-superset/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -325,7 +325,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-chart-controls/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -339,7 +339,7 @@ updates:
|
||||
- dependency-name: "react-markdown"
|
||||
- dependency-name: "remark-gfm"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -349,7 +349,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-demo/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
@@ -359,7 +359,7 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/superset-frontend/packages/superset-ui-switchboard/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- npm
|
||||
- dependabot
|
||||
|
||||
70
.github/workflows/bashlib.sh
vendored
70
.github/workflows/bashlib.sh
vendored
@@ -182,76 +182,6 @@ 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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v6
|
||||
uses: actions/setup-python@v5
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -25,9 +25,9 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
- name: Check and notify
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
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@v8
|
||||
uses: actions/github-script@v7
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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@v4
|
||||
uses: github/codeql-action/init@v3
|
||||
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@v4
|
||||
uses: github/codeql-action/analyze@v3
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
- 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@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
|
||||
8
.github/workflows/docker.yml
vendored
8
.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", "py312"]'; fi)
|
||||
MATRIX_CONFIG=$(if [ "${{ github.event_name }}" == "pull_request" ]; then echo '["dev", "lean"]'; else echo '["dev", "lean", "py310", "websocket", "dockerize", "py311"]'; 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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
docker history $IMAGE_TAG
|
||||
|
||||
- name: docker-compose sanity check
|
||||
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && matrix.build_preset == 'dev'
|
||||
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && (matrix.build_preset == 'dev' || matrix.build_preset == 'lean')
|
||||
shell: bash
|
||||
run: |
|
||||
export SUPERSET_BUILD_TARGET=${{ matrix.build_preset }}
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
- uses: actions/setup-node@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
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@v5
|
||||
- uses: actions/setup-node@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
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,10 +1,4 @@
|
||||
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
|
||||
name: Cleanup ephemeral envs (PR close)
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
@@ -33,7 +27,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -69,7 +63,7 @@ jobs:
|
||||
|
||||
- name: Comment (success)
|
||||
if: steps.describe-services.outputs.active == 'true'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
@@ -77,5 +71,5 @@ jobs:
|
||||
issue_number: ${{ github.event.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '⚠️ **DEPRECATED WORKFLOW** - Ephemeral environment shutdown and build artifacts deleted. Please migrate to the new Superset Showtime system for future PRs.'
|
||||
body: 'Ephemeral environment shutdown and build artifacts deleted.'
|
||||
})
|
||||
|
||||
37
.github/workflows/ephemeral-env.yml
vendored
37
.github/workflows/ephemeral-env.yml
vendored
@@ -1,12 +1,4 @@
|
||||
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
|
||||
name: Ephemeral env workflow
|
||||
|
||||
# Example manual trigger:
|
||||
# gh workflow run ephemeral-env.yml --ref fix_ephemerals --field label_name="testenv-up" --field issue_number=666
|
||||
@@ -63,7 +55,7 @@ jobs:
|
||||
- name: Get event SHA
|
||||
id: get-sha
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
@@ -94,7 +86,7 @@ jobs:
|
||||
core.setOutput("sha", prSha);
|
||||
|
||||
- name: Looking for feature flags in PR description
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
id: eval-feature-flags
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
with:
|
||||
@@ -116,7 +108,7 @@ jobs:
|
||||
return results;
|
||||
|
||||
- name: Reply with confirmation comment
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
if: steps.eval-label.outputs.result == 'up'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -134,11 +126,8 @@ jobs:
|
||||
throw new Error("Issue number is not available.");
|
||||
}
|
||||
|
||||
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}**.` +
|
||||
const body = `@${user} 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)`;
|
||||
|
||||
@@ -160,7 +149,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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
|
||||
persist-credentials: false
|
||||
@@ -189,7 +178,7 @@ jobs:
|
||||
--extra-flags "--build-arg INCLUDE_CHROMIUM=false"
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -220,12 +209,12 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -248,7 +237,7 @@ jobs:
|
||||
|
||||
- name: Fail on missing container image
|
||||
if: steps.check-image.outcome == 'failure'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
script: |
|
||||
@@ -318,7 +307,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@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{github.token}}
|
||||
script: |
|
||||
@@ -331,7 +320,7 @@ jobs:
|
||||
});
|
||||
- name: Comment (failure)
|
||||
if: ${{ failure() }}
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "11"
|
||||
|
||||
@@ -14,10 +14,10 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v6
|
||||
- uses: actions/labeler@v5
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
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@v8
|
||||
uses: actions/github-script@v7
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
- uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
|
||||
|
||||
50
.github/workflows/showtime-cleanup.yml
vendored
50
.github/workflows/showtime-cleanup.yml
vendored
@@ -1,50 +0,0 @@
|
||||
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
179
.github/workflows/showtime-trigger.yml
vendored
@@ -1,179 +0,0 @@
|
||||
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
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
ref: master
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install eyes-storybook dependencies
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Superset App CLI tests
|
||||
name: Superset CLI tests
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './docs/.nvmrc'
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
- uses: actions/setup-java@v5
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '21'
|
||||
|
||||
26
.github/workflows/superset-docs-verify.yml
vendored
26
.github/workflows/superset-docs-verify.yml
vendored
@@ -18,17 +18,15 @@ jobs:
|
||||
name: Link Checking
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
# Do not bump this linkinator-action version without opening
|
||||
# an ASF Infra ticket to allow the new version first!
|
||||
- uses: JustinBeckwith/linkinator-action@3d5ba091319fa7b0ac14703761eebb7d100e6f6d # v1.11.0
|
||||
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
||||
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
||||
with:
|
||||
paths: "**/*.md, **/*.mdx"
|
||||
paths: "**/*.md, **/*.mdx, !superset-frontend/CHANGELOG.md"
|
||||
linksToSkip: >-
|
||||
^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,
|
||||
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
||||
http://localhost:8088/,
|
||||
http://127.0.0.1:3000/,
|
||||
http://localhost:9001/,
|
||||
@@ -43,12 +41,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
|
||||
@@ -58,12 +56,12 @@ jobs:
|
||||
working-directory: docs
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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
|
||||
uses: actions/checkout@v4
|
||||
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
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
|
||||
64
.github/workflows/superset-extensions-cli.yml
vendored
64
.github/workflows/superset-extensions-cli.yml
vendored
@@ -1,64 +0,0 @@
|
||||
name: Superset Extensions CLI Package Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "[0-9].[0-9]*"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened, ready_for_review]
|
||||
|
||||
# cancel previous workflow jobs for PRs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-superset-extensions-cli-package:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["previous", "current", "next"]
|
||||
defaults:
|
||||
run:
|
||||
working-directory: superset-extensions-cli
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Python
|
||||
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-extensions-cli
|
||||
run: |
|
||||
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-extensions-cli
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: superset-extensions-cli
|
||||
name: superset-extensions-cli-coverage
|
||||
fail_ci_if_error: false
|
||||
|
||||
- name: Upload HTML coverage report
|
||||
if: steps.check.outputs.superset-extensions-cli
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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-trixie \
|
||||
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-bookworm \
|
||||
--target superset-node-ci \
|
||||
.
|
||||
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Download Coverage Artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v4
|
||||
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@v5
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
@@ -143,7 +143,7 @@ jobs:
|
||||
- name: tsc
|
||||
run: |
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm run plugins:build && npm run type"
|
||||
"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@v5
|
||||
uses: actions/download-artifact@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const branchName = '${{ env.branch_name }}';
|
||||
|
||||
141
.github/workflows/superset-playwright.yml
vendored
141
.github/workflows/superset-playwright.yml
vendored
@@ -1,141 +0,0 @@
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
- 16379:6379
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
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@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
});
|
||||
|
||||
- name: "Checkout ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
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", "py312"]
|
||||
build_preset: ["dev", "lean", "py310", "websocket", "dockerize", "py311"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
build: "true"
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
@@ -107,12 +107,12 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
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@v3
|
||||
uses: actions/first-interaction@v2
|
||||
continue-on-error: true
|
||||
with:
|
||||
repo-token: ${{ github.token }}
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -43,7 +43,7 @@ _modules
|
||||
_static
|
||||
build
|
||||
app.db
|
||||
*.egg-info/
|
||||
apache_superset.egg-info/
|
||||
changelog.sh
|
||||
dist
|
||||
dump.rdb
|
||||
@@ -130,7 +130,7 @@ superset/static/stats/statistics.html
|
||||
|
||||
# LLM-related
|
||||
CLAUDE.local.md
|
||||
PROJECT.md
|
||||
.aider*
|
||||
.claude_rc*
|
||||
.env.local
|
||||
PROJECT.md
|
||||
|
||||
@@ -23,9 +23,7 @@ repos:
|
||||
rev: v1.15.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy (main)
|
||||
args: [--check-untyped-defs]
|
||||
exclude: ^superset-extensions-cli/
|
||||
additional_dependencies: [
|
||||
types-simplejson,
|
||||
types-python-dateutil,
|
||||
@@ -40,10 +38,6 @@ repos:
|
||||
types-paramiko,
|
||||
types-Markdown,
|
||||
]
|
||||
- id: mypy
|
||||
name: mypy (superset-extensions-cli)
|
||||
args: [--check-untyped-defs]
|
||||
files: ^superset-extensions-cli/
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
@@ -60,25 +54,25 @@ repos:
|
||||
args: ["--markdown-linebreak-ext=md"]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: eslint-frontend
|
||||
name: eslint (frontend)
|
||||
entry: ./scripts/eslint.sh
|
||||
language: system
|
||||
pass_filenames: true
|
||||
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 --quiet $FILES'
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^docs/.*\.(js|jsx|ts|tsx)$
|
||||
- id: type-checking-frontend
|
||||
name: Type-Checking (Frontend)
|
||||
entry: ./scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base
|
||||
language: system
|
||||
files: ^superset-frontend\/.*\.(js|jsx|ts|tsx)$
|
||||
exclude: ^superset-frontend/cypress-base\/
|
||||
require_serial: true
|
||||
- id: eslint-frontend
|
||||
name: eslint (frontend)
|
||||
entry: ./scripts/eslint.sh
|
||||
language: system
|
||||
pass_filenames: true
|
||||
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'
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^docs/.*\.(js|jsx|ts|tsx)$
|
||||
- id: type-checking-frontend
|
||||
name: Type-Checking (Frontend)
|
||||
entry: ./scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base
|
||||
language: system
|
||||
files: ^superset-frontend\/.*\.(js|jsx|ts|tsx)$
|
||||
exclude: ^superset-frontend/cypress-base\/
|
||||
require_serial: true
|
||||
# blacklist unsafe functions like make_url (see #19526)
|
||||
- repo: https://github.com/skorokithakis/blacklist-pre-commit-hook
|
||||
rev: e2f070289d8eddcaec0b580d3bde29437e7c8221
|
||||
@@ -100,21 +94,21 @@ repos:
|
||||
args: [--fix]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pylint
|
||||
name: pylint with custom Superset plugins
|
||||
entry: bash
|
||||
language: system
|
||||
types: [python]
|
||||
exclude: ^(tests/|superset/migrations/|scripts/|RELEASING/|docker/)
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
TARGET_BRANCH=${GITHUB_BASE_REF:-master}
|
||||
git fetch origin "$TARGET_BRANCH"
|
||||
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD)
|
||||
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD | grep '^superset/.*\.py$' || true)
|
||||
if [ -n "$files" ]; then
|
||||
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint --reports=no $files
|
||||
else
|
||||
echo "No Python files to lint."
|
||||
fi
|
||||
- id: pylint
|
||||
name: pylint with custom Superset plugins
|
||||
entry: bash
|
||||
language: system
|
||||
types: [python]
|
||||
exclude: ^(tests/|superset/migrations/|scripts/|RELEASING/|docker/)
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
TARGET_BRANCH=${GITHUB_BASE_REF:-master}
|
||||
git fetch origin "$TARGET_BRANCH"
|
||||
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD)
|
||||
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD | grep '^superset/.*\.py$' || true)
|
||||
if [ -n "$files" ]; then
|
||||
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint --reports=no $files
|
||||
else
|
||||
echo "No Python files to lint."
|
||||
fi
|
||||
|
||||
@@ -32,8 +32,6 @@ apache_superset.egg-info
|
||||
# json and csv in general cannot have comments
|
||||
.*json
|
||||
.*csv
|
||||
# jinja templates often need to be as-is
|
||||
.*j2
|
||||
# Generated doc files
|
||||
env/*
|
||||
docs/.htaccess*
|
||||
@@ -73,7 +71,6 @@ ibm-db2.svg
|
||||
postgresql.svg
|
||||
snowflake.svg
|
||||
ydb.svg
|
||||
loading.svg
|
||||
|
||||
# docs-related
|
||||
erd.puml
|
||||
@@ -82,7 +79,6 @@ intro_header.txt
|
||||
|
||||
# for LLMs
|
||||
llm-context.md
|
||||
AGENTS.md
|
||||
LLMS.md
|
||||
CLAUDE.md
|
||||
CURSOR.md
|
||||
|
||||
@@ -44,8 +44,4 @@ 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)
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<!--
|
||||
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,23 +16,9 @@
|
||||
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.
|
||||
|
||||
## 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).
|
||||
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).
|
||||
|
||||
68
Dockerfile
68
Dockerfile
@@ -18,7 +18,7 @@
|
||||
######################################################################
|
||||
# Node stage to deal with static asset construction
|
||||
######################################################################
|
||||
ARG PY_VER=3.11.13-slim-trixie
|
||||
ARG PY_VER=3.11.13-slim-bookworm
|
||||
|
||||
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
|
||||
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
||||
@@ -26,13 +26,10 @@ 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-trixie-slim AS superset-node-ci
|
||||
FROM --platform=${BUILDPLATFORM} node:20-bookworm-slim AS superset-node-ci
|
||||
ARG BUILD_TRANSLATIONS
|
||||
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
||||
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
||||
@@ -67,7 +64,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"; \
|
||||
@@ -83,7 +80,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 \
|
||||
@@ -94,10 +91,11 @@ 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,mo];
|
||||
rm -rf /app/superset/translations/*/*/*.po; \
|
||||
rm -rf /app/superset/translations/*/*/*.mo;
|
||||
|
||||
|
||||
######################################################################
|
||||
@@ -108,10 +106,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/
|
||||
@@ -136,19 +134,17 @@ 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,json]
|
||||
rm -f /app/translations_mo/*/*/*.po; \
|
||||
rm -f /app/translations_mo/*/*/*.json;
|
||||
|
||||
######################################################################
|
||||
# Python APP common layer
|
||||
######################################################################
|
||||
FROM python-base AS python-common
|
||||
|
||||
# Re-declare build arg to receive it in this stage
|
||||
ARG LOAD_EXAMPLES_DUCKDB
|
||||
|
||||
ENV SUPERSET_HOME="/app/superset_home" \
|
||||
HOME="/app/superset_home" \
|
||||
SUPERSET_ENV="production" \
|
||||
@@ -174,11 +170,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
|
||||
@@ -200,18 +196,6 @@ RUN /app/docker/apt-install.sh \
|
||||
libecpg-dev \
|
||||
libldap2-dev
|
||||
|
||||
# Pre-load examples DuckDB file if requested
|
||||
RUN if [ "$LOAD_EXAMPLES_DUCKDB" = "true" ]; then \
|
||||
mkdir -p /app/data && \
|
||||
echo "Downloading pre-built examples.duckdb..." && \
|
||||
curl -L -o /app/data/examples.duckdb \
|
||||
"https://raw.githubusercontent.com/apache-superset/examples-data/master/examples.duckdb" && \
|
||||
chown -R superset:superset /app/data; \
|
||||
else \
|
||||
mkdir -p /app/data && \
|
||||
chown -R superset:superset /app/data; \
|
||||
fi
|
||||
|
||||
# Copy compiled things from previous stages
|
||||
COPY --from=superset-node /app/superset/static/assets superset/static/assets
|
||||
|
||||
@@ -235,10 +219,6 @@ FROM python-common AS lean
|
||||
|
||||
# Install Python dependencies using docker/pip-install.sh
|
||||
COPY requirements/base.txt requirements/
|
||||
|
||||
# Copy superset-core package needed for editable install in base.txt
|
||||
COPY superset-core superset-core
|
||||
|
||||
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||
/app/docker/pip-install.sh --requires-build-essential -r requirements/base.txt
|
||||
# Install the superset package
|
||||
@@ -261,11 +241,6 @@ RUN /app/docker/apt-install.sh \
|
||||
|
||||
# Copy development requirements and install them
|
||||
COPY requirements/*.txt requirements/
|
||||
|
||||
# Copy local packages needed for editable installs in development.txt
|
||||
COPY superset-core superset-core
|
||||
COPY superset-extensions-cli superset-extensions-cli
|
||||
|
||||
# Install Python dependencies using docker/pip-install.sh
|
||||
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||
/app/docker/pip-install.sh --requires-build-essential -r requirements/development.txt
|
||||
@@ -283,15 +258,6 @@ USER superset
|
||||
######################################################################
|
||||
FROM lean AS ci
|
||||
USER root
|
||||
RUN uv pip install .[postgres,duckdb]
|
||||
USER superset
|
||||
CMD ["/app/docker/entrypoints/docker-ci.sh"]
|
||||
|
||||
######################################################################
|
||||
# Showtime image - lean + DuckDB for examples database
|
||||
######################################################################
|
||||
FROM lean AS showtime
|
||||
USER root
|
||||
RUN uv pip install .[duckdb]
|
||||
RUN uv pip install .[postgres]
|
||||
USER superset
|
||||
CMD ["/app/docker/entrypoints/docker-ci.sh"]
|
||||
|
||||
@@ -9,17 +9,13 @@ Apache Superset is a data visualization platform with Flask/Python backend and R
|
||||
### Frontend Modernization
|
||||
- **NO `any` types** - Use proper TypeScript types
|
||||
- **NO JavaScript files** - Convert to TypeScript (.ts/.tsx)
|
||||
- **Use @superset-ui/core** - Don't import Ant Design directly, prefer Ant Design component wrappers from @superset-ui/core/components
|
||||
- **Use antd theming tokens** - Prefer antd tokens over legacy theming tokens
|
||||
- **Avoid custom css and styles** - Follow antd best practices and avoid styling and custom CSS whenever possible
|
||||
- **Use @superset-ui/core** - Don't import Ant Design directly
|
||||
|
||||
### Testing Strategy Migration
|
||||
- **Prefer unit tests** over integration tests
|
||||
- **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
|
||||
- **Prefer integration tests** over Cypress end-to-end tests
|
||||
- **Cypress is last resort** - Actively moving away from Cypress
|
||||
- **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
|
||||
|
||||
### Backend Type Safety
|
||||
- **Add type hints** - All new Python code needs proper typing
|
||||
@@ -68,11 +64,7 @@ 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 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
|
||||
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
||||
|
||||
## Documentation Requirements
|
||||
|
||||
@@ -112,18 +104,6 @@ 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
|
||||
@@ -153,19 +133,6 @@ 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:**
|
||||
2
Makefile
2
Makefile
@@ -91,7 +91,7 @@ js-format:
|
||||
cd superset-frontend; npm run prettier
|
||||
|
||||
flask-app:
|
||||
flask run -p 8088 --reload --debugger
|
||||
flask run -p 8088 --with-threads --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-trixie
|
||||
FROM python:3.10-slim-bookworm
|
||||
|
||||
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-trixie
|
||||
FROM python:3.10-slim-bookworm
|
||||
|
||||
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-trixie
|
||||
FROM python:3.10-slim-bookworm
|
||||
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-trixie
|
||||
FROM python:3.10-slim-bookworm
|
||||
|
||||
RUN apt-get update -y
|
||||
RUN apt-get install -y \
|
||||
|
||||
@@ -469,10 +469,6 @@ 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/*
|
||||
```
|
||||
|
||||
@@ -522,8 +518,6 @@ 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,10 +23,6 @@ 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
|
||||
- Change any hex color values to one of: `"success"`, `"processing"`, `"error"`, `"warning"`, `"default"`
|
||||
|
||||
@@ -28,7 +28,6 @@ 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,13 +71,12 @@ 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-trixie
|
||||
- apache/superset-cache:3.10-slim-bookworm
|
||||
args:
|
||||
DEV_MODE: "true"
|
||||
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
|
||||
INCLUDE_FIREFOX: ${INCLUDE_FIREFOX:-false}
|
||||
BUILD_TRANSLATIONS: ${BUILD_TRANSLATIONS:-false}
|
||||
LOAD_EXAMPLES_DUCKDB: ${LOAD_EXAMPLES_DUCKDB:-true}
|
||||
|
||||
services:
|
||||
db-light:
|
||||
@@ -92,7 +91,9 @@ services:
|
||||
- db_home_light:/var/lib/postgresql/data
|
||||
- ./docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
|
||||
environment:
|
||||
# Override database name to avoid conflicts
|
||||
POSTGRES_DB: superset_light
|
||||
# Increase max connections for test runs
|
||||
command: postgres -c max_connections=200
|
||||
|
||||
superset-light:
|
||||
@@ -105,6 +106,7 @@ services:
|
||||
<<: *common-build
|
||||
command: ["/app/docker/docker-bootstrap.sh", "app"]
|
||||
restart: unless-stopped
|
||||
# No host port mapping - accessed via webpack dev server proxy
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
user: *superset-user
|
||||
@@ -113,13 +115,16 @@ services:
|
||||
condition: service_completed_successfully
|
||||
volumes: *superset-volumes
|
||||
environment:
|
||||
# Override DB connection for light service
|
||||
DATABASE_HOST: db-light
|
||||
DATABASE_DB: superset_light
|
||||
POSTGRES_DB: superset_light
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: "duckdb:////app/data/examples.duckdb"
|
||||
EXAMPLES_HOST: db-light
|
||||
EXAMPLES_DB: superset_light
|
||||
EXAMPLES_USER: superset
|
||||
EXAMPLES_PASSWORD: superset
|
||||
# Use light-specific config that disables Redis
|
||||
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:
|
||||
@@ -130,16 +135,21 @@ services:
|
||||
required: true
|
||||
- path: docker/.env-local # optional override
|
||||
required: false
|
||||
user: *superset-user
|
||||
depends_on:
|
||||
db-light:
|
||||
condition: service_started
|
||||
user: *superset-user
|
||||
volumes: *superset-volumes
|
||||
environment:
|
||||
# Override DB connection for light service
|
||||
DATABASE_HOST: db-light
|
||||
DATABASE_DB: superset_light
|
||||
POSTGRES_DB: superset_light
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: "duckdb:////app/data/examples.duckdb"
|
||||
EXAMPLES_HOST: db-light
|
||||
EXAMPLES_DB: superset_light
|
||||
EXAMPLES_USER: superset
|
||||
EXAMPLES_PASSWORD: superset
|
||||
# Use light-specific config that disables Redis
|
||||
SUPERSET_CONFIG_PATH: /app/docker/pythonpath_dev/superset_config_docker_light.py
|
||||
healthcheck:
|
||||
disable: true
|
||||
@@ -162,11 +172,8 @@ 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:
|
||||
- "${NODE_PORT:-9001}:9000" # Parameterized port, accessible on all interfaces
|
||||
- "127.0.0.1:${NODE_PORT:-9001}:9000" # Parameterized port
|
||||
command: ["/app/docker/docker-frontend.sh"]
|
||||
env_file:
|
||||
- path: docker/.env # default
|
||||
@@ -192,12 +199,15 @@ services:
|
||||
user: *superset-user
|
||||
volumes: *superset-volumes
|
||||
environment:
|
||||
# Test-specific database configuration
|
||||
DATABASE_HOST: db-light
|
||||
DATABASE_DB: test
|
||||
POSTGRES_DB: test
|
||||
# Point to test database
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@db-light:5432/test
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: "duckdb:////app/data/examples.duckdb"
|
||||
# Use the light test config that doesn't require Redis
|
||||
SUPERSET_CONFIG: superset_test_config_light
|
||||
# Python path includes test directory
|
||||
PYTHONPATH: /app/pythonpath:/app/docker/pythonpath_dev:/app
|
||||
|
||||
volumes:
|
||||
|
||||
@@ -33,7 +33,7 @@ x-common-build: &common-build
|
||||
context: .
|
||||
target: dev
|
||||
cache_from:
|
||||
- apache/superset-cache:3.10-slim-trixie
|
||||
- apache/superset-cache:3.10-slim-bookworm
|
||||
|
||||
services:
|
||||
redis:
|
||||
|
||||
@@ -29,22 +29,19 @@ 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-trixie
|
||||
- apache/superset-cache:3.10-slim-bookworm
|
||||
args:
|
||||
DEV_MODE: "true"
|
||||
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
|
||||
INCLUDE_FIREFOX: ${INCLUDE_FIREFOX:-false}
|
||||
BUILD_TRANSLATIONS: ${BUILD_TRANSLATIONS:-false}
|
||||
LOAD_EXAMPLES_DUCKDB: ${LOAD_EXAMPLES_DUCKDB:-true}
|
||||
|
||||
services:
|
||||
nginx:
|
||||
@@ -110,8 +107,6 @@ services:
|
||||
superset-init:
|
||||
condition: service_completed_successfully
|
||||
volumes: *superset-volumes
|
||||
environment:
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: "duckdb:////app/data/examples.duckdb"
|
||||
|
||||
superset-websocket:
|
||||
container_name: superset_websocket
|
||||
@@ -163,8 +158,6 @@ services:
|
||||
condition: service_started
|
||||
user: *superset-user
|
||||
volumes: *superset-volumes
|
||||
environment:
|
||||
SUPERSET__SQLALCHEMY_EXAMPLES_URI: "duckdb:////app/data/examples.duckdb"
|
||||
healthcheck:
|
||||
disable: true
|
||||
|
||||
@@ -276,5 +269,3 @@ 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 -yqq --purge
|
||||
apt-get autoremove -y
|
||||
|
||||
echo -e "${GREEN}Cleaning up package cache and metadata...${RESET}"
|
||||
apt-get clean
|
||||
|
||||
@@ -21,15 +21,8 @@ set -eo pipefail
|
||||
# Make python interactive
|
||||
if [ "$DEV_MODE" == "true" ]; then
|
||||
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
|
||||
# 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
|
||||
echo "Reinstalling the app in editable mode"
|
||||
uv pip install -e .
|
||||
fi
|
||||
fi
|
||||
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
||||
@@ -41,8 +34,7 @@ if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
|
||||
PORT=8081
|
||||
fi
|
||||
# Skip postgres requirements installation for workers to avoid conflicts
|
||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ] && [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ]; then
|
||||
# older images may not have the postgres dev requirements installed
|
||||
echo "Installing postgres requirements"
|
||||
if command -v uv > /dev/null 2>&1; then
|
||||
@@ -80,7 +72,7 @@ case "${1}" in
|
||||
;;
|
||||
app)
|
||||
echo "Starting web app (using development server)..."
|
||||
flask run -p $PORT --reload --debugger --without-threads --host=0.0.0.0
|
||||
flask run -p $PORT --with-threads --reload --debugger --host=0.0.0.0
|
||||
;;
|
||||
app-gunicorn)
|
||||
echo "Starting web app..."
|
||||
|
||||
@@ -69,8 +69,6 @@ echo_step "3" "Complete" "Setting up roles and perms"
|
||||
if [ "$SUPERSET_LOAD_EXAMPLES" = "yes" ]; then
|
||||
# Load some data to play with
|
||||
echo_step "4" "Starting" "Loading examples"
|
||||
|
||||
|
||||
# If Cypress run which consumes superset_test_config – load required data for tests
|
||||
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||
superset load_examples --load-test-data
|
||||
|
||||
@@ -26,7 +26,7 @@ gunicorn \
|
||||
--workers ${SERVER_WORKER_AMOUNT:-1} \
|
||||
--worker-class ${SERVER_WORKER_CLASS:-gthread} \
|
||||
--threads ${SERVER_THREADS_AMOUNT:-20} \
|
||||
--log-level "${GUNICORN_LOGLEVEL:-info}" \
|
||||
--log-level "${GUNICORN_LOGLEVEL:info}" \
|
||||
--timeout ${GUNICORN_TIMEOUT:-60} \
|
||||
--keep-alive ${GUNICORN_KEEPALIVE:-2} \
|
||||
--max-requests ${WORKER_MAX_REQUESTS:-0} \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -49,18 +49,12 @@ SQLALCHEMY_DATABASE_URI = (
|
||||
f"{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_DB}"
|
||||
)
|
||||
|
||||
# Use environment variable if set, otherwise construct from components
|
||||
# This MUST take precedence over any other configuration
|
||||
SQLALCHEMY_EXAMPLES_URI = os.getenv(
|
||||
"SUPERSET__SQLALCHEMY_EXAMPLES_URI",
|
||||
(
|
||||
f"{DATABASE_DIALECT}://"
|
||||
f"{EXAMPLES_USER}:{EXAMPLES_PASSWORD}@"
|
||||
f"{EXAMPLES_HOST}:{EXAMPLES_PORT}/{EXAMPLES_DB}"
|
||||
),
|
||||
SQLALCHEMY_EXAMPLES_URI = (
|
||||
f"{DATABASE_DIALECT}://"
|
||||
f"{EXAMPLES_USER}:{EXAMPLES_PASSWORD}@"
|
||||
f"{EXAMPLES_HOST}:{EXAMPLES_PORT}/{EXAMPLES_DB}"
|
||||
)
|
||||
|
||||
|
||||
REDIS_HOST = os.getenv("REDIS_HOST", "redis")
|
||||
REDIS_PORT = os.getenv("REDIS_PORT", "6379")
|
||||
REDIS_CELERY_DB = os.getenv("REDIS_CELERY_DB", "0")
|
||||
@@ -138,7 +132,7 @@ try:
|
||||
from superset_config_docker import * # noqa: F403
|
||||
|
||||
logger.info(
|
||||
"Loaded your Docker configuration at [%s]", superset_config_docker.__file__
|
||||
f"Loaded your Docker configuration at [{superset_config_docker.__file__}]"
|
||||
)
|
||||
except ImportError:
|
||||
logger.info("Using default Docker config...")
|
||||
|
||||
@@ -1,642 +0,0 @@
|
||||
<!--
|
||||
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.
|
||||
180
docs/README.md
180
docs/README.md
@@ -21,183 +21,3 @@ This is the public documentation site for Superset, built using
|
||||
[Docusaurus 3](https://docusaurus.io/). See
|
||||
[CONTRIBUTING.md](../CONTRIBUTING.md#documentation) for documentation on
|
||||
contributing to documentation.
|
||||
|
||||
## Version Management
|
||||
|
||||
The Superset documentation site uses Docusaurus versioning with three independent versioned sections:
|
||||
|
||||
- **Main Documentation** (`/docs/`) - Core Superset documentation
|
||||
- **Developer Portal** (`/developer_portal/`) - Developer guides and tutorials
|
||||
- **Component Playground** (`/components/`) - Interactive component examples (currently disabled)
|
||||
|
||||
Each section maintains its own version history and can be versioned independently.
|
||||
|
||||
### Creating a New Version
|
||||
|
||||
To create a new version for any section, use the Docusaurus version command with the appropriate plugin ID or use our automated scripts:
|
||||
|
||||
#### Using Automated Scripts (Required)
|
||||
|
||||
**⚠️ Important:** Always use these custom commands instead of the native Docusaurus commands. These scripts ensure that both the Docusaurus versioning system AND the `versions-config.json` file are updated correctly.
|
||||
|
||||
```bash
|
||||
# Main Documentation
|
||||
yarn version:add:docs 1.2.0
|
||||
|
||||
# Developer Portal
|
||||
yarn version:add:developer_portal 1.2.0
|
||||
|
||||
# Component Playground (when enabled)
|
||||
yarn version:add:components 1.2.0
|
||||
```
|
||||
|
||||
**Do NOT use** the native Docusaurus commands directly (`yarn docusaurus docs:version`), as they will:
|
||||
- ❌ Create version files but NOT update `versions-config.json`
|
||||
- ❌ Cause versions to not appear in dropdown menus
|
||||
- ❌ Require manual fixes to synchronize the configuration
|
||||
|
||||
### Managing Versions
|
||||
|
||||
#### With Automated Scripts
|
||||
The automated scripts handle all configuration updates automatically. No manual editing required!
|
||||
|
||||
#### Manual Configuration
|
||||
If creating versions manually, you'll need to:
|
||||
|
||||
1. **Update `versions-config.json`** (or `docusaurus.config.ts` if not using dynamic config):
|
||||
- Add version to `onlyIncludeVersions` array
|
||||
- Add version metadata to `versions` object
|
||||
- Update `lastVersion` if needed
|
||||
|
||||
2. **Files Created by Versioning**:
|
||||
When a new version is created, Docusaurus generates:
|
||||
- **Versioned docs folder**: `[section]_versioned_docs/version-X.X.X/`
|
||||
- **Versioned sidebars**: `[section]_versioned_sidebars/version-X.X.X-sidebars.json`
|
||||
- **Versions list**: `[section]_versions.json`
|
||||
|
||||
Note: For main docs, the prefix is omitted (e.g., `versioned_docs/` instead of `docs_versioned_docs/`)
|
||||
|
||||
3. **Important**: After adding a version, restart the development server to see changes:
|
||||
```bash
|
||||
yarn stop
|
||||
yarn start
|
||||
```
|
||||
|
||||
### Removing a Version
|
||||
|
||||
#### Using Automated Scripts (Recommended)
|
||||
```bash
|
||||
# Main Documentation
|
||||
yarn version:remove:docs 1.0.0
|
||||
|
||||
# Developer Portal
|
||||
yarn version:remove:developer_portal 1.0.0
|
||||
|
||||
# Component Playground
|
||||
yarn version:remove:components 1.0.0
|
||||
```
|
||||
|
||||
#### Manual Removal
|
||||
To manually remove a version:
|
||||
|
||||
1. **Delete the version folder** from the appropriate location:
|
||||
- Main docs: `versioned_docs/version-X.X.X/` (no prefix for main)
|
||||
- Developer Portal: `developer_portal_versioned_docs/version-X.X.X/`
|
||||
- Components: `components_versioned_docs/version-X.X.X/`
|
||||
|
||||
2. **Delete the version metadata file**:
|
||||
- Main docs: `versioned_sidebars/version-X.X.X-sidebars.json` (no prefix)
|
||||
- Developer Portal: `developer_portal_versioned_sidebars/version-X.X.X-sidebars.json`
|
||||
- Components: `components_versioned_sidebars/version-X.X.X-sidebars.json`
|
||||
|
||||
3. **Update the versions list file**:
|
||||
- Main docs: `versions.json`
|
||||
- Developer Portal: `developer_portal_versions.json`
|
||||
- Components: `components_versions.json`
|
||||
|
||||
4. **Update configuration**:
|
||||
- If using dynamic config: Update `versions-config.json`
|
||||
- If using static config: Update `docusaurus.config.ts`
|
||||
|
||||
5. **Restart the server** to see changes
|
||||
|
||||
### Version Configuration Examples
|
||||
|
||||
#### Main Documentation (default plugin)
|
||||
```typescript
|
||||
docs: {
|
||||
includeCurrentVersion: true,
|
||||
lastVersion: 'current', // Makes /docs/ show Next version
|
||||
onlyIncludeVersions: ['current', '1.1.0', '1.0.0'],
|
||||
versions: {
|
||||
current: {
|
||||
label: 'Next',
|
||||
path: '', // Empty path for default routing
|
||||
banner: 'unreleased',
|
||||
},
|
||||
'1.1.0': {
|
||||
label: '1.1.0',
|
||||
path: '1.1.0',
|
||||
banner: 'none',
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### Developer Portal & Components (custom plugins)
|
||||
```typescript
|
||||
{
|
||||
id: 'developer_portal',
|
||||
path: 'developer_portal',
|
||||
routeBasePath: 'developer_portal',
|
||||
includeCurrentVersion: true,
|
||||
lastVersion: '1.1.0', // Default version
|
||||
onlyIncludeVersions: ['current', '1.1.0', '1.0.0'],
|
||||
versions: {
|
||||
current: {
|
||||
label: 'Next',
|
||||
path: 'next',
|
||||
banner: 'unreleased',
|
||||
},
|
||||
'1.1.0': {
|
||||
label: '1.1.0',
|
||||
path: '1.1.0',
|
||||
banner: 'none',
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Version naming**: Use semantic versioning (e.g., 1.0.0, 1.1.0, 2.0.0)
|
||||
2. **Version banners**: Use `'unreleased'` for development versions, `'none'` for stable releases
|
||||
3. **Limit displayed versions**: Use `onlyIncludeVersions` to show only relevant versions
|
||||
4. **Test locally**: Always test version changes locally before deploying
|
||||
5. **Independent versioning**: Each section can have different version numbers and release cycles
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### Version Not Showing After Creation
|
||||
|
||||
If you accidentally used `yarn docusaurus docs:version` instead of `yarn version:add`:
|
||||
1. **Problem**: The version files were created but `versions-config.json` wasn't updated
|
||||
2. **Solution**: Either:
|
||||
- Revert the changes: `git restore versions.json && rm -rf versioned_docs/ versioned_sidebars/`
|
||||
- Then use the correct command: `yarn version:add:docs <version>`
|
||||
|
||||
For other issues:
|
||||
- **Restart the server**: Changes to version configuration require a server restart
|
||||
- **Check config file**: Ensure `versions-config.json` includes the new version
|
||||
- **Verify files exist**: Check that versioned docs folder was created
|
||||
|
||||
#### Broken Links in Versioned Documentation
|
||||
When creating a new version, links in the documentation are preserved as-is. Common issues:
|
||||
- **Cross-section links**: Links between sections (e.g., from developer_portal to docs) need to be version-aware
|
||||
- **Absolute vs relative paths**: Use relative paths within the same section
|
||||
- **Version-specific URLs**: Update hardcoded URLs to use version variables
|
||||
|
||||
To fix broken links:
|
||||
1. Use `type: 'doc'` with `docId` for version-aware navigation in navbar
|
||||
2. Use relative paths within the same documentation section
|
||||
3. Test all versions after creation to identify broken links
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
<!--
|
||||
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: Bar Chart
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Bar Chart Component
|
||||
|
||||
The Bar Chart component is used to visualize categorical data with rectangular bars.
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `data` | `array` | `[]` | Array of data objects to visualize |
|
||||
| `width` | `number` | `800` | Width of the chart in pixels |
|
||||
| `height` | `number` | `600` | Height of the chart in pixels |
|
||||
| `xField` | `string` | - | Field name for x-axis values |
|
||||
| `yField` | `string` | - | Field name for y-axis values |
|
||||
| `colorField` | `string` | - | Field name for color encoding |
|
||||
| `colorScheme` | `string` | `'supersetColors'` | Color scheme to use |
|
||||
| `showLegend` | `boolean` | `true` | Whether to show the legend |
|
||||
| `showGrid` | `boolean` | `true` | Whether to show grid lines |
|
||||
| `labelPosition` | `string` | `'top'` | Position of bar labels: 'top', 'middle', 'bottom' |
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Bar Chart
|
||||
|
||||
```jsx
|
||||
import { BarChart } from '@superset-ui/chart-components';
|
||||
|
||||
const data = [
|
||||
{ category: 'A', value: 10 },
|
||||
{ category: 'B', value: 20 },
|
||||
{ category: 'C', value: 15 },
|
||||
{ category: 'D', value: 25 },
|
||||
];
|
||||
|
||||
function Example() {
|
||||
return (
|
||||
<BarChart
|
||||
data={data}
|
||||
width={800}
|
||||
height={400}
|
||||
xField="category"
|
||||
yField="value"
|
||||
colorScheme="supersetColors"
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Grouped Bar Chart
|
||||
|
||||
```jsx
|
||||
import { BarChart } from '@superset-ui/chart-components';
|
||||
|
||||
const data = [
|
||||
{ category: 'A', group: 'Group 1', value: 10 },
|
||||
{ category: 'A', group: 'Group 2', value: 15 },
|
||||
{ category: 'B', group: 'Group 1', value: 20 },
|
||||
{ category: 'B', group: 'Group 2', value: 25 },
|
||||
{ category: 'C', group: 'Group 1', value: 15 },
|
||||
{ category: 'C', group: 'Group 2', value: 10 },
|
||||
];
|
||||
|
||||
function Example() {
|
||||
return (
|
||||
<BarChart
|
||||
data={data}
|
||||
width={800}
|
||||
height={400}
|
||||
xField="category"
|
||||
yField="value"
|
||||
colorField="group"
|
||||
colorScheme="supersetColors"
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use bar charts when comparing quantities across categories
|
||||
- Sort bars by value for better readability, unless there's a natural order to the categories
|
||||
- Use consistent colors for the same categories across different charts
|
||||
- Consider using horizontal bar charts when category labels are long
|
||||
@@ -1,59 +0,0 @@
|
||||
<!--
|
||||
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: Component Library
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Superset Component Library
|
||||
|
||||
Welcome to the Apache Superset Component Library documentation. This section provides comprehensive documentation for all the UI components, chart components, and layout components used in Superset.
|
||||
|
||||
## What is the Component Library?
|
||||
|
||||
The Component Library is a collection of reusable UI components that are used to build the Superset user interface. These components are designed to be consistent, accessible, and easy to use.
|
||||
|
||||
## Component Categories
|
||||
|
||||
The Component Library is organized into the following categories:
|
||||
|
||||
### UI Components
|
||||
|
||||
Basic UI components like buttons, inputs, dropdowns, and other form elements.
|
||||
|
||||
### Chart Components
|
||||
|
||||
Visualization components used to render different types of charts and graphs.
|
||||
|
||||
### Layout Components
|
||||
|
||||
Components used for page layout, such as containers, grids, and navigation elements.
|
||||
|
||||
## Versioning
|
||||
|
||||
The Component Library documentation follows its own versioning scheme, independent from the main Superset documentation. This allows us to update the component documentation as the components evolve, without affecting the main documentation.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Browse the sidebar to explore the different components available in the library. Each component documentation includes:
|
||||
|
||||
- Component description and purpose
|
||||
- Props and configuration options
|
||||
- Usage examples
|
||||
- Best practices
|
||||
@@ -1,113 +0,0 @@
|
||||
<!--
|
||||
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: Grid
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Grid Component
|
||||
|
||||
The Grid component provides a flexible layout system for arranging content in rows and columns.
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `gutter` | `number` or `[number, number]` | `0` | Grid spacing between items, can be a single number or [horizontal, vertical] |
|
||||
| `columns` | `number` | `12` | Number of columns in the grid |
|
||||
| `justify` | `string` | `'start'` | Horizontal alignment: 'start', 'center', 'end', 'space-between', 'space-around' |
|
||||
| `align` | `string` | `'top'` | Vertical alignment: 'top', 'middle', 'bottom' |
|
||||
| `wrap` | `boolean` | `true` | Whether to wrap items when they overflow |
|
||||
|
||||
### Row Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `gutter` | `number` or `[number, number]` | `0` | Spacing between items in the row |
|
||||
| `justify` | `string` | `'start'` | Horizontal alignment for this row |
|
||||
| `align` | `string` | `'top'` | Vertical alignment for this row |
|
||||
|
||||
### Col Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `span` | `number` | - | Number of columns the grid item spans |
|
||||
| `offset` | `number` | `0` | Number of columns the grid item is offset |
|
||||
| `xs`, `sm`, `md`, `lg`, `xl` | `number` or `object` | - | Responsive props for different screen sizes |
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Grid
|
||||
|
||||
```jsx
|
||||
import { Grid, Row, Col } from '@superset-ui/core';
|
||||
|
||||
function Example() {
|
||||
return (
|
||||
<Grid>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<div>Column 1</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div>Column 2</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div>Column 3</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Responsive Grid
|
||||
|
||||
```jsx
|
||||
import { Grid, Row, Col } from '@superset-ui/core';
|
||||
|
||||
function Example() {
|
||||
return (
|
||||
<Grid>
|
||||
<Row gutter={[16, 24]}>
|
||||
<Col xs={24} sm={12} md={8} lg={6}>
|
||||
<div>Responsive Column 1</div>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={8} lg={6}>
|
||||
<div>Responsive Column 2</div>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={8} lg={6}>
|
||||
<div>Responsive Column 3</div>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={8} lg={6}>
|
||||
<div>Responsive Column 4</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use the Grid system for complex layouts that need to be responsive
|
||||
- Specify column widths for different screen sizes to ensure proper responsive behavior
|
||||
- Use gutters to create appropriate spacing between grid items
|
||||
- Keep the grid structure consistent throughout your application
|
||||
- Consider using the grid system for dashboard layouts to ensure consistent spacing and alignment
|
||||
@@ -1,35 +0,0 @@
|
||||
<!--
|
||||
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: Test
|
||||
---
|
||||
|
||||
import { StoryExample } from '../src/components/StorybookWrapper';
|
||||
|
||||
# Test
|
||||
|
||||
This is a test using our custom StorybookWrapper component.
|
||||
|
||||
<StoryExample
|
||||
component={() => (
|
||||
<div style={{ padding: '10px', background: '#f0f0f0', borderRadius: '4px' }}>
|
||||
This is a simple example component
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
@@ -1,146 +0,0 @@
|
||||
<!--
|
||||
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: Button Component
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
import { StoryExample, StoryWithControls } from '../../src/components/StorybookWrapper';
|
||||
import { Button } from '../../../superset-frontend/packages/superset-ui-core/src/components/Button';
|
||||
|
||||
# Button Component
|
||||
|
||||
The Button component is a fundamental UI element used throughout Superset for user interactions.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
The default button with primary styling:
|
||||
<StoryExample
|
||||
component={() => (
|
||||
<Button buttonStyle="primary" onClick={() => console.log('Clicked!')}>
|
||||
Click Me
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
|
||||
## Interactive Example
|
||||
|
||||
<StoryWithControls
|
||||
component={({ buttonStyle, buttonSize, label, disabled }) => (
|
||||
<Button
|
||||
buttonStyle={buttonStyle}
|
||||
buttonSize={buttonSize}
|
||||
disabled={disabled}
|
||||
onClick={() => console.log('Clicked!')}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
)}
|
||||
props={{
|
||||
buttonStyle: 'primary',
|
||||
buttonSize: 'default',
|
||||
label: 'Click Me',
|
||||
disabled: false
|
||||
}}
|
||||
controls={[
|
||||
{
|
||||
name: 'buttonStyle',
|
||||
label: 'Button Style',
|
||||
type: 'select',
|
||||
options: ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'default', 'link', 'dashed']
|
||||
},
|
||||
{
|
||||
name: 'buttonSize',
|
||||
label: 'Button Size',
|
||||
type: 'select',
|
||||
options: ['default', 'small', 'xsmall']
|
||||
},
|
||||
{
|
||||
name: 'label',
|
||||
label: 'Button Text',
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'disabled',
|
||||
label: 'Disabled',
|
||||
type: 'boolean'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `buttonStyle` | `'primary' \| 'secondary' \| 'tertiary' \| 'success' \| 'warning' \| 'danger' \| 'default' \| 'link' \| 'dashed'` | `'default'` | Button style |
|
||||
| `buttonSize` | `'default' \| 'small' \| 'xsmall'` | `'default'` | Button size |
|
||||
| `disabled` | `boolean` | `false` | Whether the button is disabled |
|
||||
| `cta` | `boolean` | `false` | Whether the button is a call-to-action button |
|
||||
| `tooltip` | `ReactNode` | - | Tooltip content |
|
||||
| `placement` | `TooltipProps['placement']` | - | Tooltip placement |
|
||||
| `onClick` | `function` | - | Callback when button is clicked |
|
||||
| `href` | `string` | - | Turns button into an anchor link |
|
||||
| `target` | `string` | - | Target attribute for anchor links |
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
function MyComponent() {
|
||||
return (
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
onClick={() => console.log('Button clicked')}
|
||||
>
|
||||
Click Me
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Button Styles
|
||||
|
||||
Superset provides a variety of button styles for different purposes:
|
||||
|
||||
- **Primary**: Used for primary actions
|
||||
- **Secondary**: Used for secondary actions
|
||||
- **Tertiary**: Used for less important actions
|
||||
- **Success**: Used for successful or confirming actions
|
||||
- **Warning**: Used for actions that require caution
|
||||
- **Danger**: Used for destructive actions
|
||||
- **Link**: Used for navigation
|
||||
- **Dashed**: Used for adding new items or features
|
||||
|
||||
## Button Sizes
|
||||
|
||||
Buttons come in three sizes:
|
||||
|
||||
- **Default**: Standard size for most use cases
|
||||
- **Small**: Compact size for tight spaces
|
||||
- **XSmall**: Extra small size for very limited spaces
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use primary buttons for the main action in a form or page
|
||||
- Use secondary buttons for alternative actions
|
||||
- Use danger buttons for destructive actions
|
||||
- Limit the number of primary buttons on a page to avoid confusion
|
||||
- Use consistent button styles throughout your application
|
||||
- Add tooltips to buttons when their purpose might not be immediately clear
|
||||
@@ -1 +0,0 @@
|
||||
[]
|
||||
@@ -1 +0,0 @@
|
||||
[]
|
||||
@@ -1,772 +0,0 @@
|
||||
---
|
||||
title: Frontend API Reference
|
||||
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.
|
||||
-->
|
||||
|
||||
# Frontend Extension API Reference
|
||||
|
||||
The `@apache-superset/core` package provides comprehensive APIs for frontend extensions to interact with Apache Superset. All APIs are versioned and follow semantic versioning principles.
|
||||
|
||||
## Core APIs
|
||||
|
||||
### Extension Context
|
||||
|
||||
Every extension receives a context object during activation that provides access to the extension system.
|
||||
|
||||
```typescript
|
||||
interface ExtensionContext {
|
||||
// Unique extension identifier
|
||||
extensionId: string;
|
||||
|
||||
// Extension metadata
|
||||
extensionPath: string;
|
||||
extensionUri: Uri;
|
||||
|
||||
// Storage paths
|
||||
globalStorageUri: Uri;
|
||||
workspaceStorageUri: Uri;
|
||||
|
||||
// Subscription management
|
||||
subscriptions: Disposable[];
|
||||
|
||||
// State management
|
||||
globalState: Memento;
|
||||
workspaceState: Memento;
|
||||
|
||||
// Extension-specific APIs
|
||||
registerView(viewId: string, component: React.Component): Disposable;
|
||||
registerCommand(commandId: string, handler: CommandHandler): Disposable;
|
||||
}
|
||||
```
|
||||
|
||||
### Lifecycle Methods
|
||||
|
||||
```typescript
|
||||
// Required: Called when extension is activated
|
||||
export function activate(context: ExtensionContext): void | Promise<void> {
|
||||
console.log('Extension activated');
|
||||
}
|
||||
|
||||
// Optional: Called when extension is deactivated
|
||||
export function deactivate(): void | Promise<void> {
|
||||
console.log('Extension deactivated');
|
||||
}
|
||||
```
|
||||
|
||||
## SQL Lab APIs
|
||||
|
||||
The `sqlLab` namespace provides APIs specific to SQL Lab functionality.
|
||||
|
||||
### Query Management
|
||||
|
||||
```typescript
|
||||
// Get current query editor content
|
||||
sqlLab.getCurrentQuery(): string | undefined
|
||||
|
||||
// Get active tab information
|
||||
sqlLab.getCurrentTab(): Tab | undefined
|
||||
|
||||
// Get all open tabs
|
||||
sqlLab.getTabs(): Tab[]
|
||||
|
||||
// Get available databases
|
||||
sqlLab.getDatabases(): Database[]
|
||||
|
||||
// Get schemas for a database
|
||||
sqlLab.getSchemas(databaseId: number): Promise<Schema[]>
|
||||
|
||||
// Get tables for a schema
|
||||
sqlLab.getTables(databaseId: number, schema: string): Promise<Table[]>
|
||||
|
||||
// Insert text at cursor position
|
||||
sqlLab.insertText(text: string): void
|
||||
|
||||
// Replace entire query
|
||||
sqlLab.replaceQuery(query: string): void
|
||||
|
||||
// Execute current query
|
||||
sqlLab.executeQuery(): Promise<QueryResult>
|
||||
|
||||
// Stop query execution
|
||||
sqlLab.stopQuery(queryId: string): Promise<void>
|
||||
```
|
||||
|
||||
### Event Subscriptions
|
||||
|
||||
```typescript
|
||||
// Query execution events
|
||||
sqlLab.onDidQueryRun(
|
||||
listener: (event: QueryRunEvent) => void
|
||||
): Disposable
|
||||
|
||||
sqlLab.onDidQueryComplete(
|
||||
listener: (event: QueryCompleteEvent) => void
|
||||
): Disposable
|
||||
|
||||
sqlLab.onDidQueryFail(
|
||||
listener: (event: QueryFailEvent) => void
|
||||
): Disposable
|
||||
|
||||
// Editor events
|
||||
sqlLab.onDidChangeEditorContent(
|
||||
listener: (content: string) => void
|
||||
): Disposable
|
||||
|
||||
sqlLab.onDidChangeActiveTab(
|
||||
listener: (tab: Tab) => void
|
||||
): Disposable
|
||||
|
||||
// Panel events
|
||||
sqlLab.onDidOpenPanel(
|
||||
listener: (panel: Panel) => void
|
||||
): Disposable
|
||||
|
||||
sqlLab.onDidClosePanel(
|
||||
listener: (panel: Panel) => void
|
||||
): Disposable
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
```typescript
|
||||
interface Tab {
|
||||
id: string;
|
||||
title: string;
|
||||
query: string;
|
||||
database: Database;
|
||||
schema?: string;
|
||||
isActive: boolean;
|
||||
queryId?: string;
|
||||
status?: 'pending' | 'running' | 'success' | 'error';
|
||||
}
|
||||
|
||||
interface Database {
|
||||
id: number;
|
||||
name: string;
|
||||
backend: string;
|
||||
allows_subquery: boolean;
|
||||
allows_ctas: boolean;
|
||||
allows_cvas: boolean;
|
||||
}
|
||||
|
||||
interface QueryResult {
|
||||
queryId: string;
|
||||
status: 'success' | 'error';
|
||||
data?: any[];
|
||||
columns?: Column[];
|
||||
error?: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
rows: number;
|
||||
}
|
||||
```
|
||||
|
||||
## Commands API
|
||||
|
||||
Register and execute commands within Superset.
|
||||
|
||||
### Registration
|
||||
|
||||
```typescript
|
||||
interface CommandHandler {
|
||||
execute(...args: any[]): any | Promise<any>;
|
||||
isEnabled?(): boolean;
|
||||
isVisible?(): boolean;
|
||||
}
|
||||
|
||||
// Register a command
|
||||
commands.registerCommand(
|
||||
commandId: string,
|
||||
handler: CommandHandler
|
||||
): Disposable
|
||||
|
||||
// Register with metadata
|
||||
commands.registerCommand(
|
||||
commandId: string,
|
||||
metadata: CommandMetadata,
|
||||
handler: (...args: any[]) => any
|
||||
): Disposable
|
||||
|
||||
interface CommandMetadata {
|
||||
title: string;
|
||||
category?: string;
|
||||
icon?: string;
|
||||
enablement?: string;
|
||||
when?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Execution
|
||||
|
||||
```typescript
|
||||
// Execute a command
|
||||
commands.executeCommand<T>(
|
||||
commandId: string,
|
||||
...args: any[]
|
||||
): Promise<T>
|
||||
|
||||
// Get all registered commands
|
||||
commands.getCommands(): Promise<string[]>
|
||||
|
||||
// Check if command exists
|
||||
commands.hasCommand(commandId: string): boolean
|
||||
```
|
||||
|
||||
### Built-in Commands
|
||||
|
||||
```typescript
|
||||
// SQL Lab commands
|
||||
'sqllab.executeQuery'
|
||||
'sqllab.formatQuery'
|
||||
'sqllab.saveQuery'
|
||||
'sqllab.shareQuery'
|
||||
'sqllab.downloadResults'
|
||||
|
||||
// Editor commands
|
||||
'editor.action.formatDocument'
|
||||
'editor.action.commentLine'
|
||||
'editor.action.findReferences'
|
||||
|
||||
// Extension commands
|
||||
'extensions.installExtension'
|
||||
'extensions.uninstallExtension'
|
||||
'extensions.enableExtension'
|
||||
'extensions.disableExtension'
|
||||
```
|
||||
|
||||
## UI Components
|
||||
|
||||
Pre-built components from `@apache-superset/core` for consistent UI.
|
||||
|
||||
### Basic Components
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Select,
|
||||
Checkbox,
|
||||
Radio,
|
||||
Switch,
|
||||
Slider,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Tooltip,
|
||||
Popover,
|
||||
Modal,
|
||||
Drawer,
|
||||
Alert,
|
||||
Message,
|
||||
Notification,
|
||||
Spin,
|
||||
Progress
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
### Data Display
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Table,
|
||||
List,
|
||||
Card,
|
||||
Collapse,
|
||||
Tabs,
|
||||
Tag,
|
||||
Badge,
|
||||
Statistic,
|
||||
Timeline,
|
||||
Tree,
|
||||
Empty,
|
||||
Result
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
### Form Components
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Form,
|
||||
FormItem,
|
||||
FormList,
|
||||
InputNumber,
|
||||
TextArea,
|
||||
Upload,
|
||||
Rate,
|
||||
Cascader,
|
||||
AutoComplete,
|
||||
Mentions
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
## Authentication API
|
||||
|
||||
Access authentication and user information.
|
||||
|
||||
```typescript
|
||||
// Get current user
|
||||
authentication.getCurrentUser(): User | undefined
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
roles: Role[];
|
||||
isActive: boolean;
|
||||
isAnonymous: boolean;
|
||||
}
|
||||
|
||||
// Get CSRF token for API requests
|
||||
authentication.getCSRFToken(): Promise<string>
|
||||
|
||||
// Check permissions
|
||||
authentication.hasPermission(
|
||||
permission: string,
|
||||
resource?: string
|
||||
): boolean
|
||||
|
||||
// Get user preferences
|
||||
authentication.getPreferences(): UserPreferences
|
||||
|
||||
// Update preferences
|
||||
authentication.setPreference(
|
||||
key: string,
|
||||
value: any
|
||||
): Promise<void>
|
||||
```
|
||||
|
||||
## Storage API
|
||||
|
||||
Persist data across sessions.
|
||||
|
||||
### Global Storage
|
||||
|
||||
```typescript
|
||||
// Shared across all workspaces
|
||||
const globalState = context.globalState;
|
||||
|
||||
// Get value
|
||||
const value = globalState.get<T>(key: string): T | undefined
|
||||
|
||||
// Set value
|
||||
await globalState.update(key: string, value: any): Promise<void>
|
||||
|
||||
// Get all keys
|
||||
globalState.keys(): readonly string[]
|
||||
```
|
||||
|
||||
### Workspace Storage
|
||||
|
||||
```typescript
|
||||
// Specific to current workspace
|
||||
const workspaceState = context.workspaceState;
|
||||
|
||||
// Same API as globalState
|
||||
workspaceState.get<T>(key: string): T | undefined
|
||||
workspaceState.update(key: string, value: any): Promise<void>
|
||||
workspaceState.keys(): readonly string[]
|
||||
```
|
||||
|
||||
### Secrets Storage
|
||||
|
||||
```typescript
|
||||
// Secure storage for sensitive data
|
||||
secrets.store(key: string, value: string): Promise<void>
|
||||
secrets.get(key: string): Promise<string | undefined>
|
||||
secrets.delete(key: string): Promise<void>
|
||||
```
|
||||
|
||||
## Events API
|
||||
|
||||
Subscribe to and emit custom events.
|
||||
|
||||
```typescript
|
||||
// Create an event emitter
|
||||
const onDidChange = new EventEmitter<ChangeEvent>();
|
||||
|
||||
// Expose as event
|
||||
export const onChange = onDidChange.event;
|
||||
|
||||
// Fire event
|
||||
onDidChange.fire({
|
||||
type: 'update',
|
||||
data: newData
|
||||
});
|
||||
|
||||
// Subscribe to event
|
||||
const disposable = onChange((event) => {
|
||||
console.log('Changed:', event);
|
||||
});
|
||||
|
||||
// Cleanup
|
||||
disposable.dispose();
|
||||
```
|
||||
|
||||
## Window API
|
||||
|
||||
Interact with the UI window.
|
||||
|
||||
### Notifications
|
||||
|
||||
```typescript
|
||||
// Show info message
|
||||
window.showInformationMessage(
|
||||
message: string,
|
||||
...items: string[]
|
||||
): Promise<string | undefined>
|
||||
|
||||
// Show warning
|
||||
window.showWarningMessage(
|
||||
message: string,
|
||||
...items: string[]
|
||||
): Promise<string | undefined>
|
||||
|
||||
// Show error
|
||||
window.showErrorMessage(
|
||||
message: string,
|
||||
...items: string[]
|
||||
): Promise<string | undefined>
|
||||
|
||||
// Show with options
|
||||
window.showInformationMessage(
|
||||
message: string,
|
||||
options: MessageOptions,
|
||||
...items: MessageItem[]
|
||||
): Promise<MessageItem | undefined>
|
||||
|
||||
interface MessageOptions {
|
||||
modal?: boolean;
|
||||
detail?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Input Dialogs
|
||||
|
||||
```typescript
|
||||
// Show input box
|
||||
window.showInputBox(
|
||||
options?: InputBoxOptions
|
||||
): Promise<string | undefined>
|
||||
|
||||
interface InputBoxOptions {
|
||||
title?: string;
|
||||
prompt?: string;
|
||||
placeHolder?: string;
|
||||
value?: string;
|
||||
password?: boolean;
|
||||
validateInput?(value: string): string | null;
|
||||
}
|
||||
|
||||
// Show quick pick
|
||||
window.showQuickPick(
|
||||
items: string[] | QuickPickItem[],
|
||||
options?: QuickPickOptions
|
||||
): Promise<string | QuickPickItem | undefined>
|
||||
|
||||
interface QuickPickOptions {
|
||||
title?: string;
|
||||
placeHolder?: string;
|
||||
canPickMany?: boolean;
|
||||
matchOnDescription?: boolean;
|
||||
matchOnDetail?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### Progress
|
||||
|
||||
```typescript
|
||||
// Show progress
|
||||
window.withProgress<T>(
|
||||
options: ProgressOptions,
|
||||
task: (progress: Progress<{message?: string}>) => Promise<T>
|
||||
): Promise<T>
|
||||
|
||||
interface ProgressOptions {
|
||||
location: ProgressLocation;
|
||||
title?: string;
|
||||
cancellable?: boolean;
|
||||
}
|
||||
|
||||
// Example usage
|
||||
await window.withProgress(
|
||||
{
|
||||
location: ProgressLocation.Notification,
|
||||
title: "Processing",
|
||||
cancellable: true
|
||||
},
|
||||
async (progress) => {
|
||||
progress.report({ message: 'Step 1...' });
|
||||
await step1();
|
||||
progress.report({ message: 'Step 2...' });
|
||||
await step2();
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Workspace API
|
||||
|
||||
Access workspace information and configuration.
|
||||
|
||||
```typescript
|
||||
// Get workspace folders
|
||||
workspace.workspaceFolders: readonly WorkspaceFolder[]
|
||||
|
||||
// Get configuration
|
||||
workspace.getConfiguration(
|
||||
section?: string
|
||||
): WorkspaceConfiguration
|
||||
|
||||
// Update configuration
|
||||
workspace.getConfiguration('myExtension')
|
||||
.update('setting', value, ConfigurationTarget.Workspace)
|
||||
|
||||
// Watch for configuration changes
|
||||
workspace.onDidChangeConfiguration(
|
||||
listener: (e: ConfigurationChangeEvent) => void
|
||||
): Disposable
|
||||
|
||||
// File system operations
|
||||
workspace.fs.readFile(uri: Uri): Promise<Uint8Array>
|
||||
workspace.fs.writeFile(uri: Uri, content: Uint8Array): Promise<void>
|
||||
workspace.fs.delete(uri: Uri): Promise<void>
|
||||
workspace.fs.rename(oldUri: Uri, newUri: Uri): Promise<void>
|
||||
workspace.fs.copy(source: Uri, destination: Uri): Promise<void>
|
||||
workspace.fs.createDirectory(uri: Uri): Promise<void>
|
||||
workspace.fs.readDirectory(uri: Uri): Promise<[string, FileType][]>
|
||||
workspace.fs.stat(uri: Uri): Promise<FileStat>
|
||||
```
|
||||
|
||||
## HTTP Client API
|
||||
|
||||
Make HTTP requests from extensions.
|
||||
|
||||
```typescript
|
||||
import { api } from '@apache-superset/core';
|
||||
|
||||
// GET request
|
||||
const response = await api.get('/api/v1/chart/');
|
||||
|
||||
// POST request
|
||||
const response = await api.post('/api/v1/chart/', {
|
||||
data: chartData
|
||||
});
|
||||
|
||||
// PUT request
|
||||
const response = await api.put('/api/v1/chart/123', {
|
||||
data: updatedData
|
||||
});
|
||||
|
||||
// DELETE request
|
||||
const response = await api.delete('/api/v1/chart/123');
|
||||
|
||||
// Custom headers
|
||||
const response = await api.get('/api/v1/chart/', {
|
||||
headers: {
|
||||
'X-Custom-Header': 'value'
|
||||
}
|
||||
});
|
||||
|
||||
// Query parameters
|
||||
const response = await api.get('/api/v1/chart/', {
|
||||
params: {
|
||||
page: 1,
|
||||
page_size: 20
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Theming API
|
||||
|
||||
Access and customize theme settings.
|
||||
|
||||
```typescript
|
||||
// Get current theme
|
||||
theme.getActiveTheme(): Theme
|
||||
|
||||
interface Theme {
|
||||
name: string;
|
||||
isDark: boolean;
|
||||
colors: ThemeColors;
|
||||
typography: Typography;
|
||||
spacing: Spacing;
|
||||
}
|
||||
|
||||
// Listen for theme changes
|
||||
theme.onDidChangeTheme(
|
||||
listener: (theme: Theme) => void
|
||||
): Disposable
|
||||
|
||||
// Get theme colors
|
||||
const colors = theme.colors;
|
||||
colors.primary
|
||||
colors.success
|
||||
colors.warning
|
||||
colors.error
|
||||
colors.info
|
||||
colors.text
|
||||
colors.background
|
||||
colors.border
|
||||
```
|
||||
|
||||
## Disposable Pattern
|
||||
|
||||
Manage resource cleanup consistently.
|
||||
|
||||
```typescript
|
||||
interface Disposable {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
// Create a disposable
|
||||
class MyDisposable implements Disposable {
|
||||
dispose() {
|
||||
// Cleanup logic
|
||||
}
|
||||
}
|
||||
|
||||
// Combine disposables
|
||||
const composite = Disposable.from(
|
||||
disposable1,
|
||||
disposable2,
|
||||
disposable3
|
||||
);
|
||||
|
||||
// Dispose all at once
|
||||
composite.dispose();
|
||||
|
||||
// Use in extension
|
||||
export function activate(context: ExtensionContext) {
|
||||
// All disposables added here are cleaned up on deactivation
|
||||
context.subscriptions.push(
|
||||
registerCommand(...),
|
||||
registerView(...),
|
||||
onDidChange(...)
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Type Definitions
|
||||
|
||||
Complete TypeScript definitions are available:
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
ExtensionContext,
|
||||
Disposable,
|
||||
Event,
|
||||
EventEmitter,
|
||||
Uri,
|
||||
Command,
|
||||
QuickPickItem,
|
||||
InputBoxOptions,
|
||||
Progress,
|
||||
CancellationToken
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
## Version Compatibility
|
||||
|
||||
The API follows semantic versioning:
|
||||
|
||||
```typescript
|
||||
// Check API version
|
||||
const version = superset.version;
|
||||
|
||||
// Version components
|
||||
version.major // Breaking changes
|
||||
version.minor // New features
|
||||
version.patch // Bug fixes
|
||||
|
||||
// Check minimum version
|
||||
if (version.major < 1) {
|
||||
throw new Error('Requires Superset API v1.0.0 or higher');
|
||||
}
|
||||
```
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### From v0.x to v1.0
|
||||
|
||||
```typescript
|
||||
// Before (v0.x)
|
||||
sqlLab.runQuery(query);
|
||||
|
||||
// After (v1.0)
|
||||
sqlLab.executeQuery();
|
||||
|
||||
// Before (v0.x)
|
||||
core.registerPanel(id, component);
|
||||
|
||||
// After (v1.0)
|
||||
context.registerView(id, component);
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
export async function activate(context: ExtensionContext) {
|
||||
try {
|
||||
await initializeExtension();
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize:', error);
|
||||
window.showErrorMessage(
|
||||
`Extension failed to activate: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Resource Management
|
||||
|
||||
```typescript
|
||||
// Always use disposables
|
||||
const disposables: Disposable[] = [];
|
||||
|
||||
disposables.push(
|
||||
commands.registerCommand(...),
|
||||
sqlLab.onDidQueryRun(...),
|
||||
workspace.onDidChangeConfiguration(...)
|
||||
);
|
||||
|
||||
// Cleanup in deactivate
|
||||
export function deactivate() {
|
||||
disposables.forEach(d => d.dispose());
|
||||
}
|
||||
```
|
||||
|
||||
### Type Safety
|
||||
|
||||
```typescript
|
||||
// Use type guards
|
||||
function isDatabase(obj: any): obj is Database {
|
||||
return obj && typeof obj.id === 'number' && typeof obj.name === 'string';
|
||||
}
|
||||
|
||||
// Use generics
|
||||
function getValue<T>(key: string, defaultValue: T): T {
|
||||
return context.globalState.get(key) ?? defaultValue;
|
||||
}
|
||||
```
|
||||
@@ -1,194 +0,0 @@
|
||||
---
|
||||
title: Extension Architecture
|
||||
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.
|
||||
-->
|
||||
|
||||
# Superset Extension Architecture
|
||||
|
||||
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 Concepts
|
||||
|
||||
### Extensions vs Plugins
|
||||
|
||||
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.
|
||||
|
||||
### Lean Core Philosophy
|
||||
|
||||
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.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
The extension architecture consists of several key components:
|
||||
|
||||
### Core Packages
|
||||
|
||||
#### @apache-superset/core (Frontend)
|
||||
Provides essential building blocks for extensions:
|
||||
- Shared UI components
|
||||
- Utility functions
|
||||
- Type definitions
|
||||
- Frontend APIs for interacting with the host
|
||||
|
||||
#### apache-superset-core (Backend)
|
||||
Exposes backend functionality:
|
||||
- Database access APIs
|
||||
- Security models
|
||||
- REST API extensions
|
||||
- SQLAlchemy models and utilities
|
||||
|
||||
### Extension CLI
|
||||
|
||||
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
|
||||
|
||||
### Host Application
|
||||
|
||||
Superset acts as the host, providing:
|
||||
- Extension registration and management
|
||||
- Dynamic loading of extension assets
|
||||
- API implementation for extensions
|
||||
- Lifecycle management (activation/deactivation)
|
||||
|
||||
## Extension Points
|
||||
|
||||
Extensions can contribute to various parts of Superset:
|
||||
|
||||
### SQL Lab Extensions
|
||||
- Custom panels (left, right, bottom)
|
||||
- Editor enhancements
|
||||
- Query processors
|
||||
- Autocomplete providers
|
||||
- Execution plan visualizers
|
||||
|
||||
### Dashboard Extensions (Future)
|
||||
- Custom widget types
|
||||
- Filter components
|
||||
- Interaction handlers
|
||||
|
||||
### 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:
|
||||
|
||||
```typescript
|
||||
// Frontend activation
|
||||
export function activate(context) {
|
||||
// Register a new SQL Lab panel
|
||||
const panel = core.registerView('dataset_references.main',
|
||||
<DatasetReferencesPanel />
|
||||
);
|
||||
|
||||
// Listen to query changes
|
||||
const listener = sqlLab.onDidQueryRun(editor => {
|
||||
// Analyze query and update panel
|
||||
});
|
||||
|
||||
// Cleanup on deactivation
|
||||
context.subscriptions.push(panel, listener);
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# Backend API extension
|
||||
from superset_core.api import rest_api
|
||||
from .api import DatasetReferencesAPI
|
||||
|
||||
# Register custom REST endpoints
|
||||
rest_api.add_extension_api(DatasetReferencesAPI)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Extension Design
|
||||
- Keep extensions focused on specific functionality
|
||||
- Use versioned APIs for stability
|
||||
- Handle cleanup properly on deactivation
|
||||
- Follow Superset's coding standards
|
||||
|
||||
### Performance
|
||||
- Lazy load assets when possible
|
||||
- Minimize bundle sizes
|
||||
- Share dependencies with host
|
||||
- Cache expensive operations
|
||||
|
||||
### Compatibility
|
||||
- Declare API version requirements
|
||||
- Test across Superset versions
|
||||
- Provide migration guides for breaking changes
|
||||
- Document compatibility clearly
|
||||
|
||||
## 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)
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
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!*
|
||||
@@ -1,62 +0,0 @@
|
||||
---
|
||||
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!*
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
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!*
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
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,578 +0,0 @@
|
||||
---
|
||||
title: Extension CLI
|
||||
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.
|
||||
-->
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
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 structure and boilerplate code.
|
||||
|
||||
```bash
|
||||
superset-extensions init [options] <extension-name>
|
||||
```
|
||||
|
||||
#### 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```
|
||||
my-extension/
|
||||
├── extension.json # Extension metadata
|
||||
├── frontend/ # Frontend source code
|
||||
│ ├── src/
|
||||
│ │ ├── index.tsx # Main entry point
|
||||
│ │ └── components/ # React components
|
||||
│ ├── package.json
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── backend/ # Backend source code
|
||||
│ ├── src/
|
||||
│ │ └── my_extension/
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── api.py
|
||||
│ ├── tests/
|
||||
│ └── requirements.txt
|
||||
├── README.md
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
### dev
|
||||
|
||||
Starts development mode with automatic rebuilding and hot reload.
|
||||
|
||||
```bash
|
||||
superset-extensions dev [options]
|
||||
```
|
||||
|
||||
#### 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
|
||||
|
||||
```bash
|
||||
# Start development mode
|
||||
superset-extensions dev
|
||||
|
||||
# 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 extension assets for production deployment.
|
||||
|
||||
```bash
|
||||
superset-extensions build [options]
|
||||
```
|
||||
|
||||
#### 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
|
||||
|
||||
```bash
|
||||
# Production build
|
||||
superset-extensions build
|
||||
|
||||
# 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
|
||||
|
||||
Packages the built extension into a distributable `.supx` file.
|
||||
|
||||
```bash
|
||||
superset-extensions bundle [options]
|
||||
```
|
||||
|
||||
#### 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
|
||||
|
||||
```bash
|
||||
# Create bundle
|
||||
superset-extensions bundle
|
||||
|
||||
# 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 structure, metadata, and compatibility.
|
||||
|
||||
```bash
|
||||
superset-extensions validate [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- `--strict` - Enable strict validation
|
||||
- `--fix` - Auto-fix correctable issues
|
||||
- `--check-deps` - Validate dependencies
|
||||
- `--check-security` - Run security checks
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Basic validation
|
||||
superset-extensions validate
|
||||
|
||||
# Strict mode with auto-fix
|
||||
superset-extensions validate --strict --fix
|
||||
|
||||
# Full validation
|
||||
superset-extensions validate --check-deps --check-security
|
||||
```
|
||||
|
||||
#### Validation Checks
|
||||
|
||||
- Extension metadata completeness
|
||||
- File structure conformity
|
||||
- API version compatibility
|
||||
- Dependency security vulnerabilities
|
||||
- Code quality standards
|
||||
- Bundle size limits
|
||||
|
||||
## Configuration File
|
||||
|
||||
Create `.superset-extension.json` for project-specific settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"mode": "production",
|
||||
"sourceMaps": true,
|
||||
"analyze": false,
|
||||
"parallel": true
|
||||
},
|
||||
"dev": {
|
||||
"port": 9001,
|
||||
"host": "localhost",
|
||||
"autoOpen": true
|
||||
},
|
||||
"bundle": {
|
||||
"compression": 6,
|
||||
"sign": false,
|
||||
"exclude": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*",
|
||||
"**/tests/**"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"strict": true,
|
||||
"autoFix": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Configure CLI behavior using environment variables:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Templates
|
||||
|
||||
Create custom project templates:
|
||||
|
||||
```bash
|
||||
# Use custom template
|
||||
superset-extensions init my-ext --template https://github.com/user/template
|
||||
|
||||
# Use local template
|
||||
superset-extensions init my-ext --template ./my-template
|
||||
```
|
||||
|
||||
### CI/CD Integration
|
||||
|
||||
#### GitHub Actions
|
||||
|
||||
```yaml
|
||||
name: Build Extension
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@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: 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'
|
||||
```
|
||||
|
||||
### Automated Deployment
|
||||
|
||||
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)
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
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!*
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user