Skip to content

Commit c2acef9

Browse files
committed
Add possibility to provide dev env in CLI
1 parent 7980214 commit c2acef9

8 files changed

Lines changed: 66 additions & 13 deletions

File tree

docs/cli.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ python -m finecode run [options] <action> [<action> ...] [payload] [--config.<ke
5858
| `--log-level=<level>` | Set log level: `TRACE`, `DEBUG`, `INFO`, `WARNING`, `ERROR` (default: `INFO`) |
5959
| `--no-env-config` | Ignore `FINECODE_CONFIG_*` environment variables |
6060
| `--no-save-results` | Do not write action results to the cache directory |
61+
| `--dev-env=<env>` | Override the detected dev environment. One of: `ai`, `ci`, `cli`, `ide`, `precommit` (default: auto-detected — see [Dev environment detection](#dev-environment-detection)) |
6162

6263
### Payload
6364

@@ -124,6 +125,7 @@ Must be run from the workspace or project root. Creates venvs under `.venvs/<env
124125
| `--recreate` | Delete and recreate all venvs from scratch |
125126
| `--log-level=<level>` | Set log level: `TRACE`, `DEBUG`, `INFO`, `WARNING`, `ERROR` (default: `INFO`) |
126127
| `--debug` | Wait for a debugpy client on port 5680 before starting |
128+
| `--dev-env=<env>` | Override the detected dev environment. One of: `ai`, `ci`, `cli`, `ide`, `precommit` (default: auto-detected) |
127129

128130
---
129131

@@ -142,6 +144,34 @@ Output is written to `<cwd>/finecode_config_dump/`.
142144
| `--project=<name>` | **(Required)** Project to dump config for |
143145
| `--log-level=<level>` | Set log level: `TRACE`, `DEBUG`, `INFO`, `WARNING`, `ERROR` (default: `INFO`) |
144146
| `--debug` | Wait for a debugpy client on port 5680 |
147+
| `--dev-env=<env>` | Override the detected dev environment. One of: `ai`, `ci`, `cli`, `ide`, `precommit` (default: auto-detected) |
148+
149+
---
150+
151+
## Dev environment detection
152+
153+
FineCode tracks which environment triggered an action run (e.g. IDE, CLI, CI/CD). This value is passed to handlers via `RunActionMeta.dev_env` and can be used to adjust behavior — for example, to emit machine-readable output in CI.
154+
155+
The `run`, `prepare-envs`, and `dump-config` commands detect the environment automatically:
156+
157+
| Condition | Detected value |
158+
|---|---|
159+
| `CI` environment variable is set (any non-empty value) | `ci` |
160+
| Default | `cli` |
161+
162+
The `CI` variable is set automatically by GitHub Actions, GitLab CI, CircleCI, Travis CI, Bitbucket Pipelines, and most other CI systems.
163+
164+
Use `--dev-env=<value>` on any command to override the detected value explicitly:
165+
166+
```bash
167+
# Force CI/CD mode locally
168+
python -m finecode run --dev-env=ci lint
169+
170+
# Mark as a pre-commit run
171+
python -m finecode run --dev-env=precommit lint
172+
```
173+
174+
Valid values: `ai`, `ci`, `cli`, `ide`, `precommit`.
145175

146176
---
147177

docs/wm-protocol.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ Required: `action`, `project`. All other fields optional.
376376

377377
`trigger` values: `"user"`, `"system"`, `"unknown"` (default: `"unknown"`)
378378

379-
`dev_env` values: `"ide"`, `"cli"`, `"ai"`, `"precommit"`, `"cicd"` (default: `"cli"`)
379+
`dev_env` values: `"ide"`, `"cli"`, `"ai"`, `"precommit"`, `"ci"` (default: `"cli"`)
380380

381381
**Result:**
382382

finecode_extension_api/src/finecode_extension_api/code_action.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class DevEnv(enum.StrEnum):
2929
CLI = "cli"
3030
AI = "ai"
3131
PRECOMMIT = "precommit"
32-
CI_CD = "cicd"
32+
CI = "ci"
3333

3434

3535
@dataclasses.dataclass

src/finecode/cli.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616

1717

1818
FINECODE_CONFIG_ENV_PREFIX = "FINECODE_CONFIG_"
19+
_VALID_DEV_ENVS = {"ide", "cli", "ai", "precommit", "ci"}
20+
21+
22+
def detect_dev_env() -> str:
23+
"""Detect dev environment from context. CI env var overrides the default 'cli'."""
24+
if os.environ.get("CI"):
25+
return "ci"
26+
return "cli"
1927

2028
# TODO: unify possibilities of CLI options and env vars
2129
def parse_handler_config_from_env() -> dict[str, dict[str, dict[str, str]]]:
@@ -252,6 +260,7 @@ def run(ctx) -> None:
252260
save_results: bool = True
253261
map_payload_fields: set[str] = set()
254262
shared_server: bool = False
263+
dev_env: str = detect_dev_env()
255264

256265
# finecode run parameters
257266
for arg in args:
@@ -283,6 +292,14 @@ def run(ctx) -> None:
283292
map_payload_fields = {f.replace("-", "_") for f in fields.split(",")}
284293
elif arg == "--shared-server":
285294
shared_server = True
295+
elif arg.startswith("--dev-env"):
296+
dev_env = arg.removeprefix("--dev-env=")
297+
if dev_env not in _VALID_DEV_ENVS:
298+
click.echo(
299+
f"Invalid --dev-env value '{dev_env}'. Valid values: {', '.join(sorted(_VALID_DEV_ENVS))}",
300+
err=True,
301+
)
302+
sys.exit(1)
286303
elif not arg.startswith("--"):
287304
break
288305
processed_args_count += 1
@@ -360,6 +377,7 @@ def run(ctx) -> None:
360377
map_payload_fields,
361378
own_server=not shared_server,
362379
log_level=log_level,
380+
dev_env=dev_env,
363381
)
364382
)
365383
click.echo(result.output)
@@ -389,7 +407,8 @@ def run(ctx) -> None:
389407
@click.option("--debug", "debug", is_flag=True, default=False)
390408
@click.option("--recreate", "recreate", is_flag=True, default=False)
391409
@click.option("--shared-server", "shared_server", is_flag=True, default=False)
392-
def prepare_envs(log_level: str, debug: bool, recreate: bool, shared_server: bool) -> None:
410+
@click.option("--dev-env", "dev_env", default=None, type=click.Choice(sorted(_VALID_DEV_ENVS)), help="Override detected dev environment")
411+
def prepare_envs(log_level: str, debug: bool, recreate: bool, shared_server: bool, dev_env: str | None) -> None:
393412
"""
394413
`prepare-envs` should be called from workspace/project root directory.
395414
"""
@@ -413,6 +432,7 @@ def prepare_envs(log_level: str, debug: bool, recreate: bool, shared_server: boo
413432
recreate=recreate,
414433
own_server=not shared_server,
415434
log_level=log_level,
435+
dev_env=dev_env or detect_dev_env(),
416436
)
417437
)
418438
except prepare_envs_cmd.PrepareEnvsFailed as exception:
@@ -429,7 +449,8 @@ def prepare_envs(log_level: str, debug: bool, recreate: bool, shared_server: boo
429449
@click.option("--debug", "debug", is_flag=True, default=False)
430450
@click.option("--project", "project", type=str)
431451
@click.option("--shared-server", "shared_server", is_flag=True, default=False)
432-
def dump_config(log_level: str, debug: bool, project: str | None, shared_server: bool):
452+
@click.option("--dev-env", "dev_env", default=None, type=click.Choice(sorted(_VALID_DEV_ENVS)), help="Override detected dev environment")
453+
def dump_config(log_level: str, debug: bool, project: str | None, shared_server: bool, dev_env: str | None):
433454
if debug is True:
434455
import debugpy
435456

@@ -453,6 +474,7 @@ def dump_config(log_level: str, debug: bool, project: str | None, shared_server:
453474
project_name=project,
454475
own_server=not shared_server,
455476
log_level=log_level,
477+
dev_env=dev_env or detect_dev_env(),
456478
)
457479
)
458480
except dump_config_cmd.DumpFailed as exception:

src/finecode/cli_app/commands/dump_config_cmd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def __init__(self, message: str) -> None:
1010

1111

1212
async def dump_config(
13-
workdir_path: pathlib.Path, project_name: str, own_server: bool = True, log_level: str = "INFO"
13+
workdir_path: pathlib.Path, project_name: str, own_server: bool = True, log_level: str = "INFO", dev_env: str = "cli"
1414
):
1515
port_file = None
1616
try:
@@ -55,7 +55,7 @@ async def dump_config(
5555
options={
5656
"result_formats": ["string"],
5757
"trigger": "user",
58-
"dev_env": "cli",
58+
"dev_env": dev_env,
5959
},
6060
)
6161
except ApiError as exc:

src/finecode/cli_app/commands/prepare_envs_cmd.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def __init__(self, message: str) -> None:
1212

1313

1414
async def prepare_envs(
15-
workdir_path: pathlib.Path, recreate: bool, own_server: bool = True, log_level: str = "INFO"
15+
workdir_path: pathlib.Path, recreate: bool, own_server: bool = True, log_level: str = "INFO", dev_env: str = "cli"
1616
) -> None:
1717
"""Prepare all virtual environments for a workspace.
1818
@@ -42,7 +42,7 @@ async def prepare_envs(
4242
client = ApiClient()
4343
await client.connect("127.0.0.1", port)
4444
try:
45-
await _run(client, workdir_path, recreate)
45+
await _run(client, workdir_path, recreate, dev_env)
4646
finally:
4747
await client.close()
4848
finally:
@@ -51,7 +51,7 @@ async def prepare_envs(
5151

5252

5353
async def _run(
54-
client: ApiClient, workdir_path: pathlib.Path, recreate: bool
54+
client: ApiClient, workdir_path: pathlib.Path, recreate: bool, dev_env: str = "cli"
5555
) -> None:
5656
# Step 1 — discover projects without starting runners (envs may not exist).
5757
logger.info("Discovering projects...")
@@ -135,7 +135,7 @@ async def _run(
135135
options={
136136
"result_formats": ["string"],
137137
"trigger": "user",
138-
"dev_env": "cli",
138+
"dev_env": dev_env,
139139
},
140140
)
141141
except ApiError as exc:
@@ -168,7 +168,7 @@ async def _run(
168168
"concurrently": False,
169169
"result_formats": ["string"],
170170
"trigger": "user",
171-
"dev_env": "cli",
171+
"dev_env": dev_env,
172172
},
173173
)
174174
except ApiError as exc:

src/finecode/cli_app/commands/run_cmd.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ async def run_actions(
2727
map_payload_fields: set[str] | None = None,
2828
own_server: bool = False,
2929
log_level: str = "INFO",
30+
dev_env: str = "cli",
3031
) -> utils.RunActionsResult:
3132
port_file = None
3233
try:
@@ -78,7 +79,7 @@ async def run_actions(
7879
"concurrently": concurrently,
7980
"result_formats": result_formats,
8081
"trigger": "user",
81-
"dev_env": "cli",
82+
"dev_env": dev_env,
8283
},
8384
)
8485
except ApiError as exc:

src/finecode/wm_server/runner/runner_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class DevEnv(enum.StrEnum):
104104
CLI = 'cli'
105105
AI = 'ai'
106106
PRECOMMIT = 'precommit'
107-
CI_CD = 'cicd'
107+
CI = 'ci'
108108

109109

110110
async def run_action(

0 commit comments

Comments
 (0)