Skip to content

cron: support Windows script extensions in resolveScriptInterpreter #26

@Arry8

Description

@Arry8

Summary

resolveScriptInterpreter in src/cron/exec-script.ts maps file extensions to interpreter binaries, but Windows-native script formats (.cmd, .bat, .ps1) are not covered. On Windows, these require explicit interpreters — cmd.exe /C for .cmd/.bat and powershell.exe -NoProfile -ExecutionPolicy Bypass -File for .ps1.

Problem

A user on Windows who creates a cron script job with a .bat, .cmd, or .ps1 command path gets a spawn error or ENOENT because the function returns null (direct execution), which requires the executable bit — a concept that doesn't exist on Windows. The script will not run.

Acceptance Criteria

  • .cmd and .bat extensions map to cmd.exe with /C flag (or equivalent) on Windows
  • .ps1 extension maps to powershell.exe with -NoProfile -ExecutionPolicy Bypass -File on Windows
  • On non-Windows platforms, these extensions return null (not applicable; user gets a clear error if they try)
  • Existing POSIX interpreter mappings (.sh, .bash, .zsh, .js, .py, etc.) are unaffected
  • A test covers Windows extension detection (can use process.platform mocking or platform guard)
  • pnpm build && pnpm check && pnpm test -- src/cron/exec-script.test.ts passes

Implementation Plan

  1. In resolveScriptInterpreter, add a platform guard (process.platform === "win32") for Windows-specific cases:
    • .cmd, .bat["cmd.exe", "/C"] (interpreter + leading args)
    • .ps1["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File"]
  2. The return type needs to change from string | null to { cmd: string; leadingArgs?: string[] } | null (or similar) so the caller can prepend interpreter args before the script path.
  3. Update the execCmd/execArgs construction in execCronScript to handle the new shape.
  4. Add platform-conditional test cases.

Files Affected

  • src/cron/exec-script.tsresolveScriptInterpreter + call site
  • src/cron/exec-script.test.ts — new test cases with platform guard

Notes

  • cmd /C <path> runs a .bat/.cmd script and exits after completion — correct semantics for cron.
  • PowerShell's -ExecutionPolicy Bypass is needed because the default policy blocks unsigned scripts; consistent with the OC Windows smoke harness pattern (CLAUDE.md).
  • Cross-platform scripts (.js, .py, etc.) already work on Windows via the existing mappings since node and python3 are in PATH when properly installed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions