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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ concore init my-project
# Validate your workflow
concore validate workflow.graphml

# Run your workflow
concore run workflow.graphml --auto-build
# Compile your workflow
concore build workflow.graphml --auto-build
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This quick-start section now uses concore build, which is correct, but readers following older instructions may still try concore run. Consider adding a brief migration note here (e.g., 'run was renamed to build') so the top-level README helps users troubleshoot command-not-found errors.

Suggested change
concore build workflow.graphml --auto-build
concore build workflow.graphml --auto-build
# Note: older instructions may use 'concore run'; this was renamed to 'concore build'.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required, since we are still in development phase


# Monitor running processes
concore status
Expand Down
14 changes: 7 additions & 7 deletions concore_cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ cd my-project
# Validate your workflow
concore validate workflow.graphml

# Run your workflow
concore run workflow.graphml
# Build your workflow
concore build workflow.graphml

# Check running processes
concore status
Expand Down Expand Up @@ -53,9 +53,9 @@ my-workflow/
└── README.md # Project documentation
```

### `concore run <workflow_file>`
### `concore build <workflow_file>`

Generates and optionally builds a workflow from a GraphML file.
Compiles a concore workflow GraphML file into executable scripts (POSIX, Windows, or Docker).

**Options:**
- `-s, --source <dir>` - Source directory (default: src)
Expand All @@ -66,13 +66,13 @@ Generates and optionally builds a workflow from a GraphML file.

**Example:**
```bash
concore run workflow.graphml --source ./src --output ./build --auto-build
concore build workflow.graphml --source ./src --output ./build --auto-build
```

Docker compose example:

```bash
concore run workflow.graphml --source ./src --output ./out --type docker --compose
concore build workflow.graphml --source ./src --output ./out --type docker --compose
cd out
docker compose up
```
Expand Down Expand Up @@ -150,7 +150,7 @@ concore stop

5. **Generate and run**
```bash
concore run workflow.graphml --auto-build
concore build workflow.graphml --auto-build
cd out
./run.bat # or ./run on Linux/Mac
```
Expand Down
10 changes: 5 additions & 5 deletions concore_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys

from .commands.init import init_project, init_project_interactive, run_wizard
from .commands.run import run_workflow
from .commands.build import build_workflow
from .commands.validate import validate_workflow
from .commands.status import show_status
from .commands.stop import stop_all
Expand Down Expand Up @@ -68,17 +68,17 @@ def init(name, template, interactive):
help="Execution type",
)
@click.option(
"--auto-build", is_flag=True, help="Automatically run build after generation"
"--auto-build", is_flag=True, help="Automatically run build script after generation"
)
@click.option(
"--compose",
is_flag=True,
help="Generate docker-compose.yml in output directory (docker type only)",
)
def run(workflow_file, source, output, type, auto_build, compose):
"""Run a concore workflow"""
def build(workflow_file, source, output, type, auto_build, compose):
"""Compile a concore workflow into executable scripts"""
try:
run_workflow(
build_workflow(
workflow_file,
source,
output,
Expand Down
4 changes: 2 additions & 2 deletions concore_cli/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .init import init_project
from .run import run_workflow
from .build import build_workflow
from .validate import validate_workflow
from .status import show_status
from .stop import stop_all
Expand All @@ -8,7 +8,7 @@

__all__ = [
"init_project",
"run_workflow",
"build_workflow",
"validate_workflow",
"show_status",
"stop_all",
Expand Down
4 changes: 2 additions & 2 deletions concore_cli/commands/run.py → concore_cli/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _write_docker_compose(output_path):
return compose_path


def run_workflow(
def build_workflow(
workflow_file,
source,
output,
Expand Down Expand Up @@ -201,7 +201,7 @@ def run_workflow(
try:
metadata_path = write_study_metadata(
output_path,
generated_by="concore run",
generated_by="concore build",
workflow_file=workflow_path,
)
console.print(
Expand Down
8 changes: 4 additions & 4 deletions concore_cli/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@

1. Edit your workflow in `workflow.graphml` using yEd or similar GraphML editor
2. Add your processing scripts to the `src/` directory
3. Run your workflow:
3. Build your workflow:
```
concore run workflow.graphml
concore build workflow.graphml
```

## Project Structure
Expand Down Expand Up @@ -318,7 +318,7 @@ def init_project_interactive(name, selected_langs, console):
f"Next steps:\n"
f" cd {name}\n"
f" concore validate workflow.graphml\n"
f" concore run workflow.graphml",
f" concore build workflow.graphml",
title="Success",
border_style="green",
)
Expand Down Expand Up @@ -371,7 +371,7 @@ def init_project(name, template, console):
f"Next steps:\n"
f" cd {name}\n"
f" concore validate workflow.graphml\n"
f" concore run workflow.graphml",
f" concore build workflow.graphml",
title="Success",
border_style="green",
)
Expand Down
47 changes: 24 additions & 23 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,24 @@ def test_status_command(self):
result = self.runner.invoke(cli, ["status"])
self.assertEqual(result.exit_code, 0)

def test_run_command_missing_source(self):
def test_build_command_missing_source(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
result = self.runner.invoke(
cli, ["run", "test-project/workflow.graphml", "--source", "nonexistent"]
cli,
["build", "test-project/workflow.graphml", "--source", "nonexistent"],
)
self.assertNotEqual(result.exit_code, 0)

def test_run_command_from_project_dir(self):
def test_build_command_from_project_dir(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)

result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -119,20 +120,20 @@ def test_run_command_from_project_dir(self):
self.assertTrue(Path("out/STUDY.json").exists())

metadata = json.loads(Path("out/STUDY.json").read_text())
self.assertEqual(metadata["generated_by"], "concore run")
self.assertEqual(metadata["generated_by"], "concore build")
self.assertEqual(metadata["study_name"], "out")
self.assertEqual(metadata["schema_version"], 1)
self.assertIn("workflow.graphml", metadata["checksums"])

def test_run_command_default_type(self):
def test_build_command_default_type(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)

result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -146,15 +147,15 @@ def test_run_command_default_type(self):
else:
self.assertTrue(Path("out/build").exists())

def test_run_command_nested_output_path(self):
def test_build_command_nested_output_path(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)

result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -167,7 +168,7 @@ def test_run_command_nested_output_path(self):
self.assertEqual(result.exit_code, 0)
self.assertTrue(Path("build/out/src/concore.py").exists())

def test_run_command_subdir_source(self):
def test_build_command_subdir_source(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)
Expand All @@ -184,7 +185,7 @@ def test_run_command_subdir_source(self):
result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -197,7 +198,7 @@ def test_run_command_subdir_source(self):
self.assertEqual(result.exit_code, 0)
self.assertTrue(Path("out/src/subdir/script.py").exists())

def test_run_command_docker_subdir_source_build_paths(self):
def test_build_command_docker_subdir_source_build_paths(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)
Expand All @@ -214,7 +215,7 @@ def test_run_command_docker_subdir_source_build_paths(self):
result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -233,15 +234,15 @@ def test_run_command_docker_subdir_source_build_paths(self):
self.assertIn("cp ../src/subdir/script.iport concore.iport", build_script)
self.assertIn("cd ..", build_script)

def test_run_command_compose_requires_docker_type(self):
def test_build_command_compose_requires_docker_type(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)

result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -257,15 +258,15 @@ def test_run_command_compose_requires_docker_type(self):
"--compose can only be used with --type docker", result.output
)

def test_run_command_docker_compose_single_node(self):
def test_build_command_docker_compose_single_node(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
self.assertEqual(result.exit_code, 0)

result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand All @@ -288,7 +289,7 @@ def test_run_command_docker_compose_single_node(self):
metadata = json.loads(Path("out/STUDY.json").read_text())
self.assertIn("docker-compose.yml", metadata["checksums"])

def test_run_command_docker_compose_multi_node(self):
def test_build_command_docker_compose_multi_node(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
Path("src").mkdir()
Path("src/common.py").write_text(
Expand All @@ -313,7 +314,7 @@ def test_run_command_docker_compose_multi_node(self):
result = self.runner.invoke(
cli,
[
"run",
"build",
"workflow.graphml",
"--source",
"src",
Expand All @@ -332,7 +333,7 @@ def test_run_command_docker_compose_multi_node(self):
self.assertIn("container_name: 'C'", compose_content)
self.assertIn("image: 'docker-common'", compose_content)

def test_run_command_shared_source_specialization_merges_edge_params(self):
def test_build_command_shared_source_specialization_merges_edge_params(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
Path("src").mkdir()
Path("src/common.py").write_text(
Expand All @@ -357,7 +358,7 @@ def test_run_command_shared_source_specialization_merges_edge_params(self):
result = self.runner.invoke(
cli,
[
"run",
"build",
"workflow.graphml",
"--source",
"src",
Expand All @@ -377,15 +378,15 @@ def test_run_command_shared_source_specialization_merges_edge_params(self):
self.assertIn("PORT_NAME_B_C", content)
self.assertIn("PORT_B_C", content)

def test_run_command_existing_output(self):
def test_build_command_existing_output(self):
with self.runner.isolated_filesystem(temp_dir=self.temp_dir):
result = self.runner.invoke(cli, ["init", "test-project"])
Path("output").mkdir()

result = self.runner.invoke(
cli,
[
"run",
"build",
"test-project/workflow.graphml",
"--source",
"test-project/src",
Expand Down
Loading