Skip to content

Commit 26c2d62

Browse files
authored
fix(crafter): resolve commit info in git worktrees (#3020)
Signed-off-by: Jose I. Paris <jiparis@chainloop.dev>
1 parent 3211387 commit 26c2d62

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

pkg/attestation/crafter/crafter.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ func gracefulGitRepoHead(path string) (*HeadCommit, error) {
314314
repo, err := git.PlainOpenWithOptions(path, &git.PlainOpenOptions{
315315
// walk up the directory tree until we find a git repo
316316
DetectDotGit: true,
317+
// enable .git/commondir support so worktrees can resolve HEAD
318+
EnableDotGitCommonDir: true,
317319
})
318320

319321
if err != nil {

pkg/attestation/crafter/crafter_unit_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package crafter
1717

1818
import (
1919
"os"
20+
"os/exec"
2021
"path/filepath"
2122
"slices"
2223
"testing"
@@ -315,6 +316,63 @@ func (s *crafterUnitSuite) TestPolicyEvaluationDedup() {
315316
}
316317
}
317318

319+
func (s *crafterUnitSuite) TestGitRepoHeadWorktree() {
320+
// go-git cannot create worktrees, so use the git CLI
321+
if _, err := exec.LookPath("git"); err != nil {
322+
s.T().Skip("git not found in PATH")
323+
}
324+
325+
repoPath := s.T().TempDir()
326+
327+
// Initialize a repo and create a commit using go-git
328+
repo, err := git.PlainInit(repoPath, false)
329+
require.NoError(s.T(), err)
330+
331+
_, err = repo.CreateRemote(&config.RemoteConfig{
332+
Name: "origin",
333+
URLs: []string{"git@cyberdyne.com:skynet.git"},
334+
})
335+
require.NoError(s.T(), err)
336+
337+
wt, err := repo.Worktree()
338+
require.NoError(s.T(), err)
339+
340+
filename := filepath.Join(repoPath, "example-git-file")
341+
require.NoError(s.T(), os.WriteFile(filename, []byte("hello world!"), 0o600))
342+
343+
_, err = wt.Add("example-git-file")
344+
require.NoError(s.T(), err)
345+
346+
h, err := wt.Commit("test commit", &git.CommitOptions{
347+
Author: &object.Signature{
348+
Name: "John Doe",
349+
Email: "john@doe.org",
350+
When: time.Now(),
351+
},
352+
})
353+
require.NoError(s.T(), err)
354+
355+
// Create a worktree using git CLI (go-git doesn't support this)
356+
worktreePath := filepath.Join(s.T().TempDir(), "test-worktree")
357+
cmd := exec.Command("git", "-C", repoPath, "worktree", "add", worktreePath)
358+
out, err := cmd.CombinedOutput()
359+
require.NoError(s.T(), err, "git worktree add: %s", out)
360+
361+
got, err := gracefulGitRepoHead(worktreePath)
362+
require.NoError(s.T(), err)
363+
require.NotNil(s.T(), got)
364+
365+
assert.Equal(s.T(), h.String(), got.Hash)
366+
assert.Equal(s.T(), "john@doe.org", got.AuthorEmail)
367+
assert.Equal(s.T(), "John Doe", got.AuthorName)
368+
assert.NotEmpty(s.T(), got.Remotes)
369+
assert.Equal(s.T(), &CommitRemote{
370+
Name: "origin",
371+
URL: "git@cyberdyne.com:skynet.git",
372+
}, got.Remotes[0])
373+
assert.NotEmpty(s.T(), got.Date)
374+
}
375+
318376
func TestSuite(t *testing.T) {
319377
suite.Run(t, new(crafterUnitSuite))
320378
}

0 commit comments

Comments
 (0)