Skip to main content

hatch-global-env-vars

CI/CD CI - Test CD - Build
Package PyPI - Version PyPI - Python Version
Meta Hatch project uv Ruff types - Mypy License - MIT

This provides an environment collector plugin for Hatch that sets global environment variables during Hatch initialization. This allows you to dynamically configure environment variables with conditional logic, variable copying, and recursive resolution.

Key Feature: Unlike Hatch's built-in env-vars which are scoped to individual environments, this plugin sets variables globally using os.environ, making them available to all environments and processes.

Features

  1. Copy environment variables with fallback defaults
  2. Optional variable copying (only set if source exists)
  3. Conditional variable setting based on environment state
  4. Recursive variable resolution with dict syntax
  5. Global scope - variables are set in os.environ, not just in Hatch environments

The value and default fields support Hatch's generic context formatting fields:

  • {root}, {root:real}, {root:parent}, and {root:uri}
  • {home}, {home:real}, {home:parent}, and {home:uri}
  • {env:VARIABLE} or {env:VARIABLE:default}
  • {/} and {;} for platform-specific path separators

Formatting is performed while Hatch initializes the collector. Environment-specific fields such as {env_name}, {env_type}, and {matrix:python} are not available because no concrete Hatch environment exists at that point. Values set by an earlier entry are available to later {env:...} expressions.

Installation

  • pyproject.toml

    [tool.hatch.env]
    requires = ["hatch-global-env-vars"]
    
  • hatch.toml

    [env]
    requires = ["hatch-global-env-vars"]
    

Usage

  • pyproject.toml

    [tool.hatch.env.collectors.global-env-vars]
    env-vars = [
        # ...
    ]
    
  • hatch.toml

    [env.collectors.global-env-vars]
    env-vars = [
        # ...
    ]
    

Examples

[tool.hatch.env.collectors.global-env-vars]
env-vars = [
    # Example 1: Copy with fallback
    { name = "LOG_LEVEL", copy = "CI_LOG_LEVEL", default = "info" },

    # Example 2: Optional copy (only if source exists)
    { name = "API_KEY", copy = "SECRET_API_KEY", required = false },

    # Example 3: Existence check
    { name = "HAS_TOKEN", value = "yes", condition = "AUTH_TOKEN" },
    { name = "NO_TOKEN", value = "yes", condition = "!AUTH_TOKEN" },

    # Example 4: Empty/non-empty checks
    { name = "TOKEN_EMPTY", value = "true", condition = "AUTH_TOKEN==" },
    { name = "TOKEN_HAS_VALUE", value = "true", condition = "AUTH_TOKEN!=" },

    # Example 5: Value equality
    { name = "VERBOSE", value = "true", condition = "LOG_LEVEL==debug" },
    { name = "PROD_MODE", value = "true", condition = "ENVIRONMENT==production" },

    # Example 6: Value inequality
    { name = "NOT_PROD", value = "true", condition = "ENVIRONMENT!=production" },

    # Example 7: AND logic (all conditions must be true)
    { name = "DEPLOY", value = "true", condition = ["CI", "BRANCH==main", "DEPLOY_KEY"] },

    # Example 8: OR logic (any condition can be true)
    { name = "USE_CACHE", value = "redis", condition = { any = ["PROD", "STAGING"] } },

    # Example 9: Recursive resolution with variable reference dict
    { name = "APP_ENV", copy = "ENVIRONMENT", default = { name = "ENV", default = "development" } },

    # Example 10: Complex nested conditions
    { name = "FEATURE_X", value = "enabled", condition = { any = [
        { all = ["PROD", "FEATURE_FLAG==on"] },
        "FORCE_FEATURE_X"
    ] } },
]

Configuration Options

Each entry in env-vars is a dictionary with these fields:

Required Fields

  • name (string): Name of the environment variable to set

Variable Source (choose one)

  • copy (string): Copy value from this environment variable
  • value (string or dict): Set to this literal value or variable reference

String values and defaults can contain the generic Hatch context fields described above. For example:

[tool.hatch.env.collectors.global-env-vars]
env-vars = [
    { name = "PROJECT_ROOT", value = "{root:real}" },
    { name = "CONFIG_DIR", value = "{env:PROJECT_ROOT}/config" },
]

Optional Fields

  • default (string or dict): Fallback value if copy source doesn't exist
    • Can be a literal string: "development"
    • Can be a variable reference dict: { name = "ENV", default = "dev" }
    • Supports recursive nesting for fallback chains
  • required (boolean): If true (default), raise error when copy source is missing and no default provided. If false, skip setting the variable when copy source is missing.
  • condition (string, list, or dict): Only set the variable if this condition is true
    • String conditions:
      • "ENV": true if ENV exists (regardless of value)
      • "!ENV": true if ENV doesn't exist
      • "ENV==": true if ENV exists and is empty string
      • "ENV!=": true if ENV exists and is non-empty
      • "ENV==value": true if ENV equals value (value must be non-empty)
      • "ENV!=value": true if ENV doesn't equal value
    • List conditions (AND logic): ["COND1", "COND2"] - all must be true
    • Dict conditions (OR logic): { any = ["COND1", "COND2"] } - at least one must be true
    • Dict conditions (explicit AND): { all = ["COND1", "COND2"] } - all must be true

Examples

CI Detection

[tool.hatch.env.collectors.global-env-vars]
env-vars = [
    # Detect CI environment
    { name = "IS_CI", copy = "CI", default = "false" },

    # Set verbose logging in CI
    { name = "LOG_LEVEL", value = "debug", condition = "CI" },

    # Use different pytest args in CI
    { name = "PYTEST_ARGS", value = "-v --cov --cov-report=xml", condition = "CI" },
    { name = "PYTEST_ARGS", value = "-v", condition = "!CI" },

    # Only deploy from main branch in CI
    { name = "SHOULD_DEPLOY", value = "true", condition = ["CI", "BRANCH==main"] },

    # Require non-empty deploy key
    { name = "CAN_DEPLOY", value = "true", condition = ["CI", "BRANCH==main", "DEPLOY_KEY!="] },
]

Multi-Environment Setup

[tool.hatch.env.collectors.global-env-vars]
env-vars = [
    # Copy environment with fallback chain using dict syntax
    { name = "APP_ENV", copy = "DEPLOY_ENV", default = { name = "ENVIRONMENT", default = "development" } },

    # Database URL based on environment
    { name = "DATABASE_URL", copy = "PROD_DATABASE_URL", condition = "ENVIRONMENT==production" },
    { name = "DATABASE_URL", copy = "STAGE_DATABASE_URL", condition = "ENVIRONMENT==staging" },
    { name = "DATABASE_URL", value = "sqlite:///dev.db", condition = { any = ["!ENVIRONMENT", "ENVIRONMENT==development"] } },

    # Config file with multiple fallbacks
    { name = "CONFIG_FILE", copy = "CUSTOM_CONFIG", default = { name = "ENV_CONFIG", default = "config/default.yaml" } },

    # Feature flags for prod or staging
    { name = "FEATURE_BETA", value = "enabled", condition = { any = ["ENVIRONMENT==production", "ENVIRONMENT==staging"] } },
]

Secret Management

[tool.hatch.env.collectors.global-env-vars]
env-vars = [
    # Only set API key if secret exists (don't fail if missing)
    { name = "API_KEY", copy = "SECRET_API_KEY", required = false },

    # Use different key in CI
    { name = "API_KEY", copy = "CI_API_KEY", condition = "CI_API_KEY" },

    # Require authentication in production
    { name = "REQUIRE_AUTH", value = "true", condition = "ENVIRONMENT==production" },
    { name = "REQUIRE_AUTH", value = "false", condition = "ENVIRONMENT!=production" },

    # Only enable feature if token has a value (not empty)
    { name = "PREMIUM_FEATURES", value = "enabled", condition = "API_TOKEN!=" },
]

Distinguishing Empty vs Non-existent Variables

[tool.hatch.env.collectors.global-env-vars]
env-vars = [
    # Check if TOKEN exists (regardless of value)
    { name = "TOKEN_SET", value = "true", condition = "TOKEN" },

    # Check if TOKEN doesn't exist
    { name = "NO_TOKEN", value = "true", condition = "!TOKEN" },

    # Check if TOKEN exists AND is empty string
    { name = "TOKEN_EMPTY", value = "true", condition = "TOKEN==" },

    # Check if TOKEN exists AND is non-empty
    { name = "TOKEN_HAS_VALUE", value = "true", condition = "TOKEN!=" },
]

Truth table for different TOKEN states:

TOKEN state TOKEN !TOKEN TOKEN== TOKEN!=
Not set false true false false
Set to "" true false true false
Set to "x" true false false true

How It Works

This plugin implements a Hatch environment collector that runs during Hatch's initialization phase, before any environments are created.

The collector:

  1. Reads configuration from [tool.hatch.env.collectors.global-env-vars]
  2. Evaluates conditions to determine which variables to set
  3. Resolves variable references recursively
  4. Sets variables globally in os.environ, making them available to:
    • All Hatch environments (default, test, docs, etc.)
    • Child processes spawned by Hatch
    • Scripts run through Hatch

This is different from Hatch's built-in env-vars section, which only sets variables within specific environment scopes.

Error Handling

The plugin will raise errors for:

  • Missing required source variables (when required=true and no default)
  • Invalid configuration (missing required fields, conflicting options)
  • Circular references in recursive resolution

License

hatch-global-env-vars is distributed under the terms of the MIT license.

Metadata

Release files for hatch-global-env-vars 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hatch-global-env-vars 1.1.0
File Size Uploaded
hatch_global_env_vars-1.1.0.tar.gz 8.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hatch-global-env-vars 1.1.0
File Interpreter ABI Platform
hatch_global_env_vars-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 18.7 kB

Release files / hatch_global_env_vars-1.1.0.tar.gz

Download URL hatch_global_env_vars-1.1.0.tar.gz
Size 8.6 kB
Tags Source
SHA-256 checksum
How to use checksums
b89dee876adef482a5a5bbb9189dc257ec45794894784c1b7444b770fee365c2
BLAKE2b-256 checksum
How to use checksums
7aef983c03a956002e4719fbbf6dd01f7a2edcff228fafcb3f90e44676753fce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.

Transparency log

Release files / hatch_global_env_vars-1.1.0-py3-none-any.whl

Download URL hatch_global_env_vars-1.1.0-py3-none-any.whl
Size 10.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b2215a6d70eb10da6046a08cdb7169f0eccb26056c1314c69736b5489294a109
BLAKE2b-256 checksum
How to use checksums
31348bbd28159e19b5ec1e563bf7d6b4b72fc190ba2ea623e57bd44e52b00828
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page