Skip to content

Commit b10fc7a

Browse files
Automate Node Upgrade Process: Update Script (#478)
* Automate Updates Script * add versions.env * delete dependency_updater * dependency updater script updates * Add retries/fix commit hash * Single client * Sorted env file * Fix dockerfile --------- Co-authored-by: Danyal Prout <git@dany.al>
1 parent cfd8eca commit b10fc7a

File tree

7 files changed

+320
-17
lines changed

7 files changed

+320
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
/geth-data/
33
/reth-data/
44
/nethermind-data/
5+
/dependency_updater/dependency_updater
56
.DS_Store
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"github.com/ethereum-optimism/optimism/op-service/retry"
8+
"github.com/google/go-github/v72/github"
9+
"github.com/urfave/cli/v3"
10+
"slices"
11+
"time"
12+
13+
"log"
14+
"os"
15+
"strings"
16+
)
17+
18+
type Info struct {
19+
RepoUrl string `json:"repoUrl"`
20+
Tag string `json:"tag"`
21+
Commit string `json:"commit"`
22+
CommitUrl string `json:"commitUrl"`
23+
VersionUrl string `json:"versionUrl"`
24+
TagPrefix string `json:"tagPrefix,omitempty"`
25+
Owner string `json:"owner`
26+
Repo string `json:"repo`
27+
}
28+
29+
type VersionTag []struct {
30+
Tag string `json:"tag_name"`
31+
}
32+
33+
type Commit struct {
34+
Commit string `json:"sha"`
35+
}
36+
37+
type Dependencies = map[string]*Info
38+
39+
func main() {
40+
cmd := &cli.Command{
41+
Name: "updater",
42+
Usage: "Updates the dependencies in the geth, nethermind and reth Dockerfiles",
43+
Flags: []cli.Flag{
44+
&cli.StringFlag{
45+
Name: "token",
46+
Usage: "Auth token used to make requests to the Github API must be set using export",
47+
Sources: cli.EnvVars("GITHUB_TOKEN"),
48+
Required: true,
49+
},
50+
&cli.StringFlag{
51+
Name: "repo",
52+
Usage: "Specifies repo location to run the version updater on",
53+
Required: true,
54+
},
55+
},
56+
Action: func(ctx context.Context, cmd *cli.Command) error {
57+
err := updater(string(cmd.String("token")), string(cmd.String("repo")))
58+
if err != nil {
59+
return fmt.Errorf("error running updater: %s", err)
60+
}
61+
return nil
62+
},
63+
}
64+
65+
if err := cmd.Run(context.Background(), os.Args); err != nil {
66+
log.Fatal(err)
67+
}
68+
}
69+
70+
func updater(token string, repoPath string) error {
71+
var err error
72+
73+
f, err := os.ReadFile(repoPath + "/versions.json")
74+
if err != nil {
75+
return fmt.Errorf("error reading versions JSON: %s", err)
76+
}
77+
78+
client := github.NewClient(nil).WithAuthToken(token)
79+
ctx := context.Background()
80+
81+
var dependencies Dependencies
82+
83+
err = json.Unmarshal(f, &dependencies)
84+
if err != nil {
85+
return fmt.Errorf("error unmarshaling versions JSON to dependencies: %s", err)
86+
}
87+
88+
for dependency := range dependencies {
89+
err := retry.Do0(context.Background(), 3, retry.Fixed(1*time.Second), func() error {
90+
return getAndUpdateDependency(
91+
ctx,
92+
client,
93+
dependency,
94+
repoPath,
95+
dependencies,
96+
)
97+
})
98+
99+
if err != nil {
100+
return fmt.Errorf("error getting and updating version/commit for "+dependency+": %s", err)
101+
}
102+
}
103+
104+
e := createVersionsEnv(repoPath, dependencies)
105+
if e != nil {
106+
return fmt.Errorf("error creating versions.env: %s", e)
107+
}
108+
109+
return nil
110+
}
111+
112+
func getAndUpdateDependency(ctx context.Context, client *github.Client, dependencyType string, repoPath string, dependencies Dependencies) error {
113+
version, commit, err := getVersionAndCommit(ctx, client, dependencies, dependencyType)
114+
if err != nil {
115+
return err
116+
}
117+
118+
e := updateVersionTagAndCommit(commit, version, dependencyType, repoPath, dependencies)
119+
if e != nil {
120+
return fmt.Errorf("error updating version tag and commit: %s", e)
121+
}
122+
123+
return nil
124+
}
125+
126+
func getVersionAndCommit(ctx context.Context, client *github.Client, dependencies Dependencies, dependencyType string) (string, string, error) {
127+
128+
var version *github.RepositoryRelease
129+
var err error
130+
// handle dependencies with prefix
131+
releases, _, err := client.Repositories.ListReleases(
132+
ctx,
133+
dependencies[dependencyType].Owner,
134+
dependencies[dependencyType].Repo,
135+
nil)
136+
137+
if err != nil {
138+
return "", "", fmt.Errorf("error getting releases: %s", err)
139+
}
140+
141+
if dependencies[dependencyType].TagPrefix == "" {
142+
version = releases[0]
143+
} else {
144+
for release := range releases {
145+
if strings.HasPrefix(*releases[release].TagName, dependencies[dependencyType].TagPrefix) {
146+
version = releases[release]
147+
break
148+
}
149+
}
150+
}
151+
152+
commit, _, err := client.Repositories.GetCommit(
153+
ctx,
154+
dependencies[dependencyType].Owner,
155+
dependencies[dependencyType].Repo,
156+
"refs/tags/"+*version.TagName,
157+
&github.ListOptions{})
158+
if err != nil {
159+
return "", "", fmt.Errorf("error getting commit for "+dependencyType+": %s", err)
160+
}
161+
162+
return *version.TagName, *commit.SHA, nil
163+
}
164+
165+
func updateVersionTagAndCommit(
166+
commit string,
167+
tag string,
168+
dependencyType string,
169+
repoPath string,
170+
dependencies Dependencies) error {
171+
dependencies[dependencyType].Tag = tag
172+
dependencies[dependencyType].Commit = commit
173+
err := writeToVersionsEnv(repoPath, dependencies)
174+
if err != nil {
175+
return fmt.Errorf("error writing to versions "+dependencyType+": %s", err)
176+
}
177+
return nil
178+
}
179+
180+
func writeToVersionsEnv(repoPath string, dependencies Dependencies) error {
181+
// formatting json
182+
updatedJson, err := json.MarshalIndent(dependencies, "", " ")
183+
if err != nil {
184+
return fmt.Errorf("error Marshaling dependencies json: %s", err)
185+
}
186+
187+
e := os.WriteFile(repoPath+"/versions.json", updatedJson, 0644)
188+
if e != nil {
189+
return fmt.Errorf("error writing to versions.json: %s", e)
190+
}
191+
192+
return nil
193+
}
194+
195+
func createVersionsEnv(repoPath string, dependencies Dependencies) error {
196+
envLines := []string{}
197+
198+
for dependency := range dependencies {
199+
dependencyPrefix := strings.ToUpper(dependency)
200+
201+
envLines = append(envLines, fmt.Sprintf("export %s_%s=%s",
202+
dependencyPrefix, "TAG", dependencies[dependency].Tag))
203+
204+
envLines = append(envLines, fmt.Sprintf("export %s_%s=%s",
205+
dependencyPrefix, "COMMIT", dependencies[dependency].Commit))
206+
207+
envLines = append(envLines, fmt.Sprintf("export %s_%s=%s",
208+
dependencyPrefix, "REPO", dependencies[dependency].RepoUrl))
209+
}
210+
211+
slices.Sort(envLines)
212+
213+
file, err := os.Create(repoPath + "/versions.env")
214+
if err != nil {
215+
return fmt.Errorf("error creating versions.env file: %s", err)
216+
}
217+
defer file.Close()
218+
219+
_, err = file.WriteString(strings.Join(envLines, "\n"))
220+
if err != nil {
221+
return fmt.Errorf("error writing to versions.env file: %s", err)
222+
}
223+
224+
return nil
225+
}

dependency_updater/go.mod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module dependency_updater
2+
3+
go 1.24.3
4+
5+
require (
6+
github.com/ethereum-optimism/optimism v1.13.3
7+
github.com/google/go-github/v72 v72.0.0
8+
github.com/urfave/cli/v3 v3.3.8
9+
)
10+
11+
require github.com/google/go-querystring v1.1.0 // indirect

dependency_updater/go.sum

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
2+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/ethereum-optimism/optimism v1.13.3 h1:rfPx7OembMnoEASU1ozA/Foa7Am7UA+h0SB+OUrxn7s=
4+
github.com/ethereum-optimism/optimism v1.13.3/go.mod h1:WrVFtk3cP45tvHs7MARn9KGQu35XIoXo/IOWU6K/rzk=
5+
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
6+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
7+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
8+
github.com/google/go-github/v72 v72.0.0 h1:FcIO37BLoVPBO9igQQ6tStsv2asG4IPcYFi655PPvBM=
9+
github.com/google/go-github/v72 v72.0.0/go.mod h1:WWtw8GMRiL62mvIquf1kO3onRHeWWKmK01qdCY8c5fg=
10+
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
11+
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
12+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
13+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
14+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
15+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
16+
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
17+
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
18+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
19+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
20+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module dependency_updater
2+
3+
go 1.24.3

versions.env

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
export OP_NODE_TAG=op-node/v1.13.3
2-
export OP_NODE_COMMIT=b1e7c63bb2ffea46771c302bcb05f72ba1a7bf61
3-
export OP_NODE_REPO=https://github.com/ethereum-optimism/optimism.git
4-
5-
export OP_GETH_TAG=v1.101511.0
1+
export BASE_RETH_NODE_COMMIT=7fe1d4e7c74d322d2cf78df55db40e14f466cfc6
2+
export BASE_RETH_NODE_REPO=https://github.com/base/node-reth.git
3+
export BASE_RETH_NODE_TAG=v0.1.2
4+
export NETHERMIND_COMMIT=2be1890ee4f21f921a471de058dcb57937bd9b90
5+
export NETHERMIND_REPO=https://github.com/NethermindEth/nethermind.git
6+
export NETHERMIND_TAG=1.31.11
67
export OP_GETH_COMMIT=68075997f33907401a93216aa426514c5ddc8870
78
export OP_GETH_REPO=https://github.com/ethereum-optimism/op-geth.git
8-
9-
export OP_RETH_TAG=v1.4.3
10-
export OP_RETH_COMMIT=fe3653ffe602d4e85ad213e8bd9f06e7b710c0c5
9+
export OP_GETH_TAG=v1.101511.0
10+
export OP_NODE_COMMIT=b1e7c63bb2ffea46771c302bcb05f72ba1a7bf61
11+
export OP_NODE_REPO=https://github.com/ethereum-optimism/optimism.git
12+
export OP_NODE_TAG=op-node/v1.13.3
13+
export OP_RETH_COMMIT=127595e23079de2c494048d0821ea1f1107eb624
1114
export OP_RETH_REPO=https://github.com/paradigmxyz/reth.git
12-
13-
export NETHERMIND_TAG=1.31.11
14-
export NETHERMIND_COMMIT=2be1890ee4f21f921a471de058dcb57937bd9b90
15-
export NETHERMIND_REPO=https://github.com/NethermindEth/nethermind.git
16-
17-
export BASE_RETH_NODE_TAG=v0.1.2
18-
export BASE_RETH_NODE_COMMIT=7fe1d4e7c74d322d2cf78df55db40e14f466cfc6
19-
export BASE_RETH_NODE_REPO=https://github.com/base/node-reth.git
20-
15+
export OP_RETH_TAG=v1.4.8

versions.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"base_reth_node": {
3+
"repoUrl": "https://github.com/base/node-reth.git",
4+
"tag": "v0.1.2",
5+
"commit": "7fe1d4e7c74d322d2cf78df55db40e14f466cfc6",
6+
"commitUrl": "https://api.github.com/repos/base/node-reth/commits/",
7+
"versionUrl": "https://api.github.com/repos/base/node-reth/releases",
8+
"Owner": "base",
9+
"Repo": "node-reth"
10+
},
11+
"nethermind": {
12+
"repoUrl": "https://github.com/NethermindEth/nethermind.git",
13+
"tag": "1.31.11",
14+
"commit": "2be1890ee4f21f921a471de058dcb57937bd9b90",
15+
"commitUrl": "https://api.github.com/repos/NethermindEth/nethermind/commits/",
16+
"versionUrl": "https://api.github.com/repos/NethermindEth/nethermind/releases",
17+
"Owner": "NethermindEth",
18+
"Repo": "nethermind"
19+
},
20+
"op_geth": {
21+
"repoUrl": "https://github.com/ethereum-optimism/op-geth.git",
22+
"tag": "v1.101511.0",
23+
"commit": "68075997f33907401a93216aa426514c5ddc8870",
24+
"commitUrl": "https://api.github.com/repos/ethereum-optimism/op-geth/commits/",
25+
"versionUrl": "https://api.github.com/repos/ethereum-optimism/op-geth/releases",
26+
"Owner": "ethereum-optimism",
27+
"Repo": "op-geth"
28+
},
29+
"op_node": {
30+
"repoUrl": "https://github.com/ethereum-optimism/optimism.git",
31+
"tag": "op-node/v1.13.3",
32+
"commit": "b1e7c63bb2ffea46771c302bcb05f72ba1a7bf61",
33+
"commitUrl": "https://api.github.com/repos/ethereum-optimism/optimism/commits/",
34+
"versionUrl": "https://api.github.com/repos/ethereum-optimism/optimism/releases",
35+
"tagPrefix": "op-node",
36+
"Owner": "ethereum-optimism",
37+
"Repo": "optimism"
38+
},
39+
"op_reth": {
40+
"repoUrl": "https://github.com/paradigmxyz/reth.git",
41+
"tag": "v1.4.8",
42+
"commit": "127595e23079de2c494048d0821ea1f1107eb624",
43+
"commitUrl": "https://api.github.com/repos/paradigmxyz/reth/commits/",
44+
"versionUrl": "https://api.github.com/repos/paradigmxyz/reth/releases",
45+
"Owner": "paradigmxyz",
46+
"Repo": "reth"
47+
}
48+
}

0 commit comments

Comments
 (0)