From 3e7e67066dc5a3038c09e4630bad724d9eea6c41 Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Fri, 12 Sep 2025 04:25:55 -0400 Subject: [PATCH 1/7] HIP: Automated Release Process for Helm Proposes GitHub Actions automation for Helm releases while preserving human oversight. Creates PRs for version updates, generates draft release candidates, and coordinates documentation updates between helm/helm and helm/helm-www. Addresses time-consuming aspects of the current 11-step manual release process while preserving all security and quality controls. Key benefits: - Reduces manual errors in version updates - Eliminates repetitive tasks - Maintains security with draft releases and PR approvals - Full backward compatibility with existing process Signed-off-by: Scott Rigby --- hips/hip-9999.md | 246 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 hips/hip-9999.md diff --git a/hips/hip-9999.md b/hips/hip-9999.md new file mode 100644 index 000000000..5e556f99a --- /dev/null +++ b/hips/hip-9999.md @@ -0,0 +1,246 @@ +--- +hip: 9999 +title: "Automated Release Process for Helm" +authors: ["Scott Rigby "] +created: "2025-09-12" +type: "process" +status: "draft" +--- + +## Abstract + +This HIP proposes automating significant portions of the Helm release process through GitHub Actions workflows while maintaining human oversight and security. The proposal introduces pull request-based automation for version updates, release candidate generation, documentation synchronization, and cross-repository coordination between helm/helm and helm/helm-www. The automation preserves the current manual review checkpoints while eliminating error-prone repetitive tasks, reducing release cycle time, and improving consistency. + +## Motivation + +The current Helm release process, documented in the [Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md), involves 11 manual steps requiring maintainers to: + +- Manually edit multiple files across different repositories +- Coordinate updates between helm/helm and helm/helm-www repositories +- Perform repetitive version string replacements in test files +- Manually manage GitHub milestones and releases +- Switch between multiple repository contexts during a single release + +This manual process introduces several problems: + +1. **Human Error**: Manual file editing leads to version mismatches and missed updates +2. **Time Consumption**: Maintainers spend significant time on repetitive tasks +3. **Context Switching**: Managing two repositories simultaneously increases cognitive load +4. **Inconsistency**: Manual processes vary between different release managers +5. **Bottlenecks**: Only maintainers familiar with the entire process can perform releases +6. **Delayed Documentation**: Website updates often lag behind releases + +The existing process works but does not scale efficiently with Helm's release cadence and growing maintainer team. + +## Rationale + +### Design Principles + +1. **Human Review Preserved**: All automation presents changes as pull requests requiring maintainer approval +2. **Security First**: No bypass of existing security measures (signed commits, GPG signatures) +3. **Draft Mode**: Automated releases created in draft mode for final human review +4. **Incremental Adoption**: Can be implemented and rolled out progressively +5. **Rollback Capability**: Easy to revert to manual process if needed + +### Alternative Approaches Considered + +**Full Automation**: Rejected because it removes necessary human judgment for release timing, quality assessment, and community communication. + +**External Tools**: Considered tools like Release Drafter, but they lack the cross-repository coordination and Helm-specific requirements. + +**Monolithic Workflow**: Rejected in favor of modular workflows that can be maintained and debugged independently. + +## Specification + +### Workflow Architecture + +#### 1. Release Preparation Workflow (`helm/helm`) + +**Trigger**: Manual workflow dispatch with inputs: +- Release type (major/minor/patch) +- Target version (e.g., v3.20.0) +- Release date + +**Actions**: +1. Create release branch from main +2. Update version in `internal/version/version.go` +3. Update all test data files with new version +4. Generate release notes template using commit history +5. Create/update GitHub milestone +6. Create pull request with all changes + +**Artifacts**: Pull request ready for maintainer review + +#### 2. Release Candidate Workflow (`helm/helm`) + +**Trigger**: Merge of release preparation PR + +**Actions**: +1. Create signed, annotated git tag for RC +2. Trigger existing CI/CD for artifact building +3. Create draft GitHub release with RC tag +4. Generate and attach PGP signatures (if signing key available) +5. Post notification to configured channels + +**Artifacts**: Draft GitHub release with RC artifacts + +#### 3. Final Release Workflow (`helm/helm`) + +**Trigger**: Manual approval/publication of RC draft release + +**Actions**: +1. Create signed, annotated final release tag +2. Update draft release to final +3. Trigger documentation update workflow +4. Close milestone +5. Generate community announcement template + +#### 4. Documentation Update Workflow (`helm/helm-www`) + +**Trigger**: Webhook from helm/helm final release publication + +**Actions**: +1. Update `config.toml` with new version information +2. Update `params.nextversion` with next planned release +3. Update version skew documentation +4. Update release calendar with next release dates +5. Create pull request in helm/helm-www + +**Artifacts**: Pull request in helm/helm-www ready for review + +### File Structure + +``` +.github/workflows/ +├── prepare-release.yml # Release preparation automation +├── release-candidate.yml # RC creation and management +├── finalize-release.yml # Final release publication +└── update-documentation.yml # Cross-repo docs updates + +scripts/ +├── update-version-files.sh # Version update automation +├── generate-release-notes.sh # Release notes generation +└── update-test-data.sh # Test file version updates +``` + +### Configuration + +New configuration file `.github/release-config.yml`: + +```yaml +# Release automation configuration +version_files: + - path: "internal/version/version.go" + pattern: 'version = "v{VERSION}"' + - path: "cmd/helm/testdata/output/version.txt" + pattern: 'Version:"{VERSION}"' + # ... additional files + +repositories: + docs_repo: "helm/helm-www" + +signing: + gpg_key_id: "${{ secrets.GPG_KEY_ID }}" + gpg_private_key: "${{ secrets.GPG_PRIVATE_KEY }}" +``` + +### Permissions and Security + +Required GitHub App permissions: +- Contents: Write (for creating branches, tags, releases) +- Pull Requests: Write (for creating PRs) +- Metadata: Read (for accessing repository info) +- Actions: Write (for triggering cross-repo workflows) + +Required secrets: +- `GITHUB_APP_ID`: GitHub App ID for cross-repo access +- `GITHUB_APP_PRIVATE_KEY`: GitHub App private key +- `GPG_PRIVATE_KEY`: PGP signing key (optional) + +## Backwards Compatibility + +This proposal introduces new automation alongside the existing manual process: + +1. **Graceful Rollback**: Manual process remains fully functional if automation fails +2. **Opt-in Adoption**: Teams can choose to use automation for specific steps +3. **No Breaking Changes**: No modifications to existing release artifacts or tags +4. **Existing Tool Compatibility**: All existing tooling continues to work unchanged + +The automation enhances rather than replaces the current process, ensuring maintainers can fall back to manual steps if needed. + +## Security Implications + +### Enhanced Security + +1. **Consistent Process**: Automation reduces risk of human error in security-critical steps +2. **Audit Trail**: All changes tracked through GitHub PR system +3. **Access Control**: GitHub App permissions more restrictive than individual maintainer access +4. **Signed Commits**: Automation maintains commit signing requirements + +### Security Considerations + +1. **Secret Management**: GPG keys and tokens stored in GitHub Secrets +2. **Cross-Repo Access**: GitHub App tokens limited to minimum required permissions +3. **Draft Mode**: All releases created in draft mode, requiring manual publication +4. **Approval Gates**: All changes require PR approval before implementation + +## How to Teach This + +### Maintainer Documentation + +1. Update existing release checklist with automation options +2. Create troubleshooting guide for automation failures +3. Document rollback procedures +4. Provide workflow customization examples + +### Training Materials + +1. Video walkthrough of automated release process +2. Comparison guide: manual vs. automated steps +3. Emergency procedures documentation +4. FAQ for common automation issues + +## Reference Implementation + +Initial implementation should focus on the release preparation workflow as it provides the highest value with lowest risk: + +1. **Phase 1**: Release preparation automation (version updates, PR creation) +2. **Phase 2**: Release candidate automation +3. **Phase 3**: Documentation update automation +4. **Phase 4**: Full workflow integration and community notification + +Each phase can be tested in isolation and rolled back if issues arise. + +## Rejected Ideas + +### Fully Automated Releases + +Rejected because release timing requires human judgment based on: +- Community feedback on release candidates +- Critical bug discovery during testing +- External factors (holidays, conferences, security issues) + +### Slack/Discord Bot Interface + +While potentially useful, adds complexity and another system to maintain. GitHub's existing interfaces provide sufficient control. + +### Automatic Backporting + +Patch release cherry-picking requires human judgment for: +- Risk assessment of changes +- Conflict resolution +- Testing scope determination + +## Open Issues + +1. **GPG Key Management**: Best practices for storing and rotating signing keys in CI +2. **Cross-Org Coordination**: Technical approach for coordinating releases with other CNCF projects +3. **Rollback Testing**: Comprehensive testing scenarios for automation failures +4. **Metrics Collection**: Tracking automation success rates and time savings + +## References + +1. [Current Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md) +2. [GitHub Actions Documentation](https://docs.github.com/en/actions) +3. [Semantic Versioning](https://semver.org/) +4. [GitHub Apps Documentation](https://docs.github.com/en/developers/apps) From 525def29b01813a4b30e2f9f1703ae6016b31d30 Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Fri, 12 Sep 2025 16:44:46 -0400 Subject: [PATCH 2/7] WIP automate helm releases Signed-off-by: Scott Rigby --- hips/hip-9999.md | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/hips/hip-9999.md b/hips/hip-9999.md index 5e556f99a..36163d896 100644 --- a/hips/hip-9999.md +++ b/hips/hip-9999.md @@ -138,7 +138,7 @@ version_files: repositories: docs_repo: "helm/helm-www" - + signing: gpg_key_id: "${{ secrets.GPG_KEY_ID }}" gpg_private_key: "${{ secrets.GPG_PRIVATE_KEY }}" @@ -202,14 +202,29 @@ The automation enhances rather than replaces the current process, ensuring maint ## Reference Implementation -Initial implementation should focus on the release preparation workflow as it provides the highest value with lowest risk: +The implementation consists of three GitHub Actions workflows and two shell scripts that automate the core release tasks while maintaining human oversight through pull request reviews. + +### Repository Structure + +**helm/helm repository:** +- `.github/workflows/prepare-release.yml` - Creates release branch and PR with version updates +- `.github/workflows/create-release-candidate.yml` - Creates RC tag and draft release when prep PR merges +- `.github/workflows/finalize-release.yml` - Triggers documentation updates when release is published +- `scripts/update-version.sh` - Updates version strings in code and test files +- `scripts/generate-release-notes.sh` - Generates release notes template from git history + +**helm/helm-www repository:** +- `.github/workflows/update-helm-version.yml` - Creates PR to update website configuration + +### Key Implementation Details + +**Cross-repository communication** uses GitHub's `repository_dispatch` event to trigger the helm-www workflow when a helm/helm release is published. This requires a `HELM_RELEASE_TOKEN` secret with cross-repository access. + +**Version file updates** use sed pattern matching to find and replace version strings across multiple file types, handling both semantic version formats and Go version variables. -1. **Phase 1**: Release preparation automation (version updates, PR creation) -2. **Phase 2**: Release candidate automation -3. **Phase 3**: Documentation update automation -4. **Phase 4**: Full workflow integration and community notification +**Pull request automation** leverages GitHub CLI (`gh`) to create PRs with proper titles and generated content, ensuring all changes go through standard review processes. -Each phase can be tested in isolation and rolled back if issues arise. +The implementation handles the three primary release types (major/minor/patch) through a single workflow with input parameters, automatically extracting version information and creating appropriate branch names. ## Rejected Ideas From 9a11baf1e3378a13e5a9b8a37eb2587b499520ce Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Sat, 13 Sep 2025 02:01:26 -0400 Subject: [PATCH 3/7] Add example reference implementation - functioning WIP Signed-off-by: Scott Rigby --- hips/hip-9999.md | 66 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/hips/hip-9999.md b/hips/hip-9999.md index 36163d896..4f52e82f3 100644 --- a/hips/hip-9999.md +++ b/hips/hip-9999.md @@ -202,19 +202,73 @@ The automation enhances rather than replaces the current process, ensuring maint ## Reference Implementation -The implementation consists of three GitHub Actions workflows and two shell scripts that automate the core release tasks while maintaining human oversight through pull request reviews. +### Workflow Process + +```mermaid +flowchart TD + A[Manual: Prepare Release Workflow] --> B[Auto: Create PR with version updates] + B --> C{Manual: Review & Merge PR} + C -->|Merge| D[Auto: Create Draft Release] + D --> E{Manual: Review Draft & Publish} + E -->|Publish| F[Auto: Trigger Docs Workflow
repository_dispatch] + F --> G[Auto: Create Docs PR] + G --> H{Manual: Review & Merge Docs PR} + + %% Manual fallback options + A -.->|Fallback| I[Manual: Docs Update Workflow] + I --> G + + %% Styling for light/dark mode compatibility + classDef manual fill:#cce7ff,stroke:#0066cc,stroke-width:2px,color:#000 + classDef auto fill:#e6ccff,stroke:#6600cc,stroke-width:2px,color:#000 + classDef decision fill:#ffe6cc,stroke:#cc6600,stroke-width:2px,color:#000 + + class A,C,E,H,I manual + class B,D,F,G auto + class C,E,H decision +``` + +### User Experience + +The release process starts with a **manual workflow trigger** where maintainers enter the target version (e.g., `v3.20.0`) in GitHub's workflow dispatch UI. This creates a preparation branch with all necessary version updates and opens a pull request for review. + +Once the PR is **merged**, automation takes over: it creates a persistent **release branch** (like `release-3.20`) from the appropriate base branch (`main` for v4.x, `dev-v3` for v3.x), cherry-picks the version commit, creates a signed tag, and **drafts the GitHub release**. The draft sits ready for maintainer review - they can test artifacts, verify release notes, and make adjustments before publishing. + +When the maintainer **publishes the draft release**, it automatically triggers the documentation workflow in the helm-www repository, creating a pull request with updated version information, release dates, and compatibility matrices. This ensures the website stays synchronized with each release without manual coordination. + +**Fallback options** provide resilience: if the cross-repository automation fails, maintainers can manually trigger the docs update workflow with the same simple version input interface. Every change flows through pull request reviews, maintaining quality control while eliminating repetitive manual tasks. + +The experience transforms release management from an error-prone 11-step checklist into a **three-click process**: trigger preparation, publish draft, merge docs PR. + +### Example Implementation Repos + +Working examples demonstrating the complete automation: +- [Example Source Repository](https://github.com/scottrigby/example-actions-autorelease-source) - Demonstrates helm/helm automation +- [Example Docs Repository](https://github.com/scottrigby/example-actions-autorelease-docs) - Demonstrates helm/helm-www automation + +Example completion status: +- [x] Cross-repository automation via repository_dispatch +- [x] Draft release creation with human review gates +- [x] Persistent release branches for patch releases +- [x] Dynamic documentation updates with version/date tracking +- [x] Manual fallback workflows +- [ ] GPG signing of release artifacts +- [ ] Kubernetes version skew calculation from go.mod +- [ ] GitHub milestone management +- [ ] Release artifact attachment -### Repository Structure +### Corresponding Helm Workflow Plan **helm/helm repository:** -- `.github/workflows/prepare-release.yml` - Creates release branch and PR with version updates -- `.github/workflows/create-release-candidate.yml` - Creates RC tag and draft release when prep PR merges -- `.github/workflows/finalize-release.yml` - Triggers documentation updates when release is published +- `.github/workflows/prepare-release.yml` - Creates preparation branch and PR with version updates +- `.github/workflows/trigger-release.yml` - Triggers release creation when prep PR merges +- `.github/workflows/create-release.yml` - Creates release branch, tag, and draft release - `scripts/update-version.sh` - Updates version strings in code and test files - `scripts/generate-release-notes.sh` - Generates release notes template from git history **helm/helm-www repository:** -- `.github/workflows/update-helm-version.yml` - Creates PR to update website configuration +- `.github/workflows/update-version.yml` - Creates PR to update website configuration +- `.github/workflows/manual-update-docs.yml` - Manual fallback for docs updates ### Key Implementation Details From ead89b3969e7c41e2c46286771d3d4025e448dce Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Sat, 13 Sep 2025 02:19:51 -0400 Subject: [PATCH 4/7] More concise and to the point Signed-off-by: Scott Rigby --- hips/hip-9999.md | 268 ++++++----------------------------------------- 1 file changed, 34 insertions(+), 234 deletions(-) diff --git a/hips/hip-9999.md b/hips/hip-9999.md index 4f52e82f3..d990b644d 100644 --- a/hips/hip-9999.md +++ b/hips/hip-9999.md @@ -9,198 +9,20 @@ status: "draft" ## Abstract -This HIP proposes automating significant portions of the Helm release process through GitHub Actions workflows while maintaining human oversight and security. The proposal introduces pull request-based automation for version updates, release candidate generation, documentation synchronization, and cross-repository coordination between helm/helm and helm/helm-www. The automation preserves the current manual review checkpoints while eliminating error-prone repetitive tasks, reducing release cycle time, and improving consistency. +This HIP proposes automating the Helm release process through GitHub Actions while maintaining human review gates. The automation transforms the current 11-step manual checklist into a three-click process: trigger preparation, publish draft, merge docs PR. All changes flow through pull request reviews, preserving security while eliminating repetitive tasks. ## Motivation -The current Helm release process, documented in the [Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md), involves 11 manual steps requiring maintainers to: +The current 11-step [Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md) requires manual coordination across helm/helm and helm/helm-www repositories, leading to human error, time consumption, and documentation delays. This automation preserves human judgment while eliminating repetitive tasks. -- Manually edit multiple files across different repositories -- Coordinate updates between helm/helm and helm/helm-www repositories -- Perform repetitive version string replacements in test files -- Manually manage GitHub milestones and releases -- Switch between multiple repository contexts during a single release +## Design Principles -This manual process introduces several problems: +- **Human Review Gates**: All changes require PR approval before implementation +- **Draft Releases**: Created for review before triggering documentation updates +- **Security Preserved**: Maintains signed commits and GPG signatures +- **Fallback Ready**: Manual process remains fully functional -1. **Human Error**: Manual file editing leads to version mismatches and missed updates -2. **Time Consumption**: Maintainers spend significant time on repetitive tasks -3. **Context Switching**: Managing two repositories simultaneously increases cognitive load -4. **Inconsistency**: Manual processes vary between different release managers -5. **Bottlenecks**: Only maintainers familiar with the entire process can perform releases -6. **Delayed Documentation**: Website updates often lag behind releases - -The existing process works but does not scale efficiently with Helm's release cadence and growing maintainer team. - -## Rationale - -### Design Principles - -1. **Human Review Preserved**: All automation presents changes as pull requests requiring maintainer approval -2. **Security First**: No bypass of existing security measures (signed commits, GPG signatures) -3. **Draft Mode**: Automated releases created in draft mode for final human review -4. **Incremental Adoption**: Can be implemented and rolled out progressively -5. **Rollback Capability**: Easy to revert to manual process if needed - -### Alternative Approaches Considered - -**Full Automation**: Rejected because it removes necessary human judgment for release timing, quality assessment, and community communication. - -**External Tools**: Considered tools like Release Drafter, but they lack the cross-repository coordination and Helm-specific requirements. - -**Monolithic Workflow**: Rejected in favor of modular workflows that can be maintained and debugged independently. - -## Specification - -### Workflow Architecture - -#### 1. Release Preparation Workflow (`helm/helm`) - -**Trigger**: Manual workflow dispatch with inputs: -- Release type (major/minor/patch) -- Target version (e.g., v3.20.0) -- Release date - -**Actions**: -1. Create release branch from main -2. Update version in `internal/version/version.go` -3. Update all test data files with new version -4. Generate release notes template using commit history -5. Create/update GitHub milestone -6. Create pull request with all changes - -**Artifacts**: Pull request ready for maintainer review - -#### 2. Release Candidate Workflow (`helm/helm`) - -**Trigger**: Merge of release preparation PR - -**Actions**: -1. Create signed, annotated git tag for RC -2. Trigger existing CI/CD for artifact building -3. Create draft GitHub release with RC tag -4. Generate and attach PGP signatures (if signing key available) -5. Post notification to configured channels - -**Artifacts**: Draft GitHub release with RC artifacts - -#### 3. Final Release Workflow (`helm/helm`) - -**Trigger**: Manual approval/publication of RC draft release - -**Actions**: -1. Create signed, annotated final release tag -2. Update draft release to final -3. Trigger documentation update workflow -4. Close milestone -5. Generate community announcement template - -#### 4. Documentation Update Workflow (`helm/helm-www`) - -**Trigger**: Webhook from helm/helm final release publication - -**Actions**: -1. Update `config.toml` with new version information -2. Update `params.nextversion` with next planned release -3. Update version skew documentation -4. Update release calendar with next release dates -5. Create pull request in helm/helm-www - -**Artifacts**: Pull request in helm/helm-www ready for review - -### File Structure - -``` -.github/workflows/ -├── prepare-release.yml # Release preparation automation -├── release-candidate.yml # RC creation and management -├── finalize-release.yml # Final release publication -└── update-documentation.yml # Cross-repo docs updates - -scripts/ -├── update-version-files.sh # Version update automation -├── generate-release-notes.sh # Release notes generation -└── update-test-data.sh # Test file version updates -``` - -### Configuration - -New configuration file `.github/release-config.yml`: - -```yaml -# Release automation configuration -version_files: - - path: "internal/version/version.go" - pattern: 'version = "v{VERSION}"' - - path: "cmd/helm/testdata/output/version.txt" - pattern: 'Version:"{VERSION}"' - # ... additional files - -repositories: - docs_repo: "helm/helm-www" - -signing: - gpg_key_id: "${{ secrets.GPG_KEY_ID }}" - gpg_private_key: "${{ secrets.GPG_PRIVATE_KEY }}" -``` - -### Permissions and Security - -Required GitHub App permissions: -- Contents: Write (for creating branches, tags, releases) -- Pull Requests: Write (for creating PRs) -- Metadata: Read (for accessing repository info) -- Actions: Write (for triggering cross-repo workflows) - -Required secrets: -- `GITHUB_APP_ID`: GitHub App ID for cross-repo access -- `GITHUB_APP_PRIVATE_KEY`: GitHub App private key -- `GPG_PRIVATE_KEY`: PGP signing key (optional) - -## Backwards Compatibility - -This proposal introduces new automation alongside the existing manual process: - -1. **Graceful Rollback**: Manual process remains fully functional if automation fails -2. **Opt-in Adoption**: Teams can choose to use automation for specific steps -3. **No Breaking Changes**: No modifications to existing release artifacts or tags -4. **Existing Tool Compatibility**: All existing tooling continues to work unchanged - -The automation enhances rather than replaces the current process, ensuring maintainers can fall back to manual steps if needed. - -## Security Implications - -### Enhanced Security - -1. **Consistent Process**: Automation reduces risk of human error in security-critical steps -2. **Audit Trail**: All changes tracked through GitHub PR system -3. **Access Control**: GitHub App permissions more restrictive than individual maintainer access -4. **Signed Commits**: Automation maintains commit signing requirements - -### Security Considerations - -1. **Secret Management**: GPG keys and tokens stored in GitHub Secrets -2. **Cross-Repo Access**: GitHub App tokens limited to minimum required permissions -3. **Draft Mode**: All releases created in draft mode, requiring manual publication -4. **Approval Gates**: All changes require PR approval before implementation - -## How to Teach This - -### Maintainer Documentation - -1. Update existing release checklist with automation options -2. Create troubleshooting guide for automation failures -3. Document rollback procedures -4. Provide workflow customization examples - -### Training Materials - -1. Video walkthrough of automated release process -2. Comparison guide: manual vs. automated steps -3. Emergency procedures documentation -4. FAQ for common automation issues - -## Reference Implementation +## Automation Flow ### Workflow Process @@ -257,59 +79,37 @@ Example completion status: - [ ] GitHub milestone management - [ ] Release artifact attachment -### Corresponding Helm Workflow Plan - -**helm/helm repository:** -- `.github/workflows/prepare-release.yml` - Creates preparation branch and PR with version updates -- `.github/workflows/trigger-release.yml` - Triggers release creation when prep PR merges -- `.github/workflows/create-release.yml` - Creates release branch, tag, and draft release -- `scripts/update-version.sh` - Updates version strings in code and test files -- `scripts/generate-release-notes.sh` - Generates release notes template from git history - -**helm/helm-www repository:** -- `.github/workflows/update-version.yml` - Creates PR to update website configuration -- `.github/workflows/manual-update-docs.yml` - Manual fallback for docs updates - -### Key Implementation Details - -**Cross-repository communication** uses GitHub's `repository_dispatch` event to trigger the helm-www workflow when a helm/helm release is published. This requires a `HELM_RELEASE_TOKEN` secret with cross-repository access. - -**Version file updates** use sed pattern matching to find and replace version strings across multiple file types, handling both semantic version formats and Go version variables. - -**Pull request automation** leverages GitHub CLI (`gh`) to create PRs with proper titles and generated content, ensuring all changes go through standard review processes. - -The implementation handles the three primary release types (major/minor/patch) through a single workflow with input parameters, automatically extracting version information and creating appropriate branch names. - -## Rejected Ideas - -### Fully Automated Releases - -Rejected because release timing requires human judgment based on: -- Community feedback on release candidates -- Critical bug discovery during testing -- External factors (holidays, conferences, security issues) - -### Slack/Discord Bot Interface +### File Structure -While potentially useful, adds complexity and another system to maintain. GitHub's existing interfaces provide sufficient control. +``` +helm/helm/ +├── .github/workflows/ +│ ├── prepare-release.yml # Manual trigger, creates PR with version updates +│ ├── trigger-release.yml # Auto trigger on PR merge +│ └── create-release.yml # Creates release branch, tag, and draft release +└── scripts/ + ├── update-version.sh # Updates version strings in code and test files + └── generate-release-notes.sh # Release notes template from git history + +helm/helm-www/ +└── .github/workflows/ + ├── update-version.yml # Creates PR to update website configuration + └── manual-update-docs.yml # Manual fallback for docs updates +``` -### Automatic Backporting +**Key mechanisms:** +- Cross-repository communication via `repository_dispatch` events +- Draft releases created for human review before docs automation triggers +- Persistent release branches for patch release support +- All changes flow through pull request reviews -Patch release cherry-picking requires human judgment for: -- Risk assessment of changes -- Conflict resolution -- Testing scope determination +## Security & Compatibility -## Open Issues +**Backwards Compatibility**: Manual process remains fully functional as fallback. No changes to existing release artifacts or tooling. -1. **GPG Key Management**: Best practices for storing and rotating signing keys in CI -2. **Cross-Org Coordination**: Technical approach for coordinating releases with other CNCF projects -3. **Rollback Testing**: Comprehensive testing scenarios for automation failures -4. **Metrics Collection**: Tracking automation success rates and time savings +**Security**: All releases created in draft mode requiring manual publication. GPG signing and commit signing preserved. Cross-repo access via fine-grained Personal Access Token with minimal permissions. ## References -1. [Current Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md) -2. [GitHub Actions Documentation](https://docs.github.com/en/actions) -3. [Semantic Versioning](https://semver.org/) -4. [GitHub Apps Documentation](https://docs.github.com/en/developers/apps) +- [Current Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md) +- [Working Examples](https://github.com/scottrigby/example-actions-autorelease-source) From 0e125276d3c9ce4fd8f343b85f7ec67921ca96de Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Sat, 13 Sep 2025 02:47:35 -0400 Subject: [PATCH 5/7] manual workflow run image Signed-off-by: Scott Rigby --- hips/hip-9999-01.png | Bin 0 -> 54242 bytes hips/hip-9999.md | 11 ++++------- 2 files changed, 4 insertions(+), 7 deletions(-) create mode 100644 hips/hip-9999-01.png diff --git a/hips/hip-9999-01.png b/hips/hip-9999-01.png new file mode 100644 index 0000000000000000000000000000000000000000..d7cf933490da9de6be79782cc652d584d0a9c002 GIT binary patch literal 54242 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 wz5FwwyUgUPaw*O7!c+9Q;@bu48}N + +Once the PR is **merged**, automation takes over: it creates a persistent **release branch** (like `release-4.0` and `release-3.20`) from the appropriate base branch (`main` for v4.x, `dev-v3` for v3.x), cherry-picks the version commit, creates a signed tag, and **drafts the GitHub release**. The draft sits ready for maintainer review - they can test artifacts, verify release notes, and make adjustments before publishing. When the maintainer **publishes the draft release**, it automatically triggers the documentation workflow in the helm-www repository, creating a pull request with updated version information, release dates, and compatibility matrices. This ensures the website stays synchronized with each release without manual coordination. @@ -108,8 +110,3 @@ helm/helm-www/ **Backwards Compatibility**: Manual process remains fully functional as fallback. No changes to existing release artifacts or tooling. **Security**: All releases created in draft mode requiring manual publication. GPG signing and commit signing preserved. Cross-repo access via fine-grained Personal Access Token with minimal permissions. - -## References - -- [Current Release Checklist](https://github.com/helm/helm-www/blob/main/content/en/docs/community/release_checklist.md) -- [Working Examples](https://github.com/scottrigby/example-actions-autorelease-source) From 40c7565a596e3c4dd47fe1a0f96e796d51136c10 Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Sat, 13 Sep 2025 03:02:33 -0400 Subject: [PATCH 6/7] shorten user experience section Signed-off-by: Scott Rigby --- hips/hip-9999.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hips/hip-9999.md b/hips/hip-9999.md index 06ed06b08..33c369bbc 100644 --- a/hips/hip-9999.md +++ b/hips/hip-9999.md @@ -52,17 +52,17 @@ flowchart TD ### User Experience -The release process starts with a **manual workflow trigger** where maintainers enter the target version (e.g., `v4.0.0-alpha.2` or `v3.20.0`) in GitHub's workflow dispatch UI. This creates a preparation branch with all necessary version updates and opens a pull request for review. +**Step 1**: Maintainer triggers "Prepare Release" workflow with target version (e.g., `v3.20.0`), creating a PR with version updates. -Once the PR is **merged**, automation takes over: it creates a persistent **release branch** (like `release-4.0` and `release-3.20`) from the appropriate base branch (`main` for v4.x, `dev-v3` for v3.x), cherry-picks the version commit, creates a signed tag, and **drafts the GitHub release**. The draft sits ready for maintainer review - they can test artifacts, verify release notes, and make adjustments before publishing. +**Step 2**: After PR merge, automation creates persistent release branch, signed tag, and **draft release** for review. -When the maintainer **publishes the draft release**, it automatically triggers the documentation workflow in the helm-www repository, creating a pull request with updated version information, release dates, and compatibility matrices. This ensures the website stays synchronized with each release without manual coordination. +**Step 3**: Maintainer publishes draft, automatically triggering docs workflow to create website update PR. -**Fallback options** provide resilience: if the cross-repository automation fails, maintainers can manually trigger the docs update workflow with the same simple version input interface. Every change flows through pull request reviews, maintaining quality control while eliminating repetitive manual tasks. +**Fallback**: If automated docs trigger fails, maintainer can manually run "Update Docs" workflow in helm-www repository. -The experience transforms release management from an error-prone 11-step checklist into a **three-click process**: trigger preparation, publish draft, merge docs PR. +**Result**: 11-step manual checklist becomes a three-click process with full human review gates and automatic fallbacks. ### Example Implementation Repos From e7154bd5c11ac7bcb8a13077bfc9fd22518b5e59 Mon Sep 17 00:00:00 2001 From: Scott Rigby Date: Mon, 22 Sep 2025 15:11:38 -0700 Subject: [PATCH 7/7] Update HIP diagram and description to match changes in reference example Signed-off-by: Scott Rigby --- hips/hip-9999.md | 57 +++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/hips/hip-9999.md b/hips/hip-9999.md index 33c369bbc..e2a1a7fd1 100644 --- a/hips/hip-9999.md +++ b/hips/hip-9999.md @@ -9,7 +9,7 @@ status: "draft" ## Abstract -This HIP proposes automating the Helm release process through GitHub Actions while maintaining human review gates. The automation transforms the current 11-step manual checklist into a three-click process: trigger preparation, publish draft, merge docs PR. All changes flow through pull request reviews, preserving security while eliminating repetitive tasks. +This HIP proposes automating the Helm release process through GitHub Actions while maintaining human review gates. The automation transforms the current 11-step manual checklist into a two-click process: trigger release, publish draft. All changes flow through pull request reviews, preserving security while eliminating repetitive tasks. ## Motivation @@ -28,41 +28,38 @@ The current 11-step [Release Checklist](https://github.com/helm/helm-www/blob/ma ```mermaid flowchart TD - A[Manual: Prepare Release Workflow] --> B[Auto: Create PR with version updates] - B --> C{Manual: Review & Merge PR} - C -->|Merge| D[Auto: Create Draft Release] - D --> E{Manual: Review Draft & Publish} - E -->|Publish| F[Auto: Trigger Docs Workflow
repository_dispatch] - F --> G[Auto: Create Docs PR] - G --> H{Manual: Review & Merge Docs PR} + A[Manual: Trigger Release Workflow] --> B[Auto: Create Release Branch & Update Versions] + B --> C[Auto: Create Draft Release with Artifacts] + C --> D{Manual: Review Draft & Publish} + D -->|Publish| E[Auto: Trigger Docs Workflow
repository_dispatch] + E --> F[Auto: Create Docs PR] + F --> G{Manual: Review & Merge Docs PR} %% Manual fallback options - A -.->|Fallback| I[Manual: Docs Update Workflow] - I --> G + A -.->|Fallback| H[Manual: Docs Update Workflow] + H --> F %% Styling for light/dark mode compatibility classDef manual fill:#cce7ff,stroke:#0066cc,stroke-width:2px,color:#000 classDef auto fill:#e6ccff,stroke:#6600cc,stroke-width:2px,color:#000 classDef decision fill:#ffe6cc,stroke:#cc6600,stroke-width:2px,color:#000 - class A,C,E,H,I manual - class B,D,F,G auto - class C,E,H decision + class A,D,G,H manual + class B,C,E,F auto + class D,G decision ``` ### User Experience -**Step 1**: Maintainer triggers "Prepare Release" workflow with target version (e.g., `v3.20.0`), creating a PR with version updates. +**Step 1**: Maintainer triggers "Release" workflow with target version (e.g., `v3.20.0`). Automation creates release branch, updates versions, generates artifacts, and creates **draft release** for review. -**Step 2**: After PR merge, automation creates persistent release branch, signed tag, and **draft release** for review. - -**Step 3**: Maintainer publishes draft, automatically triggering docs workflow to create website update PR. +**Step 2**: Maintainer publishes draft, automatically triggering docs workflow to create website update PR. **Fallback**: If automated docs trigger fails, maintainer can manually run "Update Docs" workflow in helm-www repository. -**Result**: 11-step manual checklist becomes a three-click process with full human review gates and automatic fallbacks. +**Result**: 11-step manual checklist becomes a two-click process with full human review gates and automatic fallbacks. ### Example Implementation Repos @@ -76,34 +73,34 @@ Example completion status: - [x] Persistent release branches for patch releases - [x] Dynamic documentation updates with version/date tracking - [x] Manual fallback workflows -- [ ] GPG signing of release artifacts -- [ ] Kubernetes version skew calculation from go.mod +- [x] GPG signing of release artifacts (simulated) +- [x] Kubernetes version skew calculation from go.mod +- [x] Release artifact attachment - [ ] GitHub milestone management -- [ ] Release artifact attachment ### File Structure ``` helm/helm/ ├── .github/workflows/ -│ ├── prepare-release.yml # Manual trigger, creates PR with version updates -│ ├── trigger-release.yml # Auto trigger on PR merge -│ └── create-release.yml # Creates release branch, tag, and draft release -└── scripts/ - ├── update-version.sh # Updates version strings in code and test files - └── generate-release-notes.sh # Release notes template from git history +│ ├── release.yml # Single atomic workflow: creates branch, artifacts, draft release +│ └── update-docs.yml # Triggers docs when release published (not drafted) +├── scripts/ +│ └── [supporting scripts] # Artifact generation, signing, and version extraction +└── KEYS # Public GPG keys for verification helm/helm-www/ └── .github/workflows/ - ├── update-version.yml # Creates PR to update website configuration - └── manual-update-docs.yml # Manual fallback for docs updates + ├── auto-version-update.yml # Creates PR to update website configuration + └── manual-version-update.yml # Manual fallback for docs updates ``` **Key mechanisms:** +- Single atomic workflow eliminates complex multi-step coordination - Cross-repository communication via `repository_dispatch` events - Draft releases created for human review before docs automation triggers - Persistent release branches for patch release support -- All changes flow through pull request reviews +- GPG signing and checksum generation for release verification ## Security & Compatibility