Skip to content

Commit 4606279

Browse files
authored
feat: allow nameless executables (#212)
1 parent c7b630a commit 4606279

File tree

22 files changed

+199
-102
lines changed

22 files changed

+199
-102
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
<p align="center">
66
<a href="https://img.shields.io/github/v/release/jahvon/flow"><img src="https://img.shields.io/github/v/release/jahvon/flow" alt="GitHub release"></a>
77
<a href="https://pkg.go.dev/github.com/jahvon/flow"><img src="https://pkg.go.dev/badge/github.com/jahvon/flow.svg" alt="Go Reference"></a>
8-
<a href="https://goreportcard.com/report/github.com/jahvon/flow"><img src="https://goreportcard.com/badge/github.com/jahvon/flow" alt="Go Report Card"></a>
98
</p>
109

1110
<p align="center">

cmd/internal/exec.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func RegisterExecCmd(ctx *context.Context, rootCmd *cobra.Command) {
4040
io.TypesDocsURL("flowfile", "ExecutableRef"),
4141
execExamples,
4242
),
43-
Args: cobra.MinimumNArgs(1),
43+
Args: cobra.ArbitraryArgs,
4444
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
4545
execList, err := ctx.ExecutableCache.GetExecutableList(ctx.Logger)
4646
if err != nil {
@@ -82,8 +82,14 @@ func execFunc(ctx *context.Context, cmd *cobra.Command, verb executable.Verb, ar
8282
logger.FatalErr(err)
8383
}
8484

85-
idArg := args[0]
86-
ref := context.ExpandRef(ctx, executable.NewRef(idArg, verb))
85+
var ref executable.Ref
86+
if len(args) == 0 {
87+
ref = context.ExpandRef(ctx, executable.NewRef("", verb))
88+
} else {
89+
idArg := args[0]
90+
ref = context.ExpandRef(ctx, executable.NewRef(idArg, verb))
91+
}
92+
8793
e, err := ctx.ExecutableCache.GetExecutableByRef(logger, ref)
8894
if err != nil && errors.Is(cache.NewExecutableNotFoundError(ref.String()), err) {
8995
logger.Debugf("Executable %s not found in cache, syncing cache", ref)
@@ -108,7 +114,10 @@ func execFunc(ctx *context.Context, cmd *cobra.Command, verb executable.Verb, ar
108114
))
109115
}
110116

111-
execArgs := args[1:]
117+
execArgs := make([]string, 0)
118+
if len(args) >= 2 {
119+
execArgs = args[1:]
120+
}
112121
envMap, err := argUtils.ProcessArgs(e, execArgs, nil)
113122
if err != nil {
114123
logger.FatalErr(err)
@@ -369,6 +378,14 @@ Flag arguments are specified with the format 'flag=value' and positional argumen
369378
`
370379
execExamples = `
371380
#### Examples
381+
**Execute a nameless flow in the current workspace with the 'install' verb**
382+
383+
flow install
384+
385+
**Execute a nameless flow in the 'ws' workspace with the 'test' verb**
386+
387+
flow test ws
388+
372389
**Execute the 'build' flow in the current workspace and namespace**
373390
374391
flow exec build

cmd/internal/library.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ func libraryFunc(ctx *context.Context, cmd *cobra.Command, _ []string) {
4646
wsFilter := flags.ValueFor[string](ctx, cmd, *flags.FilterWorkspaceFlag, false)
4747
if wsFilter == "." {
4848
wsFilter = ctx.Config.CurrentWorkspace
49+
} else if wsFilter == executable.WildcardWorkspace {
50+
wsFilter = ""
4951
}
5052

5153
nsFilter := flags.ValueFor[string](ctx, cmd, *flags.FilterNamespaceFlag, false)
@@ -55,7 +57,7 @@ func libraryFunc(ctx *context.Context, cmd *cobra.Command, _ []string) {
5557
logger.PlainTextWarn("cannot use both --all and --namespace flags, ignoring --namespace")
5658
fallthrough
5759
case allNs:
58-
nsFilter = "*"
60+
nsFilter = executable.WildcardNamespace
5961
case nsFilter == ".":
6062
nsFilter = ctx.Config.CurrentNamespace
6163
}
@@ -122,7 +124,7 @@ func glanceLibraryCmd(ctx *context.Context, cmd *cobra.Command, _ []string) {
122124
logger.PlainTextWarn("cannot use both --all and --namespace flags, ignoring --namespace")
123125
fallthrough
124126
case allNs:
125-
nsFilter = "*"
127+
nsFilter = executable.WildcardNamespace
126128
case nsFilter == ".":
127129
nsFilter = ctx.Config.CurrentNamespace
128130
}
@@ -188,7 +190,7 @@ func viewLibraryFunc(ctx *context.Context, cmd *cobra.Command, args []string) {
188190
logger.FatalErr(err)
189191
}
190192
id := args[1]
191-
ws, ns, name := executable.ParseExecutableID(id)
193+
ws, ns, name := executable.MustParseExecutableID(id)
192194
if ws == "" {
193195
ws = ctx.CurrentWorkspace.AssignedName()
194196
}

development.flow

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
visibility: private
33
tags: [development]
44
executables:
5-
- verb: run
6-
name: checks
7-
aliases: [precommit, pc, ci, validate]
5+
- verb: validate
86
description: |
97
Run the repository validation checks. This includes linting, tests, and code generation.
108
Validate should be run before committing changes.

docs/cli/flow_exec.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ See https://flowexec.io/#/types/flowfile#ExecutableVerb for more information on
1616

1717

1818
#### Examples
19+
**Execute a nameless flow in the current workspace with the 'install' verb**
20+
21+
flow install
22+
23+
**Execute a nameless flow in the 'ws' workspace with the 'test' verb**
24+
25+
flow test ws
26+
1927
**Execute the 'build' flow in the current workspace and namespace**
2028

2129
flow exec build

docs/development.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ flow install deps
3434
flow build binary <output-path>
3535

3636
# Validate code changes (runs tests, linters, codegen, etc)
37-
flow run checks
37+
flow validate
3838

39-
# Run tests
39+
# Run only tests
4040
flow run tests
4141
```
4242

docs/guide/executable.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ the current workspace and namespace are assumed. See the [workspace guide](works
5656
5757
The name of an executable can also be replaced with an alias if one is defined in the flowfile.
5858
59+
**Nameless Executables**
60+
61+
If an executable is defined without a namespace and name, it is considered "nameless" and can be run by its verb alone.
62+
Nameless executables cannot exist within a namespace.
63+
64+
```shell
65+
# run the current workspaces nameless executable with the verb 'validate'
66+
flow validate
67+
# run the (non-current) 'my-project' workspaces nameless executable with the verb 'build'
68+
flow build my-project/
69+
```
70+
5971
## Flowfile
6072
6173
The flowfile is the primary configuration file that defines what an executable should do. The file is written in YAML but
@@ -89,7 +101,7 @@ executables:
89101
90102
### Executables
91103
92-
The only required field in an executable's configuration is the `name`.
104+
The only required field in an executable's configuration is the `name` (if the `namespace` is unset).
93105
94106
Additionally, you can define the following fields:
95107

docs/schemas/flowfile_schema.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"description": "The executable schema defines the structure of an executable in the Flow CLI.\nExecutables are the building blocks of workflows and are used to define the actions that can be performed in a workspace.\n",
3434
"type": "object",
3535
"required": [
36-
"name",
3736
"verb"
3837
],
3938
"properties": {
@@ -53,7 +52,7 @@
5352
"$ref": "#/definitions/ExecutableLaunchExecutableType"
5453
},
5554
"name": {
56-
"description": "The name of the executable. \n\nName is used to reference the executable in the CLI using the format `workspace:namespace/name`.\n[Verb group + Name] must be unique within the namespace of the workspace.\n",
55+
"description": "The name of the executable. \n\nName is used to reference the executable in the CLI using the format `workspace/namespace:name`.\n[Verb group + Name] must be unique within the namespace of the workspace. \nName is required if the executable is defined within a namespace.\n",
5756
"type": "string",
5857
"default": ""
5958
},
@@ -307,7 +306,7 @@
307306
}
308307
},
309308
"ExecutableRef": {
310-
"description": "A reference to an executable.\nThe format is `\u003cverb\u003e \u003cworkspace\u003e/\u003cnamespace\u003e:\u003cexecutable name\u003e`.\nFor example, `exec ws/ns:my-workflow`.\n\nThe workspace and namespace are optional.\nIf the workspace is not specified, the current workspace will be used.\nIf the namespace is not specified, the current namespace will be used.\n",
309+
"description": "A reference to an executable.\nThe format is `\u003cverb\u003e \u003cworkspace\u003e/\u003cnamespace\u003e:\u003cexecutable name\u003e`.\nFor example, `exec ws/ns:my-workflow`.\n\n- If the workspace is not specified, the current workspace will be used.\n- If the namespace is not specified, the current namespace will be used.\n- Excluding the name will reference the executable with a matching verb but an unspecified name and namespace (e.g. `exec ws` or simply `exec`).\n",
311310
"type": "string"
312311
},
313312
"ExecutableRenderExecutableType": {

docs/schemas/template_schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
}
4747
},
4848
"ExecutableRef": {
49-
"description": "A reference to an executable.\nThe format is `\u003cverb\u003e \u003cworkspace\u003e/\u003cnamespace\u003e:\u003cexecutable name\u003e`.\nFor example, `exec ws/ns:my-workflow`.\n\nThe workspace and namespace are optional.\nIf the workspace is not specified, the current workspace will be used.\nIf the namespace is not specified, the current namespace will be used.\n",
49+
"description": "A reference to an executable.\nThe format is `\u003cverb\u003e \u003cworkspace\u003e/\u003cnamespace\u003e:\u003cexecutable name\u003e`.\nFor example, `exec ws/ns:my-workflow`.\n\n- If the workspace is not specified, the current workspace will be used.\n- If the namespace is not specified, the current namespace will be used.\n- Excluding the name will reference the executable with a matching verb but an unspecified name and namespace (e.g. `exec ws` or simply `exec`).\n",
5050
"type": "string"
5151
},
5252
"Field": {

docs/types/flowfile.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Executables are the building blocks of workflows and are used to define the acti
8484
| `description` | A description of the executable. This description is rendered as markdown in the interactive UI. | `string` | | |
8585
| `exec` | | [ExecutableExecExecutableType](#ExecutableExecExecutableType) | <no value> | |
8686
| `launch` | | [ExecutableLaunchExecutableType](#ExecutableLaunchExecutableType) | <no value> | |
87-
| `name` | The name of the executable. Name is used to reference the executable in the CLI using the format `workspace:namespace/name`. [Verb group + Name] must be unique within the namespace of the workspace. | `string` | | |
87+
| `name` | The name of the executable. Name is used to reference the executable in the CLI using the format `workspace/namespace:name`. [Verb group + Name] must be unique within the namespace of the workspace. Name is required if the executable is defined within a namespace. | `string` | | |
8888
| `parallel` | | [ExecutableParallelExecutableType](#ExecutableParallelExecutableType) | <no value> | |
8989
| `render` | | [ExecutableRenderExecutableType](#ExecutableRenderExecutableType) | <no value> | |
9090
| `request` | | [ExecutableRequestExecutableType](#ExecutableRequestExecutableType) | <no value> | |
@@ -254,9 +254,9 @@ A reference to an executable.
254254
The format is `<verb> <workspace>/<namespace>:<executable name>`.
255255
For example, `exec ws/ns:my-workflow`.
256256

257-
The workspace and namespace are optional.
258-
If the workspace is not specified, the current workspace will be used.
259-
If the namespace is not specified, the current namespace will be used.
257+
- If the workspace is not specified, the current workspace will be used.
258+
- If the namespace is not specified, the current namespace will be used.
259+
- Excluding the name will reference the executable with a matching verb but an unspecified name and namespace (e.g. `exec ws` or simply `exec`).
260260

261261

262262
**Type:** `string`

0 commit comments

Comments
 (0)