github.com/actions-on-google/gactions@v3.2.0+incompatible/cmd/gactions/cli/releasechannels/releasechannels.go (about) 1 // Copyright 2021 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Package releasechannels provides an implementation of an action on "release-channels". 16 package releasechannels 17 18 import ( 19 "context" 20 "fmt" 21 "os" 22 "regexp" 23 "text/tabwriter" 24 25 "github.com/actions-on-google/gactions/api/sdk" 26 "github.com/actions-on-google/gactions/project" 27 "github.com/actions-on-google/gactions/project/studio" 28 "github.com/spf13/cobra" 29 ) 30 31 var releaseChannelNameRegExp = regexp.MustCompile(`^projects/[^/]+/releaseChannels/(?P<releaseChannelName>[^/]+)$`) 32 var releaseChannelPrefixRegExp = regexp.MustCompile(`^actions[\.]channels[\.](?P<unknownBuiltInReleaseChannelName>[^/]+)$`) 33 var versionIDRegExp = regexp.MustCompile(`^projects/[^/]+/versions/(?P<versionID>[^/]+)$`) 34 35 // AddCommand adds the release-channels list sub-command to the passed in root command. 36 func AddCommand(ctx context.Context, root *cobra.Command, project project.Project) { 37 releaseChannels := &cobra.Command{ 38 Use: "release-channels", 39 Short: "This is the main command for viewing and managing release channels. See below for a complete list of sub-commands.", 40 Long: "This is the main command for viewing and managing release channels. See below for a complete list of sub-commands.", 41 Args: cobra.MinimumNArgs(1), 42 } 43 list := &cobra.Command{ 44 Use: "list", 45 Short: "This command lists information about release channels for the project and their current and pending versions.", 46 Long: "This command lists information about release channels for the project and their current and pending versions.", 47 RunE: func(cmd *cobra.Command, args []string) error { 48 studioProj, ok := project.(studio.Studio) 49 if !ok { 50 return fmt.Errorf("can not convert %T to %T", project, studio.Studio{}) 51 } 52 pid, err := cmd.Flags().GetString("project-id") 53 if err != nil { 54 return err 55 } 56 if err := (&studioProj).SetProjectID(pid); err != nil { 57 return err 58 } 59 res, err := sdk.ListReleaseChannelsJSON(ctx, studioProj) 60 if err != nil { 61 return err 62 } 63 printReleaseChannels(res) 64 return nil 65 }, 66 } 67 list.Flags().String("project-id", "", "List release channels of the project specified by the ID. The value provided in this flag will overwrite the value from settings file, if present.") 68 releaseChannels.AddCommand(list) 69 root.AddCommand(releaseChannels) 70 } 71 72 func printReleaseChannels(releaseChannels []project.ReleaseChannel) { 73 w := new(tabwriter.Writer) 74 // Format in tab-separated columns with a tab stop of 8. 75 w.Init(os.Stdout, 40, 8, 1, '\t', 0) 76 fmt.Fprintln(w, "Release Channel\tCurrent Version\tPending Version\t") 77 for _, releaseChannel := range releaseChannels { 78 fmt.Fprintf(w, "%v\t%v\t%v\t\n", releaseChannelName(releaseChannel.Name), versionID(releaseChannel.CurrentVersion), versionID(releaseChannel.PendingVersion)) 79 } 80 fmt.Fprintf(w, "To learn more about release channels, visit https://developers.google.com/assistant/actionssdk/reference/rest/Shared.Types/ReleaseChannel.") 81 fmt.Fprintln(w) 82 w.Flush() 83 } 84 85 func releaseChannelName(releaseChannel string) string { 86 releaseChannelMatch := releaseChannelNameRegExp.FindStringSubmatch(releaseChannel) 87 if releaseChannelMatch == nil { 88 return "N/A" 89 } 90 releaseChannelName := releaseChannelMatch[releaseChannelNameRegExp.SubexpIndex("releaseChannelName")] 91 92 // If release channel is a known built-in release channel with a short name, fetch the short name and display it. 93 displayReleaseChannelName, found := sdk.BuiltInReleaseChannels[releaseChannelName] 94 if found { 95 return displayReleaseChannelName 96 } 97 98 // Else, check for prefix "actions.channels", and if present, remove it. This is used as a catch for built in channels without short names in the map. 99 releaseChannelPrefixMatch := releaseChannelPrefixRegExp.FindStringSubmatch(releaseChannelName) 100 if releaseChannelPrefixMatch == nil { 101 return releaseChannelName 102 } 103 return releaseChannelPrefixMatch[releaseChannelPrefixRegExp.SubexpIndex("unknownBuiltInReleaseChannelName")] 104 } 105 106 func versionID(version string) string { 107 if versionIDMatch := versionIDRegExp.FindStringSubmatch(version); versionIDMatch == nil { 108 return "N/A" 109 } 110 return versionIDRegExp.FindStringSubmatch(version)[versionIDRegExp.SubexpIndex("versionID")] 111 }