* Perform a dry run: parse the file and show what would be executed without running. * Also validates that all requirements (inputs, integrations) are met.
(path: string, options: RunOptions)
| 715 | * Also validates that all requirements (inputs, integrations) are met. |
| 716 | */ |
| 717 | async function dryRunDeepnoteProject(path: string, options: RunOptions): Promise<void> { |
| 718 | const { absolutePath, file, isMachineOutput, pythonEnv } = await setupProject(path, options) |
| 719 | const blockIds = await resolveUpstreamExecutionBlockIds(file, options, pythonEnv) |
| 720 | const executableBlocks = collectExecutableBlocks(file, { ...options, blockIds }) |
| 721 | |
| 722 | const notebookCount = options.notebook ? 1 : file.project.notebooks.length |
| 723 | |
| 724 | if (isMachineOutput) { |
| 725 | const result: DryRunResult = { |
| 726 | dryRun: true, |
| 727 | path: absolutePath, |
| 728 | totalBlocks: executableBlocks.length, |
| 729 | blocks: executableBlocks, |
| 730 | } |
| 731 | if (options.output === 'toon') { |
| 732 | outputToon(result) |
| 733 | } else { |
| 734 | outputJson(result) |
| 735 | } |
| 736 | } else { |
| 737 | const c = getChalk() |
| 738 | output(c.bold('\nExecution Plan (dry run)')) |
| 739 | output(c.dim('─'.repeat(50))) |
| 740 | |
| 741 | if (executableBlocks.length === 0) { |
| 742 | output(c.yellow('No executable blocks found.')) |
| 743 | } else { |
| 744 | for (let i = 0; i < executableBlocks.length; i++) { |
| 745 | const block = executableBlocks[i] |
| 746 | output(`${c.cyan(`[${i + 1}/${executableBlocks.length}]`)} ${block.label}`) |
| 747 | if (notebookCount > 1) { |
| 748 | output(c.dim(` Notebook: ${block.notebook}`)) |
| 749 | } |
| 750 | } |
| 751 | } |
| 752 | |
| 753 | output(c.dim('─'.repeat(50))) |
| 754 | output(c.dim(`Total: ${executableBlocks.length} block(s) would be executed`)) |
| 755 | } |
| 756 | } |
| 757 | |
| 758 | /** |
| 759 | * Validate that all required configuration is present before running. |
no test coverage detected