main.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "regexp"
  8. "strings"
  9. "time"
  10. "github.com/Masterminds/semver/v3"
  11. "github.com/otiai10/copy"
  12. "github.com/spf13/pflag"
  13. )
  14. const (
  15. changelogSource = "CHANGELOG.md"
  16. changelogTarget = "website/docs/changelog.mdx"
  17. docsSource = "website/docs"
  18. docsTarget = "website/versioned_docs/version-latest"
  19. )
  20. var (
  21. changelogReleaseRegex = regexp.MustCompile(`## Unreleased`)
  22. versionRegex = regexp.MustCompile(`(?m)^ "version": "\d+\.\d+\.\d+",$`)
  23. )
  24. // Flags
  25. var (
  26. versionFlag bool
  27. )
  28. func init() {
  29. pflag.BoolVarP(&versionFlag, "version", "v", false, "resolved version number")
  30. pflag.Parse()
  31. }
  32. func main() {
  33. if err := release(); err != nil {
  34. fmt.Println(err)
  35. os.Exit(1)
  36. }
  37. }
  38. func release() error {
  39. if len(pflag.Args()) != 1 {
  40. return errors.New("error: expected version number")
  41. }
  42. version, err := getVersion()
  43. if err != nil {
  44. return err
  45. }
  46. if err := bumpVersion(version, pflag.Arg(0)); err != nil {
  47. return err
  48. }
  49. if versionFlag {
  50. fmt.Println(version)
  51. return nil
  52. }
  53. if err := changelog(version); err != nil {
  54. return err
  55. }
  56. if err := setJSONVersion("package.json", version); err != nil {
  57. return err
  58. }
  59. if err := setJSONVersion("package-lock.json", version); err != nil {
  60. return err
  61. }
  62. if err := docs(); err != nil {
  63. return err
  64. }
  65. return nil
  66. }
  67. func getVersion() (*semver.Version, error) {
  68. cmd := exec.Command("git", "describe", "--tags", "--abbrev=0")
  69. b, err := cmd.Output()
  70. if err != nil {
  71. return nil, err
  72. }
  73. return semver.NewVersion(strings.TrimSpace(string(b)))
  74. }
  75. func bumpVersion(version *semver.Version, verb string) error {
  76. switch verb {
  77. case "major":
  78. *version = version.IncMajor()
  79. case "minor":
  80. *version = version.IncMinor()
  81. case "patch":
  82. *version = version.IncPatch()
  83. default:
  84. *version = *semver.MustParse(verb)
  85. }
  86. return nil
  87. }
  88. func changelog(version *semver.Version) error {
  89. // Open changelog target file
  90. b, err := os.ReadFile(changelogTarget)
  91. if err != nil {
  92. return err
  93. }
  94. // Get the current frontmatter
  95. currentChangelog := string(b)
  96. sections := strings.SplitN(currentChangelog, "---", 3)
  97. if len(sections) != 3 {
  98. return errors.New("error: invalid frontmatter")
  99. }
  100. frontmatter := strings.TrimSpace(sections[1])
  101. // Open changelog source file
  102. b, err = os.ReadFile(changelogSource)
  103. if err != nil {
  104. return err
  105. }
  106. changelog := string(b)
  107. date := time.Now().Format("2006-01-02")
  108. // Replace "Unreleased" with the new version and date
  109. changelog = changelogReleaseRegex.ReplaceAllString(changelog, fmt.Sprintf("## v%s - %s", version, date))
  110. // Write the changelog to the source file
  111. if err := os.WriteFile(changelogSource, []byte(changelog), 0o644); err != nil {
  112. return err
  113. }
  114. // Add the frontmatter to the changelog
  115. changelog = fmt.Sprintf("---\n%s\n---\n\n%s", frontmatter, changelog)
  116. // Write the changelog to the target file
  117. return os.WriteFile(changelogTarget, []byte(changelog), 0o644)
  118. }
  119. func setJSONVersion(fileName string, version *semver.Version) error {
  120. // Read the JSON file
  121. b, err := os.ReadFile(fileName)
  122. if err != nil {
  123. return err
  124. }
  125. // Replace the version
  126. new := versionRegex.ReplaceAllString(string(b), fmt.Sprintf(` "version": "%s",`, version.String()))
  127. // Write the JSON file
  128. return os.WriteFile(fileName, []byte(new), 0o644)
  129. }
  130. func docs() error {
  131. if err := os.RemoveAll(docsTarget); err != nil {
  132. return err
  133. }
  134. if err := copy.Copy(docsSource, docsTarget); err != nil {
  135. return err
  136. }
  137. return nil
  138. }