Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
if input.useNewActionCache || len(input.localRepository) > 0 {
if input.actionOfflineMode {
config.ActionCache = &runner.GoGitActionCacheOfflineMode{
Parent: runner.GoGitActionCache{
Parent: &runner.GoGitActionCache{
Path: config.ActionCacheDir,
},
}
Expand Down
23 changes: 20 additions & 3 deletions pkg/runner/action_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io/fs"
"path"
"strings"
"sync"
"time"

git "github.com/go-git/go-git/v5"
Expand All @@ -28,16 +29,28 @@ type ActionCache interface {
}

type GoGitActionCache struct {
Path string
Path string
locks sync.Map
}

func (c GoGitActionCache) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) {
// repoMu returns a per-gitPath mutex to serialize concurrent access to the
// same bare git repository. Different repos are not contended.
func (c *GoGitActionCache) repoMu(gitPath string) *sync.Mutex {
v, _ := c.locks.LoadOrStore(gitPath, &sync.Mutex{})
return v.(*sync.Mutex)
}

func (c *GoGitActionCache) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) {
logger := common.Logger(ctx)

gitPath := path.Join(c.Path, safeFilename(cacheDir)+".git")

logger.Infof("GoGitActionCache fetch %s with ref %s at %s", url, ref, gitPath)

mu := c.repoMu(gitPath)
mu.Lock()
defer mu.Unlock()

gogitrepo, err := git.PlainInit(gitPath, true)
if errors.Is(err, git.ErrRepositoryAlreadyExists) {
logger.Debugf("GoGitActionCache cache hit %s with ref %s at %s", url, ref, gitPath)
Expand Down Expand Up @@ -127,13 +140,17 @@ func (g *GitFileInfo) Sys() any {
return nil
}

func (c GoGitActionCache) GetTarArchive(ctx context.Context, cacheDir, sha, includePrefix string) (io.ReadCloser, error) {
func (c *GoGitActionCache) GetTarArchive(ctx context.Context, cacheDir, sha, includePrefix string) (io.ReadCloser, error) {
logger := common.Logger(ctx)

gitPath := path.Join(c.Path, safeFilename(cacheDir)+".git")

logger.Infof("GoGitActionCache get content %s with sha %s subpath '%s' at %s", cacheDir, sha, includePrefix, gitPath)

mu := c.repoMu(gitPath)
mu.Lock()
defer mu.Unlock()

gogitrepo, err := git.PlainOpen(gitPath)
if err != nil {
return nil, fmt.Errorf("GoGitActionCache failed to open bare git %s with sha %s subpath '%s' at %s: %w", cacheDir, sha, includePrefix, gitPath, err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/runner/action_cache_offline_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

type GoGitActionCacheOfflineMode struct {
Parent GoGitActionCache
Parent *GoGitActionCache
}

func (c GoGitActionCacheOfflineMode) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) {
Expand Down
6 changes: 3 additions & 3 deletions pkg/runner/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@ func TestRunEvent(t *testing.T) {
if yaml.Unmarshal(file, testConfig) == nil {
if testConfig.LocalRepositories != nil {
config.ActionCache = &LocalRepositoryCache{
Parent: GoGitActionCache{
path.Clean(path.Join(workdir, "cache")),
Parent: &GoGitActionCache{
Path: path.Clean(path.Join(workdir, "cache")),
},
LocalRepositories: testConfig.LocalRepositories,
CacheDirCache: map[string]string{},
Expand Down Expand Up @@ -386,7 +386,7 @@ func TestPullAndPostStepFailureIsJobFailure(t *testing.T) {
}

defCache := &GoGitActionCache{
path.Clean(path.Join(workdir, "cache")),
Path: path.Clean(path.Join(workdir, "cache")),
}

mockCache := &mockCache{}
Expand Down