Skip to main content
Version: 0.0.9

Release System

Release System Multi-Target Security

The test-python-uv-project-template uses a comprehensive, intent-driven release system that supports multi-target deployments with full supply chain security. The system provides production, validation, and staging workflows for safe and reliable releases.

Overview​

The release system follows modern DevOps practices with:

  • Intent-Driven Configuration: YAML-based release configuration with schema validation
  • Multi-Target Deployment: Python packages (PyPI), Docker images (dual registry), and documentation (Docusaurus)
  • Supply Chain Security: SBOM generation, vulnerability scanning, cosign signing, and SLSA attestation
  • Comprehensive Validation: Pre-release validation without publishing artifacts
  • Staging Environment: Safe testing environment with TestPyPI and staging tags
  • Git Synchronization: Fixed critical version sync issues ensuring artifacts use correct bumped versions

Release Workflows​

1. Production Release Workflow (release.yml)​

Release

Purpose: Production releases to PyPI, Docker registries, and documentation deployment

Triggers:

  • Push to master branch
  • Manual dispatch (workflow_dispatch)

Enhanced Config-Based Architecture:

Enhanced Workflow Steps​

The production release workflow now includes an enhanced config-based flow with the following steps:

Step 1: Configuration Parsing

config:
name: Parse Configuration
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master
  • Parses enhanced intent.yaml with project, docker, git, validation, and docs configuration
  • Provides structured outputs for all downstream jobs
  • Auto-detects project name and package name from repository and pyproject.toml
  • Applies smart defaults for missing configuration sections

Step 2: Release Intent Analysis

intent:
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master
needs: config
  • Validates release intent against enhanced JSON schema
  • Compatible with both legacy and enhanced configuration formats
  • Determines release artifacts (python, docker, docs) based on configuration

Multi-Target Deployments​

  1. Python Package (PyPI) - Config Enhanced:

    • Uses uv build and uv publish
    • OIDC Trusted Publishers for secure authentication
    • Config Integration: Uses ${{ needs.config.outputs.package_name }} for package identification
    • Git Configuration: Commits using ${{ needs.config.outputs.git_commit_name }} and ${{ needs.config.outputs.git_commit_email }}
    • Fixed: Automatic version synchronization with git sync fix
    • Enhanced: uv.lock file automatically updated and committed with version bumps
    • Builds from correct bumped version (e.g., 0.0.1, not 0.0.0)
  2. Docker Image (GHCR & DockerHub) - Config Enhanced:

    • Config-Based Registry URLs:
      • Docker Hub: Uses ${{ needs.config.outputs.docker_registry_dockerhub }}
      • GHCR: Uses ${{ needs.config.outputs.docker_registry_ghcr }}
    • Health Check Configuration: Uses config-based ${{ needs.config.outputs.docker_health_check_path }} and ${{ needs.config.outputs.docker_health_check_port }}
    • Application Environment: Uses ${{ needs.config.outputs.docker_app_env_name }} and ${{ needs.config.outputs.docker_app_env_value }}
    • Dual Registry Publishing: Publishes to both registries simultaneously
    • Parallel Publishing Jobs: Separate jobs ensure isolated registry operations
    • Multi-architecture builds: amd64, arm64 support for both registries
    • Supply Chain Security: SBOM generation, Cosign signing, SLSA attestation
    • Registry-Specific Authentication: GHCR uses GitHub token, Docker Hub uses dedicated credentials
    • Consistent Tagging: Same version tags applied to both registries
    • Fixed: Uses correct version tags from git sync fix
  3. Documentation (Docusaurus) - Config Enhanced:

    • Config-Based Documentation Paths: Uses structured config outputs:
      • README Path: ${{ needs.config.outputs.docs_readme_path }}
      • Installation Guide: ${{ needs.config.outputs.docs_installation_path }}
      • CI/CD Documentation: ${{ needs.config.outputs.docs_ci_cd_path }}
    • Preview Branch Configuration: Uses ${{ needs.config.outputs.docs_preview_branch }} for staging documentation
    • Enhanced Configuration Support: Works with both legacy string format and new object format:
      # Enhanced format (from config)
      docs:
      mode: "auto"
      sections: ["docs", "dev"]
      strategy: "changed"
    • Intelligent Documentation Triggering: Uses DOCS_UPDATED flag to automatically trigger documentation deployment
    • Version Reference Updates: Automatically updates documentation files that reference the package version
    • Workflow Run Pattern: Triggers documentation workflow via workflow_run to overcome GITHUB_TOKEN limitations
    • Multi-section versioning support: Independent versioning for docs, dev, and api sections
    • Change detection: Selective updates based on actual file changes
    • Matrix-based concurrent processing: Efficient parallel versioning
    • Fixed: Versions using correct bumped version from git sync fix

    📖 For detailed documentation deployment architecture, see Documentation Deployment

2. Release Validation Workflow (release-validate.yml)​

Release Validation

Purpose: Pre-release validation without publishing artifacts

Triggers:

  • Pull requests to master
  • Manual dispatch

Enhanced Config-Based Validation Steps:

Step-by-Step Enhanced Validation:

Step 1: Configuration Parsing & Validation

config:
name: Parse Configuration
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master
  • Validates enhanced intent.yaml structure and syntax
  • Tests config output generation for all sections (project, docker, git, validation, docs)
  • Verifies auto-detection logic for project and package names
  • Validates Docker registry URLs and health check configurations
  • Confirms documentation path accessibility

Step 2: Release Intent Validation

intent-parse:
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master
needs: config
  • Enhanced JSON schema validation supporting both legacy and new config formats
  • Validates release intent against config-provided defaults
  • Tests artifact configuration (python, docker, docs) with enhanced format support

Enhanced Security Validation​

  • Defensive Checks: Pre-flight image existence validation
  • Vulnerability Scanning: Grype integration for CVE detection
  • Fallback SBOM: Workspace scanning if Docker image scan fails
  • Supply Chain Security: Full SBOM, signing, and attestation testing

3. Staging Release Workflow (release-staging.yml)​

Release Staging

Purpose: Deploy to staging environments for testing with enhanced config-based customization

Triggers:

  • Manual dispatch only (workflow_dispatch)

Enhanced Config-Based Staging Architecture:

Enhanced Staging Steps:

Step 1: Configuration Parsing

config:
name: Parse Configuration
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master
  • Loads staging-specific configuration from enhanced intent.yaml
  • Provides validation version settings: ${{ needs.config.outputs.validation_version }} and ${{ needs.config.outputs.validation_test_version }}
  • Configures preview documentation branch: ${{ needs.config.outputs.docs_preview_branch }}

Step 2: Staging Version Computation

  • Uses config-based validation version format
  • Creates release candidate versions with config-provided settings
  • Integrates with git configuration from config outputs

Config-Enhanced Staging Targets:

  1. TestPyPI - Config Enhanced:

    • Pre-release Python packages using ${{ needs.config.outputs.validation_version }}
    • Git commits with ${{ needs.config.outputs.git_commit_name }} and ${{ needs.config.outputs.git_commit_email }}
  2. GHCR Staging - Config Enhanced:

    • Docker images with -rc tags using ${{ needs.config.outputs.docker_registry_ghcr }}
    • Health check validation using config-based ${{ needs.config.outputs.docker_health_check_path }} and ${{ needs.config.outputs.docker_health_check_port }}
    • Application environment testing with ${{ needs.config.outputs.docker_app_env_name }} and ${{ needs.config.outputs.docker_app_env_value }}
  3. Documentation Preview - Config Enhanced:

    • Staging documentation branch using ${{ needs.config.outputs.docs_preview_branch }}
    • Documentation paths from config: README, installation, and CI/CD documentation
    • Version testing using ${{ needs.config.outputs.validation_test_version }}

Enhanced Staging Validation Process​

  • Config-Based RC Version Generation: Creates release candidate versions using validation settings from config
  • Multi-Environment Testing: Tests all config-provided registry URLs and settings
  • Preview Environment: Safe testing environment with customizable branch names
  • Configuration Validation: Validates that all config outputs work in staging environment

Multi-Section Documentation Versioning​

The release system supports advanced documentation versioning:

Features​

  • Section-Based Versioning: Independent versioning for docs, dev, and api sections
  • Change Detection: Automatic detection of changes per section
  • Strategy Control: Version all sections or only changed sections
  • Matrix Processing: Concurrent versioning for performance

Configuration Examples​

# Legacy format (backward compatible)
docs: "auto"

# Enhanced format
docs:
mode: "auto"
sections: ["docs", "dev"]
strategy: "changed" # Only version changed sections

Supply Chain Security​

All release workflows include comprehensive supply chain security:

Security Features​

  • SBOM Generation: Software Bill of Materials with Syft
  • Vulnerability Scanning: CVE detection with Grype
  • Digital Signing: Cosign keyless signing
  • Attestation: SLSA provenance attestation
  • Defensive Programming: Pre-flight checks and clear error messages

Security Workflow​

Release System Benefits​

✅ Configurable: Intent-based release configuration
✅ Secure: Full supply chain security pipeline
✅ Validated: Comprehensive pre-release validation
✅ Staged: Safe staging environment testing
✅ Multi-Target: Python, Docker, and docs deployment
✅ Efficient: Matrix-based concurrent processing
✅ Robust: Fallback mechanisms and defensive checks

Enhanced Configuration System (New)​

Config System Centralized

Overview​

The template now features a comprehensive config-based system that extends beyond release intent to provide centralized project configuration management. This eliminates scattered environment variables and provides a single source of truth for all project settings.

Architecture​

Enhanced Configuration Structure​

The enhanced intent.yaml now includes comprehensive project settings:

# === RELEASE INTENT (Original) ===
release: true
level: "patch"
artifacts:
python: "auto"
docker: "auto"
docs:
mode: "auto"
sections: ["docs", "dev"]
strategy: "always"
notes: "Enhanced release with comprehensive configuration"

# === PROJECT CONFIGURATION (New) ===
project:
name: null # Auto-detected from repository
package_name: null # Auto-detected from pyproject.toml
base_branch: "master" # Default branch for operations

git:
commit:
name: "GitHub Actions Bot"
email: "actions@github.com"

docker:
registries:
dockerhub: "docker.io"
ghcr: "ghcr.io"
health_check:
path: "/health"
port: 8000
application:
env_var_name: "API_TOKEN"
env_var_value: "test_token"

validation:
version: "1.0.0-validation"
test_version: "validation-test"

docs:
paths:
readme: "README.md"
installation: "docs/INSTALLATION.md"
ci_cd: "docs/CI_CD.md"
preview:
branch: "docs-preview"

Configuration Parser Workflow​

The new rw_parse_project_config.yaml reusable workflow centralizes configuration parsing:

# Called by all release workflows
config:
name: Parse Configuration
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master

# Other jobs reference config outputs
other-job:
needs: config
steps:
- name: Use config values
env:
PROJECT_NAME: ${{ needs.config.outputs.project_name }}
BASE_BRANCH: ${{ needs.config.outputs.base_branch }}
DOCKER_REGISTRY: ${{ needs.config.outputs.docker_registry_dockerhub }}

Configuration Outputs​

The parser provides structured outputs for all workflows:

Project Configuration​

  • project_name: Project name (auto-detected)
  • package_name: Python package name (auto-detected)
  • base_branch: Default branch for operations

Git Configuration​

  • git_commit_name: Git commit author name
  • git_commit_email: Git commit author email

Docker Configuration​

  • docker_registry_dockerhub: Docker Hub registry URL
  • docker_registry_ghcr: GitHub Container Registry URL
  • docker_health_check_path: Health check endpoint
  • docker_health_check_port: Health check port
  • docker_app_env_name: Application environment variable name
  • docker_app_env_value: Application environment variable value

Validation Configuration​

  • validation_version: Version for validation workflows
  • validation_test_version: Test version identifier

Documentation Configuration​

  • docs_readme_path: README file path
  • docs_installation_path: Installation documentation path
  • docs_ci_cd_path: CI/CD documentation path
  • docs_preview_branch: Documentation preview branch

Benefits of Config-Based System​

✅ Centralized Management: Single source of truth in intent.yaml
✅ Smart Defaults: Works without configuration file
✅ Self-Documenting: Clear structure and validation
✅ Backward Compatible: Maintains existing release intent functionality
✅ Easy Customization: Child projects edit one file
✅ Type Safety: JSON schema validation for all configuration
✅ External References: Uses template repository for reusable workflows

Migration from Environment Variables​

Before (Scattered Variables):

# Multiple places with hardcoded values
env:
DOCKER_REGISTRY: "docker.io"
GIT_EMAIL: "actions@github.com"
BASE_BRANCH: "master"
# ... scattered across multiple files

After (Centralized Configuration):

# Single intent.yaml configuration
docker:
registries:
dockerhub: "docker.io"
git:
commit:
email: "actions@github.com"
project:
base_branch: "master"

Usage in Child Projects​

Child projects customize by editing intent.yaml sections:

# Customize for your project
project:
base_branch: "main" # Use main instead of master

docker:
registries:
dockerhub: "myregistry.io" # Use custom registry
health_check:
port: 3000 # Custom port

git:
commit:
name: "My Bot" # Custom commit author
email: "bot@mycompany.com"

docs:
preview:
branch: "preview" # Custom preview branch

All workflows automatically use these customized values via the config parsing system.

Technical Implementation Details​

Schema Compatibility​

The enhanced system maintains full backward compatibility with existing release intent configurations:

{
"title": "Release Intent and Project Configuration",
"description": "Validates release intent core properties while allowing additional project configuration sections",
"additionalProperties": true, // Allows new config sections
// ... release intent validation unchanged
}

Workflow Dependencies​

All enhanced workflows follow a consistent dependency pattern:

jobs:
# Step 1: Parse configuration (always first)
config:
name: Parse Configuration
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master

# Step 2: Parse release intent (depends on config)
intent:
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master
needs: config

# Step 3: All other jobs depend on both
other-jobs:
needs: [config, intent]
env:
PROJECT_NAME: ${{ needs.config.outputs.project_name }}
RELEASE_ENABLED: ${{ needs.intent.outputs.release }}

Auto-Detection Logic​

The config parser includes intelligent auto-detection:

# Auto-detection with fallbacks
project_name: ${{ github.event.repository.name || 'auto-detected' }}
package_name: # Extracted from pyproject.toml [project.name]
base_branch: ${{ config.project.base_branch || 'master' }}

Migration Guide for Child Projects​

Step 1: Update intent.yaml (Optional)​

Child projects can optionally enhance their intent.yaml with project-specific configuration:

# Minimal - uses all defaults (works unchanged)
release: true
level: auto
artifacts:
python: auto
docker: auto
docs: auto

# Enhanced - customize for your project
project:
base_branch: "main" # If you use 'main' instead of 'master'

docker:
registries:
dockerhub: "myorg" # Your Docker Hub organization
health_check:
port: 3000 # Your application port

git:
commit:
name: "Deploy Bot" # Your preferred commit author
email: "deploy@yourcompany.com"

docs:
preview:
branch: "docs-staging" # Your docs preview branch

Step 2: Verify External Workflow References​

Ensure your workflows reference the template repository:

# ✅ Correct - External repository reference
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master

# ❌ Incorrect - Local reference (won't work in child projects)
uses: ./.github/workflows/rw_parse_project_config.yaml

Step 3: Update Custom Workflows (If Any)​

If you have custom workflows that need config values:

jobs:
config:
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master

my-custom-job:
needs: config
runs-on: ubuntu-latest
steps:
- name: Use config values
env:
DOCKER_REGISTRY: ${{ needs.config.outputs.docker_registry_dockerhub }}
BASE_BRANCH: ${{ needs.config.outputs.base_branch }}
GIT_EMAIL: ${{ needs.config.outputs.git_commit_email }}
run: |
echo "Using registry: $DOCKER_REGISTRY"
echo "Base branch: $BASE_BRANCH"
echo "Git email: $GIT_EMAIL"

Compatibility Matrix​

Template VersionChild Project ActionCompatibilityNotes
EnhancedNo changes✅ FullUses smart defaults
EnhancedAdd project config✅ FullUses custom values
EnhancedOld intent.yaml only✅ FullBackward compatible
LegacyEnhanced intent.yaml⚠️ PartialConfig ignored, no errors

Best Practices​

1. Configuration Management​

✅ Recommended Approach:

# Use smart defaults, customize only what you need
project:
base_branch: "main" # Only if different from 'master'

docker:
registries:
dockerhub: "myorganization" # Only if different from auto-detected

❌ Avoid Over-Configuration:

# Don't set values that match defaults
project:
name: "my-project" # Auto-detected from repository
package_name: "my_project" # Auto-detected from pyproject.toml

2. Workflow Dependencies​

✅ Always Use Config Dependency:

jobs:
config:
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master

my-job:
needs: config # Always depend on config

3. External References​

✅ Pin to Stable Versions:

# Production workflows - use stable tags
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@v1.0.0

# Development - can use master
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master

4. Testing Configuration Changes​

Validation Workflow:

# Test configuration parsing
gh workflow run release-validate.yml

# Check config outputs
gh run list --workflow=release-validate.yml --limit=1
gh run view <run-id> --log

Troubleshooting​

Common Issues​

1. Configuration Not Taking Effect

  • Symptom: Workflows use default values despite custom config
  • Solution: Ensure workflows reference needs.config.outputs.*
  • Check: Verify config job runs before dependent jobs

2. External Workflow Not Found

  • Symptom: workflow not found error in GitHub Actions
  • Solution: Ensure external repository reference includes @master or version tag
  • Check: Verify repository access permissions

3. Schema Validation Errors

  • Symptom: Release intent parsing fails with validation error
  • Solution: Check configuration syntax against schema
  • Check: Use JSON schema validator for syntax verification

Debug Configuration​

View Parsed Configuration:

# Add debug step to any workflow
- name: Debug Configuration
env:
CONFIG_OUTPUTS: ${{ toJson(needs.config.outputs) }}
run: |
echo "=== PARSED CONFIGURATION ==="
echo "$CONFIG_OUTPUTS" | jq '.'

Test Configuration Parsing:

# Run release intent script locally
uv run python scripts/ci/release_intent.py

# Validates schema and shows full parsed config

Enhanced Release Intent & Project Configuration Reference​

The .github/tag_and_release/intent.yaml file is now the central configuration hub for both release behavior and comprehensive project settings. This enhanced system eliminates scattered environment variables and provides a single source of truth for all project configuration.

Complete Enhanced Configuration Schema​

# === RELEASE INTENT CONFIGURATION (Original) ===
# Master release control
release: true # boolean - Enable/disable releases entirely

# Version bump configuration
level: "auto" # string - Version bump level

# Artifact publishing configuration
artifacts:
python: "auto" # string - Python package publishing
docker: "auto" # string - Docker image publishing
docs: # object | string - Documentation versioning
mode: "auto" # string - Docs versioning mode
sections: ["docs", "dev"] # array - Docusaurus sections to version
strategy: "changed" # string - Versioning strategy

# Release notes
notes: "Release description" # string - GitHub release notes

# === ENHANCED PROJECT CONFIGURATION (New) ===
# Project identification and settings
project:
name: null # string | null - Project name (auto-detected from repository)
package_name: null # string | null - Python package name (auto-detected from pyproject.toml)
base_branch: "master" # string - Default branch for operations

# Git configuration for automated commits
git:
commit:
name: "GitHub Actions Bot" # string - Git commit author name
email: "actions@github.com" # string - Git commit author email

# Docker configuration for container operations
docker:
registries:
dockerhub: "docker.io" # string - Docker Hub registry URL
ghcr: "ghcr.io" # string - GitHub Container Registry URL
health_check:
path: "/health" # string - Health check endpoint path
port: 8000 # number - Health check port
application:
env_var_name: "API_TOKEN" # string - Application environment variable name
env_var_value: "test_token" # string - Application environment variable value

# Validation and staging configuration
validation:
version: "1.0.0-validation" # string - Version identifier for validation workflows
test_version: "validation-test" # string - Test version identifier

# Documentation configuration
docs:
paths:
readme: "README.md" # string - README file path
installation: "docs/INSTALLATION.md" # string - Installation documentation path
ci_cd: "docs/CI_CD.md" # string - CI/CD documentation path
preview:
branch: "docs-preview" # string - Documentation preview branch name

How Enhanced Configuration Works​

The enhanced system follows this two-step parsing process:

  1. Configuration Parsing (rw_parse_project_config.yaml):

    • Loads and validates the complete intent.yaml structure
    • Provides structured outputs for project, git, docker, validation, and docs settings
    • Applies smart defaults for missing configuration sections
    • Auto-detects project and package names
  2. Release Intent Analysis (rw_parse_release_intent.yaml):

    • Focuses on release-specific logic (release, level, artifacts, notes)
    • Compatible with both legacy and enhanced configuration formats
    • Uses configuration parser outputs for enhanced validation

Configuration Options​

Release Intent Configuration (Core)​

These are the core release control options that determine release behavior:

1. Master Release Control​

release (boolean, default: true)

  • true: Enable release processing with config-enhanced workflows
  • false: Skip all release operations
# Enable releases with enhanced config system
release: true

# Disable releases entirely
release: false
2. Version Bump Level​

level (string, default: "auto") Controls semantic version bumping with config-enhanced git operations:

  • "auto": Determine version bump automatically based on commit messages
  • "patch": Force patch version bump (e.g., 1.0.0 → 1.0.1)
  • "minor": Force minor version bump (e.g., 1.0.0 → 1.1.0)
  • "major": Force major version bump (e.g., 1.0.0 → 2.0.0)
# Automatic version detection - uses config-based git settings
level: auto

# Force specific version bumps - commits use enhanced git configuration
level: patch # 1.0.0 → 1.0.1 (commits with config.outputs.git_commit_name)
level: minor # 1.0.0 → 1.1.0 (commits with config.outputs.git_commit_email)
level: major # 1.0.0 → 2.0.0 (commits with config-enhanced settings)

Enhanced Project Configuration (New)​

These are the new project-level configuration sections that provide centralized management:

6. Project Configuration​

project (object) Defines project identification and base settings:

project:
name: null # string | null - Auto-detected from repository name
package_name: null # string | null - Auto-detected from pyproject.toml
base_branch: "master" # string - Default branch for workflow operations

Configuration Options:

  • name: Project name (auto-detected from ${{ github.event.repository.name }})
  • package_name: Python package name (extracted from pyproject.toml [project.name])
  • base_branch: Default branch for git operations and branch references

Usage in Workflows:

# Workflows use these via config outputs:
PROJECT_NAME: ${{ needs.config.outputs.project_name }}
PACKAGE_NAME: ${{ needs.config.outputs.package_name }}
BASE_BRANCH: ${{ needs.config.outputs.base_branch }}
7. Git Configuration​

git (object) Configures git commit settings for automated operations:

git:
commit:
name: "GitHub Actions Bot" # string - Git commit author name
email: "actions@github.com" # string - Git commit author email

Configuration Options:

  • commit.name: Author name for automated commits (version bumps, documentation updates)
  • commit.email: Author email for automated commits

Usage in Workflows:

# All version bump and automated commit operations use:
GIT_COMMIT_NAME: ${{ needs.config.outputs.git_commit_name }}
GIT_COMMIT_EMAIL: ${{ needs.config.outputs.git_commit_email }}

# Example: Version bump commits
- name: Configure Git
run: |
git config user.name "${{ needs.config.outputs.git_commit_name }}"
git config user.email "${{ needs.config.outputs.git_commit_email }}"
8. Docker Configuration​

docker (object) Comprehensive Docker deployment configuration:

docker:
registries:
dockerhub: "docker.io" # string - Docker Hub registry URL
ghcr: "ghcr.io" # string - GitHub Container Registry URL
health_check:
path: "/health" # string - Health check endpoint
port: 8000 # number - Health check port
run_options: "-e API_TOKEN=test_token -e DEBUG=true -v /host/data:/app/data --network mynetwork"

Configuration Options:

  • registries.dockerhub: Docker Hub registry URL for dual publishing
  • registries.ghcr: GitHub Container Registry URL for dual publishing
  • health_check.path: HTTP health check endpoint path
  • health_check.port: Port for health check operations
  • run_options: Flexible string for Docker run options (environment variables, volumes, networks, etc.)

Advanced Docker Run Options Examples:

# Basic environment variables
docker:
run_options: "-e API_TOKEN=test_token -e DEBUG=true"

# Multiple environment variables with volumes
docker:
run_options: "-e API_TOKEN=test_token -e DB_URL=postgresql://localhost:5432/app -v /host/data:/app/data -v /host/logs:/app/logs"

# Complex configuration with network and resource limits
docker:
run_options: "-e API_TOKEN=test_token -e REDIS_URL=redis://localhost:6379 --network mynetwork --memory=512m --cpus=0.5 -v /host/config:/app/config:ro"

# Production-ready configuration
docker:
run_options: "-e NODE_ENV=production -e API_TOKEN=prod_token -e DB_URL=postgresql://prod-db:5432/app -e REDIS_URL=redis://prod-redis:6379 --network prod-network --restart unless-stopped -v /data/app:/app/data -v /logs/app:/app/logs"

Usage in Workflows:

# Docker build and publish operations use:
DOCKERHUB_REGISTRY: ${{ needs.config.outputs.docker_registry_dockerhub }}
GHCR_REGISTRY: ${{ needs.config.outputs.docker_registry_ghcr }}
HEALTH_CHECK_PATH: ${{ needs.config.outputs.docker_health_check_path }}
HEALTH_CHECK_PORT: ${{ needs.config.outputs.docker_health_check_port }}
DOCKER_RUN_OPTIONS: ${{ needs.config.outputs.docker_run_options }}

# Example: Using the flexible Docker run options in workflows
jobs:
docker-operations:
uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master
needs: config
with:
operation: 'push'
registry: ${{ needs.config.outputs.docker_registry_dockerhub }}
version: '1.0.0'
docker-run-options: ${{ needs.config.outputs.docker_run_options }}

# Example: Health check validation
- name: Test Health Check
run: |
curl -f "http://localhost:${{ needs.config.outputs.docker_health_check_port }}${{ needs.config.outputs.docker_health_check_path }}"

Benefits of Flexible Docker Run Options:

  • Multiple Environment Variables: Pass any number of environment variables in a single string
  • Volume Mounts: Configure data persistence and file sharing between host and container
  • Network Configuration: Specify custom Docker networks for container connectivity
  • Resource Limits: Set memory and CPU constraints for container resource management
  • Runtime Options: Configure restart policies, security contexts, and other Docker runtime settings
  • Child Project Flexibility: Each project using the template can customize Docker behavior without modifying workflows
9. Validation Configuration​

validation (object) Settings for validation and staging workflows:

validation:
version: "1.0.0-validation" # string - Version for validation workflows
test_version: "validation-test" # string - Test version identifier

Configuration Options:

  • version: Version identifier used in validation and staging workflows
  • test_version: Test version identifier for staging operations

Usage in Workflows:

# Validation and staging workflows use:
VALIDATION_VERSION: ${{ needs.config.outputs.validation_version }}
TEST_VERSION: ${{ needs.config.outputs.validation_test_version }}

# Example: Staging deployment
- name: Deploy to TestPyPI
env:
VERSION: ${{ needs.config.outputs.validation_version }}
run: |
uv publish --repository testpypi
10. Documentation Configuration​

docs (object) Documentation paths and preview settings:

docs:
paths:
readme: "README.md" # string - README file path
installation: "docs/INSTALLATION.md" # string - Installation guide path
ci_cd: "docs/CI_CD.md" # string - CI/CD documentation path
preview:
branch: "docs-preview" # string - Preview branch name

Configuration Options:

  • paths.readme: Path to README file for version reference updates
  • paths.installation: Path to installation documentation
  • paths.ci_cd: Path to CI/CD documentation
  • preview.branch: Branch name for documentation preview/staging

Usage in Workflows:

# Documentation workflows use:
README_PATH: ${{ needs.config.outputs.docs_readme_path }}
INSTALLATION_PATH: ${{ needs.config.outputs.docs_installation_path }}
CICD_PATH: ${{ needs.config.outputs.docs_ci_cd_path }}
PREVIEW_BRANCH: ${{ needs.config.outputs.docs_preview_branch }}

# Example: Update version references
- name: Update Documentation Version References
run: |
sed -i "s/version: .*/version: $NEW_VERSION/" "${{ needs.config.outputs.docs_readme_path }}"

3. Python Package Configuration​

artifacts.python (string, default: "auto") Controls Python package publishing to PyPI with dual authentication support:

  • "auto": Publish if package files changed
  • "force": Always publish regardless of changes
  • "skip": Skip Python package publishing
artifacts:
# Conditional publishing (recommended)
python: auto

# Always publish
python: force

# Skip publishing
python: skip
PyPI Authentication Methods​

OIDC Auth Token Auth

The template now supports dual authentication methods for PyPI package uploads, providing both modern security and backward compatibility:

Authentication Configuration:

# Enhanced project configuration (New)
python:
auth_method: "oidc" # or "token"

Benefits:

  • ✅ Keyless Authentication: No API tokens to manage or rotate
  • ✅ Enhanced Security: Uses GitHub's OIDC identity tokens
  • ✅ Zero Secrets: No repository secrets needed
  • ✅ PyPI Recommended: Official PyPI recommendation for CI/CD

Setup Requirements:

  1. Configure Trusted Publisher on PyPI:

    • Go to PyPI → Account Settings → Publishing
    • Add GitHub as trusted publisher
    • Repository: your-org/your-repo
    • Workflow: release.yml (or your release workflow name)
    • Environment: production (optional)
  2. Set Authentication Method:

# In .github/tag_and_release/intent.yaml
python:
auth_method: "oidc" # Default, recommended
  1. No Additional Setup: OIDC works automatically! ✨

How OIDC Works:

Token Authentication (Legacy) 🔑​

Benefits:

  • ✅ Backward Compatible: Works with existing PyPI token setups
  • ✅ Universal Support: Works with all PyPI-compatible repositories
  • ✅ Simple Migration: Easy transition from existing token-based workflows

Setup Requirements:

  1. Generate API Tokens:

  2. Add Repository Secrets:

    • PYPI_API_TOKEN: Your production PyPI API token
    • TEST_PYPI_API_TOKEN: Your TestPyPI API token
  3. Configure Authentication Method:

# In .github/tag_and_release/intent.yaml
python:
auth_method: "token"

Security Considerations:

  • 🔄 Token Rotation: Regularly rotate API tokens
  • 🔒 Secret Management: Store tokens securely in GitHub repository secrets
  • 🎯 Scope Limitation: Use project-scoped tokens when possible
Authentication Configuration Examples​

Example 1: OIDC Authentication (Recommended)

# Modern, secure, keyless authentication
python:
auth_method: "oidc"

artifacts:
python: "auto"

# No secrets needed - uses GitHub OIDC identity

Example 2: Token Authentication (Legacy)

# Traditional API token authentication
python:
auth_method: "token"

artifacts:
python: "auto"

# Requires repository secrets:
# - PYPI_API_TOKEN
# - TEST_PYPI_API_TOKEN

Example 3: Mixed Environment Strategy

# Development projects can use OIDC for simplicity
# Production projects might prefer token control
python:
auth_method: "oidc" # Easy setup for development

artifacts:
python: "auto"
Authentication Method Comparison​
FeatureOIDC AuthenticationToken Authentication
Security🟢 Keyless, identity-based🟡 Token-based, requires rotation
Setup Complexity🟢 Simple (just configure trusted publisher)🟡 Moderate (generate + store tokens)
Maintenance🟢 Zero maintenance🟡 Regular token rotation needed
PyPI Support🟢 Official recommendation🟢 Universal support
Secrets Required🟢 None🔴 2 secrets (PYPI + TEST_PYPI tokens)
Backward Compatibility🟡 Modern PyPI feature🟢 Works everywhere
Troubleshooting🟢 Clear OIDC validation errors🟡 Token validation complexity
Authentication Workflow Architecture​

The dual authentication system seamlessly integrates with the existing release architecture:

Implementation Details:

  • Centralized Configuration: Authentication method specified once in intent.yaml
  • Secret Forwarding: Proper secret passing from calling workflows to reusable workflows
  • Conditional Logic: Workflows automatically select authentication method
  • Error Handling: Clear validation and error messages for missing tokens
  • Operation Summary: Workflow reports which authentication method was used
Migration Guide​

From Token to OIDC (Recommended):

  1. Set up PyPI Trusted Publisher for your repository
  2. Update intent.yaml:
    python:
    auth_method: "oidc" # Change from "token"
  3. Test with staging release workflow
  4. Optionally remove PyPI token secrets (but keep for rollback)

From OIDC to Token (if needed):

  1. Generate PyPI API tokens
  2. Add PYPI_API_TOKEN and TEST_PYPI_API_TOKEN to repository secrets
  3. Update intent.yaml:
    python:
    auth_method: "token" # Change from "oidc"
  4. Test with staging release workflow
Troubleshooting Authentication​

OIDC Authentication Issues:

  • Error: OIDC token validation failed
  • Solution: Verify PyPI Trusted Publisher configuration matches your repository and workflow
  • Check: Repository name, workflow filename, and optional environment name

Token Authentication Issues:

  • Error: PyPI API token not found in secrets
  • Solution: Verify PYPI_API_TOKEN and TEST_PYPI_API_TOKEN are added to repository secrets
  • Check: Token scope and expiration date

General Authentication Debugging:

  • Workflow Logs: Check the Python package workflow step for detailed authentication logs
  • Operation Summary: Each workflow reports which authentication method was used
  • Validation Workflow: Test authentication setup with release-validate.yml

4. Docker Image Configuration​

artifacts.docker (string, default: "auto") Controls Docker image publishing to both Docker Hub and GitHub Container Registry (GHCR):

  • "auto": Publish if Docker-related files changed (Dockerfile, scripts, etc.)
  • "force": Always publish to both registries regardless of changes
  • "skip": Skip Docker image publishing to both registries
artifacts:
# Conditional publishing (recommended)
docker: auto # Publishes to both registries if Docker files changed

# Always publish
docker: force # Always publishes to both registries

# Skip publishing
docker: skip # Skips both registries
Dual Registry Publishing Details

When docker: auto or docker: force, the workflow creates two parallel jobs:

  1. Docker Hub Job (release_docker_dockerhub):

    • Registry: docker.io
    • Image: chisanan232/test-python-uv-project-template:VERSION
    • Authentication: DockerHub credentials (DOCKERHUB_USERNAME, DOCKERHUB_TOKEN)
  2. GHCR Job (release_docker_ghcr):

    • Registry: ghcr.io
    • Image: ghcr.io/chisanan232/test-python-uv-project-template:VERSION
    • Authentication: GitHub token (GITHUB_TOKEN)

Both jobs run simultaneously and produce identical images with the same version tags.

5. Documentation Configuration​

artifacts.docs (object | string) Controls documentation versioning with support for both legacy and enhanced formats.

Legacy Format (String)​
artifacts:
docs: "auto" # auto, force, skip
Enhanced Format (Object)​
artifacts:
docs:
mode: "auto" # auto, force, skip
sections: ["docs", "dev"] # array of section names
strategy: "changed" # changed, always

Configuration Options:

docs.mode (string, default: "auto")

  • "auto": Version docs based on strategy and change detection
  • "force": Always version docs regardless of changes or strategy
  • "skip": Skip documentation versioning entirely

docs.sections (array, default: ["docs", "dev"]) Array of Docusaurus plugin IDs to version:

  • "docs": Main user documentation
  • "dev": Development/contributor documentation
  • "api": API reference documentation

docs.strategy (string, default: "changed")

  • "changed": Only version sections that have file changes
  • "always": Version all configured sections regardless of changes

Configuration Examples​

# Only release what has actually changed
release: true
level: auto
artifacts:
python: auto
docker: auto
docs:
mode: auto
sections: ["docs", "dev"]
strategy: changed
notes: "Automatic release with change detection"

Example 2: Force Full Release​

# Force release all artifacts regardless of changes
release: true
level: patch
artifacts:
python: force
docker: force
docs:
mode: force
sections: ["docs", "dev", "api"]
strategy: always
notes: "Full release of all components"

Example 3: Selective Release​

# Only release Python package, skip others
release: true
level: minor
artifacts:
python: force
docker: skip
docs: skip
notes: "Python package only release"

Example 4: Documentation-Only Release​

# Only version documentation
release: true
level: patch
artifacts:
python: skip
docker: skip
docs:
mode: force
sections: ["docs", "dev"]
strategy: always
notes: "Documentation update release"

Behavioral Matrix​

ConfigurationChanged FilesBehavior
python: autoPython files changed✅ Publishes to PyPI
python: autoNo Python files changed⏭️ Skips publishing
python: forceAny/no changes✅ Always publishes
python: skipAny/no changes⏭️ Always skips
docs.mode: auto, strategy: changedDocs files changed✅ Versions changed sections
docs.mode: auto, strategy: alwaysAny changes✅ Versions all sections
docs.mode: forceAny/no changes✅ Always versions

Configuration Validation​

The release intent parser includes JSON schema validation to ensure configuration correctness:

  • Invalid Options: Unsupported values are rejected with clear error messages
  • Type Checking: Ensures correct data types for all fields
  • Required Fields: Validates that essential configuration is present
  • Default Values: Applies sensible defaults for missing optional fields

Example Validation Errors:

# ❌ Invalid configuration
level: invalid_level # Error: Must be auto, patch, minor, or major
artifacts:
docs:
strategy: invalid # Error: Must be changed or always
sections: "not-array" # Error: Must be array of strings

Developer Guide​

Using the Release System​

1. Configuring a Release​

Edit .github/tag_and_release/intent.yaml to configure your release:

# Example: Patch release with selective docs versioning
version_bump: "patch"
python: "auto"
docker: "auto"
docs:
mode: "auto"
sections: ["docs", "dev"] # Only version docs and dev sections
strategy: "changed" # Only version if changes detected
github_release: "auto"

2. Triggering Releases​

Automatic Release (Push to master):

git push origin master
# Triggers release workflow automatically

Manual Release (GitHub UI):

  1. Go to Actions → Release
  2. Click "Run workflow"
  3. Optionally override intent configuration

3. Pre-Release Validation​

For Pull Requests:

  • Release validation runs automatically on PRs to master
  • Provides comprehensive validation without publishing
  • Reviews security scan results and vulnerability reports

Manual Validation:

# Trigger validation workflow manually
gh workflow run release-validate.yml

4. Staging Releases​

Deploy to Staging:

# Manual staging release
gh workflow run release-staging.yml

Staging Artifacts:

  • TestPyPI: pip install -i https://test.pypi.org/simple/ test-python-uv-project-template
  • GHCR Staging: docker pull ghcr.io/chisanan232/test-python-uv-project-template:1.0.0-rc.0
  • Preview Docs: Available on docs-preview branch

Common Workflows​

Release Preparation​

  1. Update Code: Make your changes and ensure tests pass
  2. Configure Intent: Set release configuration in intent.yaml
  3. Validate: Create PR and review validation results
  4. Stage (Optional): Test in staging environment
  5. Release: Merge to master for automatic release

Troubleshooting​

Git Synchronization Issues:

  • Fixed: Critical issue where artifacts built with old version (0.0.0) instead of bumped version (0.0.1)
  • Root Cause: Downstream jobs used actions/checkout@v5 without ref parameter, defaulting to original commit SHA
  • Solution: All workflows now use ref: ${{ github.ref_name }} to checkout latest branch state
  • Impact: Python packages, Docker images, and docs now use correct bumped version

UV Lock File Synchronization:

  • Enhanced: Version bump now automatically updates uv.lock file to maintain dependency synchronization
  • Process: After uv version --bump, the workflow runs uv lock to update lock file
  • Commit: Both pyproject.toml and uv.lock are committed together in version bump
  • Benefit: Ensures dependency lock file stays in sync with version changes

Tag Mismatch Issues:

  • Check that Docker build and security scan jobs use consistent tags
  • Validation workflow includes defensive checks to catch this early

SBOM Generation Failures:

  • System includes fallback SBOM generation from workspace
  • Check security scan artifacts for detailed logs

Best Practices​

  1. Use Conservative Configuration: Start with auto settings and change detection
  2. Validate Before Release: Always run validation workflows on PRs
  3. Test in Staging: Use staging environment for major releases
  4. Monitor Security: Review security scan results and vulnerability reports
  5. Version Documentation: Keep documentation in sync with code changes

🔗 Next Steps: