Skip to content
Merged
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
16 changes: 6 additions & 10 deletions pkg/cmd/cache/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co
# Delete all caches (exit code 1 on no caches)
$ gh cache delete --all

# Delete all caches for a specific ref
$ gh cache delete --all --ref refs/pull/<PR-number>/merge

# Delete all caches (exit code 0 on no caches)
$ gh cache delete --all --succeed-on-no-caches
`),
Expand All @@ -76,18 +79,11 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co
return err
}

if err := cmdutil.MutuallyExclusive(
"--ref cannot be used with --all",
opts.DeleteAll, opts.Ref != "",
); err != nil {
return err
}

if !opts.DeleteAll && opts.SucceedOnNoCaches {
return cmdutil.FlagErrorf("--succeed-on-no-caches must be used in conjunction with --all")
}

if opts.Ref != "" && len(args) == 0 {
if opts.Ref != "" && len(args) == 0 && !opts.DeleteAll {
return cmdutil.FlagErrorf("must provide a cache key")
}

Expand All @@ -113,7 +109,7 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co
},
}

cmd.Flags().BoolVarP(&opts.DeleteAll, "all", "a", false, "Delete all caches")
cmd.Flags().BoolVarP(&opts.DeleteAll, "all", "a", false, "Delete all caches, can be used with --ref to delete all caches for a specific ref")
cmd.Flags().StringVarP(&opts.Ref, "ref", "r", "", "Delete by cache key and ref, formatted as refs/heads/<branch name> or refs/pull/<number>/merge")
cmd.Flags().BoolVar(&opts.SucceedOnNoCaches, "succeed-on-no-caches", false, "Return exit code 0 if no caches found. Must be used in conjunction with `--all`")

Expand All @@ -135,7 +131,7 @@ func deleteRun(opts *DeleteOptions) error {
var toDelete []string
if opts.DeleteAll {
opts.IO.StartProgressIndicator()
caches, err := shared.GetCaches(client, repo, shared.GetCachesOptions{Limit: -1})
caches, err := shared.GetCaches(client, repo, shared.GetCachesOptions{Limit: -1, Ref: opts.Ref})
opts.IO.StopProgressIndicator()
if err != nil {
return err
Expand Down
82 changes: 79 additions & 3 deletions pkg/cmd/cache/delete/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ func TestNewCmdDelete(t *testing.T) {
wantsErr: "--ref cannot be used with cache ID",
},
{
name: "ref flag with all flag",
cli: "--all --ref refs/heads/main",
wantsErr: "--ref cannot be used with --all",
name: "ref flag with all flag",
cli: "--all --ref refs/heads/main",
wants: DeleteOptions{DeleteAll: true, Ref: "refs/heads/main"},
},
}

Expand Down Expand Up @@ -374,6 +374,82 @@ func TestDeleteRun(t *testing.T) {
wantErr: true,
wantErrMsg: "X Could not find a cache matching existing-cache-key (with ref invalid-ref) in OWNER/REPO",
},
{
name: "deletes all caches with ref",
opts: DeleteOptions{DeleteAll: true, Ref: "refs/heads/main"},
stubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.QueryMatcher("GET", "repos/OWNER/REPO/actions/caches", url.Values{
"ref": []string{"refs/heads/main"},
}),
httpmock.JSONResponse(shared.CachePayload{
ActionsCaches: []shared.Cache{
{
Id: 123,
Key: "foo",
Ref: "refs/heads/main",
CreatedAt: time.Date(2021, 1, 1, 1, 1, 1, 1, time.UTC),
LastAccessedAt: time.Date(2022, 1, 1, 1, 1, 1, 1, time.UTC),
},
{
Id: 456,
Key: "bar",
Ref: "refs/heads/main",
CreatedAt: time.Date(2021, 1, 1, 1, 1, 1, 1, time.UTC),
LastAccessedAt: time.Date(2022, 1, 1, 1, 1, 1, 1, time.UTC),
},
},
TotalCount: 2,
}),
)
reg.Register(
httpmock.REST("DELETE", "repos/OWNER/REPO/actions/caches/123"),
httpmock.StatusStringResponse(204, ""),
)
reg.Register(
httpmock.REST("DELETE", "repos/OWNER/REPO/actions/caches/456"),
httpmock.StatusStringResponse(204, ""),
)
},
tty: true,
wantStdout: "✓ Deleted 2 caches from OWNER/REPO\n",
},
{
name: "no caches to delete when deleting all with ref",
opts: DeleteOptions{DeleteAll: true, Ref: "refs/heads/main"},
stubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.QueryMatcher("GET", "repos/OWNER/REPO/actions/caches", url.Values{
"ref": []string{"refs/heads/main"},
}),
httpmock.JSONResponse(shared.CachePayload{
ActionsCaches: []shared.Cache{},
TotalCount: 0,
}),
)
},
tty: false,
wantErr: true,
wantErrMsg: "X No caches to delete",
},
{
name: "no caches to delete when deleting all for ref but succeed on no cache tty",
opts: DeleteOptions{DeleteAll: true, SucceedOnNoCaches: true, Ref: "refs/heads/main"},
stubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.QueryMatcher("GET", "repos/OWNER/REPO/actions/caches", url.Values{
"ref": []string{"refs/heads/main"},
}),
httpmock.JSONResponse(shared.CachePayload{
ActionsCaches: []shared.Cache{},
TotalCount: 0,
}),
)
},
tty: true,
wantErr: false,
wantStdout: "✓ No caches to delete\n",
},
}

for _, tt := range tests {
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/copilot/copilot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,9 @@ func TestFetchExpectedChecksum(t *testing.T) {
)

client := &http.Client{Transport: reg}
_, err := fetchExpectedChecksum(client, "https://example.com/checksums", "copilot-windows-x64.zip")
_, err := fetchExpectedChecksum(client, "https://example.com/checksums", "copilot-win32-x64.zip")
require.Error(t, err, "expected error for missing archive")
require.Equal(t, "checksum not found for copilot-windows-x64.zip", err.Error(), "unexpected error")
require.Equal(t, "checksum not found for copilot-win32-x64.zip", err.Error(), "unexpected error")
})

t.Run("handles single space separator", func(t *testing.T) {
Expand Down