Skip to main content
Version: Next

rw_release_complete.yaml

Complete production release workflow that handles versioning, building, and deploying all release artifacts.

View Source

Descriptionโ€‹

This workflow orchestrates the complete production release process including version bumping, Python package publishing to PyPI, Docker image publishing to multiple registries, documentation versioning, and supply chain security.

Purposeโ€‹

  • Production Releases: Deploy stable releases to production registries
  • Multi-Target Deployment: Python (PyPI), Docker (DockerHub & GHCR), Documentation
  • Version Management: Automatic semantic versioning and Git tagging
  • Supply Chain Security: SBOM, vulnerability scanning, signing, and attestation
  • Documentation Versioning: Multi-section Docusaurus versioning
  • GitHub Releases: Automatic GitHub release creation with notes

Inputsโ€‹

ParameterTypeRequiredDefaultDescription
levelstringNoautoRelease level (auto, patch, minor, major)
pythonstringNoautoPython package release (auto, force, skip)
dockerstringNoautoDocker image release (auto, force, skip)
docsstringNoautoDocumentation versioning (auto, force, skip)
notesstringNo''Release notes for GitHub release

Secretsโ€‹

SecretRequiredDescription
DOCKERHUB_USERNAMEConditionalDockerHub username (required if publishing to DockerHub)
DOCKERHUB_TOKENConditionalDockerHub access token (required if publishing to DockerHub)
PYPI_API_TOKENConditionalPyPI API token (required for token-based auth)
TEST_PYPI_API_TOKENConditionalTestPyPI API token (required for token-based auth)

Outputsโ€‹

OutputDescription
versionReleased version number
release_performedWhether release was performed
python_releasedWhether Python package was released
docker_releasedWhether Docker images were released
docs_releasedWhether documentation was versioned

Workflow Architectureโ€‹

Release Process Flowโ€‹

Step 1: Configuration Parsingโ€‹

config:
name: Parse Configuration
uses: ./.github/workflows/rw_parse_project_config.yaml

Loads:

  • Project name and package name
  • Git commit settings
  • Docker registry URLs and health check configuration
  • Documentation paths and preview branch
  • Validation version settings

Step 2: Dockerfile Detectionโ€‹

check-dockerfile:
name: Check Dockerfile Exists
runs-on: ubuntu-latest
outputs:
has_dockerfile: ${{ steps.check.outputs.has_dockerfile }}

Determines:

  • Whether Docker processes should run
  • Enables conditional Docker job execution
  • Provides clear logging for Docker availability

Step 3: Release Intent Analysisโ€‹

intent:
uses: ./.github/workflows/rw_parse_release_intent.yaml
needs: config
with:
level: ${{ inputs.level }}
python: ${{ inputs.python }}
docker: ${{ inputs.docker }}
docs: ${{ inputs.docs }}
notes: ${{ inputs.notes }}

Determines:

  • Whether to perform release
  • Which artifacts to release
  • Version bump level
  • Release notes content

Step 4: Change Detectionโ€‹

detect_changes:
name: Detect Changes
runs-on: ubuntu-latest
outputs:
docs_changed: ${{ steps.changes.outputs.docs }}
dev_changed: ${{ steps.changes.outputs.dev }}

Detects:

  • Documentation section changes
  • Development documentation changes
  • Determines which docs sections to version

Step 5: Version Bumpโ€‹

bump_version:
uses: ./.github/workflows/rw_version_bump.yaml
with:
level: ${{ needs.intent.outputs.level }}

Process:

  1. Reads current version from Git tags
  2. Increments version based on level
  3. Updates pyproject.toml
  4. Updates uv.lock file
  5. Commits changes with config-based git settings
  6. Creates Git tag

Version Examples:

  • auto: Detects from commit messages
  • patch: 1.0.0 โ†’ 1.0.1
  • minor: 1.0.0 โ†’ 1.1.0
  • major: 1.0.0 โ†’ 2.0.0

Step 6: GitHub Release Creationโ€‹

create_github_release:
uses: ./.github/workflows/rw_create_github_release.yaml
with:
version: ${{ needs.bump_version.outputs.version }}
notes: ${{ needs.intent.outputs.notes }}

Creates:

  • GitHub release with version tag
  • Release notes (from input or auto-generated)
  • Links to release artifacts
  • Changelog from commits

Multi-Target Deploymentsโ€‹

1. Python Package (PyPI)โ€‹

Registry: https://pypi.org

Authentication: Dual support (OIDC or Token)

python:
auth_method: "oidc"

Benefits:

  • โœ… Keyless authentication
  • โœ… No secrets to manage
  • โœ… Enhanced security
  • โœ… PyPI recommended

Setup:

  1. Configure PyPI Trusted Publisher
  2. Set auth_method: oidc in intent.yaml
  3. No additional secrets needed

Token Authentication (Legacy)โ€‹

python:
auth_method: "token"

Requirements:

  • PYPI_API_TOKEN secret
  • TEST_PYPI_API_TOKEN secret (for staging)

Process:

  1. Build package with uv build
  2. Publish to PyPI with uv publish
  3. Uses config-based package name
  4. Commits with config-based git settings

Installation:

pip install your-package-name

2. Docker Images (Dual Registry)โ€‹

Only runs if Dockerfile exists

DockerHub Publishingโ€‹

docker_dockerhub:
if: needs.check-dockerfile.outputs.has_dockerfile == 'true'
uses: ./.github/workflows/rw_docker_operations.yaml
with:
operation: 'push'
registry: ${{ needs.config.outputs.docker_registry_dockerhub }}
version: ${{ needs.bump_version.outputs.version }}

Registry: docker.io

Image: username/repo:version

Authentication: DockerHub credentials

Features:

  • Multi-architecture builds (amd64, arm64)
  • Config-based registry URL
  • Health check validation
  • Automatic tagging

Pull Command:

docker pull username/repo:1.0.0

GHCR Publishingโ€‹

docker_ghcr:
if: needs.check-dockerfile.outputs.has_dockerfile == 'true'
uses: ./.github/workflows/rw_docker_operations.yaml
with:
operation: 'push'
registry: ${{ needs.config.outputs.docker_registry_ghcr }}
version: ${{ needs.bump_version.outputs.version }}

Registry: ghcr.io

Image: ghcr.io/owner/repo:version

Authentication: GitHub token

Features:

  • Integrated with GitHub
  • Multi-architecture support
  • Config-based registry URL
  • Automatic tagging

Pull Command:

docker pull ghcr.io/owner/repo:1.0.0

Dual Registry Benefitsโ€‹

  • Redundancy: Images available on both registries
  • Flexibility: Users choose preferred registry
  • Parallel Publishing: Both registries updated simultaneously
  • Consistent Tagging: Same version tags on both registries

3. Documentation (Docusaurus)โ€‹

Multi-Section Versioning Support

docs_versioning:
uses: ./.github/workflows/rw_docs_versioning.yaml
with:
version: ${{ needs.bump_version.outputs.version }}
sections: ${{ needs.prepare_docs_matrix.outputs.sections_to_version }}
strategy: ${{ needs.prepare_docs_matrix.outputs.strategy }}

Supported Sections:

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

Versioning Strategies:

  • changed: Only version sections with changes
  • always: Version all configured sections

Configuration:

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

Process:

  1. Detects changed documentation sections
  2. Creates version snapshots
  3. Updates version selectors
  4. Commits versioned docs
  5. Triggers documentation deployment

Supply Chain Securityโ€‹

Only runs if Dockerfile exists

SBOM Generationโ€‹

Tool: Syft

Process:

  1. Generate SBOM for Docker images
  2. Create SPDX and CycloneDX formats
  3. Upload SBOM as artifact
  4. Fallback to workspace SBOM if needed

Output:

sbom-{version}.spdx.json
sbom-{version}.cyclonedx.json

Vulnerability Scanningโ€‹

Tool: Grype

Process:

  1. Scan Docker images for CVEs
  2. Generate vulnerability report
  3. Upload scan results
  4. Fail on critical vulnerabilities (configurable)

Output:

vulnerability-report-{version}.json

Digital Signingโ€‹

Tool: Cosign

Method: Keyless signing with GitHub OIDC

Process:

  1. Sign Docker images
  2. Sign SBOM files
  3. Verify signatures
  4. Upload signature artifacts

Verification:

cosign verify ghcr.io/owner/repo:1.0.0

SLSA Attestationโ€‹

Level: SLSA Level 3

Process:

  1. Generate build provenance
  2. Create attestation
  3. Sign attestation
  4. Upload to registry

Verification:

cosign verify-attestation ghcr.io/owner/repo:1.0.0

Automatic Dockerfile Detectionโ€‹

The production release workflow automatically handles Dockerfile presence:

  • โœ… Dockerfile exists: All Docker processes run
  • โš ๏ธ No Dockerfile: Docker processes are skipped
  • ๐Ÿ“‹ Clear logging: Workflow indicates what was skipped

Example Output (No Dockerfile):

=== Release Summary ===
โœ… Version: 1.0.0
โœ… Python Package: Published to PyPI
โญ๏ธ Docker (DockerHub): Skipped (no Dockerfile)
โญ๏ธ Docker (GHCR): Skipped (no Dockerfile)
โœ… Documentation: Versioned (docs, dev)
โญ๏ธ Supply Chain Security: Skipped (no Docker)

Release Complete: โœ… Success

Usage Examplesโ€‹

Basic Production Releaseโ€‹

jobs:
release:
uses: Chisanan232/GitHub-Action_Reusable_Workflows-Python/.github/workflows/rw_release_complete.yaml@master
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}

Custom Release Configurationโ€‹

jobs:
release:
uses: Chisanan232/GitHub-Action_Reusable_Workflows-Python/.github/workflows/rw_release_complete.yaml@master
with:
level: 'minor'
python: 'force'
docker: 'auto'
docs: 'force'
notes: |
## What's New
- Feature A
- Feature B

## Bug Fixes
- Fixed issue X
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}

Automatic Release on Pushโ€‹

name: Release

on:
push:
branches: [master]

jobs:
release:
uses: Chisanan232/GitHub-Action_Reusable_Workflows-Python/.github/workflows/rw_release_complete.yaml@master
secrets: inherit

Manual Release with Inputsโ€‹

name: Manual Release

on:
workflow_dispatch:
inputs:
level:
description: 'Release level'
required: true
type: choice
options:
- auto
- patch
- minor
- major

jobs:
release:
uses: Chisanan232/GitHub-Action_Reusable_Workflows-Python/.github/workflows/rw_release_complete.yaml@master
with:
level: ${{ inputs.level }}
secrets: inherit

Configuration Examplesโ€‹

# In intent.yaml
release: true
level: auto
artifacts:
python: auto
docker: auto
docs:
mode: auto
sections: ["docs", "dev"]
strategy: changed

Force Full Releaseโ€‹

# In intent.yaml
release: true
level: patch
artifacts:
python: force
docker: force
docs:
mode: force
sections: ["docs", "dev", "api"]
strategy: always

Python-Only Releaseโ€‹

# In intent.yaml
release: true
level: minor
artifacts:
python: force
docker: skip
docs: skip

Best Practicesโ€‹

1. Use Semantic Versioningโ€‹

Follow semantic versioning principles:

  • Major: Breaking changes
  • Minor: New features (backward compatible)
  • Patch: Bug fixes

2. Write Clear Release Notesโ€‹

with:
notes: |
## What's New
- Added feature X
- Improved performance

## Bug Fixes
- Fixed issue Y

## Breaking Changes
- Changed API Z

3. Test Before Releaseโ€‹

  1. Run validation workflow
  2. Deploy to staging
  3. Test staging artifacts
  4. Then run production release

4. Monitor Release Processโ€‹

  • Review workflow logs
  • Check artifact uploads
  • Verify registry publications
  • Test installed packages/images

5. Use OIDC Authenticationโ€‹

For PyPI, use OIDC instead of tokens:

python:
auth_method: "oidc"

Troubleshootingโ€‹

Release Not Createdโ€‹

Symptoms:

  • Workflow runs but no release appears
  • Version not bumped

Solutions:

  1. Check release: true in intent.yaml
  2. Verify release intent parsing succeeded
  3. Review workflow permissions
  4. Check for existing tags with same version

Python Package Upload Failedโ€‹

Symptoms:

  • Package build succeeds but upload fails
  • Authentication errors

Solutions:

  1. Verify PyPI authentication method
  2. For OIDC: Check Trusted Publisher configuration
  3. For tokens: Verify PYPI_API_TOKEN secret
  4. Check package version doesn't already exist

Docker Push Failedโ€‹

Symptoms:

  • Docker build succeeds but push fails
  • Registry authentication errors

Solutions:

  1. Verify Dockerfile exists (check detection logs)
  2. For DockerHub: Check DOCKERHUB_USERNAME and DOCKERHUB_TOKEN
  3. For GHCR: Verify GitHub token permissions
  4. Check registry URLs in config

Documentation Versioning Failedโ€‹

Symptoms:

  • Documentation build succeeds but versioning fails
  • Version creation errors

Solutions:

  1. Check documentation section configuration
  2. Verify version doesn't already exist
  3. Review documentation build logs
  4. Check file permissions

Supply Chain Security Failedโ€‹

Symptoms:

  • SBOM generation fails
  • Signing errors

Solutions:

  1. Verify Docker image exists before scanning
  2. Check Cosign configuration
  3. Review security scan logs
  4. Verify OIDC permissions for signing