package releaseprep import ( "fmt" "os" "path/filepath" "regexp" "strings" ) var versionPattern = regexp.MustCompile(`const String = "[^"]+"`) func Prepare(rootDir, version, releaseDate string) error { normalizedVersion := strings.TrimPrefix(strings.TrimSpace(version), "v") if normalizedVersion == "" { return fmt.Errorf("version must not be empty") } releaseDate = strings.TrimSpace(releaseDate) if releaseDate == "" { return fmt.Errorf("release date must not be empty") } if err := updateVersionFile(rootDir, normalizedVersion); err != nil { return err } if err := updateChangelog(rootDir, normalizedVersion, releaseDate); err != nil { return err } return nil } func updateVersionFile(rootDir, version string) error { path := filepath.Join(rootDir, "internal", "homesick", "version", "version.go") contents, err := os.ReadFile(path) if err != nil { return fmt.Errorf("read version file: %w", err) } updated := versionPattern.ReplaceAllString(string(contents), fmt.Sprintf(`const String = %q`, version)) if updated == string(contents) { return fmt.Errorf("version constant not found in %s", path) } if err := os.WriteFile(path, []byte(updated), 0o644); err != nil { return fmt.Errorf("write version file: %w", err) } return nil } func updateChangelog(rootDir, version, releaseDate string) error { path := filepath.Join(rootDir, "changelog.md") contents, err := os.ReadFile(path) if err != nil { return fmt.Errorf("read changelog: %w", err) } text := string(contents) unreleasedHeader := "## [Unreleased]\n" start := strings.Index(text, unreleasedHeader) if start == -1 { return fmt.Errorf("unreleased section not found in changelog") } afterHeader := start + len(unreleasedHeader) nextSectionRelative := strings.Index(text[afterHeader:], "\n## [") if nextSectionRelative == -1 { nextSectionRelative = len(text[afterHeader:]) } nextSectionStart := afterHeader + nextSectionRelative unreleasedBody := strings.TrimLeft(text[afterHeader:nextSectionStart], "\n") newSection := fmt.Sprintf("## [%s] - %s\n", version, releaseDate) if strings.TrimSpace(unreleasedBody) != "" { newSection += "\n" + unreleasedBody if !strings.HasSuffix(newSection, "\n") { newSection += "\n" } } updated := text[:afterHeader] + "\n" + newSection + text[nextSectionStart:] if err := os.WriteFile(path, []byte(updated), 0o644); err != nil { return fmt.Errorf("write changelog: %w", err) } return nil }