feat(scenarios): require environment for scenario runs

- require environmentId when creating runs in API and MCP tools

- pass selected environment data into step execution helpers

- prompt for environment selection before running scenarios in UI
This commit is contained in:
2026-04-11 00:12:21 +03:00
parent d8ea2d0126
commit 56d23f913d
13 changed files with 237 additions and 28 deletions
+14 -2
View File
@@ -12,6 +12,7 @@ import { ScenarioRunStepEntity } from "./scenario-run-step.entity";
import { ScenarioRunLogEntity } from "./scenario-run-log.entity";
import { ScenarioCredentialEntity } from "./scenario-credential.entity";
import { CredentialEntity } from "../credential/credential.entity";
import { EnvironmentEntity } from "../environment/environment.entity";
import { CreateScenarioDto } from "./dto/create-scenario.dto";
import { UpdateScenarioDto } from "./dto/update-scenario.dto";
import { CreateScenarioStepDto } from "./dto/create-scenario-step.dto";
@@ -44,6 +45,8 @@ export class ScenarioService {
private readonly scenarioCredRepo: Repository<ScenarioCredentialEntity>,
@InjectRepository(CredentialEntity)
private readonly credentialRepo: Repository<CredentialEntity>,
@InjectRepository(EnvironmentEntity)
private readonly environmentRepo: Repository<EnvironmentEntity>,
) {}
// ── Scenarios ─────────────────────────────────────────────────────────────
@@ -355,11 +358,20 @@ export class ScenarioService {
return this.findRun(scenarioId, runId);
}
async createRun(scenarioId: string): Promise<ScenarioRunEntity> {
async createRun(
scenarioId: string,
environmentId: string,
): Promise<ScenarioRunEntity> {
const scenario = await this.findOne(scenarioId);
const environment = await this.environmentRepo.findOneBy({
id: environmentId,
});
if (!environment) {
throw new NotFoundException(`Environment ${environmentId} not found`);
}
const run = await this.runRepo.save(
this.runRepo.create({ scenarioId, status: "pending" }),
this.runRepo.create({ scenarioId, environmentId, status: "pending" }),
);
const stepRuns = scenario.steps.map((step, index) =>