From 934b13a7a126198019800e79fb2ae7fe57a1c2bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 03:08:44 +0000 Subject: [PATCH 01/12] build(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0 (#2235) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index fd672e5..7f82fe6 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a go.etcd.io/bbolt v1.3.9 golang.org/x/term v0.17.0 @@ -73,7 +73,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/skeema/knownhosts v1.2.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect diff --git a/go.sum b/go.sum index 3b0829d..84b1b2a 100644 --- a/go.sum +++ b/go.sum @@ -163,18 +163,15 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a h1:oIi7H/bwFUYKYhzKbHc+3MvHRWqhQwXVB4LweLMiVy0= github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a/go.mod h1:iSvujNDmpZ6eQX+bg/0X3lF7LEmZ8N77g2a/J/+Zt2U= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= From 75e4ad93f4c6ba51a7a64f12335dd0268dd7465a Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Tue, 5 Mar 2024 07:04:54 +0100 Subject: [PATCH 02/12] fix: docker buildx cache restore not working (#2236) * To take effect artifacts v4 pr is needed with adjusted claims --- pkg/artifactcache/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/artifactcache/handler.go b/pkg/artifactcache/handler.go index 3178260..1f0a6f6 100644 --- a/pkg/artifactcache/handler.go +++ b/pkg/artifactcache/handler.go @@ -385,7 +385,7 @@ func (h *Handler) findCache(db *bolthold.Store, keys []string, version string) ( } stop := fmt.Errorf("stop") - for _, prefix := range keys[1:] { + for _, prefix := range keys { found := false prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix)) re, err := regexp.Compile(prefixPattern) From 352ad41ad2b8a205b12442859280b0e938b7e4ab Mon Sep 17 00:00:00 2001 From: huajin tong <137764712+thirdkeyword@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:20:06 +0800 Subject: [PATCH 03/12] fix function name in comment (#2240) Signed-off-by: thirdkeyword --- pkg/model/workflow.go | 4 ++-- pkg/runner/expression.go | 2 +- pkg/runner/logger.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 1186454..7fbecd6 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -343,7 +343,7 @@ func environment(yml yaml.Node) map[string]string { return env } -// Environments returns string-based key=value map for a job +// Environment returns string-based key=value map for a job func (j *Job) Environment() map[string]string { return environment(j.Env) } @@ -578,7 +578,7 @@ func (s *Step) String() string { return s.ID } -// Environments returns string-based key=value map for a step +// Environment returns string-based key=value map for a step func (s *Step) Environment() map[string]string { return environment(s.Env) } diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go index 412d1c0..2e3152b 100644 --- a/pkg/runner/expression.go +++ b/pkg/runner/expression.go @@ -106,7 +106,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map //go:embed hashfiles/index.js var hashfiles string -// NewExpressionEvaluator creates a new evaluator +// NewStepExpressionEvaluator creates a new evaluator func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step) ExpressionEvaluator { // todo: cleanup EvaluationEnvironment creation job := rc.Run.Job() diff --git a/pkg/runner/logger.go b/pkg/runner/logger.go index 5a98210..a788f68 100644 --- a/pkg/runner/logger.go +++ b/pkg/runner/logger.go @@ -52,7 +52,7 @@ func Masks(ctx context.Context) *[]string { return &[]string{} } -// WithLogger adds a value to the context for the logger +// WithMasks adds a value to the context for the logger func WithMasks(ctx context.Context, masks *[]string) context.Context { return context.WithValue(ctx, masksContextKeyVal, masks) } From 119ceb81d906be5e1b23bd085f642ffde7144ef5 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Fri, 8 Mar 2024 02:25:03 +0100 Subject: [PATCH 04/12] fix: rootless permission bits (new actions cache) (#2242) * fix: rootless permission bits (new actions cache) * add test * fix lint / more tests --- pkg/container/docker_run.go | 2 +- pkg/container/docker_run_test.go | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/pkg/container/docker_run.go b/pkg/container/docker_run.go index c61301b..fe377fd 100644 --- a/pkg/container/docker_run.go +++ b/pkg/container/docker_run.go @@ -679,7 +679,7 @@ func (cr *containerReference) CopyTarStream(ctx context.Context, destPath string tw := tar.NewWriter(buf) _ = tw.WriteHeader(&tar.Header{ Name: destPath, - Mode: 777, + Mode: 0o777, Typeflag: tar.TypeDir, }) tw.Close() diff --git a/pkg/container/docker_run_test.go b/pkg/container/docker_run_test.go index 96bda59..7205a26 100644 --- a/pkg/container/docker_run_test.go +++ b/pkg/container/docker_run_test.go @@ -2,7 +2,9 @@ package container import ( "bufio" + "bytes" "context" + "fmt" "io" "net" "strings" @@ -75,6 +77,11 @@ func (m *mockDockerClient) ContainerExecInspect(ctx context.Context, execID stri return args.Get(0).(types.ContainerExecInspect), args.Error(1) } +func (m *mockDockerClient) CopyToContainer(ctx context.Context, id string, path string, content io.Reader, options types.CopyToContainerOptions) error { + args := m.Called(ctx, id, path, content, options) + return args.Error(0) +} + type endlessReader struct { io.Reader } @@ -165,5 +172,77 @@ func TestDockerExecFailure(t *testing.T) { client.AssertExpectations(t) } +func TestDockerCopyTarStream(t *testing.T) { + ctx := context.Background() + + conn := &mockConn{} + + client := &mockDockerClient{} + client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(nil) + client.On("CopyToContainer", ctx, "123", "/var/run/act", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(nil) + cr := &containerReference{ + id: "123", + cli: client, + input: &NewContainerInput{ + Image: "image", + }, + } + + _ = cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{}) + + conn.AssertExpectations(t) + client.AssertExpectations(t) +} + +func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) { + ctx := context.Background() + + conn := &mockConn{} + + merr := fmt.Errorf("Failure") + + client := &mockDockerClient{} + client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(merr) + client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(merr) + cr := &containerReference{ + id: "123", + cli: client, + input: &NewContainerInput{ + Image: "image", + }, + } + + err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{}) + assert.ErrorIs(t, err, merr) + + conn.AssertExpectations(t) + client.AssertExpectations(t) +} + +func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) { + ctx := context.Background() + + conn := &mockConn{} + + merr := fmt.Errorf("Failure") + + client := &mockDockerClient{} + client.On("CopyToContainer", ctx, "123", "/", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(nil) + client.On("CopyToContainer", ctx, "123", "/var/run/act", mock.Anything, mock.AnythingOfType("types.CopyToContainerOptions")).Return(merr) + cr := &containerReference{ + id: "123", + cli: client, + input: &NewContainerInput{ + Image: "image", + }, + } + + err := cr.CopyTarStream(ctx, "/var/run/act", &bytes.Buffer{}) + assert.ErrorIs(t, err, merr) + + conn.AssertExpectations(t) + client.AssertExpectations(t) +} + // Type assert containerReference implements ExecutionsEnvironment var _ ExecutionsEnvironment = &containerReference{} From 8c83d5721258537b3a47dfc060be67d180ba6a0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 02:28:21 +0000 Subject: [PATCH 05/12] build(deps): bump golang.org/x/term from 0.17.0 to 0.18.0 (#2244) Bumps [golang.org/x/term](https://github.com/golang/term) from 0.17.0 to 0.18.0. - [Commits](https://github.com/golang/term/compare/v0.17.0...v0.18.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 7f82fe6..fac0497 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a go.etcd.io/bbolt v1.3.9 - golang.org/x/term v0.17.0 + golang.org/x/term v0.18.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) @@ -82,7 +82,7 @@ require ( golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index 84b1b2a..f152031 100644 --- a/go.sum +++ b/go.sum @@ -245,15 +245,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 069720abff4e169834dda534da5b0013c03775a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:37:01 +0000 Subject: [PATCH 06/12] build(deps): bump github.com/docker/docker (#2252) Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.7+incompatible to 24.0.9+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v24.0.7...v24.0.9) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fac0497..ca6f0c6 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/creack/pty v1.1.21 github.com/docker/cli v24.0.7+incompatible github.com/docker/distribution v2.8.3+incompatible - github.com/docker/docker v24.0.7+incompatible // 24.0 branch + github.com/docker/docker v24.0.9+incompatible // 24.0 branch github.com/docker/go-connections v0.4.0 github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.11.0 diff --git a/go.sum b/go.sum index f152031..1f0487f 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1x github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From f56dd65ff69f38f68bf82d485c3cb1b90e9ffc3e Mon Sep 17 00:00:00 2001 From: Jason Song Date: Thu, 28 Mar 2024 19:56:26 +0800 Subject: [PATCH 07/12] test: use ping to improve network test (#2266) --- pkg/runner/testdata/networking/push.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/runner/testdata/networking/push.yml b/pkg/runner/testdata/networking/push.yml index 2b1bf9a..1e02ba7 100644 --- a/pkg/runner/testdata/networking/push.yml +++ b/pkg/runner/testdata/networking/push.yml @@ -7,8 +7,8 @@ jobs: - name: Install tools run: | apt update - apt install -y bind9-host + apt install -y iputils-ping - name: Run hostname test run: | hostname -f - host $(hostname -f) + ping -c 4 $(hostname -f) From b9382a2c4e6801d136c246a7e30e7ceafaad3ade Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 29 Mar 2024 00:42:02 +0800 Subject: [PATCH 08/12] Support overwriting caches (#2265) * feat: support overwrite caches * test: fix case * test: fix get_with_multiple_keys * chore: use atomic.Bool * test: improve get_with_multiple_keys * chore: use ping to improve path * fix: wrong CompareAndSwap * test: TestHandler_gcCache * chore: lint code * chore: lint code --- pkg/artifactcache/handler.go | 177 +++++++++++++++-------------- pkg/artifactcache/handler_test.go | 182 +++++++++++++++++++++++++----- pkg/artifactcache/model.go | 24 ++-- 3 files changed, 252 insertions(+), 131 deletions(-) diff --git a/pkg/artifactcache/handler.go b/pkg/artifactcache/handler.go index 1f0a6f6..395a39e 100644 --- a/pkg/artifactcache/handler.go +++ b/pkg/artifactcache/handler.go @@ -35,7 +35,7 @@ type Handler struct { server *http.Server logger logrus.FieldLogger - gcing int32 // TODO: use atomic.Bool when we can use Go 1.19 + gcing atomic.Bool gcAt time.Time outboundIP string @@ -170,7 +170,7 @@ func (h *Handler) find(w http.ResponseWriter, r *http.Request, _ httprouter.Para } defer db.Close() - cache, err := h.findCache(db, keys, version) + cache, err := findCache(db, keys, version) if err != nil { h.responseJSON(w, r, 500, err) return @@ -206,32 +206,17 @@ func (h *Handler) reserve(w http.ResponseWriter, r *http.Request, _ httprouter.P api.Key = strings.ToLower(api.Key) cache := api.ToCache() - cache.FillKeyVersionHash() db, err := h.openDB() if err != nil { h.responseJSON(w, r, 500, err) return } defer db.Close() - if err := db.FindOne(cache, bolthold.Where("KeyVersionHash").Eq(cache.KeyVersionHash)); err != nil { - if !errors.Is(err, bolthold.ErrNotFound) { - h.responseJSON(w, r, 500, err) - return - } - } else { - h.responseJSON(w, r, 400, fmt.Errorf("already exist")) - return - } now := time.Now().Unix() cache.CreatedAt = now cache.UsedAt = now - if err := db.Insert(bolthold.NextSequence(), cache); err != nil { - h.responseJSON(w, r, 500, err) - return - } - // write back id to db - if err := db.Update(cache.ID, cache); err != nil { + if err := insertCache(db, cache); err != nil { h.responseJSON(w, r, 500, err) return } @@ -364,56 +349,40 @@ func (h *Handler) middleware(handler httprouter.Handle) httprouter.Handle { } // if not found, return (nil, nil) instead of an error. -func (h *Handler) findCache(db *bolthold.Store, keys []string, version string) (*Cache, error) { - if len(keys) == 0 { - return nil, nil - } - key := keys[0] // the first key is for exact match. - - cache := &Cache{ - Key: key, - Version: version, - } - cache.FillKeyVersionHash() - - if err := db.FindOne(cache, bolthold.Where("KeyVersionHash").Eq(cache.KeyVersionHash)); err != nil { - if !errors.Is(err, bolthold.ErrNotFound) { - return nil, err - } - } else if cache.Complete { - return cache, nil - } - stop := fmt.Errorf("stop") - +func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error) { + cache := &Cache{} for _, prefix := range keys { - found := false prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix)) re, err := regexp.Compile(prefixPattern) if err != nil { continue } - if err := db.ForEach(bolthold.Where("Key").RegExp(re).And("Version").Eq(version).SortBy("CreatedAt").Reverse(), func(v *Cache) error { - if !strings.HasPrefix(v.Key, prefix) { - return stop - } - if v.Complete { - cache = v - found = true - return stop - } - return nil - }); err != nil { - if !errors.Is(err, stop) { - return nil, err + if err := db.FindOne(cache, + bolthold.Where("Key").RegExp(re). + And("Version").Eq(version). + And("Complete").Eq(true). + SortBy("CreatedAt").Reverse()); err != nil { + if errors.Is(err, bolthold.ErrNotFound) { + continue } + return nil, fmt.Errorf("find cache: %w", err) } - if found { - return cache, nil - } + return cache, nil } return nil, nil } +func insertCache(db *bolthold.Store, cache *Cache) error { + if err := db.Insert(bolthold.NextSequence(), cache); err != nil { + return fmt.Errorf("insert cache: %w", err) + } + // write back id to db + if err := db.Update(cache.ID, cache); err != nil { + return fmt.Errorf("write back id to db: %w", err) + } + return nil +} + func (h *Handler) useCache(id int64) { db, err := h.openDB() if err != nil { @@ -428,14 +397,21 @@ func (h *Handler) useCache(id int64) { _ = db.Update(cache.ID, cache) } +const ( + keepUsed = 30 * 24 * time.Hour + keepUnused = 7 * 24 * time.Hour + keepTemp = 5 * time.Minute + keepOld = 5 * time.Minute +) + func (h *Handler) gcCache() { - if atomic.LoadInt32(&h.gcing) != 0 { + if h.gcing.Load() { return } - if !atomic.CompareAndSwapInt32(&h.gcing, 0, 1) { + if !h.gcing.CompareAndSwap(false, true) { return } - defer atomic.StoreInt32(&h.gcing, 0) + defer h.gcing.Store(false) if time.Since(h.gcAt) < time.Hour { h.logger.Debugf("skip gc: %v", h.gcAt.String()) @@ -444,37 +420,18 @@ func (h *Handler) gcCache() { h.gcAt = time.Now() h.logger.Debugf("gc: %v", h.gcAt.String()) - const ( - keepUsed = 30 * 24 * time.Hour - keepUnused = 7 * 24 * time.Hour - keepTemp = 5 * time.Minute - ) - db, err := h.openDB() if err != nil { return } defer db.Close() + // Remove the caches which are not completed for a while, they are most likely to be broken. var caches []*Cache - if err := db.Find(&caches, bolthold.Where("UsedAt").Lt(time.Now().Add(-keepTemp).Unix())); err != nil { - h.logger.Warnf("find caches: %v", err) - } else { - for _, cache := range caches { - if cache.Complete { - continue - } - h.storage.Remove(cache.ID) - if err := db.Delete(cache.ID, cache); err != nil { - h.logger.Warnf("delete cache: %v", err) - continue - } - h.logger.Infof("deleted cache: %+v", cache) - } - } - - caches = caches[:0] - if err := db.Find(&caches, bolthold.Where("UsedAt").Lt(time.Now().Add(-keepUnused).Unix())); err != nil { + if err := db.Find(&caches, bolthold. + Where("UsedAt").Lt(time.Now().Add(-keepTemp).Unix()). + And("Complete").Eq(false), + ); err != nil { h.logger.Warnf("find caches: %v", err) } else { for _, cache := range caches { @@ -487,8 +444,11 @@ func (h *Handler) gcCache() { } } + // Remove the old caches which have not been used recently. caches = caches[:0] - if err := db.Find(&caches, bolthold.Where("CreatedAt").Lt(time.Now().Add(-keepUsed).Unix())); err != nil { + if err := db.Find(&caches, bolthold. + Where("UsedAt").Lt(time.Now().Add(-keepUnused).Unix()), + ); err != nil { h.logger.Warnf("find caches: %v", err) } else { for _, cache := range caches { @@ -500,6 +460,55 @@ func (h *Handler) gcCache() { h.logger.Infof("deleted cache: %+v", cache) } } + + // Remove the old caches which are too old. + caches = caches[:0] + if err := db.Find(&caches, bolthold. + Where("CreatedAt").Lt(time.Now().Add(-keepUsed).Unix()), + ); err != nil { + h.logger.Warnf("find caches: %v", err) + } else { + for _, cache := range caches { + h.storage.Remove(cache.ID) + if err := db.Delete(cache.ID, cache); err != nil { + h.logger.Warnf("delete cache: %v", err) + continue + } + h.logger.Infof("deleted cache: %+v", cache) + } + } + + // Remove the old caches with the same key and version, keep the latest one. + // Also keep the olds which have been used recently for a while in case of the cache is still in use. + if results, err := db.FindAggregate( + &Cache{}, + bolthold.Where("Complete").Eq(true), + "Key", "Version", + ); err != nil { + h.logger.Warnf("find aggregate caches: %v", err) + } else { + for _, result := range results { + if result.Count() <= 1 { + continue + } + result.Sort("CreatedAt") + caches = caches[:0] + result.Reduction(&caches) + for _, cache := range caches[:len(caches)-1] { + if time.Since(time.Unix(cache.UsedAt, 0)) < keepOld { + // Keep it since it has been used recently, even if it's old. + // Or it could break downloading in process. + continue + } + h.storage.Remove(cache.ID) + if err := db.Delete(cache.ID, cache); err != nil { + h.logger.Warnf("delete cache: %v", err) + continue + } + h.logger.Infof("deleted cache: %+v", cache) + } + } + } } func (h *Handler) responseJSON(w http.ResponseWriter, r *http.Request, code int, v ...any) { diff --git a/pkg/artifactcache/handler_test.go b/pkg/artifactcache/handler_test.go index 35ec753..b418f00 100644 --- a/pkg/artifactcache/handler_test.go +++ b/pkg/artifactcache/handler_test.go @@ -10,9 +10,11 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/timshannon/bolthold" "go.etcd.io/bbolt" ) @@ -78,6 +80,9 @@ func TestHandler(t *testing.T) { t.Run("duplicate reserve", func(t *testing.T) { key := strings.ToLower(t.Name()) version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20" + var first, second struct { + CacheID uint64 `json:"cacheId"` + } { body, err := json.Marshal(&Request{ Key: key, @@ -89,10 +94,8 @@ func TestHandler(t *testing.T) { require.NoError(t, err) assert.Equal(t, 200, resp.StatusCode) - got := struct { - CacheID uint64 `json:"cacheId"` - }{} - require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + require.NoError(t, json.NewDecoder(resp.Body).Decode(&first)) + assert.NotZero(t, first.CacheID) } { body, err := json.Marshal(&Request{ @@ -103,8 +106,13 @@ func TestHandler(t *testing.T) { require.NoError(t, err) resp, err := http.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body)) require.NoError(t, err) - assert.Equal(t, 400, resp.StatusCode) + assert.Equal(t, 200, resp.StatusCode) + + require.NoError(t, json.NewDecoder(resp.Body).Decode(&second)) + assert.NotZero(t, second.CacheID) } + + assert.NotEqual(t, first.CacheID, second.CacheID) }) t.Run("upload with bad id", func(t *testing.T) { @@ -341,9 +349,9 @@ func TestHandler(t *testing.T) { version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20" key := strings.ToLower(t.Name()) keys := [3]string{ - key + "_a", - key + "_a_b", key + "_a_b_c", + key + "_a_b", + key + "_a", } contents := [3][]byte{ make([]byte, 100), @@ -354,6 +362,7 @@ func TestHandler(t *testing.T) { _, err := rand.Read(contents[i]) require.NoError(t, err) uploadCacheNormally(t, base, keys[i], version, contents[i]) + time.Sleep(time.Second) // ensure CreatedAt of caches are different } reqKeys := strings.Join([]string{ @@ -361,29 +370,33 @@ func TestHandler(t *testing.T) { key + "_a_b", key + "_a", }, ",") - var archiveLocation string - { - resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) - require.NoError(t, err) - require.Equal(t, 200, resp.StatusCode) - got := struct { - Result string `json:"result"` - ArchiveLocation string `json:"archiveLocation"` - CacheKey string `json:"cacheKey"` - }{} - require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) - assert.Equal(t, "hit", got.Result) - assert.Equal(t, keys[1], got.CacheKey) - archiveLocation = got.ArchiveLocation - } - { - resp, err := http.Get(archiveLocation) //nolint:gosec - require.NoError(t, err) - require.Equal(t, 200, resp.StatusCode) - got, err := io.ReadAll(resp.Body) - require.NoError(t, err) - assert.Equal(t, contents[1], got) - } + + resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + + /* + Expect `key_a_b` because: + - `key_a_b_x" doesn't match any caches. + - `key_a_b" matches `key_a_b` and `key_a_b_c`, but `key_a_b` is newer. + */ + except := 1 + + got := struct { + Result string `json:"result"` + ArchiveLocation string `json:"archiveLocation"` + CacheKey string `json:"cacheKey"` + }{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + assert.Equal(t, "hit", got.Result) + assert.Equal(t, keys[except], got.CacheKey) + + contentResp, err := http.Get(got.ArchiveLocation) + require.NoError(t, err) + require.Equal(t, 200, contentResp.StatusCode) + content, err := io.ReadAll(contentResp.Body) + require.NoError(t, err) + assert.Equal(t, contents[except], content) }) t.Run("case insensitive", func(t *testing.T) { @@ -469,3 +482,112 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte assert.Equal(t, content, got) } } + +func TestHandler_gcCache(t *testing.T) { + dir := filepath.Join(t.TempDir(), "artifactcache") + handler, err := StartHandler(dir, "", 0, nil) + require.NoError(t, err) + + defer func() { + require.NoError(t, handler.Close()) + }() + + now := time.Now() + + cases := []struct { + Cache *Cache + Kept bool + }{ + { + // should be kept, since it's used recently and not too old. + Cache: &Cache{ + Key: "test_key_1", + Version: "test_version", + Complete: true, + UsedAt: now.Unix(), + CreatedAt: now.Add(-time.Hour).Unix(), + }, + Kept: true, + }, + { + // should be removed, since it's not complete and not used for a while. + Cache: &Cache{ + Key: "test_key_2", + Version: "test_version", + Complete: false, + UsedAt: now.Add(-(keepTemp + time.Second)).Unix(), + CreatedAt: now.Add(-(keepTemp + time.Hour)).Unix(), + }, + Kept: false, + }, + { + // should be removed, since it's not used for a while. + Cache: &Cache{ + Key: "test_key_3", + Version: "test_version", + Complete: true, + UsedAt: now.Add(-(keepUnused + time.Second)).Unix(), + CreatedAt: now.Add(-(keepUnused + time.Hour)).Unix(), + }, + Kept: false, + }, + { + // should be removed, since it's used but too old. + Cache: &Cache{ + Key: "test_key_3", + Version: "test_version", + Complete: true, + UsedAt: now.Unix(), + CreatedAt: now.Add(-(keepUsed + time.Second)).Unix(), + }, + Kept: false, + }, + { + // should be kept, since it has a newer edition but be used recently. + Cache: &Cache{ + Key: "test_key_1", + Version: "test_version", + Complete: true, + UsedAt: now.Add(-(keepOld - time.Minute)).Unix(), + CreatedAt: now.Add(-(time.Hour + time.Second)).Unix(), + }, + Kept: true, + }, + { + // should be removed, since it has a newer edition and not be used recently. + Cache: &Cache{ + Key: "test_key_1", + Version: "test_version", + Complete: true, + UsedAt: now.Add(-(keepOld + time.Second)).Unix(), + CreatedAt: now.Add(-(time.Hour + time.Second)).Unix(), + }, + Kept: false, + }, + } + + db, err := handler.openDB() + require.NoError(t, err) + for _, c := range cases { + require.NoError(t, insertCache(db, c.Cache)) + } + require.NoError(t, db.Close()) + + handler.gcAt = time.Time{} // ensure gcCache will not skip + handler.gcCache() + + db, err = handler.openDB() + require.NoError(t, err) + for i, v := range cases { + t.Run(fmt.Sprintf("%d_%s", i, v.Cache.Key), func(t *testing.T) { + cache := &Cache{} + err = db.Get(v.Cache.ID, cache) + if v.Kept { + assert.NoError(t, err) + } else { + assert.ErrorIs(t, err, bolthold.ErrNotFound) + } + }) + } + require.NoError(t, db.Close()) +} diff --git a/pkg/artifactcache/model.go b/pkg/artifactcache/model.go index 32b8ce5..57812b3 100644 --- a/pkg/artifactcache/model.go +++ b/pkg/artifactcache/model.go @@ -1,10 +1,5 @@ package artifactcache -import ( - "crypto/sha256" - "fmt" -) - type Request struct { Key string `json:"key" ` Version string `json:"version"` @@ -29,16 +24,11 @@ func (c *Request) ToCache() *Cache { } type Cache struct { - ID uint64 `json:"id" boltholdKey:"ID"` - Key string `json:"key" boltholdIndex:"Key"` - Version string `json:"version" boltholdIndex:"Version"` - KeyVersionHash string `json:"keyVersionHash" boltholdUnique:"KeyVersionHash"` - Size int64 `json:"cacheSize"` - Complete bool `json:"complete"` - UsedAt int64 `json:"usedAt" boltholdIndex:"UsedAt"` - CreatedAt int64 `json:"createdAt" boltholdIndex:"CreatedAt"` -} - -func (c *Cache) FillKeyVersionHash() { - c.KeyVersionHash = fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%s:%s", c.Key, c.Version)))) + ID uint64 `json:"id" boltholdKey:"ID"` + Key string `json:"key" boltholdIndex:"Key"` + Version string `json:"version" boltholdIndex:"Version"` + Size int64 `json:"cacheSize"` + Complete bool `json:"complete" boltholdIndex:"Complete"` + UsedAt int64 `json:"usedAt" boltholdIndex:"UsedAt"` + CreatedAt int64 `json:"createdAt" boltholdIndex:"CreatedAt"` } From 3949d74af58d72309706e8fc5353de080fae6f3e Mon Sep 17 00:00:00 2001 From: James Kang <164518010+majorteach@users.noreply.github.com> Date: Fri, 29 Mar 2024 07:14:53 +0800 Subject: [PATCH 09/12] chore: remove repetitive words (#2259) Signed-off-by: majorteach Co-authored-by: ChristopherHX --- IMAGES.md | 2 +- pkg/runner/action_composite.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/IMAGES.md b/IMAGES.md index 7274ce2..62e795e 100644 --- a/IMAGES.md +++ b/IMAGES.md @@ -26,7 +26,7 @@ ## Images based on [`actions/virtual-environments`][gh/actions/virtual-environments] -**Note: `nektos/act-environments-ubuntu` have been last updated in February, 2020. It's recommended to update the image manually after `docker pull` if you decide to to use it.** +**Note: `nektos/act-environments-ubuntu` have been last updated in February, 2020. It's recommended to update the image manually after `docker pull` if you decide to use it.** | Image | Size | GitHub Repository | | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- | diff --git a/pkg/runner/action_composite.go b/pkg/runner/action_composite.go index 2e36d2e..1a47aff 100644 --- a/pkg/runner/action_composite.go +++ b/pkg/runner/action_composite.go @@ -27,7 +27,7 @@ func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_") envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey)) - // lookup if key is defined in the step but the the already + // lookup if key is defined in the step but the already // evaluated value from the environment _, defined := step.getStepModel().With[inputID] if value, ok := stepEnv[envKey]; defined && ok { From d9a19c8b02aea94b8e3291a25f63a513128e0d62 Mon Sep 17 00:00:00 2001 From: Jason Collins Date: Thu, 28 Mar 2024 16:28:48 -0700 Subject: [PATCH 10/12] Trivial: reduce log spam. (#2256) Co-authored-by: ChristopherHX --- pkg/common/executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/common/executor.go b/pkg/common/executor.go index a5eb079..2417356 100644 --- a/pkg/common/executor.go +++ b/pkg/common/executor.go @@ -97,7 +97,7 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor { errs := make(chan error, len(executors)) if 1 > parallel { - log.Infof("Parallel tasks (%d) below minimum, setting to 1", parallel) + log.Debugf("Parallel tasks (%d) below minimum, setting to 1", parallel) parallel = 1 } From f825e42ce200fc4973c3f28797ffba942d322d38 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Fri, 29 Mar 2024 03:07:20 +0100 Subject: [PATCH 11/12] fix: cache adjust restore order of exact key matches (#2267) * wip: adjust restore order * fixup * add tests * cleanup * fix typo --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- pkg/artifactcache/handler.go | 11 ++++ pkg/artifactcache/handler_test.go | 104 ++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/pkg/artifactcache/handler.go b/pkg/artifactcache/handler.go index 395a39e..065c7dd 100644 --- a/pkg/artifactcache/handler.go +++ b/pkg/artifactcache/handler.go @@ -352,6 +352,17 @@ func (h *Handler) middleware(handler httprouter.Handle) httprouter.Handle { func findCache(db *bolthold.Store, keys []string, version string) (*Cache, error) { cache := &Cache{} for _, prefix := range keys { + // if a key in the list matches exactly, don't return partial matches + if err := db.FindOne(cache, + bolthold.Where("Key").Eq(prefix). + And("Version").Eq(version). + And("Complete").Eq(true). + SortBy("CreatedAt").Reverse()); err == nil || !errors.Is(err, bolthold.ErrNotFound) { + if err != nil { + return nil, fmt.Errorf("find cache: %w", err) + } + return cache, nil + } prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix)) re, err := regexp.Compile(prefixPattern) if err != nil { diff --git a/pkg/artifactcache/handler_test.go b/pkg/artifactcache/handler_test.go index b418f00..252c420 100644 --- a/pkg/artifactcache/handler_test.go +++ b/pkg/artifactcache/handler_test.go @@ -422,6 +422,110 @@ func TestHandler(t *testing.T) { assert.Equal(t, key+"_abc", got.CacheKey) } }) + + t.Run("exact keys are preferred (key 0)", func(t *testing.T) { + version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20" + key := strings.ToLower(t.Name()) + keys := [3]string{ + key + "_a", + key + "_a_b_c", + key + "_a_b", + } + contents := [3][]byte{ + make([]byte, 100), + make([]byte, 200), + make([]byte, 300), + } + for i := range contents { + _, err := rand.Read(contents[i]) + require.NoError(t, err) + uploadCacheNormally(t, base, keys[i], version, contents[i]) + time.Sleep(time.Second) // ensure CreatedAt of caches are different + } + + reqKeys := strings.Join([]string{ + key + "_a", + key + "_a_b", + }, ",") + + resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + + /* + Expect `key_a` because: + - `key_a` matches `key_a`, `key_a_b` and `key_a_b_c`, but `key_a` is an exact match. + - `key_a_b` matches `key_a_b` and `key_a_b_c`, but previous key had a match + */ + expect := 0 + + got := struct { + ArchiveLocation string `json:"archiveLocation"` + CacheKey string `json:"cacheKey"` + }{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + assert.Equal(t, keys[expect], got.CacheKey) + + contentResp, err := http.Get(got.ArchiveLocation) + require.NoError(t, err) + require.Equal(t, 200, contentResp.StatusCode) + content, err := io.ReadAll(contentResp.Body) + require.NoError(t, err) + assert.Equal(t, contents[expect], content) + }) + + t.Run("exact keys are preferred (key 1)", func(t *testing.T) { + version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20" + key := strings.ToLower(t.Name()) + keys := [3]string{ + key + "_a", + key + "_a_b_c", + key + "_a_b", + } + contents := [3][]byte{ + make([]byte, 100), + make([]byte, 200), + make([]byte, 300), + } + for i := range contents { + _, err := rand.Read(contents[i]) + require.NoError(t, err) + uploadCacheNormally(t, base, keys[i], version, contents[i]) + time.Sleep(time.Second) // ensure CreatedAt of caches are different + } + + reqKeys := strings.Join([]string{ + "------------------------------------------------------", + key + "_a", + key + "_a_b", + }, ",") + + resp, err := http.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, reqKeys, version)) + require.NoError(t, err) + require.Equal(t, 200, resp.StatusCode) + + /* + Expect `key_a` because: + - `------------------------------------------------------` doesn't match any caches. + - `key_a` matches `key_a`, `key_a_b` and `key_a_b_c`, but `key_a` is an exact match. + - `key_a_b` matches `key_a_b` and `key_a_b_c`, but previous key had a match + */ + expect := 0 + + got := struct { + ArchiveLocation string `json:"archiveLocation"` + CacheKey string `json:"cacheKey"` + }{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + assert.Equal(t, keys[expect], got.CacheKey) + + contentResp, err := http.Get(got.ArchiveLocation) + require.NoError(t, err) + require.Equal(t, 200, contentResp.StatusCode) + content, err := io.ReadAll(contentResp.Body) + require.NoError(t, err) + assert.Equal(t, contents[expect], content) + }) } func uploadCacheNormally(t *testing.T, base, key, version string, content []byte) { From 361b7e9f1abe9081edf594aa35dede4eab972c70 Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 02:16:09 +0000 Subject: [PATCH 12/12] chore: bump VERSION to 0.2.61 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 84b554a..e957d10 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.60 \ No newline at end of file +0.2.61 \ No newline at end of file