Skip to content

Commit 61ad59f

Browse files
committed
git: add opt-in command tracing
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent eaa4de0 commit 61ad59f

File tree

13 files changed

+309
-14
lines changed

13 files changed

+309
-14
lines changed

client/llb/git_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ func TestGit(t *testing.T) {
6969
"git.fullurl": "https://github.com/foo/bar.git",
7070
},
7171
},
72+
{
73+
name: "debug commands",
74+
st: Git("github.com/foo/bar.git", "ref", GitDebugCommands()),
75+
identifier: "git://github.com/foo/bar.git#ref",
76+
attrs: map[string]string{
77+
"git.authheadersecret": "GIT_AUTH_HEADER",
78+
"git.authtokensecret": "GIT_AUTH_TOKEN",
79+
"git.debugcommands": "true",
80+
"git.fullurl": "https://github.com/foo/bar.git",
81+
},
82+
},
7283
}
7384

7485
for _, tc := range tcases {

client/llb/source.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,11 +470,14 @@ func Git(url, fragment string, opts ...GitOption) State {
470470
attrs[pb.AttrGitChecksum] = checksum
471471
addCap(&gi.Constraints, pb.CapSourceGitChecksum)
472472
}
473-
474473
if gi.SkipSubmodules {
475474
attrs[pb.AttrGitSkipSubmodules] = "true"
476475
addCap(&gi.Constraints, pb.CapSourceGitSkipSubmodules)
477476
}
477+
if gi.DebugCommands {
478+
attrs[pb.AttrGitDebugCommands] = "true"
479+
addCap(&gi.Constraints, pb.CapSourceGitDebugCommands)
480+
}
478481

479482
addCap(&gi.Constraints, pb.CapSourceGit)
480483

@@ -503,6 +506,7 @@ type GitInfo struct {
503506
Ref string
504507
SubDir string
505508
SkipSubmodules bool
509+
DebugCommands bool
506510
}
507511

508512
func GitRef(v string) GitOption {
@@ -529,6 +533,12 @@ func KeepGitDir() GitOption {
529533
})
530534
}
531535

536+
func GitDebugCommands() GitOption {
537+
return gitOptionFunc(func(gi *GitInfo) {
538+
gi.DebugCommands = true
539+
})
540+
}
541+
532542
func AuthTokenSecret(v string) GitOption {
533543
return gitOptionFunc(func(gi *GitInfo) {
534544
gi.AuthTokenSecret = v

frontend/dockerui/build_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package dockerui
22

33
import (
4+
"context"
45
"testing"
56

67
"github.com/containerd/platforms"
8+
"github.com/moby/buildkit/client/llb"
79
"github.com/moby/buildkit/exporter/containerimage/exptypes"
10+
"github.com/moby/buildkit/solver/pb"
11+
digest "github.com/opencontainers/go-digest"
812
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
913
"github.com/stretchr/testify/require"
1014
)
@@ -98,3 +102,65 @@ func TestNormalizePlatform(t *testing.T) {
98102
require.Equal(t, platforms.FormatAll(platforms.Normalize(tc.p)), tc.expected.ID)
99103
}
100104
}
105+
106+
func TestDetectGitContextForwardsDebugCommands(t *testing.T) {
107+
t.Parallel()
108+
109+
enabled := true
110+
st, ok, err := DetectGitContext("https://github.com/docker/buildx.git?ref=refs/pull/3732/merge", nil, &enabled)
111+
require.True(t, ok)
112+
require.NoError(t, err)
113+
114+
g := marshalGitContext(t, st)
115+
require.Equal(t, "git://github.com/docker/buildx.git#refs/pull/3732/merge", g.Identifier)
116+
require.Equal(t, map[string]string{
117+
"git.authheadersecret": "GIT_AUTH_HEADER",
118+
"git.authtokensecret": "GIT_AUTH_TOKEN",
119+
"git.debugcommands": "true",
120+
"git.fullurl": "https://github.com/docker/buildx.git",
121+
}, g.Attrs)
122+
}
123+
124+
func marshalGitContext(t *testing.T, st *llb.State) *pb.SourceOp {
125+
t.Helper()
126+
127+
def, err := st.Marshal(context.TODO())
128+
require.NoError(t, err)
129+
130+
m, arr := parseDef(t, def.Def)
131+
require.Equal(t, 2, len(arr))
132+
133+
dgst, idx := last(t, arr)
134+
require.Equal(t, 0, idx)
135+
require.Equal(t, m[dgst], arr[0])
136+
137+
return arr[0].Op.(*pb.Op_Source).Source
138+
}
139+
140+
func parseDef(t *testing.T, def [][]byte) (map[string]*pb.Op, []*pb.Op) {
141+
t.Helper()
142+
143+
m := map[string]*pb.Op{}
144+
arr := make([]*pb.Op, 0, len(def))
145+
146+
for _, dt := range def {
147+
var op pb.Op
148+
err := op.Unmarshal(dt)
149+
require.NoError(t, err)
150+
dgst := digest.FromBytes(dt)
151+
m[string(dgst)] = &op
152+
arr = append(arr, &op)
153+
}
154+
155+
return m, arr
156+
}
157+
158+
func last(t *testing.T, arr []*pb.Op) (string, int) {
159+
t.Helper()
160+
161+
require.Greater(t, len(arr), 1)
162+
163+
op := arr[len(arr)-1]
164+
require.Equal(t, 1, len(op.Inputs))
165+
return op.Inputs[0].Digest, int(op.Inputs[0].Index)
166+
}

frontend/dockerui/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const (
5151
keyHostnameArg = "build-arg:BUILDKIT_SANDBOX_HOSTNAME"
5252
keyDockerfileLintArg = "build-arg:BUILDKIT_DOCKERFILE_CHECK"
5353
keyContextKeepGitDirArg = "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR"
54+
keyDebugGitCommandsArg = "build-arg:BUILDKIT_DEBUG_GIT_COMMANDS"
5455
keySourceDateEpoch = "build-arg:SOURCE_DATE_EPOCH"
5556
)
5657

frontend/dockerui/context.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ func (bc *Client) initContext(ctx context.Context) (*buildContext, error) {
7373
if v, err := strconv.ParseBool(opts[keyContextKeepGitDirArg]); err == nil {
7474
keepGit = &v
7575
}
76-
if st, ok, err := DetectGitContext(opts[localNameContext], keepGit); ok {
76+
var debugGitCommands *bool
77+
if v, err := strconv.ParseBool(opts[keyDebugGitCommandsArg]); err == nil {
78+
debugGitCommands = &v
79+
}
80+
if st, ok, err := DetectGitContext(opts[localNameContext], keepGit, debugGitCommands); ok {
7781
if err != nil {
7882
return nil, err
7983
}
@@ -143,7 +147,7 @@ func (bc *Client) initContext(ctx context.Context) (*buildContext, error) {
143147
return bctx, nil
144148
}
145149

146-
func DetectGitContext(ref string, keepGit *bool) (*llb.State, bool, error) {
150+
func DetectGitContext(ref string, keepGit *bool, debugGitCommands *bool) (*llb.State, bool, error) {
147151
g, isGit, err := dfgitutil.ParseGitRef(ref)
148152
if err != nil {
149153
return nil, isGit, err
@@ -158,6 +162,9 @@ func DetectGitContext(ref string, keepGit *bool) (*llb.State, bool, error) {
158162
if keepGit != nil && *keepGit {
159163
gitOpts = append(gitOpts, llb.KeepGitDir())
160164
}
165+
if debugGitCommands != nil && *debugGitCommands {
166+
gitOpts = append(gitOpts, llb.GitDebugCommands())
167+
}
161168
if g.SubDir != "" {
162169
gitOpts = append(gitOpts, llb.GitSubDir(g.SubDir))
163170
}

frontend/dockerui/namedcontext.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (nc *NamedContext) load(ctx context.Context, count int) (*llb.State, *docke
141141
}
142142
return &st, &img, nil
143143
case "git":
144-
st, ok, err := DetectGitContext(nc.input, nil)
144+
st, ok, err := DetectGitContext(nc.input, nil, nil)
145145
if !ok {
146146
return nil, nil, errors.Errorf("invalid git context %s", nc.input)
147147
}
@@ -150,7 +150,7 @@ func (nc *NamedContext) load(ctx context.Context, count int) (*llb.State, *docke
150150
}
151151
return st, nil, nil
152152
case "http", "https":
153-
st, ok, err := DetectGitContext(nc.input, nil)
153+
st, ok, err := DetectGitContext(nc.input, nil, nil)
154154
if !ok {
155155
httpst := llb.HTTP(nc.input, llb.WithCustomName("[context "+nc.nameWithPlatform+"] "+nc.input))
156156
st = &httpst

solver/pb/attr.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const AttrKnownSSHHosts = "git.knownsshhosts"
88
const AttrMountSSHSock = "git.mountsshsock"
99
const AttrGitChecksum = "git.checksum"
1010
const AttrGitSkipSubmodules = "git.skipsubmodules"
11+
const AttrGitDebugCommands = "git.debugcommands"
1112

1213
const AttrGitSignatureVerifyPubKey = "git.sig.pubkey"
1314
const AttrGitSignatureVerifyRejectExpired = "git.sig.rejectexpired"

solver/pb/caps.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const (
3333
CapSourceGitSubdir apicaps.CapID = "source.git.subdir"
3434
CapSourceGitChecksum apicaps.CapID = "source.git.checksum"
3535
CapSourceGitSkipSubmodules apicaps.CapID = "source.git.skipsubmodules"
36+
CapSourceGitDebugCommands apicaps.CapID = "source.git.debugcommands"
3637
CapSourceGitSignatureVerify apicaps.CapID = "source.git.signatureverify"
3738

3839
CapSourceHTTP apicaps.CapID = "source.http"
@@ -249,6 +250,12 @@ func init() {
249250
Status: apicaps.CapStatusExperimental,
250251
})
251252

253+
Caps.Init(apicaps.Cap{
254+
ID: CapSourceGitDebugCommands,
255+
Enabled: true,
256+
Status: apicaps.CapStatusExperimental,
257+
})
258+
252259
Caps.Init(apicaps.Cap{
253260
ID: CapSourceGitSignatureVerify,
254261
Enabled: true,

source/git/identifier.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type GitIdentifier struct {
2121
MountSSHSock string
2222
KnownSSHHosts string
2323
SkipSubmodules bool
24+
DebugCommands bool
2425

2526
VerifySignature *GitSignatureVerifyOptions
2627
}

source/git/source.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ func (gs *Source) Identifier(scheme, ref string, attrs map[string]string, platfo
114114
if v == "true" {
115115
id.SkipSubmodules = true
116116
}
117+
case pb.AttrGitDebugCommands:
118+
if v == "true" {
119+
id.DebugCommands = true
120+
}
117121
case pb.AttrGitSignatureVerifyPubKey:
118122
if id.VerifySignature == nil {
119123
id.VerifySignature = &GitSignatureVerifyOptions{}
@@ -141,7 +145,7 @@ func (gs *Source) Identifier(scheme, ref string, attrs map[string]string, platfo
141145
}
142146

143147
// needs to be called with repo lock
144-
func (gs *Source) mountRemote(ctx context.Context, remote string, authArgs []string, sha256 bool, reset bool, g session.Group) (target string, release func() error, retErr error) {
148+
func (gs *Source) mountRemote(ctx context.Context, remote string, authArgs []string, debugCommands bool, sha256 bool, reset bool, g session.Group) (target string, release func() error, retErr error) {
145149
sis, err := searchGitRemote(ctx, gs.cache, remote)
146150
if err != nil {
147151
return "", nil, errors.Wrapf(err, "failed to search metadata for %s", urlutil.RedactCredentials(remote))
@@ -206,6 +210,7 @@ func (gs *Source) mountRemote(ctx context.Context, remote string, authArgs []str
206210
git := gitCLI(
207211
gitutil.WithGitDir(dir),
208212
gitutil.WithArgs(authArgs...),
213+
gitutil.WithDebugCommands(debugCommands),
209214
)
210215

211216
if initializeRepo {
@@ -844,7 +849,7 @@ func (gs *gitSourceHandler) tryRemoteFetch(ctx context.Context, g session.Group,
844849
}
845850
repo.releasers = append(repo.releasers, cleanup)
846851

847-
gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.authArgs, gs.sha256, reset, g)
852+
gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.authArgs, gs.src.DebugCommands, gs.sha256, reset, g)
848853
if err != nil {
849854
return nil, err
850855
}
@@ -1207,6 +1212,7 @@ func (gs *gitSourceHandler) emptyGitCli(ctx context.Context, g session.Group, op
12071212

12081213
opts = append([]gitutil.Option{
12091214
gitutil.WithArgs(gs.authArgs...),
1215+
gitutil.WithDebugCommands(gs.src.DebugCommands),
12101216
gitutil.WithSSHAuthSock(sock),
12111217
gitutil.WithSSHKnownHosts(knownHosts),
12121218
}, opts...)

0 commit comments

Comments
 (0)