chore: optimize Git workflow and CI/CD for Headlamp plugin releases
Implements comprehensive workflow redesign addressing: - Non-deterministic builds → Fixed with consistent Node version and npm ci - Manual checksum management → Automated in publish workflow - Multiple artifact locations → Single source of truth (GitHub releases) - Individual file releases → Single tarball artifact - Artifact Hub mismatches → No rebuild risk, use released tarball Key improvements: - CI workflow: faster builds with npm cache, artifact verification - Publish workflow: deterministic builds, automatic checksum calculation, auto-commit of metadata updates, single tarball release - Branch protection: require PR review and passing CI before merge - Release process: simplified from manual to 5-minute automated workflow Documentation: - GIT_WORKFLOW.md: branching strategy, commit conventions, release process - RELEASE_GUIDE.md: detailed step-by-step release instructions - RELEASE_QUICK_REFERENCE.md: copy-paste commands for quick releases - CI_CD_DESIGN.md: technical architecture and design decisions - GITHUB_SETUP_CHECKLIST.md: repository configuration guide - WORKFLOW_OPTIMIZATION_SUMMARY.md: executive summary of changes Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
+420
@@ -0,0 +1,420 @@
|
||||
# CI/CD Design Document
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the CI/CD architecture and design decisions for the Headlamp Sealed Secrets plugin.
|
||||
|
||||
## Goals
|
||||
|
||||
1. **Single Source of Truth**: Build once, use everywhere
|
||||
2. **Deterministic Builds**: Same input produces same output
|
||||
3. **Reproducible Releases**: Verify artifacts can be rebuilt
|
||||
4. **Automated Checksums**: Never manually edit checksums
|
||||
5. **Fast Feedback**: Tests run in < 5 minutes
|
||||
6. **Simple Process**: Easy for developers to cut releases
|
||||
|
||||
## Architecture
|
||||
|
||||
### Workflow Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Main Branch │
|
||||
│ │
|
||||
│ Developer pushes commits │
|
||||
│ │ │
|
||||
│ ├──→ CI Workflow (*.yml) │
|
||||
│ │ ├─ Lint │
|
||||
│ │ ├─ Type check │
|
||||
│ │ └─ Build (verification only) │
|
||||
│ │ │
|
||||
│ └──→ PR review → merge to main │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ (All commits merged)
|
||||
│
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Release Process │
|
||||
│ │
|
||||
│ 1. Bump version (npm version patch) │
|
||||
│ 2. Update artifacthub-pkg.yml │
|
||||
│ 3. Commit to main │
|
||||
│ 4. Create tag: git tag -a v0.2.5 │
|
||||
│ 5. Push tag: git push origin v0.2.5 │
|
||||
│ │ │
|
||||
│ └──→ Publish Workflow (publish.yml) │
|
||||
│ ├─ Lint │
|
||||
│ ├─ Type check │
|
||||
│ ├─ Build (deterministic) │
|
||||
│ ├─ Create tarball │
|
||||
│ ├─ Calculate checksum │
|
||||
│ ├─ Create GitHub Release │
|
||||
│ ├─ Update artifacthub-pkg.yml │
|
||||
│ └─ Push metadata update │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ (Release created)
|
||||
│
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Distribution & Verification │
|
||||
│ │
|
||||
│ GitHub Releases │
|
||||
│ ├─ headlamp-sealed-secrets-0.2.5.tar.gz │
|
||||
│ └─ Release notes (auto-generated) │
|
||||
│ │
|
||||
│ Artifact Hub (syncs automatically) │
|
||||
│ ├─ Discovers from artifacthub-pkg.yml │
|
||||
│ ├─ Shows archive URL │
|
||||
│ └─ Displays checksum for verification │
|
||||
│ │
|
||||
│ Users/Headlamp │
|
||||
│ └─ Download from GitHub or Artifact Hub │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Workflow Specifications
|
||||
|
||||
### CI Workflow
|
||||
|
||||
**File**: `.github/workflows/ci.yml`
|
||||
|
||||
**Triggers**:
|
||||
- Push to `main`
|
||||
- Pull requests to `main`
|
||||
|
||||
**Jobs**: Single `test` job
|
||||
|
||||
| Step | Command | Purpose | Time |
|
||||
|------|---------|---------|------|
|
||||
| Checkout | `actions/checkout@v4` | Get source code | <1s |
|
||||
| Node Setup | `actions/setup-node@v4` | Install Node 20 + cache | 1s |
|
||||
| Dependencies | `npm ci` | Clean install | 30s |
|
||||
| Type Check | `npm run tsc` | TypeScript validation | 15s |
|
||||
| Lint | `npm run lint` | Code quality | 10s |
|
||||
| Build | `npm run build` | Production build | 4s |
|
||||
| Verify Artifacts | shell script | Check dist/ exists | <1s |
|
||||
| Upload Artifacts | `actions/upload-artifact@v4` | Store for inspection | 5s |
|
||||
|
||||
**Total Time**: ~2 minutes
|
||||
**Failure Behavior**: Blocks PR merge
|
||||
**Retention**: 7 days (artifacts)
|
||||
|
||||
**Key Features**:
|
||||
- NPM cache enabled for speed
|
||||
- Deterministic dependencies with `npm ci`
|
||||
- Upload dist/ for manual inspection
|
||||
- Clear error messages on failure
|
||||
|
||||
### Publish Workflow
|
||||
|
||||
**File**: `.github/workflows/publish.yml`
|
||||
|
||||
**Triggers**:
|
||||
- Push of version tag (e.g., `v0.2.5`)
|
||||
- Manual trigger via workflow_dispatch
|
||||
|
||||
**Jobs**: Single `publish` job
|
||||
|
||||
| Step | Purpose | Key Details |
|
||||
|------|---------|------------|
|
||||
| Checkout | Get source at tag | Include full history |
|
||||
| Node Setup | Install Node 20 + cache | Consistent with CI |
|
||||
| Extract Version | Parse version from tag | e.g., v0.2.5 → 0.2.5 |
|
||||
| Dependencies | Clean install | Deterministic |
|
||||
| Type Check | Validate types | Same as CI |
|
||||
| Lint | Code quality | Same as CI |
|
||||
| Build | Production build | Deterministic output |
|
||||
| Create Tarball | `npm pack` | Single artifact |
|
||||
| Verify Contents | Check main.js exists | Sanity check |
|
||||
| Create Release | Upload to GitHub | Make artifact accessible |
|
||||
| Update Metadata | Calculate checksum | Auto-populate artifacthub-pkg.yml |
|
||||
| Commit Update | Push checksum update | Update main branch |
|
||||
| Print Summary | Display results | For manual verification |
|
||||
|
||||
**Total Time**: ~3 minutes
|
||||
**Failure Behavior**: Release not created
|
||||
**Retention**: Permanent (GitHub releases)
|
||||
|
||||
**Key Features**:
|
||||
- **Deterministic**: Same input produces same tarball
|
||||
- **Automatic Checksums**: No manual checksum editing
|
||||
- **Single Artifact**: Only tarball uploaded (not individual files)
|
||||
- **Metadata Updated**: artifacthub-pkg.yml auto-updated with correct values
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### 1. Build Once, Use Everywhere
|
||||
|
||||
**Decision**: Publish workflow builds once, creates tarball, uses for all releases
|
||||
|
||||
**Rationale**:
|
||||
- Non-deterministic builds → different checksums each time
|
||||
- Running build locally → can't verify released artifact
|
||||
- Multiple builds → harder to debug
|
||||
|
||||
**Implementation**:
|
||||
- Publish workflow is single source of truth for released artifacts
|
||||
- Never rebuild locally for verification
|
||||
- Always download from GitHub for verification
|
||||
|
||||
### 2. Deterministic Builds
|
||||
|
||||
**Decision**: Use exact Node version, npm ci, fixed dependencies
|
||||
|
||||
**Rationale**:
|
||||
- Reproducible builds = user trust
|
||||
- Same build steps should produce same output
|
||||
- Different environment = different artifact = checksum mismatch
|
||||
|
||||
**Implementation**:
|
||||
```yaml
|
||||
- Node: 20.x (fixed in workflow)
|
||||
- npm ci (not install)
|
||||
- package-lock.json (committed to repo)
|
||||
- NODE_ENV: production
|
||||
```
|
||||
|
||||
### 3. Automatic Checksum Management
|
||||
|
||||
**Decision**: Calculate checksum in workflow, update metadata programmatically
|
||||
|
||||
**Rationale**:
|
||||
- Manual edits → errors
|
||||
- Checksum after build → guaranteed to match released artifact
|
||||
- Automation → always correct
|
||||
|
||||
**Implementation**:
|
||||
```bash
|
||||
# In publish workflow
|
||||
CHECKSUM=$(sha256sum "tarball.tar.gz" | awk '{print $1}')
|
||||
|
||||
# Python updates YAML
|
||||
python3 -c "update artifacthub-pkg.yml with checksum"
|
||||
|
||||
# Git commits the update
|
||||
git commit -m "chore(release): update checksums"
|
||||
```
|
||||
|
||||
### 4. Single Artifact Distribution
|
||||
|
||||
**Decision**: Only release tarball, not individual files
|
||||
|
||||
**Rationale**:
|
||||
- Headlamp expects tarball
|
||||
- Checksum verification requires single file
|
||||
- Smaller release size
|
||||
- Cleaner GitHub releases page
|
||||
|
||||
**Implementation**:
|
||||
- Use `npm pack` to create tarball
|
||||
- Upload only tarball to GitHub release
|
||||
- Don't upload individual main.js, package.json, etc.
|
||||
|
||||
### 5. Protected Main Branch
|
||||
|
||||
**Decision**: Require PR review before merging to main
|
||||
|
||||
**Rationale**:
|
||||
- All releases come from main
|
||||
- Protect main → protect releases
|
||||
- Code review → quality assurance
|
||||
|
||||
**Implementation**:
|
||||
```
|
||||
GitHub Settings → Branches → main
|
||||
- Require pull request reviews: ≥1
|
||||
- Require status checks pass: CI workflow
|
||||
- Dismiss stale reviews on push
|
||||
- Require branches up to date
|
||||
```
|
||||
|
||||
### 6. Semantic Versioning
|
||||
|
||||
**Decision**: MAJOR.MINOR.PATCH (SemVer 2.0.0)
|
||||
|
||||
**Rationale**:
|
||||
- Standard in package ecosystems
|
||||
- Clear upgrade impact to users
|
||||
- Matches Artifact Hub expectations
|
||||
|
||||
**Implementation**:
|
||||
- Use `npm version patch/minor/major`
|
||||
- Update artifacthub-pkg.yml to match
|
||||
- Tag with `v<VERSION>`
|
||||
|
||||
### 7. Conventional Commits
|
||||
|
||||
**Decision**: Use types (feat, fix, docs, chore) in commit messages
|
||||
|
||||
**Rationale**:
|
||||
- Structured commit history
|
||||
- Auto-generate release notes from commits
|
||||
- Easy to scan changelog
|
||||
|
||||
**Implementation**:
|
||||
```
|
||||
feat(ui): add new component
|
||||
fix(api): handle null response
|
||||
docs: update README
|
||||
chore(release): bump version
|
||||
```
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
headlamp-sealed-secrets-plugin/
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ ├── ci.yml # Push to main, PR to main
|
||||
│ └── publish.yml # Tag push triggers release
|
||||
│
|
||||
├── headlamp-sealed-secrets/ # Plugin source
|
||||
│ ├── src/ # TypeScript source
|
||||
│ ├── dist/ # Built output (gitignored)
|
||||
│ ├── package.json # Version source of truth
|
||||
│ ├── package-lock.json # Locked dependencies
|
||||
│ └── artifacthub-pkg.yml # DEPRECATED (see root)
|
||||
│
|
||||
├── artifacthub-pkg.yml # SINGLE metadata file (root)
|
||||
├── artifacthub-repo.yml # Repository info
|
||||
├── CHANGELOG.md # Release notes
|
||||
├── GIT_WORKFLOW.md # Workflow guide
|
||||
├── RELEASE_GUIDE.md # Detailed release steps
|
||||
└── RELEASE_QUICK_REFERENCE.md # Quick copy-paste commands
|
||||
```
|
||||
|
||||
**Key Point**: Only ONE `artifacthub-pkg.yml` in repository root. Version-specific directories (`headlamp-sealed-secrets-plugin/0.2.X/`) are legacy and should be removed.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### CI Workflow
|
||||
```yaml
|
||||
# None required
|
||||
# Uses standard GitHub Actions environment
|
||||
```
|
||||
|
||||
### Publish Workflow
|
||||
```yaml
|
||||
NODE_ENV: production # For build consistency
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Create release
|
||||
# NPM_TOKEN: optional if publishing to NPM
|
||||
```
|
||||
|
||||
## Secrets & Permissions
|
||||
|
||||
### Required GitHub Secrets
|
||||
- `GITHUB_TOKEN`: Pre-installed, used for creating releases
|
||||
|
||||
### Optional GitHub Secrets
|
||||
- `NPM_TOKEN`: Only if publishing to NPM (not required for Headlamp)
|
||||
|
||||
### Branch Protections
|
||||
- Require PR review before merge
|
||||
- Require CI workflow to pass
|
||||
- Require branches up to date before merge
|
||||
|
||||
## Performance Tuning
|
||||
|
||||
### NPM Cache
|
||||
```yaml
|
||||
cache: 'npm'
|
||||
cache-dependency-path: headlamp-sealed-secrets/package-lock.json
|
||||
```
|
||||
Reduces `npm ci` from 30s → 5s
|
||||
|
||||
### Parallel Jobs (Future)
|
||||
Currently single job. Could parallelize:
|
||||
```
|
||||
- Lint & Type check (parallel)
|
||||
- Build (sequential, depends on install)
|
||||
- Upload artifacts (parallel)
|
||||
```
|
||||
Expected savings: ~20-30 seconds
|
||||
|
||||
### Build Optimization
|
||||
See BUILD_VERIFICATION_SUMMARY.md for current metrics:
|
||||
- Build time: 3.87s
|
||||
- Bundle size: 359.73 KB (98.79 KB gzipped)
|
||||
|
||||
## Error Handling
|
||||
|
||||
### CI Workflow Failures
|
||||
1. PR marked as "checks failed"
|
||||
2. Cannot merge to main
|
||||
3. Developer fixes locally
|
||||
4. Pushes new commit
|
||||
5. CI re-runs automatically
|
||||
|
||||
### Publish Workflow Failures
|
||||
1. Release not created
|
||||
2. Check Actions logs for error
|
||||
3. Common causes:
|
||||
- Build error (run locally to debug)
|
||||
- Type error (npm run tsc)
|
||||
- Lint error (npm run lint)
|
||||
4. Fix and try again:
|
||||
- Delete tag locally and remotely
|
||||
- Fix issue
|
||||
- Create new tag
|
||||
- Push tag again
|
||||
|
||||
## Monitoring & Debugging
|
||||
|
||||
### Check Workflow Status
|
||||
- GitHub Actions tab: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/actions
|
||||
- Shows all runs with timestamps and status
|
||||
- Click to see detailed logs
|
||||
|
||||
### Monitor Specific Workflow
|
||||
```bash
|
||||
# See recent runs
|
||||
gh run list -R privilegedescalation/headlamp-sealed-secrets-plugin
|
||||
|
||||
# See specific run details
|
||||
gh run view <RUN_ID> -R privilegedescalation/headlamp-sealed-secrets-plugin
|
||||
```
|
||||
|
||||
### Verify Artifact
|
||||
```bash
|
||||
# Check GitHub release
|
||||
wget https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/download/v0.2.5/headlamp-sealed-secrets-0.2.5.tar.gz
|
||||
|
||||
# Verify checksum
|
||||
sha256sum headlamp-sealed-secrets-0.2.5.tar.gz
|
||||
|
||||
# Compare with artifacthub-pkg.yml
|
||||
grep archive-checksum artifacthub-pkg.yml
|
||||
```
|
||||
|
||||
## Future Improvements
|
||||
|
||||
### Phase 1 (Current)
|
||||
- Basic CI on push/PR
|
||||
- Tag-based publish with checksum automation
|
||||
- GitHub release creation
|
||||
- Artifact Hub metadata sync
|
||||
|
||||
### Phase 2 (Optional)
|
||||
- Parallel CI jobs (lint + test in parallel)
|
||||
- SBOM (Software Bill of Materials) generation
|
||||
- Signed releases with GPG
|
||||
- Automated changelog generation
|
||||
- NPM publish option
|
||||
|
||||
### Phase 3 (Optional)
|
||||
- Release notes template
|
||||
- Automated security scanning
|
||||
- Performance benchmarks
|
||||
- Docker image builds
|
||||
- Multi-platform support
|
||||
|
||||
## References
|
||||
|
||||
- [Headlamp Plugin Publishing](https://headlamp.dev/docs/latest/development/plugins/publishing/)
|
||||
- [GitHub Actions Docs](https://docs.github.com/en/actions)
|
||||
- [Artifact Hub Documentation](https://artifacthub.io/docs)
|
||||
- [Semantic Versioning](https://semver.org)
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
Reference in New Issue
Block a user