Skip to content

Commit aa68da2

Browse files
authored
Merge pull request #6194 from tonistiigi/git-sha256
git: add sha256 commit support
2 parents c04c1ce + 411c838 commit aa68da2

File tree

8 files changed

+354
-134
lines changed

8 files changed

+354
-134
lines changed

frontend/dockerfile/dockerfile_addgit_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import (
2121
)
2222

2323
var addGitTests = integration.TestFuncs(
24-
testAddGit,
24+
testAddGitSHA1,
25+
testAddGitSHA256,
2526
testAddGitChecksumCache,
2627
testGitQueryString,
2728
)
@@ -30,15 +31,27 @@ func init() {
3031
allTests = append(allTests, addGitTests...)
3132
}
3233

33-
func testAddGit(t *testing.T, sb integration.Sandbox) {
34+
func testAddGitSHA1(t *testing.T, sb integration.Sandbox) {
35+
testAddGit(t, sb, "sha1")
36+
}
37+
38+
func testAddGitSHA256(t *testing.T, sb integration.Sandbox) {
39+
testAddGit(t, sb, "sha256")
40+
}
41+
42+
func testAddGit(t *testing.T, sb integration.Sandbox, format string) {
3443
integration.SkipOnPlatform(t, "windows")
3544
f := getFrontend(t, sb)
3645

3746
gitDir, err := os.MkdirTemp("", "buildkit")
3847
require.NoError(t, err)
3948
defer os.RemoveAll(gitDir)
49+
initOptions := ""
50+
if format == "sha256" {
51+
initOptions = " --object-format=sha256"
52+
}
4053
gitCommands := []string{
41-
"git init",
54+
"git init" + initOptions,
4255
"git config --local user.email test",
4356
"git config --local user.name test",
4457
}

frontend/dockerfile/dockerfile_provenance_test.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ import (
4545

4646
var provenanceTests = integration.TestFuncs(
4747
testProvenanceAttestation,
48-
testGitProvenanceAttestation,
48+
testGitProvenanceAttestationSHA1,
49+
testGitProvenanceAttestationSHA256,
4950
testMultiPlatformProvenance,
5051
testClientFrontendProvenance,
5152
testClientLLBProvenance,
@@ -389,7 +390,15 @@ RUN echo ok> /foo
389390
}
390391
}
391392

392-
func testGitProvenanceAttestation(t *testing.T, sb integration.Sandbox) {
393+
func testGitProvenanceAttestationSHA1(t *testing.T, sb integration.Sandbox) {
394+
testGitProvenanceAttestation(t, sb, "sha1")
395+
}
396+
397+
func testGitProvenanceAttestationSHA256(t *testing.T, sb integration.Sandbox) {
398+
testGitProvenanceAttestation(t, sb, "sha256")
399+
}
400+
401+
func testGitProvenanceAttestation(t *testing.T, sb integration.Sandbox, format string) {
393402
integration.SkipOnPlatform(t, "windows")
394403
workers.CheckFeatureCompat(t, sb, workers.FeatureDirectPush, workers.FeatureProvenance)
395404
ctx := sb.Context()
@@ -423,8 +432,12 @@ COPY myapp.Dockerfile /
423432
fstest.CreateFile("myapp.Dockerfile", dockerfile, 0600),
424433
)
425434

435+
initOptions := ""
436+
if format == "sha256" {
437+
initOptions = " --object-format=sha256"
438+
}
426439
err = runShell(dir.Name,
427-
"git init",
440+
"git init"+initOptions,
428441
"git config --local user.email test",
429442
"git config --local user.name test",
430443
"git add myapp.Dockerfile",
@@ -519,15 +532,15 @@ COPY myapp.Dockerfile /
519532
require.NotEmpty(t, pred.BuildDefinition.ResolvedDependencies[1].Digest["sha256"])
520533

521534
require.Equal(t, expectedURL+"/.git#v1", pred.BuildDefinition.ResolvedDependencies[2].URI)
522-
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.BuildDefinition.ResolvedDependencies[2].Digest["sha1"])
535+
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.BuildDefinition.ResolvedDependencies[2].Digest[format])
523536
} else {
524537
require.Equal(t, 2, len(pred.BuildDefinition.ResolvedDependencies), "%+v", pred.BuildDefinition.ResolvedDependencies)
525538

526539
require.Equal(t, expBase, pred.BuildDefinition.ResolvedDependencies[0].URI)
527540
require.NotEmpty(t, pred.BuildDefinition.ResolvedDependencies[0].Digest["sha256"])
528541

529542
require.Equal(t, expectedURL+"/.git#v1", pred.BuildDefinition.ResolvedDependencies[1].URI)
530-
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.BuildDefinition.ResolvedDependencies[1].Digest["sha1"])
543+
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.BuildDefinition.ResolvedDependencies[1].Digest[format])
531544
}
532545

533546
require.Equal(t, 0, len(pred.BuildDefinition.ExternalParameters.Request.Locals))
@@ -574,15 +587,15 @@ COPY myapp.Dockerfile /
574587
require.NotEmpty(t, pred.Materials[1].Digest["sha256"])
575588

576589
require.Equal(t, expectedURL+"/.git#v1", pred.Materials[2].URI)
577-
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.Materials[2].Digest["sha1"])
590+
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.Materials[2].Digest[format])
578591
} else {
579592
require.Equal(t, 2, len(pred.Materials), "%+v", pred.Materials)
580593

581594
require.Equal(t, expBase, pred.Materials[0].URI)
582595
require.NotEmpty(t, pred.Materials[0].Digest["sha256"])
583596

584597
require.Equal(t, expectedURL+"/.git#v1", pred.Materials[1].URI)
585-
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.Materials[1].Digest["sha1"])
598+
require.Equal(t, strings.TrimSpace(string(expectedGitSHA)), pred.Materials[1].Digest[format])
586599
}
587600

588601
require.Equal(t, 0, len(pred.Invocation.Parameters.Locals))

frontend/dockerfile/dockerfile_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ var allTests = integration.TestFuncs(
9494
testCacheReleased,
9595
testDockerignore,
9696
testDockerignoreInvalid,
97-
testDockerfileFromGit,
97+
testDockerfileFromGitSHA1,
98+
testDockerfileFromGitSHA256,
9899
testMultiStageImplicitFrom,
99100
testMultiStageCaseInsensitive,
100101
testLabels,
@@ -4808,7 +4809,15 @@ ADD --chmod=10000 foo /
48084809
require.ErrorContains(t, err, "invalid chmod parameter: '10000'. it should be octal string and between 0 and 07777")
48094810
}
48104811

4811-
func testDockerfileFromGit(t *testing.T, sb integration.Sandbox) {
4812+
func testDockerfileFromGitSHA1(t *testing.T, sb integration.Sandbox) {
4813+
testDockerfileFromGit(t, sb, "sha1")
4814+
}
4815+
4816+
func testDockerfileFromGitSHA256(t *testing.T, sb integration.Sandbox) {
4817+
testDockerfileFromGit(t, sb, "sha256")
4818+
}
4819+
4820+
func testDockerfileFromGit(t *testing.T, sb integration.Sandbox, format string) {
48124821
integration.SkipOnPlatform(t, "windows")
48134822
f := getFrontend(t, sb)
48144823

@@ -4824,8 +4833,12 @@ COPY --from=build foo bar
48244833
err := os.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte(dockerfile), 0600)
48254834
require.NoError(t, err)
48264835

4836+
initOptions := ""
4837+
if format == "sha256" {
4838+
initOptions = " --object-format=sha256"
4839+
}
48274840
err = runShell(gitDir,
4828-
"git init",
4841+
"git init"+initOptions,
48294842
"git config --local user.email test",
48304843
"git config --local user.name test",
48314844
"git add Dockerfile",

solver/llbsolver/provenance/predicate.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ func slsaMaterials(srcs provenancetypes.Sources) ([]slsa.ProvenanceMaterial, err
4040

4141
for _, s := range srcs.Git {
4242
out = append(out, slsa.ProvenanceMaterial{
43-
URI: s.URL,
44-
Digest: slsa.DigestSet{
45-
"sha1": s.Commit,
46-
},
43+
URI: s.URL,
44+
Digest: digestSetForCommit(s.Commit),
4745
})
4846
}
4947

@@ -59,14 +57,22 @@ func slsaMaterials(srcs provenancetypes.Sources) ([]slsa.ProvenanceMaterial, err
5957
return out, nil
6058
}
6159

60+
func digestSetForCommit(commit string) slsa.DigestSet {
61+
dset := slsa.DigestSet{}
62+
if len(commit) == 64 {
63+
dset["sha256"] = commit
64+
} else {
65+
dset["sha1"] = commit
66+
}
67+
return dset
68+
}
69+
6270
func findMaterial(srcs provenancetypes.Sources, uri string) (*slsa.ProvenanceMaterial, bool) {
6371
for _, s := range srcs.Git {
6472
if s.URL == uri {
6573
return &slsa.ProvenanceMaterial{
66-
URI: s.URL,
67-
Digest: slsa.DigestSet{
68-
"sha1": s.Commit,
69-
},
74+
URI: s.URL,
75+
Digest: digestSetForCommit(s.Commit),
7076
}, true
7177
}
7278
}

source/git/source.go

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (gs *gitSource) Identifier(scheme, ref string, attrs map[string]string, pla
105105
}
106106

107107
// needs to be called with repo lock
108-
func (gs *gitSource) mountRemote(ctx context.Context, remote string, authArgs []string, g session.Group) (target string, release func() error, retErr error) {
108+
func (gs *gitSource) mountRemote(ctx context.Context, remote string, authArgs []string, sha256 bool, g session.Group) (target string, release func() error, retErr error) {
109109
sis, err := searchGitRemote(ctx, gs.cache, remote)
110110
if err != nil {
111111
return "", nil, errors.Wrapf(err, "failed to search metadata for %s", urlutil.RedactCredentials(remote))
@@ -171,7 +171,11 @@ func (gs *gitSource) mountRemote(ctx context.Context, remote string, authArgs []
171171
// implied default to suppress "hint:" output about not having a
172172
// default initial branch name set which otherwise spams unit
173173
// test logs.
174-
if _, err := git.Run(ctx, "-c", "init.defaultBranch=master", "init", "--bare"); err != nil {
174+
args := []string{"-c", "init.defaultBranch=master", "init", "--bare"}
175+
if sha256 {
176+
args = append(args, "--object-format=sha256")
177+
}
178+
if _, err := git.Run(ctx, args...); err != nil {
175179
return "", nil, errors.Wrapf(err, "failed to init repo at %s", dir)
176180
}
177181

@@ -198,6 +202,7 @@ type gitSourceHandler struct {
198202
*gitSource
199203
src GitIdentifier
200204
cacheKey string
205+
sha256 bool
201206
sm *session.Manager
202207
authArgs []string
203208
}
@@ -376,29 +381,30 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index
376381
if refCommitFullHash != "" {
377382
cacheKey := gs.shaToCacheKey(refCommitFullHash, ref2)
378383
gs.cacheKey = cacheKey
384+
gs.sha256 = len(refCommitFullHash) == 64
379385
// gs.src.Checksum is verified when checking out the commit
380386
return cacheKey, refCommitFullHash, nil, true, nil
381387
}
382388

383389
gs.getAuthToken(ctx, g)
384390

385-
git, cleanup, err := gs.gitCli(ctx, g)
391+
tmpGit, cleanup, err := gs.emptyGitCli(ctx, g)
386392
if err != nil {
387393
return "", "", nil, false, err
388394
}
389395
defer cleanup()
390396

391397
ref := gs.src.Ref
392398
if ref == "" {
393-
ref, err = getDefaultBranch(ctx, git, gs.src.Remote)
399+
ref, err = getDefaultBranch(ctx, tmpGit, gs.src.Remote)
394400
if err != nil {
395401
return "", "", nil, false, err
396402
}
397403
}
398404

399405
// TODO: should we assume that remote tag is immutable? add a timer?
400406

401-
buf, err := git.Run(ctx, "ls-remote", "origin", ref, ref+"^{}")
407+
buf, err := tmpGit.Run(ctx, "ls-remote", gs.src.Remote, ref, ref+"^{}")
402408
if err != nil {
403409
return "", "", nil, false, errors.Wrapf(err, "failed to fetch remote %s", urlutil.RedactCredentials(remote))
404410
}
@@ -445,6 +451,7 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index
445451
}
446452
cacheKey := gs.shaToCacheKey(sha, usedRef)
447453
gs.cacheKey = cacheKey
454+
gs.sha256 = len(sha) == 64
448455
return cacheKey, sha, nil, true, nil
449456
}
450457

@@ -475,15 +482,18 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
475482
gs.locker.Lock(gs.src.Remote)
476483
defer gs.locker.Unlock(gs.src.Remote)
477484

478-
git, cleanup, err := gs.gitCli(ctx, g)
485+
git, cleanup, err := gs.emptyGitCli(ctx, g)
479486
if err != nil {
480487
return nil, err
481488
}
482489
defer cleanup()
483-
gitDir, err := git.GitDir(ctx)
490+
491+
gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.authArgs, gs.sha256, g)
484492
if err != nil {
485493
return nil, err
486494
}
495+
defer unmountGitDir()
496+
git = git.New(gitutil.WithGitDir(gitDir))
487497

488498
ref := gs.src.Ref
489499
if ref == "" {
@@ -581,7 +591,11 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
581591
return nil, err
582592
}
583593
checkoutGit := git.New(gitutil.WithWorkTree(checkoutDir), gitutil.WithGitDir(checkoutDirGit))
584-
_, err = checkoutGit.Run(ctx, "-c", "init.defaultBranch=master", "init")
594+
args := []string{"-c", "init.defaultBranch=master", "init"}
595+
if gs.sha256 {
596+
args = append(args, "--object-format=sha256")
597+
}
598+
_, err = checkoutGit.Run(ctx, args...)
585599
if err != nil {
586600
return nil, err
587601
}
@@ -713,7 +727,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
713727
return snap, nil
714728
}
715729

716-
func (gs *gitSourceHandler) gitCli(ctx context.Context, g session.Group, opts ...gitutil.Option) (*gitutil.GitCLI, func() error, error) {
730+
func (gs *gitSourceHandler) emptyGitCli(ctx context.Context, g session.Group, opts ...gitutil.Option) (*gitutil.GitCLI, func() error, error) {
717731
var cleanups []func() error
718732
cleanup := func() error {
719733
var err error
@@ -727,13 +741,6 @@ func (gs *gitSourceHandler) gitCli(ctx context.Context, g session.Group, opts ..
727741
}
728742
var err error
729743

730-
gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.authArgs, g)
731-
if err != nil {
732-
cleanup()
733-
return nil, nil, err
734-
}
735-
cleanups = append(cleanups, unmountGitDir)
736-
737744
var sock string
738745
if gs.src.MountSSHSock != "" {
739746
var unmountSock func() error
@@ -757,7 +764,6 @@ func (gs *gitSourceHandler) gitCli(ctx context.Context, g session.Group, opts ..
757764
}
758765

759766
opts = append([]gitutil.Option{
760-
gitutil.WithGitDir(gitDir),
761767
gitutil.WithArgs(gs.authArgs...),
762768
gitutil.WithSSHAuthSock(sock),
763769
gitutil.WithSSHKnownHosts(knownHosts),

0 commit comments

Comments
 (0)