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  }