Skip to content

Latest commit

 

History

History
264 lines (205 loc) · 8.05 KB

File metadata and controls

264 lines (205 loc) · 8.05 KB

Hooks

Azure Developer CLI hooks support multiple executor types — Bash, PowerShell, Python (and future JavaScript, TypeScript, .NET). Every hook follows the same unified lifecycle regardless of its executor: Prepare → Execute → Cleanup.

Supported Executor Types

Executor kind value File extension Status
Bash sh .sh ✅ Stable
PowerShell pwsh .ps1 ✅ Stable
Python python .py ✅ Phase 1
JavaScript js .js ✅ Phase 2
TypeScript ts .ts ✅ Phase 3
.NET (C#) dotnet .cs 🔜 Planned

Configuration

Hooks are configured in azure.yaml under the hooks section at the project or service level. Two optional fields are available:

kind (string, optional)

Specifies the executor type for the hook. Allowed values: sh, pwsh, js, ts, python, dotnet.

When omitted, the executor is auto-detected from the file extension of the run path. For example, run: ./hooks/seed.py automatically selects the Python executor.

dir (string, optional) — working directory

The working directory (cwd) for hook execution. Used as the project context for dependency installation (e.g. pip install from requirements.txt) and builds.

Automatically inferred from the directory containing the script referenced by run. For example, run: hooks/preprovision/main.py infers the working directory as hooks/preprovision/. Only set dir as an override when the project root differs from the script's directory (e.g. the entry point lives in a src/ subdirectory but requirements.txt is in the parent).

Relative paths are resolved from the project or service root.

Examples

Python hook — auto-detected from .py extension

The simplest way to use a Python hook. The executor is inferred from the .py extension, and the working directory is auto-inferred from the script's location. Dependencies are installed automatically if a requirements.txt or pyproject.toml is found in the script's directory.

hooks:
  postprovision:
    run: ./hooks/seed-database.py

Python hook in a subdirectory (dir auto-inferred)

When the script lives in a subdirectory, the dir is automatically set to that directory. No explicit dir field is needed:

hooks:
  preprovision:
    run: hooks/preprovision/main.py
    # dir is auto-inferred as hooks/preprovision/

Python hook — explicit kind

When auto-detection is not desired or the file extension is ambiguous, set the kind field explicitly to select the Python executor:

hooks:
  postprovision:
    run: ./hooks/setup.py
    kind: python

Python hook with working directory override

When the script lives in a subdirectory but dependencies (requirements.txt) are at the parent level, use dir to override the auto-inferred working directory:

hooks:
  postprovision:
    run: ./tools/scripts/seed.py
    dir: ./tools    # override: requirements.txt is in ./tools, not ./tools/scripts

Python hook with platform overrides

Use windows and posix overrides to provide platform-specific hooks:

hooks:
  postprovision:
    windows:
      run: ./hooks/setup.ps1
      shell: pwsh
    posix:
      run: ./hooks/setup.py
      kind: python

Python hook with secrets

Hooks support the secrets field for resolving Azure Key Vault references, regardless of executor type:

hooks:
  postprovision:
    run: ./hooks/seed-database.py
    secrets:
      DB_CONNECTION_STRING: DATABASE_URL

JavaScript hook — auto-detected from .js extension

The simplest way to use a JavaScript hook. The executor is inferred from the .js extension. Dependencies are installed automatically if a package.json is found in the script's directory (or a parent directory up to the project root).

hooks:
  postprovision:
    run: ./hooks/seed-database.js

JavaScript hook with package.json

When a package.json exists near the script, npm install runs automatically before execution.

hooks:
  postprovision:
    run: ./hooks/seed-database.js
    # package.json in ./hooks/ → npm install runs automatically

JavaScript hook — explicit kind

hooks:
  postprovision:
    run: ./hooks/setup
    kind: js

JavaScript hook with working directory override

hooks:
  postprovision:
    run: ./tools/scripts/seed.js
    dir: ./tools    # package.json is in ./tools, not ./tools/scripts

JavaScript hook with platform overrides

hooks:
  postprovision:
    windows:
      run: ./hooks/setup.ps1
      shell: pwsh
    posix:
      run: ./hooks/setup.js
      kind: js

TypeScript hook — auto-detected from .ts extension

TypeScript hooks use npx tsx for zero-config execution. tsx handles TypeScript natively without requiring a separate compilation step, and supports both ESM and CommonJS modules automatically.

hooks:
  postprovision:
    run: ./hooks/seed-database.ts

TypeScript hook with package.json

When a package.json is found, dependencies are installed before execution. If tsx is listed as a dependency, the local version is used; otherwise npx downloads it on demand.

hooks:
  postprovision:
    run: ./hooks/seed-database.ts
    # package.json with tsx dependency → uses local tsx

TypeScript hook — explicit kind

hooks:
  postprovision:
    run: ./hooks/setup
    kind: ts

Bash hook (existing behavior, unchanged)

Bash hooks continue to work exactly as before. The kind field is optional and defaults to the appropriate shell type:

hooks:
  preprovision:
    run: echo "Provisioning starting..."
    shell: sh

How It Works

Every hook follows the unified Prepare → Execute → Cleanup lifecycle:

  1. Prepare — The executor validates prerequisites and performs any setup. This includes:
    • Kind detection from the explicit kind field, the shell field, or the file extension of the run path.
    • Runtime validation — verifying the required runtime is installed (e.g. Python 3 for .py hooks, pwsh for .ps1).
    • Project discovery — walking up the directory tree from the script to find project files (requirements.txt, pyproject.toml, package.json, *.*proj). The search stops at the project/service root boundary.
    • Dependency installation — creating a virtual environment (for Python) and installing dependencies from the discovered project file.
    • Temp file creation — for inline scripts (Bash/PowerShell only), writing the script content to a temporary file.
  2. Execute — The executor runs the hook using the appropriate runtime (e.g. python, bash, pwsh).
  3. Cleanup — The executor removes any temporary resources created during Prepare (e.g. inline script temp files). This runs regardless of whether Execute succeeded or failed.

Limitations

  • Inline scripts are only supported for Bash and PowerShell hooks. All other executor types must reference a file path.
  • Phase 1 supports Python as a non-shell executor. Phase 2 adds JavaScript and Phase 3 adds TypeScript. .NET support is planned for a future phase.
  • Virtual environments (Python) are created in the project directory alongside the dependency file, following the naming convention {dirName}_env.
  • TypeScript hooks require Node.js 18+ and use npx tsx for execution. If tsx is not installed locally, npx will download it automatically.
  • Package manager for JS/TS hooks currently uses npm for dependency installation. Support for pnpm and yarn may be added in a future release.