Repository: openllb/hlb
Pull request #121 (2020-04-24 00:57:05)

use consistent local unique id for consistent local sha


Patch:
diff --git a/codegen/chain.go b/codegen/chain.go
index 439b9ab..ee9343f 100644
--- a/codegen/chain.go
+++ b/codegen/chain.go
@@ -184,7 +184,7 @@ func (cg *CodeGen) EmitFilesystemBuiltinChainStmt(ctx context.Context, scope *pa
 			opts = append(opts, opt)
 		}
 
-		id, err := cg.LocalID(path, opts...)
+		id, err := cg.LocalID(ctx, path, opts...)
 		if err != nil {
 			return fc, err
 		}
diff --git a/codegen/codegen.go b/codegen/codegen.go
index fecf537..f59a743 100644
--- a/codegen/codegen.go
+++ b/codegen/codegen.go
@@ -30,6 +30,7 @@ import (
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/openllb/hlb/checker"
+	"github.com/openllb/hlb/local"
 	"github.com/openllb/hlb/parser"
 	"github.com/openllb/hlb/sockprovider"
 	"github.com/openllb/hlb/solver"
@@ -1478,8 +1479,12 @@ func (cg *CodeGen) EmitMountOptions(ctx context.Context, scope *parser.Scope, op
 
 // Get a consistent hash for this local (path + options) so we don't transport
 // the same content multiple times when referenced repeatedly.
-func (cg *CodeGen) LocalID(path string, opts ...llb.LocalOption) (string, error) {
-	opts = append(opts, llb.SessionID(cg.SessionID()))
+func (cg *CodeGen) LocalID(ctx context.Context, path string, opts ...llb.LocalOption) (string, error) {
+	uniqID, err := localUniqueID(ctx)
+	if err != nil {
+		return "", err
+	}
+	opts = append(opts, llb.LocalUniqueID(uniqID))
 	st := llb.Local(path, opts...)
 
 	def, err := st.Marshal(context.Background())
@@ -1494,6 +1499,37 @@ func (cg *CodeGen) LocalID(path string, opts ...llb.LocalOption) (string, error)
 	return digest.FromBytes(def.Def[len(def.Def)-1]).String(), nil
 }
 
+// returns a consistent string that is unique per host + cwd
+func localUniqueID(ctx context.Context) (string, error) {
+	wd, err := local.Cwd(ctx)
+	if err != nil {
+		return "", err
+	}
+	mac, err := firstUpMacAddr()
+	if err != nil {
+		return "", err
+	}
+	return fmt.Sprintf("cwd:%s,mac:%s", wd, mac), nil
+}
+
+// return the mac address for the first "UP" network interface
+func firstUpMacAddr() (string, error) {
+	interfaces, err := net.Interfaces()
+	if err != nil {
+		return "", err
+	}
+	for _, iface := range interfaces {
+		if iface.Flags&net.FlagUp == 0 {
+			continue // not up
+		}
+		if iface.HardwareAddr.String() == "" {
+			continue // no mac
+		}
+		return iface.HardwareAddr.String(), nil
+	}
+	return "no-valid-interface", nil
+}
+
 func SecretID(path string) string {
 	return digest.FromString(path).String()
 }


Test patch:
diff --git a/codegen/codegen_test.go b/codegen/codegen_test.go
index aae4e04..42c4d38 100644
--- a/codegen/codegen_test.go
+++ b/codegen/codegen_test.go
@@ -41,6 +41,7 @@ func cleanup(value string) string {
 }
 
 func TestCodeGen(t *testing.T) {
+	ctx := context.Background()
 	for _, tc := range []testCase{{
 		"image",
 		[]string{"default"},
@@ -76,7 +77,7 @@ func TestCodeGen(t *testing.T) {
 		}
 		`,
 		func(t *testing.T, cg *CodeGen) solver.Request {
-			id, err := cg.LocalID(".")
+			id, err := cg.LocalID(ctx, ".")
 			require.NoError(t, err)
 
 			return Expect(t, llb.Local(id, llb.SessionID(cg.SessionID()), llb.SharedKeyHint(".")))
@@ -334,7 +335,7 @@ func TestCodeGen(t *testing.T) {
 		}
 		`,
 		func(t *testing.T, cg *CodeGen) solver.Request {
-			id, err := cg.LocalID(".")
+			id, err := cg.LocalID(ctx, ".")
 			require.NoError(t, err)
 			sid := SecretID("codegen_test.go")