mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 22:55:48 +01:00
fix: add missing v3 release script and changelog template
The nightly-release-v3.yml workflow was failing because it references v3/tasks/release/release.go which did not exist. This adds: - v3/tasks/release/release.go: Release script with --check-only and --dry-run flags for the nightly release workflow - v3/UNRELEASED_CHANGELOG.md: Template file for tracking unreleased changes https://claude.ai/code/session_016FpJHv9CBS7YG9Mj6QJ7xd
This commit is contained in:
parent
8fd0340404
commit
204cddffdb
2 changed files with 267 additions and 0 deletions
20
v3/UNRELEASED_CHANGELOG.md
Normal file
20
v3/UNRELEASED_CHANGELOG.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Unreleased Changelog
|
||||
|
||||
All notable changes to the v3 alpha will be documented in this file before release.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## Categories
|
||||
|
||||
Use the following categories to organize your entries:
|
||||
- `Added` for new features.
|
||||
- `Changed` for changes in existing functionality.
|
||||
- `Deprecated` for soon-to-be removed features.
|
||||
- `Removed` for now removed features.
|
||||
- `Fixed` for any bug fixes.
|
||||
- `Security` in case of vulnerabilities.
|
||||
|
||||
---
|
||||
|
||||
<!-- Add your changelog entries below this line -->
|
||||
|
||||
247
v3/tasks/release/release.go
Normal file
247
v3/tasks/release/release.go
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
unreleasedChangelogFile = "../../UNRELEASED_CHANGELOG.md"
|
||||
versionPrefix = "v3.0.0-alpha."
|
||||
)
|
||||
|
||||
var (
|
||||
checkOnly = flag.Bool("check-only", false, "Only check if there's unreleased content, exit 0 if yes, 1 if no")
|
||||
dryRun = flag.Bool("dry-run", false, "Run in dry-run mode (no actual release)")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
// Check for unreleased content
|
||||
hasContent, entries := checkUnreleasedContent()
|
||||
|
||||
if *checkOnly {
|
||||
if hasContent {
|
||||
fmt.Println("Found unreleased changelog content")
|
||||
os.Exit(0)
|
||||
} else {
|
||||
fmt.Println("No unreleased changelog content found")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if !hasContent {
|
||||
fmt.Println("No unreleased changelog content found. Nothing to release.")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Determine the next version
|
||||
nextVersion := getNextVersion()
|
||||
releaseTag := versionPrefix + strconv.Itoa(nextVersion)
|
||||
|
||||
fmt.Printf("Preparing release: %s\n", releaseTag)
|
||||
|
||||
if *dryRun {
|
||||
fmt.Println("[DRY-RUN] Would perform the following actions:")
|
||||
fmt.Printf("[DRY-RUN] - Create release tag: %s\n", releaseTag)
|
||||
fmt.Printf("[DRY-RUN] - Changelog entries to include:\n")
|
||||
for _, entry := range entries {
|
||||
fmt.Printf("[DRY-RUN] %s\n", entry)
|
||||
}
|
||||
setGitHubOutput("release_version", releaseTag)
|
||||
setGitHubOutput("release_tag", releaseTag)
|
||||
setGitHubOutput("release_dry_run", "true")
|
||||
fmt.Println("[DRY-RUN] Release simulation complete")
|
||||
return
|
||||
}
|
||||
|
||||
// Perform actual release
|
||||
if err := performRelease(releaseTag, entries); err != nil {
|
||||
fmt.Printf("Release failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Set GitHub outputs
|
||||
setGitHubOutput("release_version", releaseTag)
|
||||
setGitHubOutput("release_tag", releaseTag)
|
||||
setGitHubOutput("release_dry_run", "false")
|
||||
|
||||
fmt.Printf("Release %s completed successfully!\n", releaseTag)
|
||||
}
|
||||
|
||||
func checkUnreleasedContent() (bool, []string) {
|
||||
content, err := os.ReadFile(unreleasedChangelogFile)
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: Could not read %s: %v\n", unreleasedChangelogFile, err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
lines := strings.Split(string(content), "\n")
|
||||
var entries []string
|
||||
|
||||
// Look for bullet point entries only after the separator line (---)
|
||||
// This avoids matching the template category descriptions
|
||||
foundSeparator := false
|
||||
bulletRegex := regexp.MustCompile(`^\s*-\s+[^\s]`)
|
||||
|
||||
for _, line := range lines {
|
||||
// Look for the separator line
|
||||
if strings.TrimSpace(line) == "---" {
|
||||
foundSeparator = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Only match entries after the separator
|
||||
if foundSeparator && bulletRegex.MatchString(line) {
|
||||
entries = append(entries, strings.TrimSpace(line))
|
||||
}
|
||||
}
|
||||
|
||||
return len(entries) > 0, entries
|
||||
}
|
||||
|
||||
func getNextVersion() int {
|
||||
// Get all existing v3.0.0-alpha.* tags
|
||||
cmd := exec.Command("git", "tag", "--list", "v3.0.0-alpha.*")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
fmt.Println("No existing alpha tags found, starting with alpha.1")
|
||||
return 1
|
||||
}
|
||||
|
||||
tags := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
if len(tags) == 0 || (len(tags) == 1 && tags[0] == "") {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Extract version numbers and find the highest
|
||||
var versions []int
|
||||
for _, tag := range tags {
|
||||
tag = strings.TrimSpace(tag)
|
||||
if tag == "" {
|
||||
continue
|
||||
}
|
||||
// Extract the number after "v3.0.0-alpha."
|
||||
parts := strings.Split(tag, "v3.0.0-alpha.")
|
||||
if len(parts) == 2 {
|
||||
num, err := strconv.Atoi(parts[1])
|
||||
if err == nil {
|
||||
versions = append(versions, num)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(versions) == 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
sort.Ints(versions)
|
||||
return versions[len(versions)-1] + 1
|
||||
}
|
||||
|
||||
func performRelease(releaseTag string, entries []string) error {
|
||||
// Reset the unreleased changelog
|
||||
if err := resetUnreleasedChangelog(); err != nil {
|
||||
return fmt.Errorf("failed to reset unreleased changelog: %w", err)
|
||||
}
|
||||
|
||||
// Stage the changes
|
||||
if err := runCommand("git", "add", unreleasedChangelogFile); err != nil {
|
||||
return fmt.Errorf("failed to stage changelog: %w", err)
|
||||
}
|
||||
|
||||
// Create commit
|
||||
commitMsg := fmt.Sprintf("chore: release %s", releaseTag)
|
||||
if err := runCommand("git", "commit", "-m", commitMsg); err != nil {
|
||||
return fmt.Errorf("failed to create commit: %w", err)
|
||||
}
|
||||
|
||||
// Create annotated tag
|
||||
tagMsg := fmt.Sprintf("Release %s\n\nChanges:\n%s", releaseTag, strings.Join(entries, "\n"))
|
||||
if err := runCommand("git", "tag", "-a", releaseTag, "-m", tagMsg); err != nil {
|
||||
return fmt.Errorf("failed to create tag: %w", err)
|
||||
}
|
||||
|
||||
// Push commit and tag
|
||||
if err := runCommand("git", "push", "origin", "HEAD"); err != nil {
|
||||
return fmt.Errorf("failed to push commit: %w", err)
|
||||
}
|
||||
|
||||
if err := runCommand("git", "push", "origin", releaseTag); err != nil {
|
||||
return fmt.Errorf("failed to push tag: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetUnreleasedChangelog() error {
|
||||
template := `# Unreleased Changelog
|
||||
|
||||
All notable changes to the v3 alpha will be documented in this file before release.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## Categories
|
||||
|
||||
Use the following categories to organize your entries:
|
||||
- ` + "`Added`" + ` for new features.
|
||||
- ` + "`Changed`" + ` for changes in existing functionality.
|
||||
- ` + "`Deprecated`" + ` for soon-to-be removed features.
|
||||
- ` + "`Removed`" + ` for now removed features.
|
||||
- ` + "`Fixed`" + ` for any bug fixes.
|
||||
- ` + "`Security`" + ` in case of vulnerabilities.
|
||||
|
||||
---
|
||||
|
||||
<!-- Add your changelog entries below this line -->
|
||||
|
||||
`
|
||||
return os.WriteFile(unreleasedChangelogFile, []byte(template), 0644)
|
||||
}
|
||||
|
||||
func runCommand(name string, args ...string) error {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func setGitHubOutput(name, value string) {
|
||||
// Write to GITHUB_OUTPUT file if available (GitHub Actions)
|
||||
outputFile := os.Getenv("GITHUB_OUTPUT")
|
||||
if outputFile != "" {
|
||||
f, err := os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err == nil {
|
||||
defer f.Close()
|
||||
writer := bufio.NewWriter(f)
|
||||
fmt.Fprintf(writer, "%s=%s\n", name, value)
|
||||
writer.Flush()
|
||||
}
|
||||
}
|
||||
// Also print for visibility
|
||||
fmt.Printf("::set-output name=%s::%s\n", name, value)
|
||||
}
|
||||
|
||||
// getToday returns today's date in YYYY-MM-DD format (used for release notes)
|
||||
func getToday() string {
|
||||
return time.Now().Format("2006-01-02")
|
||||
}
|
||||
|
||||
// getReleaseDir returns the directory where release artifacts should be stored
|
||||
func getReleaseDir() string {
|
||||
dir, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
return "."
|
||||
}
|
||||
return dir
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue