1
0
Fork 0
mirror of https://code.forgejo.org/forgejo/runner.git synced 2025-10-10 19:32:04 +00:00

Merge pull request 'PR#3. Reducing the delta between Nektos/Act and Forgejo/Act' (#117) from achyrva/act:nektos-into-forgejo-0 into main

Reviewed-on: https://code.forgejo.org/forgejo/act/pulls/117
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
This commit is contained in:
Michael Kriese 2025-04-16 10:54:47 +00:00
commit ba102368d3
4 changed files with 110 additions and 50 deletions

View file

@ -6,7 +6,6 @@ import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt"
"io" "io"
"io/fs" "io/fs"
"path" "path"
@ -43,17 +42,7 @@ func (c GoGitActionCache) Fetch(ctx context.Context, cacheDir, url, ref, token s
return "", err return "", err
} }
branchName := hex.EncodeToString(tmpBranch) branchName := hex.EncodeToString(tmpBranch)
var refSpec config.RefSpec
spec := config.RefSpec(ref + ":" + branchName)
tagOrSha := false
if spec.IsExactSHA1() {
refSpec = spec
} else if strings.HasPrefix(ref, "refs/") {
refSpec = config.RefSpec(ref + ":refs/heads/" + branchName)
} else {
tagOrSha = true
refSpec = config.RefSpec("refs/*/" + ref + ":refs/heads/*/" + branchName)
}
var auth transport.AuthMethod var auth transport.AuthMethod
if token != "" { if token != "" {
auth = &http.BasicAuth{ auth = &http.BasicAuth{
@ -71,35 +60,17 @@ func (c GoGitActionCache) Fetch(ctx context.Context, cacheDir, url, ref, token s
return "", err return "", err
} }
defer func() { defer func() {
if refs, err := gogitrepo.References(); err == nil { _ = gogitrepo.DeleteBranch(branchName)
_ = refs.ForEach(func(r *plumbing.Reference) error {
if strings.Contains(r.Name().String(), branchName) {
return gogitrepo.DeleteBranch(r.Name().String())
}
return nil
})
}
}() }()
if err := remote.FetchContext(ctx, &git.FetchOptions{ if err := remote.FetchContext(ctx, &git.FetchOptions{
RefSpecs: []config.RefSpec{ RefSpecs: []config.RefSpec{
refSpec, config.RefSpec(ref + ":" + branchName),
}, },
Auth: auth, Auth: auth,
Force: true, Force: true,
}); err != nil { }); err != nil {
if tagOrSha && errors.Is(err, git.NoErrAlreadyUpToDate) {
return "", fmt.Errorf("couldn't find remote ref \"%s\"", ref)
}
return "", err return "", err
} }
if tagOrSha {
for _, prefix := range []string{"refs/heads/tags/", "refs/heads/heads/"} {
hash, err := gogitrepo.ResolveRevision(plumbing.Revision(prefix + branchName))
if err == nil {
return hash.String(), nil
}
}
}
hash, err := gogitrepo.ResolveRevision(plumbing.Revision(branchName)) hash, err := gogitrepo.ResolveRevision(plumbing.Revision(branchName))
if err != nil { if err != nil {
return "", err return "", err

View file

@ -0,0 +1,41 @@
package runner
import (
"context"
"io"
"path"
git "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
)
type GoGitActionCacheOfflineMode struct {
Parent GoGitActionCache
}
func (c GoGitActionCacheOfflineMode) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) {
sha, fetchErr := c.Parent.Fetch(ctx, cacheDir, url, ref, token)
gitPath := path.Join(c.Parent.Path, safeFilename(cacheDir)+".git")
gogitrepo, err := git.PlainOpen(gitPath)
if err != nil {
return "", fetchErr
}
refName := plumbing.ReferenceName("refs/action-cache-offline/" + ref)
r, err := gogitrepo.Reference(refName, true)
if fetchErr == nil {
if err != nil || sha != r.Hash().String() {
if err == nil {
refName = r.Name()
}
ref := plumbing.NewHashReference(refName, plumbing.NewHash(sha))
_ = gogitrepo.Storer.SetReference(ref)
}
} else if err == nil {
return r.Hash().String(), nil
}
return sha, fetchErr
}
func (c GoGitActionCacheOfflineMode) GetTarArchive(ctx context.Context, cacheDir, sha, includePrefix string) (io.ReadCloser, error) {
return c.Parent.GetTarArchive(ctx, cacheDir, sha, includePrefix)
}

View file

@ -18,20 +18,60 @@ func TestActionCache(t *testing.T) {
Path: os.TempDir(), Path: os.TempDir(),
} }
ctx := context.Background() ctx := context.Background()
sha, err := cache.Fetch(ctx, "christopherhx/script", "https://github.com/christopherhx/script", "main", "") cacheDir := "nektos/act-test-actions"
a.NoError(err) repo := "https://github.com/nektos/act-test-actions"
a.NotEmpty(sha) refs := []struct {
atar, err := cache.GetTarArchive(ctx, "christopherhx/script", sha, "node_modules") Name string
a.NoError(err) CacheDir string
a.NotEmpty(atar) Repo string
Ref string
}{
{
Name: "Fetch Branch Name",
CacheDir: cacheDir,
Repo: repo,
Ref: "main",
},
{
Name: "Fetch Branch Name Absolutely",
CacheDir: cacheDir,
Repo: repo,
Ref: "refs/heads/main",
},
{
Name: "Fetch HEAD",
CacheDir: cacheDir,
Repo: repo,
Ref: "HEAD",
},
{
Name: "Fetch Sha",
CacheDir: cacheDir,
Repo: repo,
Ref: "de984ca37e4df4cb9fd9256435a3b82c4a2662b1",
},
}
for _, c := range refs {
t.Run(c.Name, func(t *testing.T) {
sha, err := cache.Fetch(ctx, c.CacheDir, c.Repo, c.Ref, "")
if !a.NoError(err) || !a.NotEmpty(sha) {
return
}
atar, err := cache.GetTarArchive(ctx, c.CacheDir, sha, "js")
if !a.NoError(err) || !a.NotEmpty(atar) {
return
}
mytar := tar.NewReader(atar) mytar := tar.NewReader(atar)
th, err := mytar.Next() th, err := mytar.Next()
a.NoError(err) if !a.NoError(err) || !a.NotEqual(0, th.Size) {
a.NotEqual(0, th.Size) return
}
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
// G110: Potential DoS vulnerability via decompression bomb (gosec) // G110: Potential DoS vulnerability via decompression bomb (gosec)
_, err = io.Copy(buf, mytar) _, err = io.Copy(buf, mytar)
a.NoError(err) a.NoError(err)
str := buf.String() str := buf.String()
a.NotEmpty(str) a.NotEmpty(str)
})
}
} }

View file

@ -617,10 +617,18 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
ContainerNetworkMode: docker_container.NetworkMode(input.networkName), ContainerNetworkMode: docker_container.NetworkMode(input.networkName),
} }
if input.useNewActionCache { if input.useNewActionCache {
if input.actionOfflineMode {
config.ActionCache = &runner.GoGitActionCacheOfflineMode{
Parent: runner.GoGitActionCache{
Path: config.ActionCacheDir,
},
}
} else {
config.ActionCache = &runner.GoGitActionCache{ config.ActionCache = &runner.GoGitActionCache{
Path: config.ActionCacheDir, Path: config.ActionCacheDir,
} }
} }
}
r, err := runner.New(config) r, err := runner.New(config)
if err != nil { if err != nil {
return err return err