Azure Bootstrap Library - AI Assistant Context¶
Complete context for AI assistants working on the Azure Bootstrap library repository.
Repository Purpose¶
This repository contains the Azure Bootstrap Library - a production-ready pip package that provides unified bootstrap functionality for Azure Functions applications across multiple organizations.
Package Name: azure-bootstrap
Version: 2.1.2
Language: Python 3.11+
Distribution: PyPI (public)
What This Library Does¶
v1 solved the logging ↔ configuration circular dependency that bites every Azure Functions app at startup. v2 expands that surface to cover the entire cross-cutting layer — structured logging, tracing, tiered alerts, error vocabulary, ingress hardening, Service Bus consumer plumbing, webhook auth, AI usage tracking, health probes, dynamic log refresh, DLQ digest, and more.
v1 surface (preserved byte-identical in v2)¶
- Bootstrap Logging — works immediately, before configuration loads
- Configuration Loading — Azure App Configuration + Key Vault
- Telemetry Setup — Application Insights via OpenTelemetry
- Environment Loading — all configs auto-loaded to
os.environ
v2 additions (additive, opt-in via pip extras)¶
30+ new subpackages across three tiers. See CHANGELOG.md for the catalog, examples/README.md for a reading order, and MIGRATING-FROM-V1.md for the adoption path.
The Original Problem (v1)¶
Chicken-and-egg: - Configuration loading needs logging to track progress - Logging (App Insights) needs configuration to initialize
v1 solution (still how v2 works under the hood): 1. Start with console logging (always works) 2. Try App Insights from environment if available 3. Load configuration from App Config/Key Vault 4. Upgrade to App Insights if connection string now available 5. Load all configs to os.environ
Repository Structure¶
azure-bootstrap/
├── azure_bootstrap/ # Main package (distributable)
│ ├── __init__.py # Public API surface (v1 + v2 re-exports)
│ ├── py.typed # PEP 561 type hints marker
│ │
│ │ ── v1 (preserved unchanged) ─────────────────────────────────────
│ ├── models/ # ConfigurationError / RepositoryError / KeyVaultError
│ ├── repositories/ # App Config + Key Vault loaders + interfaces
│ ├── services/ # ApplicationBootstrap, BootstrapLogger, TelemetryManager
│ │
│ │ ── v2 Tier 1 (always-on, stdlib only) ───────────────────────────
│ ├── logging/ # configure_logging, formatter, masking, correlation, noise, JsonLogFormatter
│ ├── transports/ # transport registry + console/app_insights/sumo_logic
│ ├── tracing/ # @traced, latency, slow_thresholds, timed_operation
│ ├── counters/ # bump_counter, counter_snapshot
│ ├── bootstrap/ # ensure_bootstrap, load_local_settings
│ ├── exceptions/ # PipelineError tree + is_unrecoverable
│ ├── softfail/ # soft_fail, soft_fail_with
│ ├── phases/ # run_phase, run_phases
│ ├── validation/ # queue_message_schema, validate_message
│ ├── path_safety/ # sanitize_path_segment, confine_to_root
│ ├── security/ # compare_secrets, verify_api_key_header
│ ├── identity/ # build_credential, credential_health
│ ├── audit/ # build_audit_extra
│ ├── failclose/ # require_env, optional_env, fail_open_env
│ │
│ │ ── v2 Tier 2 (opt-in extras) ────────────────────────────────────
│ ├── alerts/ # alert_dev_team + dispatcher + escalation + render
│ ├── health/ # check_app_config_health / app_insights / handler-detect
│ ├── fastapi_middleware/ # install_middleware
│ ├── heartbeat/ # background heartbeat + consumer watchdog
│ ├── config_refresh/ # refresh_log_flags
│ ├── retry/ # build_retry + Azure/AI presets
│ ├── ingress/ # 4-gate attachment classifier (ext → MIME → size → magic)
│ ├── ratelimit/ # TokenBucket + webhook/admin presets
│ ├── notify/ # two-tier notification builders + sender throttle
│ ├── subscription/ # ensure_resource + renewal_loop (5s slices for SIGTERM)
│ ├── auth/ # install_graph_webhook_route + WebhookDedup + API-key
│ │
│ │ ── v2 Tier 3 (advanced opt-in) ──────────────────────────────────
│ ├── servicebus/ # handle_message + DLQ digest + growth alarm
│ │ ├── consumer.py / consumer_wrapper.py / dlq_alarm.py / dlq_digest.py
│ ├── openai/ # AI usage tracker (SDK-agnostic)
│ ├── tokens/ # issue/verify_action_token (HMAC-SHA256)
│ ├── scheduler/ # parse_cron_trigger (NCRONTAB)
│ ├── metrics/ # build_metrics_snapshot
│ ├── pdf_safety/ # sanitize_pdf_for_passthrough
│ └── sb_lock/ # lock_for_process, ManagedLock
│
├── test/ # Test suite (469 tests, 87.48% coverage)
│ ├── alerts/ audit/ auth/ bootstrap/ config_refresh/ counters/
│ ├── exceptions/ failclose/ fastapi/ health/ heartbeat/ identity/
│ ├── ingress/ logging/ metrics/ notify/ openai/ path_safety/ phases/
│ ├── pdf_safety/ ratelimit/ repositories/ retry/ sb_lock/ scheduler/
│ ├── security/ servicebus/ services/ softfail/ subscription/ tokens/
│ ├── tracing/ validation/
│ └── conftest.py # AZURE_BOOTSTRAP_ALLOW_RESET=1 set here
│
├── examples/ # Examples library (see examples/README.md)
│ ├── README.md # Index + reading order
│ ├── 01_quickstart.py … 38_logging_transports.py
│ ├── e2e_azure_function.py # v2 successor to function_app_example
│ ├── e2e_fastapi_pipeline.py
│ ├── e2e_aks_sb_worker.py
│ ├── function_app_example.py # v1 reference (kept for back-compat)
│ └── local.settings.json.example
│
├── docs/ # Long-form usage guide + docs-site build
│ ├── USAGE.md # End-to-end Python + TypeScript/Next.js walkthrough (v2.1)
│ └── gen_pages.py # mkdocs-gen-files script: assembles the site (see below)
│
├── mkdocs.yml # MkDocs Material config → GitHub Pages
├── .github/workflows/ci-cd.yml # GitHub Actions CI/CD (PyPI + TestPyPI)
├── .github/workflows/docs.yml # GitHub Actions docs build + Pages deploy
├── .githooks/ # Git hooks (pre-commit, pre-push)
├── .vscode/ # VS Code workspace config
├── pyproject.toml # Package metadata + 40+ optional extras
├── MANIFEST.in # Distribution file control
├── README.md # Library overview + extras matrix
├── CHANGELOG.md # Release-by-release surface (v1.0.0, v2.0.0, v2.1.0)
├── MIGRATING-FROM-V1.md # v1 → v2 adoption guide
├── CLAUDE.md # AI assistant & developer context (this file)
├── CONTRIBUTING.md # Contribution guidelines
└── LICENSE # MIT
Key Concepts¶
1. Bootstrap Flow (4 Phases)¶
# Phase 1: Bootstrap Logging
BootstrapLogger.configure_bootstrap_logging()
# → Console logging works immediately
# Phase 2: Initial Telemetry
telemetry_manager.configure()
# → Try App Insights from APPLICATIONINSIGHTS_CONNECTION_STRING env var
# Phase 3: Configuration Loading
config_repo = create_enhanced_config_repository(
app_config_connection_string=conn_str,
auto_load_to_environ=True
)
# → Load from Azure App Configuration
# → Resolve Key Vault references
# → Load all to os.environ
# Phase 4: Telemetry Upgrade
telemetry_manager.try_upgrade_from_config(config_repo)
# → Upgrade to App Insights if connection string now available
2. Configuration Precedence (Hierarchical)¶
Priority Order (highest to lowest):
1. Environment variables (os.environ) - Local overrides ALWAYS win
2. Azure App Configuration - Centralized config
3. Key Vault secrets (via App Config references) - Secure secrets
4. Default values - Fallback
Example:
# local.settings.json sets:
USE_MOCK_DB = "true"
# App Config has:
USE_MOCK_DB = "false"
NEW_SETTING = "value"
# After initialize_application():
os.getenv("USE_MOCK_DB") # → "true" (local preserved!)
os.getenv("NEW_SETTING") # → "value" (remote added)
3. Automatic Key Vault Resolution¶
App Configuration can reference Key Vault secrets:
// In App Config:
{
"DATABASE_PASSWORD": {
"uri": "https://myvault.vault.azure.net/secrets/db-password"
}
}
// After bootstrap:
os.getenv("DATABASE_PASSWORD") // → Actual secret value (not URI)
4. Graceful Fallbacks¶
- Missing App Configuration → Use environment variables only
- Missing Key Vault → Use environment variables only
- Missing App Insights → Use console logging only
- Import errors → Graceful warnings, continue with reduced functionality
Public API¶
v1 — Main Functions (preserved unchanged)¶
from azure_bootstrap import initialize_application, get_bootstrap_logger
logger = get_bootstrap_logger(__name__)
config_repo = initialize_application()
# All configs now in os.environ
v1 — Core Classes (advanced usage, preserved unchanged)¶
from azure_bootstrap import (
ApplicationBootstrap, # Bootstrap orchestrator
EnhancedConfigRepository, # Config repository
SecretsRepository, # Key Vault secrets
TelemetryManager, # Telemetry manager
telemetry_manager, # Singleton instance
)
v2 — Top-level re-exports (additive)¶
The most-used v2 primitives are re-exported from the top-level namespace:
from azure_bootstrap import (
# Logging
configure_logging, correlation_scope, get_correlation_id,
mask_api_key, mask_email_address, mask_secrets_in_dict, sanitize_for_log,
# Tracing + counters
traced, latency_snapshot, bump_counter, counter_snapshot,
# Bootstrap helpers
ensure_bootstrap, bootstrap_initialized, load_local_settings, refresh_setting,
# Exception hierarchy
PipelineError, UnrecoverableError, TransientError,
InvalidMessageError, RateLimitError, NetworkError, is_unrecoverable,
# Soft-fail + phases + validation
soft_fail, soft_fail_with, SoftFailResult,
run_phase, run_phases, PhaseResult,
validate_message, MessageSchema, queue_message_schema,
# Path / security
sanitize_path_segment, confine_to_root, compare_secrets,
)
Everything else (alerts, fastapi_middleware, identity, audit, failclose, auth, sb_lock, servicebus., openai., etc.) is reachable via its subpackage import path.
Interfaces (Type hints & custom implementations)¶
from azure_bootstrap.repositories.interfaces import (
EnhancedConfigRepositoryInterface,
SecretsRepositoryInterface,
)
from azure_bootstrap.services.interfaces import (
ApplicationBootstrapInterface,
TelemetryManagerInterface,
)
Development Workflow¶
Setup Development Environment¶
# Clone repository
git clone https://github.com/TheViziusGroup/azure-bootstrap
cd azure-bootstrap
# Create virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
Run Tests¶
# Run all tests with coverage
pytest
# Run specific test
pytest test/services/test_application_bootstrap.py -v
# Generate coverage report
pytest --cov=azure_bootstrap --cov-report=html
Build Package¶
# Install build tools
pip install build
# Build wheel and sdist
python -m build
# Output:
# dist/azure_bootstrap-2.1.0-py3-none-any.whl
# dist/azure_bootstrap-2.1.0.tar.gz
Publish to PyPI¶
# Manual publish
pip install twine
twine upload dist/*
# Or push to main (automated via pipeline)
git push origin main
Documentation Site¶
The site at https://theviziusgroup.github.io/azure-bootstrap/ is built with
MkDocs Material and deployed by .github/workflows/docs.yml on every push to
main.
pip install -e ".[docs,all]" # `all` matters — see below
mkdocs serve # http://127.0.0.1:8000, live-reloads
mkdocs build --strict # what CI runs; any warning fails the build
The repo-root markdown stays the single source of truth. Nothing is
duplicated into docs/ and nothing is committed by a docs build. At build time
docs/gen_pages.py (run by mkdocs-gen-files) reads README.md,
CHANGELOG.md, CONTRIBUTING.md, CLAUDE.md, MIGRATING-*.md, and
docs/USAGE.md into an in-memory overlay, rewrites their links, and emits the
API reference. Consequences worth knowing:
- Edit the root files, not
docs/.README.mdis also the PyPI long description and its links are bookmarked, so it must stay correct as read on GitHub. The generator adapts it for the site rather than the reverse. - Links are rewritten, not hand-maintained. Absolute
github.com/.../blob/main/…URLs, root-relative paths, and../-relative paths all resolve to in-site pages when the target is one of the pages above, and stay pointed at GitHub otherwise. Anchors are translated only for in-site targets — GitHub and python-markdown slugify headings differently (## 🚀 Quick Start→-quick-startvsquick-start), sogen_pages.pycomputes both slugs per heading rather than guessing. Do not "fix" emoji anchors in the root markdown; they are correct for GitHub and translated for the site. - New subpackages must be added to
[tool.setuptools] packages. That list drives the API-reference nav as well as what ships in the wheel, so an omission now costs a missing docs page too — a useful extra signal. docs/USAGE.mdis excluded from the site as-is and republished asusage.mdwith rewritten links. Both exist by design; editUSAGE.md.- Balanced code fences matter. An unclosed
```swallows the following headings, which breaks anchors silently.mkdocs build --strictcatches the fallout.
Code Guidelines¶
Import Conventions¶
# ALWAYS use package imports (never relative)
from azure_bootstrap.services.bootstrap_logging import BootstrapLogger
# NOT this:
from .bootstrap_logging import BootstrapLogger
Public API Exports¶
All public API must be exported in azure_bootstrap/__init__.py:
# azure_bootstrap/__init__.py
from azure_bootstrap.services.application_bootstrap import (
initialize_application, # Main function
create_enhanced_config_repository,
)
__all__ = [
"initialize_application",
"create_enhanced_config_repository",
# ... all public exports
]
Interface Pattern¶
All core components implement interfaces:
# 1. Define interface
class TelemetryManagerInterface(ABC):
@abstractmethod
def configure(self) -> None:
pass
# 2. Implement interface
class TelemetryManager(TelemetryManagerInterface):
def configure(self) -> None:
# Implementation
pass
# 3. Use interface for type hints
def use_telemetry(manager: TelemetryManagerInterface) -> None:
manager.configure()
Error Handling¶
Use custom exceptions from models.exceptions:
from azure_bootstrap.models.exceptions import ConfigurationError
raise ConfigurationError("Config not found: DATABASE_HOST")
Logging Pattern¶
logger.info(
"Processing started",
extra={
"operation": "operation_name",
"component": "ComponentName",
"custom_field": value,
}
)
Testing Guidelines¶
Test Structure¶
class TestApplicationBootstrap:
def setup_method(self):
"""Setup before each test."""
self.original_env = os.environ.copy()
def teardown_method(self):
"""Cleanup after each test."""
os.environ.clear()
os.environ.update(self.original_env)
def test_specific_behavior(self):
"""Test description."""
# Arrange
os.environ["KEY"] = "value"
# Act
result = function_under_test()
# Assert
assert result == expected
Mocking Pattern¶
@patch("azure_bootstrap.services.application_bootstrap.telemetry_manager")
def test_with_mock(mock_telemetry):
mock_telemetry.configure.return_value = None
# Test code
Coverage Requirements¶
- Minimum: 85% overall coverage (raised from 80% at v2.0.0)
- Current: 87.48% overall, 469 passing tests
- New code: 90% coverage
- Run:
pytest --cov=azure_bootstrap --cov-report=term-missing
Every subpackage with global state (counters, latency histograms,
alerts dispatcher, etc.) exposes a reset_state() / _reset_* helper
gated by AZURE_BOOTSTRAP_ALLOW_RESET=1. The test suite sets this
once via test/conftest.py; production code MUST NOT set it.
CI/CD Pipeline¶
Pipeline Stages¶
- Build - Install dependencies, run tests, build package
- Publish - Upload to PyPI (main branch only)
- Validate - Test installation from feed
Triggers¶
- Push to main → Full pipeline with publish
- Pull requests → Build and test only
- Tags (v*) → Full pipeline with publish
Pipeline Configuration¶
See azure-pipelines.yml for complete configuration.
Version Management¶
Semantic Versioning¶
- Major (X.0.0) - Breaking API changes
- Minor (0.X.0) - New features (backwards compatible)
- Patch (0.0.X) - Bug fixes
Release Process¶
- Update version in
pyproject.toml - Update version in
azure_bootstrap/__init__.py - Append a section to
CHANGELOG.md(the authoritative changelog) - Mirror a short summary in the Version History section of this file
- Commit and tag:
git tag v2.x.y - Push:
git push origin main --tags - Pipeline automatically publishes to PyPI via OIDC Trusted Publisher
Common Tasks¶
Adding a New Feature¶
- Create feature branch:
git checkout -b feature/new-feature - Add code to the appropriate subpackage (Tier 1/2/3 — match the existing layout described under Repository Structure)
- Add tests (maintain ≥ 85% coverage; aim for 90% on new code)
- Update
azure_bootstrap/__init__.pyif the feature belongs in the top-level surface (most subpackage-specific features don't) - Add a numbered example under examples/ and a row in examples/README.md
- Append a section to CHANGELOG.md
- Update the Version History section here
- Create PR
Fixing a Bug¶
- Create bugfix branch:
git checkout -b bugfix/issue-description - Add failing test that reproduces bug
- Fix bug
- Ensure test passes
- Note the fix in CHANGELOG.md under the next release
- Create PR
Updating Dependencies¶
- Update
pyproject.tomldependencies section (core or optional extras) - Test with new versions:
pip install -e ".[dev]" - Run full test suite:
pytest - Note the bump in CHANGELOG.md
- Create PR
Troubleshooting¶
Tests Failing¶
# Clean environment
rm -rf .venv
python -m venv .venv
.venv\Scripts\activate
pip install -e ".[test]"
pytest -v
Import Errors in Tests¶
Check that all imports use azure_bootstrap prefix:
Build Fails¶
# Check package structure
python -m build --sdist --wheel --outdir dist/ .
# Verify no syntax errors
python -m py_compile azure_bootstrap/**/*.py
Package Import Fails¶
# Verify package installed
pip show azure-bootstrap
# Test import
python -c "from azure_bootstrap import initialize_application; print('OK')"
Related Projects¶
This library is used across 17+ repositories:
- Service A - AI Assistant + Vector Store Manager
- Service B - Excel Operations Processor
- Service C - Email Ingestion Service
- ... (13 more)
For v0 → v1 migration (extracting embedded src/infrastructure/), see
the README at the 1.0.0 tag in git history. For v1 → v2 adoption, see
MIGRATING-FROM-V1.md.
Dependencies¶
Core Dependencies¶
azure-appconfiguration-provider >= 1.0.0
azure-keyvault-secrets >= 4.7.0
azure-identity >= 1.15.0
azure-monitor-opentelemetry >= 1.2.0
opentelemetry-api >= 1.22.0
opentelemetry-instrumentation-azure-functions >= 0.45b0
# Pinned for CVE remediation:
azure-core >= 1.38.0 # CVE-2026-21226
filelock >= 3.20.3 # CVE-2025-68146, CVE-2026-22701
urllib3 >= 2.7.0 # CVE-2026-21441 + CVE-2026-44431/44432
cryptography >= 48.0.1,<49 # GHSA-537c-gmf6-5ccf (via azure-identity/msal; msal caps <49)
pyjwt >= 2.13.0 # PYSEC-2026-175..179 (via msal; msal caps <3)
Optional-extra CVE pins (v2.1.2): pypdf>=6.13.3 ([pdf-safety]) and
starlette>=1.3.1 ([fastapi]/[all]).
Optional Dependencies (40+ extras)¶
See pyproject.toml and the Installation table in README.md for the full extras matrix. Highlights:
# Tier 2 (opt-in primitives)
fastapi = ["fastapi>=0.110"]
retry = ["tenacity>=8.0"]
scheduler = ["apscheduler>=3.10"]
servicebus = ["azure-servicebus>=7.11"]
# Tier 3 (advanced opt-in)
pdf-safety = ["pypdf>=4.0"]
# v2.1 — logging transport layer
transports = [] # stdlib-only (registry + console/app-insights)
sumologic = ["requests>=2.32.0"] # requests + urllib3 Retry (lazy-imported)
# Aggregate
all = ["fastapi>=0.110", "azure-servicebus>=7.11", "apscheduler>=3.10",
"tenacity>=8.0", "pypdf>=4.0"]
# dev - Development tools
pytest >= 7.4.0
pytest-cov >= 4.1.0
black >= 23.7.0
ruff >= 0.0.285
# test - Testing only
pytest >= 7.4.0
pytest-cov >= 4.1.0
pytest-mock >= 3.11.1
Key Files Reference¶
| File | Purpose |
|---|---|
| azure_bootstrap/init.py | Public API exports - ALWAYS update when adding public functions |
| pyproject.toml | Package metadata, dependencies, build configuration |
| MANIFEST.in | Controls what gets included in distribution |
| .github/workflows/ci-cd.yml | GitHub Actions CI/CD workflow (PyPI + TestPyPI) |
| .github/workflows/docs.yml | Docs build + GitHub Pages deploy |
| mkdocs.yml | Docs-site config (theme, nav, mkdocstrings options) |
| docs/gen_pages.py | Assembles the site from root markdown + docstrings |
| README.md | Library documentation, API reference, migration guide |
| CONTRIBUTING.md | Git workflow, quality standards, tooling setup |
Documentation for Users¶
When users install this library, they should read:
- README.md — Library overview + extras matrix
- examples/README.md — Reading order through the ~40 example files (start at 01_quickstart.py)
- MIGRATING-FROM-V1.md — v1 → v2 upgrade
- CHANGELOG.md — Full release-by-release surface
Quick Reference¶
Most Common User Pattern¶
from azure_bootstrap import initialize_application, get_bootstrap_logger
_bootstrap_initialized = False
_logger = None
def _ensure_bootstrap():
global _bootstrap_initialized, _logger
if _bootstrap_initialized:
return
_logger = get_bootstrap_logger(__name__)
config_repo = initialize_application()
_bootstrap_initialized = True
# Use in Azure Functions
app = func.FunctionApp()
@app.route(route="hello")
def hello(req):
_ensure_bootstrap()
# All configs in os.environ
Support¶
- Repository: https://github.com/TheViziusGroup/azure-bootstrap
- Issues: https://github.com/TheViziusGroup/azure-bootstrap/issues
- PyPI: https://pypi.org/project/azure-bootstrap/
For AI Assistants: This is a library development repository. When helping users:
- Maintain ≥ 85% test coverage (raised at v2.0.0)
- Follow interface-based design patterns (v1) or Protocol-based shapes
(v2) — never invent new top-level subpackages without a tier label
- Keep public API additive — v1 contract is byte-identical preserved
- Update CHANGELOG.md and the Version History section
here for any user-visible change
- Ensure backwards compatibility (SemVer): bump major only when v1's
20-entry __all__ actually breaks
- Test thoroughly before suggesting changes; library has 469 tests and
the suite runs in seconds — no excuse to skip it
- When adding a new module, add a numbered example to
examples/ and a row in
examples/README.md
Historical Context¶
This library was extracted from a production Azure Functions application that processes payroll data using AI (Azure OpenAI) and semantic search (Azure AI Search). The original application had bootstrap code embedded in src/infrastructure/ that handled logging, configuration, and telemetry. This code was identical across 17+ repositories, so it was extracted into this standalone pip library to provide a single source of truth. The original application README and CLAUDE.md are preserved in git history for reference.
CI/CD Setup & Troubleshooting¶
The library uses GitHub Actions for CI/CD, publishing stable releases to
PyPI (public) and develop-branch dev builds to TestPyPI.
Workflow Overview¶
graph LR
A[Push Code] --> B[Build & Test]
B --> C{Which ref?}
C -->|main or v* tag| D[Publish to PyPI]
C -->|develop| G[Publish Dev to TestPyPI]
C -->|PR| E[Stop]
D --> F[Validate Installation]
G --> H[Validate Dev Installation]
Workflow Stages¶
- Build & Test (every push/PR): Install Python 3.11, run pytest with 85% coverage, build wheel + sdist
- Publish (main/tags only): Upload package to PyPI via Trusted Publisher or API token
- Publish Dev (develop only): Upload the timestamped
.devNbuild to TestPyPI via Trusted Publisher — keeps pre-releases out of the public PyPI release history - Validate: Install the exact built version from PyPI / TestPyPI, verify
imports and
__version__
Version Strategy¶
| Branch | Version Format | Example | Target index |
|---|---|---|---|
main |
Stable | 3.0.1 |
PyPI |
develop |
Dev + timestamp | 3.0.0.dev20260518123456 |
TestPyPI |
v* tags |
Stable | 3.0.1 |
PyPI |
GitHub Actions Setup for PyPI Publishing¶
Option A: Trusted Publishers (recommended)
1. Go to PyPI → Your Account → Publishing
2. Add a new pending publisher (or configure on existing package):
- Owner: TheViziusGroup
- Repository: azure-bootstrap
- Workflow: ci-cd.yml
- Environment: pypi (optional)
3. No secrets needed — GitHub Actions authenticates via OIDC
Option B: API Token
1. Go to PyPI → Account Settings → API tokens
2. Create a token scoped to the azure-bootstrap project
3. Add GitHub Secret: PYPI_API_TOKEN = [token value]
GitHub Actions Setup for TestPyPI Publishing (dev builds)¶
TestPyPI is a separate service with its own account — a pypi.org login does not work there.
- Go to TestPyPI → Your Account → Publishing
- Add a new pending publisher:
- PyPI Project Name:
azure-bootstrap - Owner:
TheViziusGroup - Repository:
azure-bootstrap - Workflow:
ci-cd.yml - Environment:
testpypi - Create the matching GitHub environment: Settings → Environments →
testpypi. Do not add required reviewers — that would block every push todevelop.
The environment name must match character-for-character in both places: the
OIDC token carries an environment claim that TestPyPI checks.
Publishing Logic¶
# Only publish on push (not PRs) to main or tags
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))
Using Published Packages¶
# Install from PyPI (no extra config needed)
pip install azure-bootstrap
# Install specific version
pip install azure-bootstrap==3.0.1
# Install a dev build. These live on TestPyPI, NOT PyPI — `--pre` against PyPI
# finds nothing, because PyPI now only ever holds real releases. TestPyPI does
# not mirror PyPI, so --extra-index-url is needed for the runtime deps.
pip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
'azure-bootstrap==3.0.0.dev20260518123456'
# Install with optional extras
pip install 'azure-bootstrap[alerts,fastapi,servicebus]'
pip install 'azure-bootstrap[all]'
CI/CD Troubleshooting¶
Authentication Failed (403 Forbidden)¶
- If using Trusted Publishers: verify workflow name, repo owner, and environment match PyPI config
- If using API token: verify
PYPI_API_TOKENsecret exists and hasn't been revoked
TestPyPI 403 on publish-dev¶
Reads like a permissions bug; it is almost always a claim mismatch:
- The GitHub job's environment: (testpypi) must equal the Environment
field on the TestPyPI publisher exactly — including the blank-vs-set case
(no environment: in the job ⇔ blank field on TestPyPI)
- Verify the publisher was registered at test.pypi.org, not pypi.org
- Confirm the testpypi GitHub environment exists and has no required
reviewers or branch restrictions blocking develop
Package Not Found After Publishing¶
- PyPI indexing is usually instant, but wait a few seconds and retry
- Verify package at https://pypi.org/project/azure-bootstrap/ (stable) or https://test.pypi.org/project/azure-bootstrap/ (dev builds)
Workflow Not Running¶
- Verify
.github/workflows/ci-cd.ymlexists - Check branch names match triggers (
main,develop) - Enable Actions: Settings → Actions → General → "Allow all actions"
deploy-pages 404 (Documentation workflow)¶
GitHub Pages must be enabled once, by hand, before the first deploy:
- Settings → Pages → Source: GitHub Actions (not "Deploy from a
branch")
- The build job runs actions/configure-pages@v5 first, which makes this
failure mode less cryptic, but it cannot enable Pages for you
Docs build fails only in CI (mkdocs build --strict)¶
- Reproduce with
pip install -e ".[docs,all]" && mkdocs build --strict - Unresolved-alias warnings from griffe mean an optional third-party import
isn't installed;
allomitsazure-cosmosandpypdf, so try.[docs,all,pdf-safety,nosqllog-cosmos] - Broken-anchor warnings usually mean a heading was renamed in one root markdown file while another still links to the old slug
Version Conflicts¶
- Clear pip cache:
pip cache purge - Install specific version:
pip install azure-bootstrap==3.0.1
Version History¶
All notable changes to the Azure Bootstrap library.
Format based on Keep a Changelog, adheres to Semantic Versioning.
The authoritative changelog lives at CHANGELOG.md. The short summaries below are kept for AI-assistant context.
Note: this section skips 3.0.0 — see CHANGELOG.md for the full v3 surface.
[3.0.1] - 2026-08-10¶
Patch release. One runtime fix, plus documentation and CI infrastructure.
- Fixed:
check_app_config_health()probed App Configuration by calling the provider'sload(), which downloads every setting and resolves every Key Vault reference — making a readiness probe as expensive as a full bootstrap, and able to report the config store unhealthy because of an unrelated Key Vault permission gap. It now usesAzureAppConfigurationClientand pulls a single setting off the lazy pager. - Added:
azure-appconfiguration>=1.9.0as a declared core dependency (previously relied on the provider's transitive edge). - Added: documentation site at
https://theviziusgroup.github.io/azure-bootstrap/ — MkDocs Material,
generated API reference via mkdocstrings, deployed by
.github/workflows/docs.ymlon push tomain. Assembled at build time from the repo-root markdown bydocs/gen_pages.py; nothing is duplicated into the tree. - Added:
docspip extra (not part ofall). - Changed:
develop-branch dev builds now publish to TestPyPI, not PyPI. Public release history contains only real releases.
[2.1.2] - 2026-06-29¶
Security patch. No source changes — only dependency version floors raised to
remediate CVEs. New core pins cryptography>=48.0.1,<49 (GHSA-537c-gmf6-5ccf)
and pyjwt>=2.13.0 (PYSEC-2026-175..179), both transitive via
azure-identity/msal and kept under msal's caps. Optional-extra bumps:
pypdf>=6.13.3 ([pdf-safety]) and starlette>=1.3.1 ([fastapi]/[all]).
msgpack/pip advisories are dev-tooling only and intentionally not pinned.
469 tests / 87.48 % coverage unchanged.
[2.1.1] - 2026-06-29¶
Documentation-only release. No code changes — the public API, behavior, and test surface are byte-identical to 2.1.0 (released to PyPI; that version is immutable, so the doc corrections ship as a patch). Changes:
- README links rewritten from repo-relative to absolute
https://github.com/TheViziusGroup/azure-bootstrap/blob/main/…URLs so they resolve on the PyPI project page (which renders the README with no repo base URL); relative links worked only on GitHub. - Refreshed stale metrics in README and CONTRIBUTING (469 tests / 87.48 % coverage) and example counts (38 numbered files) in README and MIGRATING-FROM-V1.
- Added
docs/USAGE.md(end-to-end Python + TypeScript/Next.js usage guide) to the tracked tree.
[2.1.0] - 2026-05-21¶
Logging transport layer. Strictly additive — configure_logging() and
TelemetryManager unchanged. New azure_bootstrap.transports subpackage: a
registry (register_transport / enable_transport / disable_transport /
list_transports) plus configure_transports(console=…, app_insights=…,
sumo_logic=…). A transport is a named logging.Handler factory; enable attaches
to the root logger, disable detaches+closes. Each toggleable from code (wins) or
per-transport env flag (CONSOLE_LOGGING_ENABLED / APP_INSIGHTS_LOGGING_ENABLED
/ SUMO_LOGIC_LOGGING_ENABLED).
console— existingStreamHandler+ExtraFieldsFormatter.app_insights— delegates to v1TelemetryManager; disable only detaches the OTel handler (exporter not torn down).sumo_logic—SumoLogicHandler: buffered background-thread batched newline-delimited-JSON POST to a Sumo HTTP Source; never blocks/raises; flush on interval/size/atexit; bounded buffer;sumologic.transport.*counters (incl.throttled). Ships viarequests+ aurllib3Retryadapter (408/429/5xx backoff+jitter, honorsRetry-After, no 401 retry); byte-size- capped batches (~1 MB) with gzip above a threshold; auth-header (x-sumo-token)X-Sumo-Fieldssupport.requestsimported lazily (the[sumologic]extra); factory returnsNonewhen it's absent. Config viaSUMO_LOGIC_COLLECTOR_URL(+ optional token/source/tuning vars).
Also adds JsonLogFormatter (re-exported from azure_bootstrap and
azure_bootstrap.logging), extras transports (stdlib-only) + sumologic
(requests), example 38_logging_transports.py, and test-only
_reset_transports() gated by
AZURE_BOOTSTRAP_ALLOW_RESET=1. New top-level symbols: configure_transports,
register_transport, enable_transport, disable_transport, list_transports,
JsonLogFormatter.
[2.0.0] - 2026-05-18¶
Major expansion. Strictly additive over v1 — every v1 public symbol is preserved byte-identical. 30+ new subpackages across three tiers; 423 passing tests at 87.07 % coverage; ~22 optional pip extras. Full surface catalog in CHANGELOG.md and reading order in examples/README.md.
Headline additions:
- Logging: configure_logging, ExtraFieldsFormatter,
correlation_scope, masking + sanitization, noisy-logger silencing
- Tracing: @traced (auto-async, latency, sensitive-arg masking,
slow-budget + error alerts), latency_snapshot
- Alerts: tiered dispatcher (WARN/ERROR/CRITICAL) with dedup +
rate-limit + escalation; install_global_exception_hooks
- Error vocab: PipelineError → UnrecoverableError /
TransientError; is_unrecoverable classifier; soft_fail + phases
- Ingress: 4-gate attachment classifier (extension → MIME → size →
magic), zip-bomb defense, PDF action stripping, bidi-stripping
filename sanitizer, confine_to_root
- Service Bus: handle_message consumer wrapper, lock_for_process,
DLQ digest with HMAC-signed resubmit tokens, DLQ growth alarm
- Webhook + auth: install_graph_webhook_route (validation
handshake, clientState verification, dedup, rate limit); API-key dep
- AI tracker: sliding-window tokens + cost; soft TPM cap;
threshold-based CRITICAL alerts; pricing for GPT-4o family + Claude 3
family
- Operational: health probes, FastAPI middleware, heartbeat +
consumer watchdog, dynamic log-level refresh, /api/metrics aggregator,
NCRONTAB parser
- Security: build_credential (Workload Identity preferred over
client secret over default), build_audit_extra masking conventions,
require_env / optional_env / fail_open_env
- Retry: build_retry, retry_azure_transient, retry_ai_transient
with counter conventions + before_sleep_log wired
Coverage threshold raised from 80 % → 85 %.
v1 surface (20 symbols in __all__) preserved byte-identical.
[1.0.0] - 2026-04-09¶
Initial public release of the Azure Bootstrap library (MIT license, published to PyPI).
Features¶
- Core bootstrap functionality for Azure Functions applications
- Azure App Configuration integration with automatic config loading
- Azure Key Vault integration with automatic secret resolution
- Application Insights telemetry with OpenTelemetry support
- Bootstrap logging that works before configuration is loaded
- Smart configuration precedence (local overrides remote)
- Automatic loading of all configs to
os.environ - Graceful fallbacks for local development
- LOG_LEVEL environment variable support
- ExtraFieldsFormatter for structured console logging
- Comprehensive error handling with custom exception hierarchy
- Full type hints and interface definitions
- 80%+ test coverage
Security¶
- Pinned minimum versions for transitive dependencies with known CVEs:
azure-core>=1.38.0- CVE-2026-21226filelock>=3.20.3- CVE-2025-68146, CVE-2026-22701urllib3>=2.6.3- CVE-2026-21441
Dependencies¶
- azure-appconfiguration-provider >= 1.0.0
- azure-keyvault-secrets >= 4.7.0
- azure-identity >= 1.15.0
- azure-monitor-opentelemetry >= 1.2.0
- opentelemetry-api >= 1.22.0
Roadmap¶
Many items previously roadmapped (config refresh, metrics export, etc.) shipped in v2.0.0. Open items still being considered:
- Azure App Configuration feature-flag support
- Configuration refresh with polling
- Custom telemetry processors / OpenTelemetry exporters beyond Application Insights
- Configuration validation schemas (Pydantic-driven)
- Support for multiple Key Vaults
- Configuration change notifications via App Config webhooks
Version Guidelines¶
- Major (X.0.0): Breaking API changes, removal of deprecated features
- Minor (0.X.0): New features (backwards compatible), deprecation warnings
- Patch (0.0.X): Bug fixes, documentation updates, security dependency updates
End of Documentation