mirror of
https://github.com/github/spec-kit.git
synced 2026-08-03 06:26:30 +08:00
fix(workflows): validate workflow ID in run command and document new CLI flags
Path-equivalent spellings like "align-wf/" previously bypassed the registry disabled check because the engine normalizes the path while the registry matches the raw string. workflow run now validates non-file sources against the workflow ID pattern before lookup. Also updates docs/reference/workflows.md with --dev/--from install options, update/enable/disable commands, and the search --author flag. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -86,8 +86,30 @@ Lists workflows installed in the current project.
|
||||
specify workflow add <source>
|
||||
```
|
||||
|
||||
| Option | Description |
|
||||
| -------- | ------------------------------------------------------ |
|
||||
| `--dev` | Install from a local workflow YAML file or directory |
|
||||
| `--from` | Install from a custom URL (`<source>` names the expected workflow ID) |
|
||||
|
||||
Installs a workflow from the catalog, a URL (HTTPS required), or a local file path.
|
||||
|
||||
## Update Workflows
|
||||
|
||||
```bash
|
||||
specify workflow update [workflow_id]
|
||||
```
|
||||
|
||||
Updates one installed catalog workflow — or all of them when no ID is given — to the latest catalog version. Prompts for confirmation and keeps the installed copy if a download or validation fails.
|
||||
|
||||
## Enable or Disable a Workflow
|
||||
|
||||
```bash
|
||||
specify workflow enable <workflow_id>
|
||||
specify workflow disable <workflow_id>
|
||||
```
|
||||
|
||||
Disabled workflows stay installed and listed (marked `[disabled]`) but refuse to run until re-enabled.
|
||||
|
||||
## Remove a Workflow
|
||||
|
||||
```bash
|
||||
@@ -102,9 +124,10 @@ Removes an installed workflow from the project.
|
||||
specify workflow search [query]
|
||||
```
|
||||
|
||||
| Option | Description |
|
||||
| ------- | --------------- |
|
||||
| `--tag` | Filter by tag |
|
||||
| Option | Description |
|
||||
| ---------- | ----------------- |
|
||||
| `--tag` | Filter by tag |
|
||||
| `--author` | Filter by author |
|
||||
|
||||
Searches all active catalogs for workflows matching the query.
|
||||
|
||||
|
||||
@@ -352,6 +352,15 @@ def workflow_run(
|
||||
if not is_file_source:
|
||||
from .catalog import WorkflowRegistry
|
||||
|
||||
# Reject path-equivalent spellings ("align-wf/", "align-wf/.") that
|
||||
# would miss the registry lookup yet still load the installed file,
|
||||
# bypassing the disabled check below.
|
||||
if source in _RESERVED_WORKFLOW_IDS or not _WORKFLOW_ID_PATTERN.match(source):
|
||||
err.print(
|
||||
f"[red]Error:[/red] Invalid workflow ID: {_escape_markup(repr(source))}"
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
|
||||
installed_meta = WorkflowRegistry(project_root).get(source)
|
||||
if isinstance(installed_meta, dict) and installed_meta.get("enabled", True) is False:
|
||||
err.print(
|
||||
|
||||
@@ -8023,6 +8023,23 @@ steps:
|
||||
result = runner.invoke(app, ["workflow", "run", "align-wf"])
|
||||
assert result.exit_code == 0, result.output
|
||||
|
||||
def test_disable_blocks_run_via_path_equivalent_id(self, project_dir, monkeypatch):
|
||||
""""align-wf/" must not run a disabled workflow by dodging the registry lookup."""
|
||||
from typer.testing import CliRunner
|
||||
from specify_cli import app
|
||||
|
||||
monkeypatch.chdir(project_dir)
|
||||
runner = CliRunner()
|
||||
self._install_dev(runner, app, project_dir)
|
||||
|
||||
result = runner.invoke(app, ["workflow", "disable", "align-wf"])
|
||||
assert result.exit_code == 0, result.output
|
||||
|
||||
for spelling in ("align-wf/", "align-wf/."):
|
||||
result = runner.invoke(app, ["workflow", "run", spelling])
|
||||
assert result.exit_code != 0, spelling
|
||||
assert "Invalid workflow ID" in result.output, spelling
|
||||
|
||||
def test_disable_shows_marker_in_list(self, project_dir, monkeypatch):
|
||||
from typer.testing import CliRunner
|
||||
from specify_cli import app
|
||||
|
||||
Reference in New Issue
Block a user