Skip to content
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 96 additions & 35 deletions dependency_updater/dependency_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@ import (
"context"
"encoding/json"
"fmt"
"slices"
"time"

"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/google/go-github/v72/github"
"github.com/urfave/cli/v3"
"slices"
"time"

"log"
"os"
"os/exec"
"strings"
)

type Info struct {
Tag string `json:"tag"`
Commit string `json:"commit"`
TagPrefix string `json:"tagPrefix,omitempty"`
Owner string `json:"owner`
Repo string `json:"repo`
Tag string `json:"tag"`
Commit string `json:"commit"`
TagPrefix string `json:"tagPrefix,omitempty"`
Owner string `json:"owner`
Repo string `json:"repo`
}

type VersionTag []struct {
Tag string `json:"tag_name"`
}

type Commit struct {
Commit string `json:"sha"`
type VersionUpdateInfo struct {
Repo string
From string
To string
DiffUrl string
}

type Dependencies = map[string]*Info
Expand All @@ -49,9 +50,14 @@ func main() {
Usage: "Specifies repo location to run the version updater on",
Required: true,
},
&cli.BoolFlag{
Name: "commit",
Usage: "Stages updater changes and creates commit message",
Required: false,
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
err := updater(string(cmd.String("token")), string(cmd.String("repo")))
err := updater(string(cmd.String("token")), string(cmd.String("repo")), cmd.Bool("commit"))
if err != nil {
return fmt.Errorf("error running updater: %s", err)
}
Expand All @@ -64,8 +70,10 @@ func main() {
}
}

func updater(token string, repoPath string) error {
func updater(token string, repoPath string, commit bool) error {
var err error
var dependencies Dependencies
var updatedDependencies []VersionUpdateInfo

f, err := os.ReadFile(repoPath + "/versions.json")
if err != nil {
Expand All @@ -75,27 +83,37 @@ func updater(token string, repoPath string) error {
client := github.NewClient(nil).WithAuthToken(token)
ctx := context.Background()

var dependencies Dependencies

err = json.Unmarshal(f, &dependencies)
if err != nil {
return fmt.Errorf("error unmarshaling versions JSON to dependencies: %s", err)
}

for dependency := range dependencies {
var updatedDependency VersionUpdateInfo
err := retry.Do0(context.Background(), 3, retry.Fixed(1*time.Second), func() error {
return getAndUpdateDependency(
updatedDependency, err = getAndUpdateDependency(
ctx,
client,
dependency,
repoPath,
dependencies,
)
return err
})

if err != nil {
return fmt.Errorf("error getting and updating version/commit for "+dependency+": %s", err)
}

if updatedDependency != (VersionUpdateInfo{}) {
updatedDependencies = append(updatedDependencies, updatedDependency)
}
}

if commit && updatedDependencies != nil {
err := createCommitMessage(updatedDependencies)
if err != nil {
return fmt.Errorf("error creating commit message: %s", err)
}
}

e := createVersionsEnv(repoPath, dependencies)
Expand All @@ -106,23 +124,46 @@ func updater(token string, repoPath string) error {
return nil
}

func getAndUpdateDependency(ctx context.Context, client *github.Client, dependencyType string, repoPath string, dependencies Dependencies) error {
version, commit, err := getVersionAndCommit(ctx, client, dependencies, dependencyType)
if err != nil {
return err
}
func createCommitMessage(updatedDependencies []VersionUpdateInfo) error {
var repos []string
commitTitle := "chore: updated "
commitDescription := "Updated dependencies for: \n"

e := updateVersionTagAndCommit(commit, version, dependencyType, repoPath, dependencies)
if e != nil {
return fmt.Errorf("error updating version tag and commit: %s", e)
for _, dependency := range updatedDependencies {
repo, tag := dependency.Repo, dependency.To
commitDescription += repo + " => " + tag + " (" + dependency.DiffUrl + ")" + "\n"
repos = append(repos, repo)
}

commitTitle += strings.Join(repos, ", ")
cmd := exec.Command("git", "commit", "-am", commitTitle, "-m", commitDescription)

if err := cmd.Run(); err != nil {
return fmt.Errorf("error running git commit -m: %s", err)
}
return nil
}

func getVersionAndCommit(ctx context.Context, client *github.Client, dependencies Dependencies, dependencyType string) (string, string, error) {
func getAndUpdateDependency(ctx context.Context, client *github.Client, dependencyType string, repoPath string, dependencies Dependencies) (VersionUpdateInfo, error) {
version, commit, updatedDependency, err := getVersionAndCommit(ctx, client, dependencies, dependencyType)
if err != nil {
return VersionUpdateInfo{}, err
}
if updatedDependency != (VersionUpdateInfo{}) {
e := updateVersionTagAndCommit(commit, version, dependencyType, repoPath, dependencies)
if e != nil {
return VersionUpdateInfo{}, fmt.Errorf("error updating version tag and commit: %s", e)
}
}

return updatedDependency, nil
}

func getVersionAndCommit(ctx context.Context, client *github.Client, dependencies Dependencies, dependencyType string) (string, string, VersionUpdateInfo, error) {
var version *github.RepositoryRelease
var err error
var diffUrl string
var updatedDependency VersionUpdateInfo
foundPrefixVersion := false
options := &github.ListOptions{Page: 1}

Expand All @@ -134,17 +175,25 @@ func getVersionAndCommit(ctx context.Context, client *github.Client, dependencie
options)

if err != nil {
return "", "", fmt.Errorf("error getting releases: %s", err)
return "", "", VersionUpdateInfo{}, fmt.Errorf("error getting releases: %s", err)
}

if dependencies[dependencyType].TagPrefix == "" {
version = releases[0]
if *version.TagName != dependencies[dependencyType].Tag {
diffUrl = generateGithubRepoUrl(dependencies, dependencyType) + "/compare/" +
dependencies[dependencyType].Tag + "..." + *version.TagName
}
break
} else if dependencies[dependencyType].TagPrefix != ""{
} else if dependencies[dependencyType].TagPrefix != "" {
for release := range releases {
if strings.HasPrefix(*releases[release].TagName, dependencies[dependencyType].TagPrefix) {
version = releases[release]
foundPrefixVersion = true
if *version.TagName != dependencies[dependencyType].Tag {
diffUrl = generateGithubRepoUrl(dependencies, dependencyType) + "/compare/" +
dependencies[dependencyType].Tag + "..." + *version.TagName
}
break
}
}
Expand All @@ -157,17 +206,26 @@ func getVersionAndCommit(ctx context.Context, client *github.Client, dependencie
}
}

if diffUrl != "" {
updatedDependency = VersionUpdateInfo{
dependencies[dependencyType].Repo,
dependencies[dependencyType].Tag,
*version.TagName,
diffUrl,
}
}

commit, _, err := client.Repositories.GetCommit(
ctx,
dependencies[dependencyType].Owner,
dependencies[dependencyType].Repo,
"refs/tags/"+*version.TagName,
&github.ListOptions{})
if err != nil {
return "", "", fmt.Errorf("error getting commit for "+dependencyType+": %s", err)
return "", "", VersionUpdateInfo{}, fmt.Errorf("error getting commit for "+dependencyType+": %s", err)
}

return *version.TagName, *commit.SHA, nil
return *version.TagName, *commit.SHA, updatedDependency, nil
}

func updateVersionTagAndCommit(
Expand All @@ -182,6 +240,7 @@ func updateVersionTagAndCommit(
if err != nil {
return fmt.Errorf("error writing to versions "+dependencyType+": %s", err)
}

return nil
}

Expand All @@ -204,9 +263,7 @@ func createVersionsEnv(repoPath string, dependencies Dependencies) error {
envLines := []string{}

for dependency := range dependencies {
repoUrl := "https://github.com/" +
dependencies[dependency].Owner + "/" +
dependencies[dependency].Repo + ".git"
repoUrl := generateGithubRepoUrl(dependencies, dependency) + ".git"

dependencyPrefix := strings.ToUpper(dependency)

Expand Down Expand Up @@ -235,3 +292,7 @@ func createVersionsEnv(repoPath string, dependencies Dependencies) error {

return nil
}

func generateGithubRepoUrl(dependencies Dependencies, dependencyType string) string {
return "https://github.com/" + dependencies[dependencyType].Owner + "/" + dependencies[dependencyType].Repo
}