From 9aa4c06154ea813eea28249e183a4578b989386e Mon Sep 17 00:00:00 2001 From: michaeljguarino Date: Fri, 30 Jun 2023 13:33:09 -0400 Subject: [PATCH] release command Allows you to trivially bulk tag module installations for an app on the command line. Ideally pluggable into cd pipelines as needed. --- cmd/plural/repos.go | 29 +++++++++++++++++++++++++++-- go.mod | 2 +- go.sum | 2 ++ pkg/api/client.go | 1 + pkg/api/repos.go | 6 +++++- pkg/test/mocks/Client.go | 25 +++++++++++++++++++------ pkg/test/mocks/Kube.go | 11 +++++------ 7 files changed, 60 insertions(+), 16 deletions(-) diff --git a/cmd/plural/repos.go b/cmd/plural/repos.go index ba41065b..3bc7c6f3 100644 --- a/cmd/plural/repos.go +++ b/cmd/plural/repos.go @@ -19,8 +19,20 @@ func (p *Plural) reposCommands() []cli.Command { { Name: "unlock", Usage: "unlocks installations in a repo that have breaking changes", - ArgsUsage: "REPO", - Action: latestVersion(p.handleUnlockRepo), + ArgsUsage: "APP", + Action: latestVersion(requireArgs(p.handleUnlockRepo, []string{"APP"})), + }, + { + Name: "release", + Usage: "tags the installations in the current cluster with the given release channels", + ArgsUsage: "APP", + Flags: []cli.Flag{ + cli.StringSliceFlag{ + Name: "tag", + Usage: "tag name for a given release channel, eg stable, warm, dev, prod", + }, + }, + Action: latestVersion(requireArgs(p.handleRelease, []string{"APP"})), }, { Name: "reinstall", @@ -63,6 +75,19 @@ func (p *Plural) reposCommands() []cli.Command { } } +func (p *Plural) handleRelease(c *cli.Context) error { + p.InitPluralClient() + app := c.Args().First() + tags := c.StringSlice("tag") + err := p.Release(c.Args().First(), c.StringSlice("tag")) + if err != nil { + return api.GetErrorResponse(err, "Release") + } + + utils.Success("Published release for %s to channels [%s]\n", app, strings.Join(tags, ", ")) + return nil +} + func (p *Plural) handleUnlockRepo(c *cli.Context) error { p.InitPluralClient() err := p.UnlockRepository(c.Args().First()) diff --git a/go.mod b/go.mod index ac38fe54..f582583e 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/packethost/packngo v0.29.0 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 - github.com/pluralsh/gqlclient v1.3.17 + github.com/pluralsh/gqlclient v1.3.18 github.com/pluralsh/plural-operator v0.5.3 github.com/pluralsh/polly v0.1.1 github.com/rodaine/hclencoder v0.0.1 diff --git a/go.sum b/go.sum index 67bc6dc1..372d712d 100644 --- a/go.sum +++ b/go.sum @@ -924,6 +924,8 @@ github.com/pluralsh/controller-reconcile-helper v0.0.4 h1:1o+7qYSyoeqKFjx+WgQTxD github.com/pluralsh/controller-reconcile-helper v0.0.4/go.mod h1:AfY0gtteD6veBjmB6jiRx/aR4yevEf6K0M13/pGan/s= github.com/pluralsh/gqlclient v1.3.17 h1:hD/rG+lhxP3kN1UUXrzZd2uN7P76MvNTEJEzYOpERXo= github.com/pluralsh/gqlclient v1.3.17/go.mod h1:z1qHnvPeqIN/a+5OzFs40e6HI6tDxzh1+yJuEpvqGy4= +github.com/pluralsh/gqlclient v1.3.18 h1:SthOBnlEgXh1bAKQXrZDNZRekaw3zDku4I4xgVsumDE= +github.com/pluralsh/gqlclient v1.3.18/go.mod h1:z1qHnvPeqIN/a+5OzFs40e6HI6tDxzh1+yJuEpvqGy4= github.com/pluralsh/oauth v0.9.2 h1:tM9hBK4tCnJUeCOgX0ctxBBCS3hiCDPoxkJLODtedmQ= github.com/pluralsh/oauth v0.9.2/go.mod h1:aTUw/75rzcsbvW+/TLvWtHVDXFIdtFrDtUncOq9vHyM= github.com/pluralsh/plural-operator v0.5.3 h1:GaPL3LgimfzKZNHt7zXzqYZpb0hgyW9noHYnkA+rqNs= diff --git a/pkg/api/client.go b/pkg/api/client.go index 1af67282..7264a58d 100644 --- a/pkg/api/client.go +++ b/pkg/api/client.go @@ -87,6 +87,7 @@ type Client interface { Cluster(id string) (*Cluster, error) CreateUpgrade(queue, repository string, attrs gqlclient.UpgradeAttributes) error TransferOwnership(name, email string) error + Release(name string, tags []string) error Chat(history []*ChatMessage) (*ChatMessage, error) } diff --git a/pkg/api/repos.go b/pkg/api/repos.go index 30a00b40..e0ac0bd2 100644 --- a/pkg/api/repos.go +++ b/pkg/api/repos.go @@ -209,8 +209,12 @@ func (client *client) ListRepositories(query string) ([]*Repository, error) { return res, err } -func (client *client) Scaffolds(in *ScaffoldInputs) ([]*ScaffoldFile, error) { +func (client *client) Release(name string, tags []string) error { + _, err := client.pluralClient.Release(context.Background(), name, tags) + return err +} +func (client *client) Scaffolds(in *ScaffoldInputs) ([]*ScaffoldFile, error) { scaffolds, err := client.pluralClient.Scaffolds(context.Background(), in.Application, in.Publisher, gqlclient.Category(strings.ToUpper(in.Category)), &in.Ingress, &in.Postgres) if err != nil { return nil, err diff --git a/pkg/test/mocks/Client.go b/pkg/test/mocks/Client.go index 22e7007f..e30b45b0 100644 --- a/pkg/test/mocks/Client.go +++ b/pkg/test/mocks/Client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.28.1. DO NOT EDIT. +// Code generated by mockery v2.30.16. DO NOT EDIT. package mocks @@ -1258,6 +1258,20 @@ func (_m *Client) PromoteCluster() error { return r0 } +// Release provides a mock function with given fields: name, tags +func (_m *Client) Release(name string, tags []string) error { + ret := _m.Called(name, tags) + + var r0 error + if rf, ok := ret.Get(0).(func(string, []string) error); ok { + r0 = rf(name, tags) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // ReleaseLock provides a mock function with given fields: repo, lock func (_m *Client) ReleaseLock(repo string, lock string) (*api.ApplyLock, error) { ret := _m.Called(repo, lock) @@ -1428,13 +1442,12 @@ func (_m *Client) UploadTerraform(dir string, repoName string) (api.Terraform, e return r0, r1 } -type mockConstructorTestingTNewClient interface { +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +}) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/pkg/test/mocks/Kube.go b/pkg/test/mocks/Kube.go index eac8f9c9..3b7ec01a 100644 --- a/pkg/test/mocks/Kube.go +++ b/pkg/test/mocks/Kube.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.28.1. DO NOT EDIT. +// Code generated by mockery v2.30.16. DO NOT EDIT. package mocks @@ -407,13 +407,12 @@ func (_m *Kube) WireguardServerList(namespace string) (*vpnv1alpha1.WireguardSer return r0, r1 } -type mockConstructorTestingTNewKube interface { +// NewKube creates a new instance of Kube. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewKube(t interface { mock.TestingT Cleanup(func()) -} - -// NewKube creates a new instance of Kube. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewKube(t mockConstructorTestingTNewKube) *Kube { +}) *Kube { mock := &Kube{} mock.Mock.Test(t)