-
Notifications
You must be signed in to change notification settings - Fork 394
/
vertexmeta.go
134 lines (123 loc) · 3.85 KB
/
vertexmeta.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package vertexmeta
import (
"encoding/base64"
"encoding/json"
"fmt"
"hash/fnv"
"regexp"
"sort"
"strings"
"github.com/earthly/earthly/ast/spec"
)
// VertexMeta is metadata associated with the vertex. This is passed from the
// converter to the solver monitor via BuildKit.
type VertexMeta struct {
SourceLocation *spec.SourceLocation `json:"sl,omitempty"`
RepoGitURL string `json:"rgu,omitempty"`
RepoGitHash string `json:"rgh,omitempty"`
RepoFileRelToRepo string `json:"rfr,omitempty"`
CommandID string `json:"cid,omitempty"`
TargetID string `json:"tid,omitempty"`
TargetName string `json:"tnm,omitempty"`
CanonicalTargetName string `json:"ctnm,omitempty"`
Platform string `json:"plt,omitempty"`
NonDefaultPlatform bool `json:"defplt,omitempty"`
Local bool `json:"lcl,omitempty"`
Interactive bool `json:"itrctv,omitempty"`
OverridingArgs map[string]string `json:"args,omitempty"`
Secrets []string `json:"secrets,omitempty"`
Internal bool `json:"itrnl,omitempty"`
Runner string `json:"runner,omitempty"`
}
var vertexRegexp = regexp.MustCompile(`(?s)^\[([^\]]*)\] (.*)$`)
// ParseFromVertexPrefix parses the vertex prefix from the given string.
func ParseFromVertexPrefix(in string) (*VertexMeta, string) {
vm := &VertexMeta{}
tail := in
if strings.HasPrefix(in, "importing cache manifest") ||
strings.HasPrefix(in, "exporting cache") {
vm.TargetName = "cache"
return vm, tail
}
match := vertexRegexp.FindStringSubmatch(in)
if len(match) < 2 {
vm.TargetName = "internal"
vm.Internal = true
return vm, tail
}
vmDt64 := match[1]
tail = match[2]
dt, err := base64.StdEncoding.DecodeString(vmDt64)
if err != nil {
// Either "context <context-name>"
// or "internal"
// or coming from Dockerfile: "<target> <step>/<total-steps>".
splits := strings.SplitN(vmDt64, " ", 2)
if len(splits) > 0 {
vm.TargetName = splits[0]
}
if vm.TargetName == "internal" {
vm.Internal = true
}
return vm, tail
}
err = json.Unmarshal(dt, vm)
if err != nil {
vm.TargetName = vmDt64
return vm, tail
}
return vm, tail
}
// ToVertexPrefix returns the vertex prefix for the given VertexMeta.
func (vm *VertexMeta) ToVertexPrefix() string {
dt, err := json.Marshal(vm)
if err != nil {
panic(err) // should never happen
}
b64Str := base64.StdEncoding.EncodeToString(dt)
return fmt.Sprintf("[%s] ", b64Str)
}
// OverridingArgsString returns the string representation of the overriding
// arguments.
func (vm *VertexMeta) OverridingArgsString() string {
if vm.OverridingArgs == nil {
return ""
}
var args []string
for k, v := range vm.OverridingArgs {
args = append(args, fmt.Sprintf("%s=%s", k, v))
}
sort.Strings(args)
return strings.Join(args, " ")
}
// SecretsString returns the string representation of the secrets. It will only
// include the names of secrets, no values.
func (vm *VertexMeta) SecretsString() string {
if len(vm.Secrets) == 0 {
return ""
}
return "secrets: " + strings.Join(vm.Secrets, " ")
}
// Salt returns a string identifying the target as uniquely as possible.
func (vm *VertexMeta) Salt() string {
if vm.TargetID != "" {
return vm.TargetID
}
var name string
switch {
case vm.TargetName != "":
name = vm.TargetName
case vm.Internal:
name = "internal"
default:
name = "unknown"
}
overridingArgsString := vm.OverridingArgsString()
if vm.Platform == "" && overridingArgsString == "" {
return name // don't hash when unmarshalling VertexMeta failed
}
h := fnv.New32a()
h.Write([]byte(vm.Platform))
h.Write([]byte(overridingArgsString))
return fmt.Sprintf("%s-%d", name, h.Sum32())
}