Skip to content

Commit

Permalink
feat: support version creation during actions create (#68)
Browse files Browse the repository at this point in the history
* feat: support version creation during actions create

* lint fixes

* bump auth0 dep

* update action version view

* fix action and version rendering

* Fix regex

* Using backtick to skip double escape

* add hack to fetch latest version/draft state after create for display

* lint

Co-authored-by: Danny Turcotte <[email protected]>
  • Loading branch information
iamjem and turcottedanny authored Jan 27, 2021
1 parent ffb9c62 commit 5d8a0c6
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 41 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ require (

// replace gopkg.in/auth0.v5 => ../auth0

replace gopkg.in/auth0.v5 => github.com/go-auth0/auth0 v1.3.1-0.20210127040011-acb7c665d062
replace gopkg.in/auth0.v5 => github.com/go-auth0/auth0 v1.3.1-0.20210127122814-819354e637e9
12 changes: 2 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/briandowns/spinner v1.11.1 h1:OixPqDEcX3juo5AjQZAnFPbeUA0jvkp2qzB5gOZJ/L0=
github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw=
github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down Expand Up @@ -84,14 +82,8 @@ github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-auth0/auth0 v1.3.1-0.20210126164439-7451a183abbd h1:O1ZCQlPODGWJNDT0qH6SpGdFEcEBWz7dd/mHFw6Kh10=
github.com/go-auth0/auth0 v1.3.1-0.20210126164439-7451a183abbd/go.mod h1:QQ9fgGj2Wpza15+Ho3mM6amMeKfhzHo2cixcOqdkoKk=
github.com/go-auth0/auth0 v1.3.1-0.20210126214458-2807092480f8 h1:x5rbuD/ay7ieXnEynRnTA92qHbe6uMTxumOWfsCPiws=
github.com/go-auth0/auth0 v1.3.1-0.20210126214458-2807092480f8/go.mod h1:QQ9fgGj2Wpza15+Ho3mM6amMeKfhzHo2cixcOqdkoKk=
github.com/go-auth0/auth0 v1.3.1-0.20210127020221-38fd79682c4a h1:TAnbIrM2gdxfqT4pdPso61aO74mS+mNuIbRDYhfSNKI=
github.com/go-auth0/auth0 v1.3.1-0.20210127020221-38fd79682c4a/go.mod h1:QQ9fgGj2Wpza15+Ho3mM6amMeKfhzHo2cixcOqdkoKk=
github.com/go-auth0/auth0 v1.3.1-0.20210127040011-acb7c665d062 h1:WOCTdmjxtCBWcSL34/v0lzvyqGvlPlH76ns86EUuF98=
github.com/go-auth0/auth0 v1.3.1-0.20210127040011-acb7c665d062/go.mod h1:QQ9fgGj2Wpza15+Ho3mM6amMeKfhzHo2cixcOqdkoKk=
github.com/go-auth0/auth0 v1.3.1-0.20210127122814-819354e637e9 h1:/Lolghe1pufQWJ+JcmX0UToYIr7bpNpDzo6PoVbFLX8=
github.com/go-auth0/auth0 v1.3.1-0.20210127122814-819354e637e9/go.mod h1:QQ9fgGj2Wpza15+Ho3mM6amMeKfhzHo2cixcOqdkoKk=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Expand Down
3 changes: 2 additions & 1 deletion internal/auth0/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ type ActionAPI interface {
type ActionVersionAPI interface {
Create(actionID string, v *management.ActionVersion) error
Read(actionID string, id string) (*management.ActionVersion, error)
UpsertDraft(id string, a *management.ActionVersion) error
UpsertDraft(actionID string, v *management.ActionVersion) error
ReadDraft(actionID string) (*management.ActionVersion, error)
Delete(actionID string, id string, opts ...management.RequestOption) error
List(actionID string, opts ...management.RequestOption) (c *management.ActionVersionList, err error)
Test(actionID string, id string, payload management.Object) (management.Object, error)
Expand Down
109 changes: 97 additions & 12 deletions internal/cli/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -256,27 +257,35 @@ func listActionVersionsCmd(cli *cli) *cobra.Command {
}

func createActionCmd(cli *cli) *cobra.Command {
var (
name string
trigger string
file string
script string
dependency []string
createVersion bool
)

cmd := &cobra.Command{
Use: "create",
Short: "Creates a new action",
Long: `$ auth0 actions create
Creates a new action:
$ auth0 actions create my-action --trigger post-login
$ auth0 actions create --name my-action --trigger post-login --file action.js --dependency [email protected]
`,
Args: func(cmd *cobra.Command, args []string) error {
if err := validators.ExactArgs("name")(cmd, args); err != nil {
RunE: func(cmd *cobra.Command, args []string) error {
if err := validators.TriggerID(trigger); err != nil {
return err
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
trigger, err := cmd.LocalFlags().GetString("trigger")

source, err := sourceFromFileOrScript(file, script)
if err != nil {
return err
}

if err := validators.TriggerID(trigger); err != nil {
dependencies, err := validators.Dependencies(dependency)
if err != nil {
return err
}

Expand All @@ -289,24 +298,73 @@ Creates a new action:
}

action := &management.Action{
Name: auth0.String(args[0]),
Name: auth0.String(name),
SupportedTriggers: &triggers,
}

version := &management.ActionVersion{
Code: source,
Dependencies: dependencies,
Runtime: "node12",
}

err = ansi.Spinner("Creating action", func() error {
return cli.api.Action.Create(action)
if err := cli.api.Action.Create(action); err != nil {
return err
}

if createVersion {
if err := cli.api.ActionVersion.Create(auth0.StringValue(action.ID), version); err != nil {
return err
}

// TODO(iamjem): this is a hack since the SDK won't decode 202 responses
list, err := cli.api.ActionVersion.List(auth0.StringValue(action.ID))
if err != nil {
return err
}

if len(list.Versions) > 0 {
version = list.Versions[0]
}
} else {
if err := cli.api.ActionVersion.UpsertDraft(auth0.StringValue(action.ID), version); err != nil {
return err
}

// TODO(iamjem): this is a hack since the SDK won't decode 202 responses
draft, err := cli.api.ActionVersion.ReadDraft(auth0.StringValue(action.ID))
if err != nil {
return err
}
version = draft
}

return nil
})

if err != nil {
return err
}

cli.renderer.Action(action)
cli.renderer.ActionVersion(version)

return nil
},
}

cmd.Flags().StringP("trigger", "t", string(management.PostLogin), "Trigger type for action.")
cmd.Flags().StringVarP(&name, "name", "n", "", "Unique name for the action.")
cmd.Flags().StringVarP(&trigger, "trigger", "t", string(management.PostLogin), "Trigger type for action.")
cmd.Flags().StringVarP(&file, "file", "f", "", "File containing the action source code.")
cmd.Flags().StringVarP(&script, "script", "s", "", "Raw source code for the action.")
cmd.Flags().StringSliceVarP(&dependency, "dependency", "d", nil, "Dependency for the source code (<name>@<semver>).")
// TODO: This name is kind of overloaded since it could also refer to the version of the trigger (though there's only v1's at this time)
cmd.Flags().BoolVarP(&createVersion, "version", "v", false, "Create an explicit action version from the source code instead of a draft.")

mustRequireFlags(cmd, "name")
if err := cmd.MarkFlagFilename("file"); err != nil {
panic(err)
}

return cmd
}
Expand Down Expand Up @@ -448,3 +506,30 @@ func createTriggerCmd(cli *cli) *cobra.Command {

return cmd
}

var errNoSource = errors.New("please provide source code via --file or --script")

func sourceFromFileOrScript(file, script string) (string, error) {
if script != "" {
return script, nil
}

if file != "" {
f, err := os.Open(file)
if err != nil {
return "", err
}
defer f.Close()

contents, err := ioutil.ReadAll(f)
if err != nil {
return "", err
}

if len(contents) > 0 {
return string(contents), nil
}
}

return "", errNoSource
}
42 changes: 28 additions & 14 deletions internal/display/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,28 @@ func (v *triggerView) AsTableRow() []string {
}

type actionVersionView struct {
ID string
Status string
Runtime string
CreatedAt string
ID string
ActionID string
ActionName string
Runtime string
Status string
CreatedAt string
}

func (v *actionVersionView) AsTableHeader() []string {
return []string{"ID", "Status", "Runtime", "Created At"}
return []string{"ID", "Action ID", "Action Name", "Runtime", "Status", "Created At"}
}

func (v *actionVersionView) AsTableRow() []string {
return []string{v.ID, v.Status, v.Runtime, v.CreatedAt}
return []string{v.getID(), v.ActionID, v.ActionName, v.Runtime, v.Status, v.CreatedAt}
}

func (v *actionVersionView) getID() string {
// draft versions don't have a unique id
if v.ID == "" {
return "draft"
}
return v.ID
}

func (r *Renderer) ActionList(actions []*management.Action) {
Expand Down Expand Up @@ -118,10 +128,12 @@ func (r *Renderer) ActionVersion(version *management.ActionVersion) {
r.Heading(ansi.Bold(r.Tenant), "action version\n")

v := &actionVersionView{
ID: auth0.StringValue(&version.ID),
Status: string(version.Status),
Runtime: auth0.StringValue(&version.Runtime),
CreatedAt: timeAgo(auth0.TimeValue(version.CreatedAt)),
ID: version.ID,
ActionID: auth0.StringValue(version.Action.ID),
ActionName: auth0.StringValue(version.Action.ID),
Runtime: auth0.StringValue(&version.Runtime),
Status: string(version.Status),
CreatedAt: timeAgo(auth0.TimeValue(version.CreatedAt)),
}

r.Results([]View{v})
Expand All @@ -133,10 +145,12 @@ func (r *Renderer) ActionVersionList(list []*management.ActionVersion) {
var res []View
for _, version := range list {
res = append(res, &actionVersionView{
ID: auth0.StringValue(&version.ID),
Status: string(version.Status),
Runtime: auth0.StringValue(&version.Runtime),
CreatedAt: timeAgo(auth0.TimeValue(version.CreatedAt)),
ID: auth0.StringValue(&version.ID),
ActionID: auth0.StringValue(version.Action.ID),
ActionName: auth0.StringValue(version.Action.Name),
Runtime: auth0.StringValue(&version.Runtime),
Status: string(version.Status),
CreatedAt: timeAgo(auth0.TimeValue(version.CreatedAt)),
})
}

Expand Down
35 changes: 35 additions & 0 deletions internal/validators/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package validators

import (
"fmt"
"regexp"
"strings"

"gopkg.in/auth0.v5/management"
Expand All @@ -24,3 +25,37 @@ func TriggerID(trigger string) error {

return fmt.Errorf("%s is not a valid trigger type (%s)", trigger, strings.Join(allTriggerIDs, ", "))
}

var semverRe = regexp.MustCompile(`^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)

// Dependencies parses a slice of dependencies of the format <name>@<semver> and returns them in their
// management.Dependency form.
func Dependencies(deps []string) ([]management.Dependency, error) {
dependencies := make([]management.Dependency, 0)
for _, dep := range deps {
name, version, err := splitNameVersion(dep)
if err != nil {
return nil, err
}
dependencies = append(dependencies, management.Dependency{
Name: name,
Version: version,
})
}
return dependencies, nil
}

func splitNameVersion(val string) (string, string, error) {
parts := strings.SplitN(val, "@", 2)
if len(parts) != 2 {
return "", "", fmt.Errorf("dependency %s missing version", val)
}

name, version := parts[0], parts[1]

if !semverRe.MatchString(version) {
return "", "", fmt.Errorf("invalid semver %s for dependency %s", name, version)
}

return name, version, nil
}
8 changes: 7 additions & 1 deletion vendor/gopkg.in/auth0.v5/management/actions.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ google.golang.org/protobuf/reflect/protoreflect
google.golang.org/protobuf/reflect/protoregistry
google.golang.org/protobuf/runtime/protoiface
google.golang.org/protobuf/runtime/protoimpl
# gopkg.in/auth0.v5 v5.8.0 => github.com/go-auth0/auth0 v1.3.1-0.20210127040011-acb7c665d062
# gopkg.in/auth0.v5 v5.8.0 => github.com/go-auth0/auth0 v1.3.1-0.20210127122814-819354e637e9
## explicit
gopkg.in/auth0.v5
gopkg.in/auth0.v5/internal/client
Expand All @@ -150,4 +150,4 @@ gopkg.in/auth0.v5/management
# gopkg.in/yaml.v2 v2.2.8
## explicit
gopkg.in/yaml.v2
# gopkg.in/auth0.v5 => github.com/go-auth0/auth0 v1.3.1-0.20210127040011-acb7c665d062
# gopkg.in/auth0.v5 => github.com/go-auth0/auth0 v1.3.1-0.20210127122814-819354e637e9

0 comments on commit 5d8a0c6

Please sign in to comment.