158 lines
4.2 KiB
Go
158 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"context"
|
|
_ "embed"
|
|
"encoding/base64"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/google/go-github/v62/github"
|
|
"github.com/supabase/cli/internal/utils"
|
|
"github.com/supabase/cli/pkg/fetcher"
|
|
"github.com/supabase/cli/tools/shared"
|
|
)
|
|
|
|
const (
|
|
SUPABASE_OWNER = "supabase"
|
|
HOMEBREW_REPO = "homebrew-tap"
|
|
SCOOP_REPO = "scoop-bucket"
|
|
)
|
|
|
|
var (
|
|
//go:embed templates/supabase.rb
|
|
brewFormula string
|
|
brewFormulaTemplate = template.Must(template.New(HOMEBREW_REPO).Parse(brewFormula))
|
|
//go:embed templates/supabase.json
|
|
scoopBucket string
|
|
scoopBucketTemplate = template.Must(template.New(SCOOP_REPO).Parse(scoopBucket))
|
|
)
|
|
|
|
func main() {
|
|
beta := flag.Bool("beta", false, "Updates the beta release channel.")
|
|
flag.Parse()
|
|
|
|
semver := flag.Arg(0)
|
|
if len(semver) == 0 {
|
|
log.Fatalln("Missing required arg: version")
|
|
} else if semver[0] == 'v' {
|
|
semver = semver[1:]
|
|
}
|
|
|
|
ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
|
|
if err := publishPackages(ctx, semver, *beta); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
}
|
|
|
|
func publishPackages(ctx context.Context, version string, beta bool) error {
|
|
config, err := fetchConfig(ctx, version)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config.FormulaName = "Supabase"
|
|
config.Description = "Supabase CLI"
|
|
filename := "supabase"
|
|
if beta {
|
|
config.FormulaName += "Beta"
|
|
config.Description += " (Beta)"
|
|
filename += "-beta"
|
|
}
|
|
client := utils.GetGitHubClient(ctx)
|
|
if err := updatePackage(ctx, client, HOMEBREW_REPO, filename+".rb", brewFormulaTemplate, config); err != nil {
|
|
return err
|
|
}
|
|
return updatePackage(ctx, client, SCOOP_REPO, filename+".json", scoopBucketTemplate, config)
|
|
}
|
|
|
|
type PackageConfig struct {
|
|
Version string
|
|
Checksum map[string]string
|
|
Description string
|
|
FormulaName string
|
|
}
|
|
|
|
func fetchConfig(ctx context.Context, version string) (PackageConfig, error) {
|
|
client := fetcher.NewFetcher("https://github.com", fetcher.WithExpectedStatus(http.StatusOK))
|
|
checkPath := fmt.Sprintf("/%s/%s/releases/download/v%[3]s/supabase_%[3]s_checksums.txt",
|
|
utils.CLI_OWNER,
|
|
utils.CLI_REPO,
|
|
version,
|
|
)
|
|
log.Println("Downloading checksum:", checkPath)
|
|
config := PackageConfig{Version: version}
|
|
resp, err := client.Send(ctx, http.MethodGet, checkPath, nil)
|
|
if err != nil {
|
|
return config, err
|
|
}
|
|
defer resp.Body.Close()
|
|
// Read checksums into map: filename -> sha256
|
|
config.Checksum = make(map[string]string)
|
|
scanner := bufio.NewScanner(resp.Body)
|
|
for scanner.Scan() {
|
|
tokens := strings.Fields(scanner.Text())
|
|
key := strings.TrimSuffix(tokens[1], ".tar.gz")
|
|
config.Checksum[key] = tokens[0]
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return config, err
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func updatePackage(ctx context.Context, client *github.Client, repo, path string, tmpl *template.Template, config PackageConfig) error {
|
|
fmt.Fprintf(os.Stderr, "Updating %s: %s\n", repo, path)
|
|
// Render formula from template
|
|
var buf bytes.Buffer
|
|
if err := tmpl.Option("missingkey=error").Execute(&buf, config); err != nil {
|
|
return err
|
|
}
|
|
branch := "release/cli"
|
|
master := "main"
|
|
if err := shared.CreateGitBranch(ctx, client, SUPABASE_OWNER, repo, branch, master); err != nil {
|
|
return err
|
|
}
|
|
// Get file SHA
|
|
opts := github.RepositoryContentGetOptions{Ref: "heads/" + branch}
|
|
file, _, _, err := client.Repositories.GetContents(ctx, SUPABASE_OWNER, repo, path, &opts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
content, err := base64.StdEncoding.DecodeString(*file.Content)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if bytes.Equal(content, buf.Bytes()) {
|
|
fmt.Fprintln(os.Stderr, "All versions are up to date.")
|
|
return nil
|
|
}
|
|
// Update file content
|
|
message := "Release " + config.Description
|
|
commit := github.RepositoryContentFileOptions{
|
|
Message: &message,
|
|
Content: buf.Bytes(),
|
|
SHA: file.SHA,
|
|
Branch: &branch,
|
|
}
|
|
resp, _, err := client.Repositories.UpdateFile(ctx, SUPABASE_OWNER, repo, path, &commit)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(os.Stderr, "Committed changes to", *resp.Commit.SHA)
|
|
// Create pull request
|
|
pr := github.NewPullRequest{
|
|
Title: &message,
|
|
Head: &branch,
|
|
Base: &master,
|
|
}
|
|
return shared.CreatePullRequest(ctx, client, SUPABASE_OWNER, repo, pr)
|
|
}
|