e2512ec500
- Remove PROMPT.md (AI scaffolding artifact) - Add .claude/settings* to .gitignore - Commit .mcp.json (MCP server config) - Fix ArtifactHub URLs (headlamp/tns-csi path) - Fix tarball name (tns-csi-VERSION.tar.gz) in all install docs - Update version URLs from v0.1.0/v0.2.0 to v0.2.4 - Update test count from 67 to 159 across 12 files - Update Node.js version from 20 to 22 - Add CHANGELOG entry for v0.2.4 - Update testing.md with full test file inventory and CI description Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
431 lines
12 KiB
Markdown
431 lines
12 KiB
Markdown
# Contributing to Headlamp TNS-CSI Plugin
|
|
|
|
Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to the project.
|
|
|
|
## Table of Contents
|
|
|
|
- [Code of Conduct](#code-of-conduct)
|
|
- [Getting Started](#getting-started)
|
|
- [Development Workflow](#development-workflow)
|
|
- [Branching Strategy](#branching-strategy)
|
|
- [Commit Message Guidelines](#commit-message-guidelines)
|
|
- [Pull Request Process](#pull-request-process)
|
|
- [Code Style](#code-style)
|
|
- [Testing Requirements](#testing-requirements)
|
|
- [Documentation](#documentation)
|
|
- [Release Process](#release-process)
|
|
|
|
## Code of Conduct
|
|
|
|
This project follows a standard code of conduct:
|
|
- Be respectful and inclusive
|
|
- Welcome newcomers and help them get started
|
|
- Focus on constructive feedback
|
|
- Assume good intentions
|
|
|
|
## Getting Started
|
|
|
|
### Prerequisites
|
|
|
|
- Node.js 22 or later
|
|
- npm
|
|
- Access to a Kubernetes cluster with Headlamp and tns-csi installed (for end-to-end testing)
|
|
- Git
|
|
|
|
### Development Setup
|
|
|
|
1. **Fork and clone the repository:**
|
|
```bash
|
|
git clone https://github.com/YOUR_USERNAME/headlamp-tns-csi-plugin.git
|
|
cd headlamp-tns-csi-plugin
|
|
```
|
|
|
|
2. **Install dependencies:**
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. **Start development mode:**
|
|
```bash
|
|
npm start
|
|
# Plugin will be available at http://localhost:4466
|
|
```
|
|
|
|
4. **Run tests:**
|
|
```bash
|
|
npm test # 159 unit tests
|
|
npm run tsc # TypeScript type-check
|
|
```
|
|
|
|
5. **Build the plugin:**
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
## Development Workflow
|
|
|
|
### Feature Development
|
|
|
|
1. Create a feature branch from `main`
|
|
2. Make your changes
|
|
3. Write/update tests
|
|
4. Update documentation
|
|
5. Run lint and tests locally
|
|
6. Submit a pull request
|
|
|
|
### Local Testing
|
|
|
|
**Option 1: Development Mode**
|
|
```bash
|
|
npm start
|
|
# Opens Headlamp at http://localhost:4466 with hot reload
|
|
```
|
|
|
|
**Option 2: Production Build**
|
|
```bash
|
|
npm run build
|
|
npm run package
|
|
# Installs the packaged tarball into a running Headlamp instance
|
|
```
|
|
|
|
### Connecting to a Real Cluster
|
|
|
|
The plugin requires a running tns-csi driver to display meaningful data. For development:
|
|
|
|
1. Configure `KUBECONFIG` to point at a cluster with tns-csi installed
|
|
2. Run `npm start` — Headlamp dev server will proxy API requests through your kubeconfig
|
|
3. The Benchmark page requires RBAC permissions for Jobs and PVCs in the target namespace
|
|
|
|
## Branching Strategy
|
|
|
|
### Main Branch
|
|
|
|
- **Purpose:** Stable, production-ready code
|
|
- **Protection:** Only merge via pull requests
|
|
- **Naming:** `main`
|
|
|
|
### Feature Branches
|
|
|
|
- **Purpose:** Development of new features or fixes
|
|
- **Naming Convention:**
|
|
- Features: `feat/description`
|
|
- Bug fixes: `fix/description`
|
|
- Documentation: `docs/description`
|
|
- Refactoring: `refactor/description`
|
|
- Chores: `chore/description`
|
|
|
|
**Examples:**
|
|
```bash
|
|
feat/add-volume-clone-support
|
|
fix/metrics-page-empty-on-restart
|
|
docs/update-rbac-guide
|
|
refactor/kbench-state-machine
|
|
chore/upgrade-dependencies
|
|
```
|
|
|
|
### Branching Rules
|
|
|
|
**✅ ALWAYS use feature branches for:**
|
|
- Code changes (new features, bug fixes, refactors)
|
|
- Test updates
|
|
- CI/CD workflow changes
|
|
- Dependency updates
|
|
|
|
**✅ MAY push directly to main for:**
|
|
- Documentation-only changes (README, CLAUDE.md, comments)
|
|
- Version bump commits (`package.json` + `artifacthub-pkg.yml`)
|
|
|
|
**❌ NEVER push directly to main for:**
|
|
- Any code changes to `src/`
|
|
- Test file changes
|
|
- Workflow changes
|
|
|
|
## Commit Message Guidelines
|
|
|
|
We follow [Conventional Commits](https://www.conventionalcommits.org/) format:
|
|
|
|
### Format
|
|
|
|
```
|
|
<type>(<scope>): <description>
|
|
|
|
[optional body]
|
|
|
|
[optional footer(s)]
|
|
```
|
|
|
|
### Types
|
|
|
|
- **feat:** New feature
|
|
- **fix:** Bug fix
|
|
- **docs:** Documentation only
|
|
- **style:** Code style (formatting, no logic change)
|
|
- **refactor:** Code change that neither fixes a bug nor adds a feature
|
|
- **perf:** Performance improvement
|
|
- **test:** Adding or updating tests
|
|
- **chore:** Maintenance tasks (deps, build, CI)
|
|
- **ci:** CI/CD changes
|
|
|
|
### Scope (Optional)
|
|
|
|
- `api` — API-related changes
|
|
- `ui` — UI component changes
|
|
- `metrics` — Prometheus metrics changes
|
|
- `kbench` — Benchmark changes
|
|
- `tests` — Test-related changes
|
|
- `docs` — Documentation changes
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
feat(ui): add PV clone button to Volumes detail panel
|
|
|
|
fix(api): extract jsonData from headlamp KubeObject instances for parameter access
|
|
|
|
docs: add RBAC examples for Benchmark page
|
|
|
|
chore: bump version to 0.2.0
|
|
|
|
test(kbench): add FIO log parser edge case tests
|
|
```
|
|
|
|
### Footer
|
|
|
|
Add `Co-Authored-By` for pair programming or AI assistance:
|
|
|
|
```
|
|
feat: add NVMe-oF protocol notes to StorageClass detail panel
|
|
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Happy <yesreply@happy.engineering>
|
|
```
|
|
|
|
## Pull Request Process
|
|
|
|
### Before Creating a PR
|
|
|
|
1. **Run all checks locally:**
|
|
```bash
|
|
npm run build # Verify build succeeds
|
|
npm run lint # Check for linting errors
|
|
npm run tsc # Type-check TypeScript
|
|
npm test # Run 159 unit tests
|
|
```
|
|
|
|
2. **Update documentation:**
|
|
- Update README.md if you added features or changed behavior
|
|
- Update CLAUDE.md if you changed architecture or constraints
|
|
- Add JSDoc comments for new exported APIs
|
|
|
|
3. **Write/update tests:**
|
|
- Add unit tests for new functions/components
|
|
- Ensure all 159 tests (plus yours) pass
|
|
|
|
### Creating a PR
|
|
|
|
1. **Push your branch:**
|
|
```bash
|
|
git push origin feat/your-feature
|
|
```
|
|
|
|
2. **Create PR on GitHub:**
|
|
- Use a descriptive title following commit conventions
|
|
- Link related issues with `Fixes #123` or `Closes #456`
|
|
|
|
3. **PR Title Format:**
|
|
```
|
|
feat: add VolumeSnapshot creation from Volumes page
|
|
fix: correct FIO log parser for multi-job output
|
|
docs: improve Benchmark RBAC setup guide
|
|
```
|
|
|
|
4. **PR Description Should Include:**
|
|
- Summary of changes
|
|
- Motivation and context
|
|
- Testing performed (which cluster/driver version)
|
|
- Screenshots for UI changes
|
|
- Breaking changes (if any)
|
|
|
|
### PR Review Process
|
|
|
|
1. **Automated Checks:**
|
|
- ✅ CI workflow (lint, type-check, build, test)
|
|
|
|
2. **Maintainer Review:**
|
|
- Code quality and style
|
|
- Test coverage
|
|
- Documentation completeness
|
|
- No new `any` types introduced
|
|
|
|
3. **Merging:**
|
|
- Use **merge commits** (not squash, not rebase)
|
|
- Delete feature branch after merge
|
|
|
|
## Code Style
|
|
|
|
### TypeScript
|
|
|
|
- **Strictness:** Full TypeScript strict mode — zero `any` types
|
|
- **Unknown at boundaries:** Use `unknown` + type guards at API boundaries (headlamp hooks, ApiProxy responses)
|
|
- **Interfaces over types:** Prefer `interface` for object shapes
|
|
- **No class components:** Functional components with hooks only
|
|
|
|
### React
|
|
|
|
- **Functional components only** — no class components
|
|
- **Props interfaces:** Always define props as named interfaces
|
|
- **Headlamp components:** Use only `@kinvolk/headlamp-plugin/lib/CommonComponents` — no direct MUI imports
|
|
- **Detail panels:** Follow the slide-in drawer pattern — URL hash state, Escape to close, backdrop overlay
|
|
|
|
### Headlamp KubeObject Access
|
|
|
|
Headlamp's `useList()` hooks return KubeObject class instances that store raw JSON under `.jsonData`. Always extract `jsonData` before passing objects to plain-object type helpers:
|
|
|
|
```typescript
|
|
// ✅ Correct — extract jsonData so .parameters, .spec, .status are accessible
|
|
const rawItems = items.map(item =>
|
|
item && typeof item === 'object' && 'jsonData' in item
|
|
? (item as { jsonData: unknown }).jsonData
|
|
: item
|
|
);
|
|
|
|
// ❌ Wrong — sc.parameters will be undefined on KubeObject instances
|
|
const scs = (allStorageClasses as unknown[]).filter(isTnsCsiStorageClass);
|
|
```
|
|
|
|
### Linting and Formatting
|
|
|
|
```bash
|
|
npm run lint # ESLint
|
|
npm run tsc # TypeScript check
|
|
```
|
|
|
|
### Naming Conventions
|
|
|
|
- **Components:** PascalCase (`OverviewPage`, `BenchmarkPage`)
|
|
- **Files:** Match component name (`OverviewPage.tsx`)
|
|
- **Hooks:** Prefix with `use` (`useTnsCsiContext`)
|
|
- **Utilities:** camelCase (`formatProtocol`, `parsePrometheusText`)
|
|
- **Constants:** UPPER_SNAKE_CASE (`TNS_CSI_PROVISIONER`)
|
|
|
|
### Import Organization
|
|
|
|
1. React imports
|
|
2. Third-party libraries
|
|
3. Headlamp plugin imports (`@kinvolk/headlamp-plugin/lib`)
|
|
4. Local imports (components, API, types)
|
|
|
|
## Testing Requirements
|
|
|
|
### Unit Tests (Required)
|
|
|
|
All 159 tests must pass before committing:
|
|
|
|
```bash
|
|
npm test # vitest run
|
|
npm run tsc # must exit 0
|
|
```
|
|
|
|
- All new functions must have unit tests
|
|
- Bug fixes should include regression tests
|
|
- Use descriptive test names
|
|
|
|
**Mock pattern for headlamp APIs:**
|
|
|
|
```typescript
|
|
vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
|
|
ApiProxy: { request: vi.fn().mockResolvedValue({ items: [] }) },
|
|
K8s: {
|
|
ResourceClasses: {
|
|
StorageClass: { useList: vi.fn(() => [[], null]) },
|
|
PersistentVolume: { useList: vi.fn(() => [[], null]) },
|
|
PersistentVolumeClaim: { useList: vi.fn(() => [[], null]) },
|
|
},
|
|
},
|
|
}));
|
|
```
|
|
|
|
### Test File Structure
|
|
|
|
```
|
|
src/api/k8s.test.ts -- Type guards, filter helpers, format utilities
|
|
src/api/metrics.test.ts -- Prometheus text parser
|
|
src/api/kbench.test.ts -- FIO log parser, manifest builders, format helpers
|
|
src/api/TnsCsiDataContext.test.tsx -- Context provider integration
|
|
```
|
|
|
|
## Documentation
|
|
|
|
### Documentation Updates Required
|
|
|
|
When making changes, update relevant documentation:
|
|
|
|
#### Code Changes
|
|
- **README.md** — User-facing features, installation, configuration, troubleshooting table
|
|
- **CLAUDE.md** — Architecture constraints, key constants, subagent guidance
|
|
- **CHANGELOG.md** — Add entry under `[Unreleased]`
|
|
- **JSDoc** — All exported functions and components
|
|
|
|
#### Architecture Changes
|
|
- **docs/architecture/overview.md** — If the data flow or component structure changes
|
|
- **CLAUDE.md** — Update architecture section
|
|
|
|
### JSDoc Style
|
|
|
|
Use JSDoc for all exported functions and types:
|
|
|
|
```typescript
|
|
/**
|
|
* Parses Prometheus text format exposition into a flat key→value map.
|
|
*
|
|
* Ignores comment lines and HELP/TYPE metadata. Returns only the last
|
|
* sample value for each unique metric+label combination.
|
|
*
|
|
* @param text - Raw Prometheus text format string
|
|
* @returns Map of metric name (with labels) to numeric value
|
|
*/
|
|
export function parsePrometheusText(text: string): Map<string, number> {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
## Release Process
|
|
|
|
### Version Numbering
|
|
|
|
We follow [Semantic Versioning](https://semver.org/):
|
|
- **Major (1.0.0):** Breaking changes
|
|
- **Minor (0.1.0):** New features, backward compatible
|
|
- **Patch (0.0.1):** Bug fixes, backward compatible
|
|
|
|
### Creating a Release (Maintainers Only)
|
|
|
|
1. **Update CHANGELOG.md:**
|
|
- Move items from `[Unreleased]` to a new `[X.Y.Z] - YYYY-MM-DD` section
|
|
|
|
2. **Trigger the release workflow:**
|
|
- Go to **Actions → Release → Run workflow**
|
|
- Enter the version number (e.g., `0.2.0`)
|
|
|
|
3. **GitHub Actions automatically:**
|
|
- Updates `package.json` and `artifacthub-pkg.yml` version
|
|
- Builds plugin tarball
|
|
- Computes SHA256 checksum and updates metadata
|
|
- Commits, creates tag, and publishes GitHub release
|
|
|
|
4. **ArtifactHub syncs within 30 minutes**
|
|
|
|
### Pre-release Versions
|
|
|
|
For testing before stable release, use `-rc.N` suffix: `v0.2.0-rc.1`. Mark as "pre-release" on GitHub.
|
|
|
|
## Getting Help
|
|
|
|
- **Questions:** Open a [GitHub Discussion](https://github.com/privilegedescalation/headlamp-tns-csi-plugin/discussions)
|
|
- **Bugs:** Open a [GitHub Issue](https://github.com/privilegedescalation/headlamp-tns-csi-plugin/issues)
|
|
- **Architecture:** See [CLAUDE.md](CLAUDE.md) and [docs/architecture/overview.md](docs/architecture/overview.md)
|
|
|
|
## License
|
|
|
|
By contributing, you agree that your contributions will be licensed under the Apache-2.0 License.
|