Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions desktop/src-tauri/src/types/generated/flowfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2203,6 +2203,11 @@ impl ::std::default::Default for ExecutableVerb {
#[doc = " }"]
#[doc = " },"]
#[doc = " \"fromFile\": {"]
#[doc = " \"description\": \"DEPRECATED: Use `imports` instead\","]
#[doc = " \"default\": [],"]
#[doc = " \"$ref\": \"#/definitions/FromFile\""]
#[doc = " },"]
#[doc = " \"imports\": {"]
#[doc = " \"default\": [],"]
#[doc = " \"$ref\": \"#/definitions/FromFile\""]
#[doc = " },"]
Expand Down Expand Up @@ -2236,8 +2241,11 @@ pub struct FlowFile {
pub description_file: ::std::string::String,
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub executables: ::std::vec::Vec<Executable>,
#[doc = "DEPRECATED: Use `imports` instead"]
#[serde(rename = "fromFile", default = "defaults::flow_file_from_file")]
pub from_file: FromFile,
#[serde(default = "defaults::flow_file_imports")]
pub imports: FromFile,
#[doc = "The namespace to be given to all executables in the flow file.\nIf not set, the executables in the file will be grouped into the root (*) namespace. \nNamespaces can be reused across multiple flow files.\n\nNamespaces are used to reference executables in the CLI using the format `workspace:namespace/name`.\n"]
#[serde(default)]
pub namespace: ::std::string::String,
Expand All @@ -2259,6 +2267,7 @@ impl ::std::default::Default for FlowFile {
description_file: Default::default(),
executables: Default::default(),
from_file: defaults::flow_file_from_file(),
imports: defaults::flow_file_imports(),
namespace: Default::default(),
tags: Default::default(),
visibility: Default::default(),
Expand Down Expand Up @@ -3813,6 +3822,7 @@ pub mod builder {
executables:
::std::result::Result<::std::vec::Vec<super::Executable>, ::std::string::String>,
from_file: ::std::result::Result<super::FromFile, ::std::string::String>,
imports: ::std::result::Result<super::FromFile, ::std::string::String>,
namespace: ::std::result::Result<::std::string::String, ::std::string::String>,
tags: ::std::result::Result<::std::vec::Vec<::std::string::String>, ::std::string::String>,
visibility: ::std::result::Result<
Expand All @@ -3827,6 +3837,7 @@ pub mod builder {
description_file: Ok(Default::default()),
executables: Ok(Default::default()),
from_file: Ok(super::defaults::flow_file_from_file()),
imports: Ok(super::defaults::flow_file_imports()),
namespace: Ok(Default::default()),
tags: Ok(Default::default()),
visibility: Ok(Default::default()),
Expand Down Expand Up @@ -3877,6 +3888,16 @@ pub mod builder {
.map_err(|e| format!("error converting supplied value for from_file: {}", e));
self
}
pub fn imports<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::FromFile>,
T::Error: ::std::fmt::Display,
{
self.imports = value
.try_into()
.map_err(|e| format!("error converting supplied value for imports: {}", e));
self
}
pub fn namespace<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::string::String>,
Expand Down Expand Up @@ -3916,6 +3937,7 @@ pub mod builder {
description_file: value.description_file?,
executables: value.executables?,
from_file: value.from_file?,
imports: value.imports?,
namespace: value.namespace?,
tags: value.tags?,
visibility: value.visibility?,
Expand All @@ -3929,6 +3951,7 @@ pub mod builder {
description_file: Ok(value.description_file),
executables: Ok(value.executables),
from_file: Ok(value.from_file),
imports: Ok(value.imports),
namespace: Ok(value.namespace),
tags: Ok(value.tags),
visibility: Ok(value.visibility),
Expand Down Expand Up @@ -3992,4 +4015,7 @@ pub mod defaults {
pub(super) fn flow_file_from_file() -> super::FromFile {
super::FromFile(vec![])
}
pub(super) fn flow_file_imports() -> super::FromFile {
super::FromFile(vec![])
}
}
7 changes: 6 additions & 1 deletion desktop/src/types/generated/flowfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ export type CommonTags = string[];
*/
export type CommonVisibility = 'public' | 'private' | 'internal' | 'hidden';
/**
* A list of `.sh` files to convert into generated executables in the file's executable group.
* DEPRECATED: Use `imports` instead
*/
export type FromFile = string[];
/**
* A list of `.sh` files to convert into generated executables in the file's executable group.
*/
export type FromFile1 = string[];

/**
* Configuration for a group of Flow CLI executables. The file must have the extension `.flow`, `.flow.yaml`, or `.flow.yml`
Expand All @@ -62,6 +66,7 @@ export interface FlowFile {
descriptionFile?: string;
executables?: Executable[];
fromFile?: FromFile;
imports?: FromFile1;
/**
* The namespace to be given to all executables in the flow file.
* If not set, the executables in the file will be grouped into the root (*) namespace.
Expand Down
95 changes: 92 additions & 3 deletions docs/guide/executables.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,17 +356,31 @@ Current time: {{ .timestamp }}
- `templateFile`: Markdown template file (required)
- `templateDataFile`: JSON/YAML data file

## Generated Executables
## Importing Executables

Generate executables from shell scripts with special comments:
Generate executables from shell scripts, Makefiles, package.json scripts, or docker-compose services:

```yaml
# In flowfile
fromFile:
imports:
- "scripts/deploy.sh"
- "scripts/backup.sh"
- "Makefile"
- "frontend/package.json"
- "docker-compose.yaml"
```

All imported executables are automatically tagged with `generated` and their file type (e.g., `docker-compose`, `makefile`, `package.json`).


<!-- tabs:start -->

#### **Shell Scripts (.sh files)**

Shell scripts are imported as single executables with the script's filename as the name and `exec` as the default verb.

You can use special comments to override executable metadata:

```bash
#!/bin/bash
# scripts/deploy.sh
Expand Down Expand Up @@ -394,6 +408,81 @@ kubectl apply -f k8s/
# <f|description>
```

#### **Makefiles**

Makefile targets are imported as executables with a verb and name that best represents the target.

```makefile
# Makefile

# f:name=app f:verb=build f:description="Build the application"
build:
go build -o bin/app ./cmd/app

# Run all tests
test:
go test ./...

# f:visibility=internal
clean:
rm -rf bin/
```

The same comment parsing syntax works in Makefiles - use `# f:key=value` to override executable configuration.

#### **Package.json Scripts**

NPM scripts from package.json are imported as executables with a verb and name that best represents the script name.

```json
{
"scripts": {
"build": "webpack --mode production",
"test": "jest",
"dev": "webpack-dev-server --mode development",
"lint": "eslint src/"
}
}
```

This creates executables like:
- `build` - Runs the build script
- `test` - Runs the test script
- `start dev` - Runs the development server
- `lint` - Runs the linter

#### **Docker Compose Services**

Docker Compose files are imported to create executables for managing services:

```yaml
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"

db:
image: postgres:13
environment:
POSTGRES_DB: myapp

redis:
image: redis:6
```

This creates executables like:
- `start app` - Start the app service
- `start db` - Start the database service
- `start redis` - Start the Redis service
- `start` (alias: all, services) - Start all services
- `stop` (alias: all, services) - Stop all services
- `build app` - Build the app service (if build config exists)

<!-- tabs:end -->

## Executable References

Reference other executables to build modular workflows:
Expand Down
5 changes: 5 additions & 0 deletions docs/schemas/flowfile_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,11 @@
}
},
"fromFile": {
"$ref": "#/definitions/FromFile",
"description": "DEPRECATED: Use `imports` instead",
"default": []
},
"imports": {
"$ref": "#/definitions/FromFile",
"default": []
},
Expand Down
3 changes: 2 additions & 1 deletion docs/types/flowfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ in order to be discovered by the CLI. It's configuration is used to define a gro
| `description` | A description of the executables defined within the flow file. This description will used as a shared description for all executables in the flow file. | `string` | | |
| `descriptionFile` | A path to a markdown file that contains the description of the executables defined within the flow file. | `string` | | |
| `executables` | | `array` ([Executable](#Executable)) | [] | |
| `fromFile` | | [FromFile](#FromFile) | [] | |
| `fromFile` | DEPRECATED: Use `imports` instead | [FromFile](#FromFile) | [] | |
| `imports` | | [FromFile](#FromFile) | [] | |
| `namespace` | The namespace to be given to all executables in the flow file. If not set, the executables in the file will be grouped into the root (*) namespace. Namespaces can be reused across multiple flow files. Namespaces are used to reference executables in the CLI using the format `workspace:namespace/name`. | `string` | | |
| `tags` | Tags to be applied to all executables defined within the flow file. | `array` (`string`) | [] | |
| `visibility` | | [CommonVisibility](#CommonVisibility) | <no value> | |
Expand Down
88 changes: 0 additions & 88 deletions internal/cache/executable_generator.go

This file was deleted.

9 changes: 5 additions & 4 deletions internal/cache/executables_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/pkg/errors"
"gopkg.in/yaml.v3"

"github.com/flowexec/flow/internal/fileparser"
"github.com/flowexec/flow/internal/filesystem"
"github.com/flowexec/flow/types/common"
"github.com/flowexec/flow/types/executable"
Expand Down Expand Up @@ -69,8 +70,8 @@ func (c *ExecutableCacheImpl) Update(logger io.Logger) error { //nolint:gocognit
continue
}
for _, flowFile := range flowFiles {
if len(flowFile.FromFile) > 0 {
generated, err := generatedExecutables(logger, name, flowFile)
if len(flowFile.FromFile) > 0 || len(flowFile.Imports) > 0 {
generated, err := fileparser.ExecutablesFromImports(logger, name, flowFile)
if err != nil {
logger.Errorx(
"failed to generate executables from files",
Expand Down Expand Up @@ -160,7 +161,7 @@ func (c *ExecutableCacheImpl) GetExecutableByRef(logger io.Logger, ref executabl
cfg.SetDefaults()
cfg.SetContext(wsInfo.WorkspaceName, wsInfo.WorkspacePath, cfgPath)

generated, err := generatedExecutables(logger, wsInfo.WorkspaceName, cfg)
generated, err := fileparser.ExecutablesFromImports(logger, wsInfo.WorkspaceName, cfg)
if err != nil {
logger.Warnx(
"failed to generate executables from files",
Expand Down Expand Up @@ -206,7 +207,7 @@ func (c *ExecutableCacheImpl) GetExecutableList(logger io.Logger) (executable.Ex
cfg.SetDefaults()
cfg.SetContext(wsInfo.WorkspaceName, wsInfo.WorkspacePath, cfgPath)

generated, err := generatedExecutables(logger, wsInfo.WorkspaceName, cfg)
generated, err := fileparser.ExecutablesFromImports(logger, wsInfo.WorkspaceName, cfg)
if err != nil {
logger.Warnx(
"failed to generate executables from files",
Expand Down
Loading
Loading