Skip to content

Commit ffd30c4

Browse files
committed
Making the go chaincode build independent of the go fabric version
Signed-off-by: Fedor Partanskiy <fredprtnsk@gmail.com>
1 parent dd0d56d commit ffd30c4

25 files changed

Lines changed: 4862 additions & 31 deletions

File tree

core/chaincode/platforms/golang/platform.go

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"github.com/hyperledger/fabric/internal/ccmetadata"
2727
"github.com/pkg/errors"
2828
"github.com/spf13/viper"
29+
"golang.org/x/mod/modfile"
30+
"golang.org/x/mod/semver"
2931
)
3032

3133
// Platform for chaincodes written in Go
@@ -207,6 +209,7 @@ func getLDFlagsOpts() string {
207209

208210
var buildScript = `
209211
set -e
212+
%[3]s
210213
if [ -f "/chaincode/input/src/go.mod" ] && [ -d "/chaincode/input/src/vendor" ]; then
211214
cd /chaincode/input/src
212215
GO111MODULE=on go build -v -mod=vendor %[1]s -o /chaincode/output/chaincode %[2]s
@@ -225,7 +228,21 @@ fi
225228
echo Done!
226229
`
227230

228-
func (p *Platform) DockerBuildOptions(path string) (util.DockerBuildOptions, error) {
231+
func (p *Platform) DockerBuildOptions(path string, goVer, osVer string, archVer string) (util.DockerBuildOptions, error) {
232+
// determine the presence of go.mod and the version of go in go.mod (go, toolchain)
233+
var insNewGo string
234+
if newGoVer, needGo := getNeedVersionGo(path, goVer); needGo {
235+
// preparing the insert for the go update
236+
insNewGoScript := `
237+
curl -sLO https://go.dev/dl/go%[1]s.%[2]s-%[3]s.tar.gz
238+
rm -rf /usr/local/go
239+
tar -C /usr/local -xzfv "go%[1]s.%[2]s-%[3]s.tar.gz"
240+
rm "go%[1]s.%[2]s-%[3]s.tar.gz"
241+
go version
242+
`
243+
insNewGo = fmt.Sprintf(insNewGoScript, newGoVer, osVer, archVer)
244+
}
245+
229246
env := []string{}
230247
for _, key := range []string{"GOPROXY", "GOSUMDB"} {
231248
if val, ok := os.LookupEnv(key); ok {
@@ -238,11 +255,54 @@ func (p *Platform) DockerBuildOptions(path string) (util.DockerBuildOptions, err
238255
}
239256
ldFlagOpts := getLDFlagsOpts()
240257
return util.DockerBuildOptions{
241-
Cmd: fmt.Sprintf(buildScript, ldFlagOpts, path),
258+
Cmd: fmt.Sprintf(buildScript, ldFlagOpts, path, insNewGo),
242259
Env: env,
243260
}, nil
244261
}
245262

263+
func getNeedVersionGo(path string, goVersion string) (string, bool) {
264+
name := filepath.Join(path, "go.mod")
265+
_, err := os.Stat(name)
266+
if err != nil {
267+
return "", false
268+
}
269+
data, err := os.ReadFile(name)
270+
if err != nil {
271+
return "", false
272+
}
273+
274+
// get your own version of go
275+
var need bool
276+
277+
// determine the presence of go.mod and the version of go in go.mod (go, toolchain)
278+
f, err := modfile.Parse("go.mod", data, nil)
279+
if err != nil {
280+
return "", false
281+
}
282+
283+
if f.Go != nil {
284+
fGoVer := "v" + f.Go.Version
285+
if semver.Compare(goVersion, fGoVer) == -1 {
286+
goVersion = fGoVer
287+
need = true
288+
}
289+
}
290+
291+
if f.Toolchain != nil {
292+
fToolchaiVer := "v" + strings.TrimPrefix(f.Toolchain.Name, "go")
293+
if semver.Compare(goVersion, fToolchaiVer) == -1 {
294+
goVersion = fToolchaiVer
295+
need = true
296+
}
297+
}
298+
299+
if need {
300+
return strings.TrimPrefix(goVersion, "v"), true
301+
}
302+
303+
return "", false
304+
}
305+
246306
// CodeDescriptor describes the code we're packaging.
247307
type CodeDescriptor struct {
248308
Source string // absolute path of the source to package

core/chaincode/platforms/golang/platform_test.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,13 @@ func TestDockerBuildOptions(t *testing.T) {
336336
platform := &Platform{}
337337

338338
t.Run("GOPROXY and GOSUMDB not set", func(t *testing.T) {
339-
opts, err := platform.DockerBuildOptions("the-path")
339+
opts, err := platform.DockerBuildOptions("the-path", "", "", "")
340340
require.NoError(t, err, "unexpected error from DockerBuildOptions")
341341

342342
expectedOpts := util.DockerBuildOptions{
343343
Cmd: `
344344
set -e
345+
345346
if [ -f "/chaincode/input/src/go.mod" ] && [ -d "/chaincode/input/src/vendor" ]; then
346347
cd /chaincode/input/src
347348
GO111MODULE=on go build -v -mod=vendor -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode the-path
@@ -368,12 +369,13 @@ echo Done!
368369
t.Setenv("GOPROXY", "the-goproxy")
369370
t.Setenv("GOSUMDB", "the-gosumdb")
370371

371-
opts, err := platform.DockerBuildOptions("the-path")
372+
opts, err := platform.DockerBuildOptions("the-path", "", "", "")
372373
require.NoError(t, err, "unexpected error from DockerBuildOptions")
373374

374375
expectedOpts := util.DockerBuildOptions{
375376
Cmd: `
376377
set -e
378+
377379
if [ -f "/chaincode/input/src/go.mod" ] && [ -d "/chaincode/input/src/vendor" ]; then
378380
cd /chaincode/input/src
379381
GO111MODULE=on go build -v -mod=vendor -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode the-path
@@ -395,6 +397,42 @@ echo Done!
395397
}
396398
require.Equal(t, expectedOpts, opts)
397399
})
400+
401+
t.Run("Upsate version go", func(t *testing.T) {
402+
opts, err := platform.DockerBuildOptions("testdata/src/chaincodes/toolchain", "v1.25.0", "linux", "arm64")
403+
require.NoError(t, err, "unexpected error from DockerBuildOptions")
404+
405+
expectedOpts := util.DockerBuildOptions{
406+
Cmd: `
407+
set -e
408+
409+
curl -sLO https://go.dev/dl/go1.26.3.linux-arm64.tar.gz
410+
rm -rf /usr/local/go
411+
tar -C /usr/local -xzfv "go1.26.3.linux-arm64.tar.gz"
412+
rm "go1.26.3.linux-arm64.tar.gz"
413+
go version
414+
415+
if [ -f "/chaincode/input/src/go.mod" ] && [ -d "/chaincode/input/src/vendor" ]; then
416+
cd /chaincode/input/src
417+
GO111MODULE=on go build -v -mod=vendor -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode testdata/src/chaincodes/toolchain
418+
elif [ -f "/chaincode/input/src/go.mod" ]; then
419+
cd /chaincode/input/src
420+
GO111MODULE=on go build -v -mod=readonly -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode testdata/src/chaincodes/toolchain
421+
elif [ -f "/chaincode/input/src/testdata/src/chaincodes/toolchain/go.mod" ] && [ -d "/chaincode/input/src/testdata/src/chaincodes/toolchain/vendor" ]; then
422+
cd /chaincode/input/src/testdata/src/chaincodes/toolchain
423+
GO111MODULE=on go build -v -mod=vendor -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode .
424+
elif [ -f "/chaincode/input/src/testdata/src/chaincodes/toolchain/go.mod" ]; then
425+
cd /chaincode/input/src/testdata/src/chaincodes/toolchain
426+
GO111MODULE=on go build -v -mod=readonly -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode .
427+
else
428+
GO111MODULE=off GOPATH=/chaincode/input:$GOPATH go build -v -ldflags "-linkmode external -extldflags '-static'" -o /chaincode/output/chaincode testdata/src/chaincodes/toolchain
429+
fi
430+
echo Done!
431+
`,
432+
Env: []string{"GOPROXY=https://proxy.golang.org"},
433+
}
434+
require.Equal(t, expectedOpts, opts)
435+
})
398436
}
399437

400438
func TestDescribeCode(t *testing.T) {
@@ -456,3 +494,17 @@ func TestMain(m *testing.M) {
456494
}
457495
os.Exit(m.Run())
458496
}
497+
498+
func TestNeedVersionGo(t *testing.T) {
499+
newGoVer, need := getNeedVersionGo("testdata/src/chaincodes/noop", "v1.26.3")
500+
require.Equal(t, newGoVer, "")
501+
require.False(t, need)
502+
503+
newGoVer, need = getNeedVersionGo("testdata/src/chaincodes/noop", "v1.12.0")
504+
require.Equal(t, newGoVer, "1.13")
505+
require.True(t, need)
506+
507+
newGoVer, need = getNeedVersionGo("testdata/src/chaincodes/toolchain", "v1.25.0")
508+
require.Equal(t, newGoVer, "1.26.3")
509+
require.True(t, need)
510+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package main
8+
9+
func main() {
10+
// Empty shell with no dependencies
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module github.com/hyperledger/fabric/core/chaincode/platforms/golang/testdata/src/chaincodes/toolchain
2+
3+
go 1.25.10
4+
5+
toolchain go1.26.3
6+
7+
// This should not get included in packages that were created from a GOPATH

core/chaincode/platforms/golang/testdata/src/chaincodes/toolchain/go.sum

Whitespace-only changes.

core/chaincode/platforms/java/platform.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (p *Platform) GenerateDockerfile() (string, error) {
129129
return dockerFileContents, nil
130130
}
131131

132-
func (p *Platform) DockerBuildOptions(path string) (util.DockerBuildOptions, error) {
132+
func (p *Platform) DockerBuildOptions(string, string, string, string) (util.DockerBuildOptions, error) {
133133
return util.DockerBuildOptions{
134134
Image: util.GetDockerImageFromConfig("chaincode.java.runtime"),
135135
Cmd: "./build.sh",

core/chaincode/platforms/java/platform_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func TestGenerateDockerfile(t *testing.T) {
161161
func TestDockerBuildOptions(t *testing.T) {
162162
platform := java.Platform{}
163163

164-
opts, err := platform.DockerBuildOptions("path")
164+
opts, err := platform.DockerBuildOptions("path", "", "", "")
165165
require.NoError(t, err, "unexpected error from DockerBuildOptions")
166166

167167
expectedOpts := util.DockerBuildOptions{

core/chaincode/platforms/mock/platform.go

Lines changed: 25 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/chaincode/platforms/node/platform.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ else
182182
fi
183183
`
184184

185-
func (p *Platform) DockerBuildOptions(path string) (util.DockerBuildOptions, error) {
185+
func (p *Platform) DockerBuildOptions(string, string, string, string) (util.DockerBuildOptions, error) {
186186
return util.DockerBuildOptions{
187187
Image: util.GetDockerImageFromConfig("chaincode.node.runtime"),
188188
Cmd: buildScript,

core/chaincode/platforms/node/platform_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ fi
140140
`
141141

142142
func TestGenerateBuildOptions(t *testing.T) {
143-
opts, err := platform.DockerBuildOptions("pathname")
143+
opts, err := platform.DockerBuildOptions("pathname", "", "", "")
144144
require.NoError(t, err)
145145

146146
expectedOpts := util.DockerBuildOptions{

0 commit comments

Comments
 (0)