Skip to content

Commit

Permalink
chore: release_prep utility
Browse files Browse the repository at this point in the history
  • Loading branch information
jkaflik committed Apr 13, 2023
1 parent 80797f3 commit 1237074
Show file tree
Hide file tree
Showing 8 changed files with 455 additions and 188 deletions.
24 changes: 12 additions & 12 deletions conn_batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,18 +226,18 @@ func (b *batchColumn) Append(v interface{}) (err error) {
}

func (b *batchColumn) AppendRow(v interface{}) (err error) {
if b.batch.IsSent() {
return ErrBatchAlreadySent
}
if b.err != nil {
b.release(b.err)
return b.err
}
if err = b.column.AppendRow(v); err != nil {
b.release(err)
return err
}
return nil
if b.batch.IsSent() {
return ErrBatchAlreadySent
}
if b.err != nil {
b.release(b.err)
return b.err
}
if err = b.column.AppendRow(v); err != nil {
b.release(err)
return err
}
return nil
}

var (
Expand Down
1 change: 1 addition & 0 deletions contributors/contributors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"strings"
)

//go:generate bash -c "git log \"--pretty=%an <%ae>\" | sort -u > list"
//go:embed list
var source string

Expand Down
271 changes: 271 additions & 0 deletions internal/cmd/release_prep/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
package main

import (
"bufio"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"time"
)

var skipWorkingTreeIsDirtyCheck = flag.Bool("skip-working-tree-is-dirty-check", false, "Skip working tree is dirty check")

func main() {
flag.Parse()

if !(*skipWorkingTreeIsDirtyCheck) && gitRepositoryWorkingTreeIsDirty() {
log.Fatalln("Git working tree is dirty")
return
}

releaseURL := getLatestDraftReleaseURL()

log.Println("Latest draft release URL:")
log.Println(releaseURL)

r := getRelease(releaseURL)

log.Println("Release tag:")
log.Println(r.TagName)
log.Println("Release body:")
log.Println(r.Body)

major, minor, patch, err := parseSemVer(r.TagName)
if err != nil {
log.Fatalln(err)
return
}

if len(r.Body) == 0 {
log.Fatalln("Release body is empty")
return
}

changelogPath := changelogFilePath()
prependReleaseToChangelog(changelogPath, r)

if err := updateClientInfo(major, minor, patch); err != nil {
log.Fatalln(err)
return
}

runGoGenerate()
runGoFmt()
}

func runGoFmt() {
cmd := exec.Command("go", "fmt", "./...")
cmd.Dir = getRootPath()
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalln(err)
return
}
}

func runGoGenerate() {
cmd := exec.Command("go", "generate", "./...")
cmd.Dir = getRootPath()
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalln(err)
return
}
}

func gitRepositoryWorkingTreeIsDirty() bool {
cmd := exec.Command("git", "status", "--porcelain")
out, err := cmd.Output()
if err != nil {
log.Fatalln(err)
return false
}
return len(out) > 0
}

func parseSemVer(version string) (major, minor, patch int, err error) {
// Define a regular expression to match SemVer format
re := regexp.MustCompile(`^v?(\d+)\.(\d+)\.(\d+)$`)

// Apply the regular expression to the version string
match := re.FindStringSubmatch(version)

// Check if the version string matches the SemVer format
if len(match) != 4 {
err = fmt.Errorf("invalid SemVer format: %s", version)
return
}

// Parse the major, minor, and patch components as integers
major, err = strconv.Atoi(match[1])
if err != nil {
return
}

minor, err = strconv.Atoi(match[2])
if err != nil {
return
}

patch, err = strconv.Atoi(match[3])
if err != nil {
return
}

return
}

func prependReleaseToChangelog(changelogPath string, r release) {
f, err := os.OpenFile(changelogPath, os.O_RDWR, 0666)
if err != nil {
log.Fatalln(err)
}
defer f.Close()

content, err := io.ReadAll(f)
if err != nil {
log.Fatalln(err)
return
}

f.Seek(0, io.SeekStart)
f.WriteString(fmt.Sprintf("# %s, %s ", r.TagName, time.Now().Format("2006-01-02")))
f.WriteString(r.Body)
f.WriteString("\n\n")
f.Write(content)
}

func changelogFilePath() string {
rootPath := getRootPath()
changelogPath := rootPath + "/CHANGELOG.md"
return changelogPath
}

func getRootPath() string {
wd, _ := os.Getwd()
rootPath := strings.Replace(wd, "internal/cmd/release_prep", "", 1)
return rootPath
}

func getRelease(releaseURL string) release {
req, err := http.NewRequest(http.MethodGet, releaseURL, nil)
if err != nil {
log.Fatalln(err)
}
req.Header.Set("Authorization", "token "+os.Getenv("GITHUB_TOKEN"))
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatalln(err)
}
defer res.Body.Close()

var release release
if err := json.NewDecoder(res.Body).Decode(&release); err != nil {
log.Fatalln(err)
}

return release
}

type release struct {
URL string `json:"url"`
Body string `json:"body"`
TagName string `json:"tag_name"`
}

func getLatestDraftReleaseURL() string {
// Fetch the latest release from GitHub repository using GitHub API
req, err := http.NewRequest(http.MethodGet, "https://api.github.com/repos/clickhouse/clickhouse-go/releases?per_page=100", nil)
if err != nil {
log.Fatalln(err)
}

req.Header.Set("Authorization", "token "+os.Getenv("GITHUB_TOKEN"))
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatalln(err)
}
defer res.Body.Close()

var releases []struct {
URL string `json:"url"`
Draft bool `json:"draft"`
}
if err := json.NewDecoder(res.Body).Decode(&releases); err != nil {
log.Fatalln(err)
}

// filter out releases that are not drafts
for i := 0; i < len(releases); {
if releases[i].Draft {
return releases[i].URL
}
}

log.Fatalln("No draft releases found")
return ""
}

func updateClientInfo(major, minor, patch int) error {
// Open the client_info.go file for reading and writing
file, err := os.OpenFile(getRootPath()+"/client_info.go", os.O_RDWR, 0644)
if err != nil {
return err
}
defer file.Close()

// Read the contents of the file into memory
bytes, err := io.ReadAll(file)
if err != nil {
return err
}

// Replace the ClientVersionMajor, ClientVersionMinor, and ClientVersionPatch lines
reMajor := regexp.MustCompile(`ClientVersionMajor\s+=\s+\d+`)
reMinor := regexp.MustCompile(`ClientVersionMinor\s+=\s+\d+`)
rePatch := regexp.MustCompile(`ClientVersionPatch\s+=\s+\d+`)
newLines := []string{
fmt.Sprintf("ClientVersionMajor = %d", major),
fmt.Sprintf("ClientVersionMinor = %d", minor),
fmt.Sprintf("ClientVersionPatch = %d", patch),
}
scanner := bufio.NewScanner(strings.NewReader(string(bytes)))
var newContent string
for scanner.Scan() {
line := scanner.Text()
if reMajor.MatchString(line) {
line = newLines[0]
} else if reMinor.MatchString(line) {
line = newLines[1]
} else if rePatch.MatchString(line) {
line = newLines[2]
}
newContent += line + "\n"
}
if err := scanner.Err(); err != nil {
return err
}

// Write the updated content back to the file
if _, err := file.Seek(0, 0); err != nil {
return err
}
if err := file.Truncate(0); err != nil {
return err
}
if _, err := file.Write([]byte(newContent)); err != nil {
return err
}

return nil
}
3 changes: 2 additions & 1 deletion lib/cityhash102/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
// specific language governing permissions and limitations
// under the License.

/** COPY from https://github.com/zentures/cityhash/
/*
* COPY from https://github.com/zentures/cityhash/
NOTE: The code is modified to be compatible with CityHash128 used in ClickHouse
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ type (
}
BatchColumn interface {
Append(interface{}) error
AppendRow(interface{}) error
AppendRow(interface{}) error
}
ColumnType interface {
Name() string
Expand Down
Loading

0 comments on commit 1237074

Please sign in to comment.