GitHub Actions Workflows¶
This document provides an overview of the GitHub Actions workflows and the structure of the
.github folder in the objectory repository.
Overview¶
The repository uses GitHub Actions for continuous integration, testing, documentation deployment, and package publishing. The workflows are designed to be modular and reusable, with a custom composite action for setting up the development environment.
.github Folder Structure¶
.github/
├── actions/ # Custom composite actions
│ └── setup-env/ # Reusable action for environment setup
│ └── action.yaml
├── workflows/ # GitHub Actions workflow definitions
│ ├── build.yaml # Build and package tests
│ ├── ci.yaml # Main CI workflow
│ ├── coverage.yaml # Code coverage reporting
│ ├── test.yaml # Unit and integration tests
│ ├── docs.yaml # Documentation deployment
│ ├── pypi.yaml # PyPI package publishing
│ └── ... # Additional workflows
├── CONTRIBUTING.md # Contribution guidelines
├── ISSUE_TEMPLATE/ # Issue templates
│ ├── bug-report.yml
│ └── feature-request.yml
├── PULL_REQUEST_TEMPLATE.md # Pull request template
└── dependabot.yml # Dependabot configuration
Custom Composite Action¶
setup-env¶
Location: .github/actions/setup-env/action.yaml
A reusable composite action that handles the common setup steps for most workflows.
Purpose:
- Installs
uvpackage manager - Sets up Python environment
- Installs dependencies using invoke tasks
- Shows environment configuration and dependency tree
Inputs:
python-version: Python version to use (default:3.13)package-name: Optional package name to installpackage-version: Optional package version to installinstall-args: Optional arguments when installing dependencies (e.g.,--docs-deps,--no-optional-deps)
Usage:
- name: Setup python environment
uses: ./.github/actions/setup-env
with:
python-version: '3.12'
install-args: '--docs-deps'
Main Workflows¶
CI Workflow (ci.yaml)¶
Triggers:
- Pull requests to
mainbranch - Pushes to
mainbranch - Manual workflow dispatch
Purpose: Main continuous integration workflow that orchestrates all quality checks.
Jobs: Calls the following reusable workflows:
build- Package build testscoverage- Code coverage reportingcyclic-imports- Cyclic import detectiondoctest- Documentation testsformat- Code formatting checkspre-commit- Pre-commit hook validationtest- Unit and integration teststest-deps- Dependency compatibility tests
Build Tests (build.yaml)¶
Triggers:
- Called by other workflows (
workflow_call) - Manual workflow dispatch
Purpose: Validates that the package can be built and installed correctly across different distribution types and configurations.
Jobs:
- build:
- Uses a matrix strategy to test:
- Distribution types:
sdist(source distribution) andwheel - Extras: base installation (no extras) and
alloptional dependencies
- Distribution types:
- Builds the package using
uv build - Checks that
py.typedis present in the distribution - Installs the built package (with or without extras)
- Validates the build with
twine check - Checks package metadata
- Checks dependency tree
- Verifies basic import works
- Validates package version is not
0.0.0 - Verifies that
pyrightrecognizes the package as typed via type checking
- Uses a matrix strategy to test:
Test Workflow (test.yaml)¶
Triggers:
- Called by other workflows (
workflow_call) - Manual workflow dispatch
Purpose: Runs comprehensive test suite across multiple Python versions and operating systems.
Jobs:
-
all:
- Runs on multiple OS: Ubuntu (latest, 24.04, 22.04, ARM), macOS (latest, 26, 15, 14, Intel)
- Tests Python versions: 3.10, 3.11, 3.12, 3.13, 3.14 (including free-threaded builds)
- Runs unit and integration tests with coverage
-
min:
- Same matrix as
allbut with minimal dependencies (--no-optional-deps) - Ensures the package works without optional dependencies
- Same matrix as
Coverage Workflow (coverage.yaml)¶
Triggers:
- Called by other workflows (
workflow_call) - Manual workflow dispatch
Purpose: Generates code coverage reports and uploads them to Codecov.
Jobs:
- Runs unit and integration tests with coverage
- Uploads coverage data to Codecov (only for the main repository)
- Failures in uploading to Codecov do not fail the workflow
Documentation Workflows¶
Stable Documentation (docs.yaml)¶
Triggers:
- Version tags (
v*.*.*) - Manual workflow dispatch
Purpose: Builds and deploys documentation for stable releases.
Jobs:
- Sets up environment with documentation dependencies
- Configures git for the docs bot
- Publishes documentation using
mike(documentation versioning tool)
Development Documentation (docs-dev.yaml)¶
Triggers:
- Pushes to
mainbranch - Manual workflow dispatch
Purpose: Builds and deploys documentation for the development version.
PyPI Publishing (pypi.yaml)¶
Triggers:
- Version tags (
v*.*.*) - Manual workflow dispatch
Purpose: Publishes the package to PyPI.
Jobs:
- Installs
uvandinvoke - Runs the publish command with PyPI token from secrets
Additional Workflows¶
Nightly Tests (nightly-tests.yaml)¶
Triggers:
- Scheduled daily at 9:10 AM UTC
- Manual workflow dispatch
Purpose: Runs the full test suite nightly to catch issues early.
Nightly Package Tests (nightly-package.yaml)¶
Triggers:
- Scheduled daily at 10:30 AM UTC
- Manual workflow dispatch
Purpose: Tests package installation and imports nightly.
Pre-commit (pre-commit.yaml)¶
Triggers:
- Called by other workflows
- Manual workflow dispatch
Purpose: Runs pre-commit hooks to validate code style and quality.
Pre-commit Auto-update (pre-commit-autoupdate.yaml)¶
Triggers:
- Scheduled weekly on Sundays at 5:10 AM UTC
- Manual workflow dispatch
Purpose: Automatically updates pre-commit hook versions.
Format Check (format.yaml)¶
Triggers:
- Called by other workflows
- Manual workflow dispatch
Purpose: Checks code formatting using Black and Ruff.
Cyclic Imports (cyclic-imports.yaml)¶
Triggers:
- Called by other workflows
- Manual workflow dispatch
Purpose: Detects circular import dependencies.
Doctest (doctest.yaml)¶
Triggers:
- Called by other workflows
- Manual workflow dispatch
Purpose: Runs doctests to validate code examples in documentation.
Test Dependencies (test-deps.yaml)¶
Triggers:
- Called by other workflows
- Manual workflow dispatch
Purpose: Tests the package with different versions of dependencies.
Dependency Review (dependency-review.yml)¶
Triggers:
- Pull requests
Purpose: Reviews dependency changes for security vulnerabilities.
Update Dependencies (update-deps.yaml)¶
Triggers:
- Scheduled weekly on Sundays at 5:10 AM UTC
- Manual workflow dispatch
Purpose: Creates pull requests to update dependencies.
Cancel Stale Queued Runs (cancel_stale_queued_runs.yaml)¶
Triggers:
- Push to any branch
- Pull requests
Purpose: Cancels outdated workflow runs to save CI resources.
Generate Package Versions (generate-package-versions.yaml)¶
Triggers:
- Manual workflow dispatch
Purpose: Generates version compatibility documentation.
Get Versions (get-versions.yaml)¶
Triggers:
- Manual workflow dispatch
Purpose: Retrieves version information from the project.
Workflow Permissions¶
Most workflows use minimal permissions following the principle of least privilege:
contents: read- Default for read-only operationscontents: write- Only for workflows that need to push changes (e.g., documentation deployment)
Secrets Used¶
The following secrets are configured in the repository settings:
CODECOV_TOKEN- For uploading coverage reports to CodecovPYPI_TOKEN- For publishing packages to PyPICI_BOT_EMAIL- Email address for the CI bot (used for documentation deployment)
Best Practices¶
-
Reusable Workflows: Common workflows are defined with
workflow_calltrigger so they can be reused by other workflows. -
Matrix Testing: The test workflows use matrix strategies to test across multiple Python versions and operating systems.
-
Composite Actions: The
setup-envaction centralizes common setup steps, reducing duplication. -
Timeouts: All jobs have reasonable timeout limits (typically 10 minutes) to prevent hung workflows.
-
Fail-Fast: Most matrix jobs use
fail-fast: falseto continue testing other combinations even if one fails. -
Version Pinning: GitHub Actions are pinned to specific major versions (e.g.,
@v6,@v7) for stability. -
Minimal Changes: Workflows are designed to make minimal assumptions about the environment and clean up after themselves.
Dependabot Configuration¶
The repository uses Dependabot to automatically update GitHub Actions dependencies. The
configuration is in .github/dependabot.yml.
Issue and Pull Request Templates¶
The repository provides templates to help contributors submit well-structured issues and pull requests:
- Bug Report:
.github/ISSUE_TEMPLATE/bug-report.yml - Feature Request:
.github/ISSUE_TEMPLATE/feature-request.yml - Pull Request Template:
.github/PULL_REQUEST_TEMPLATE.md
Troubleshooting Workflow Issues¶
Common Issues and Solutions¶
Workflow Fails with "Permission denied"¶
Cause: Insufficient permissions in the workflow configuration.
Solution: Verify that the workflow has the necessary permissions. For example, workflows that push changes need contents: write.
Workflow Hangs or Times Out¶
Cause: A step is taking longer than expected or is waiting for input.
Solution: - Check the timeout settings in the workflow (default is 10 minutes for most jobs) - Review job logs to identify which step is hanging - Consider increasing the timeout if the step legitimately needs more time
Matrix Job Failures¶
Cause: One configuration in the matrix is failing while others pass.
Solution: - Check the specific configuration that failed (Python version, OS, etc.) - Review the job logs for that specific matrix combination - Test locally with the same configuration if possible
Secret Not Available¶
Cause: Required secret is not configured in repository settings.
Solution:
- Go to repository Settings > Secrets and variables > Actions
- Add the required secret (e.g., CODECOV_TOKEN, PYPI_TOKEN)
Dependabot PR Fails¶
Cause: Dependency update breaks tests or compatibility.
Solution: - Review the Dependabot PR description for breaking changes - Check the failing test logs - Either fix the compatibility issue or close the PR if the update is not needed
Manually Triggering Workflows¶
Most workflows can be manually triggered using workflow_dispatch:
- Go to the "Actions" tab in GitHub
- Select the workflow you want to run
- Click "Run workflow"
- Select the branch and any required inputs
- Click "Run workflow" button
Viewing Workflow Logs¶
To view detailed logs for a workflow run:
- Go to the "Actions" tab
- Click on the workflow run
- Click on a specific job to see its steps
- Click on a step to expand its logs
- Use the search box to filter log output
Local Testing¶
Before pushing changes, you can test workflows locally:
# Run tests locally
inv unit-test --cov
inv integration-test --cov
# Check code formatting
inv check-format
# Check types
inv check-types
# Run pre-commit hooks
pre-commit run --all-files
# Check markdown documentation
./dev/check_markdown.sh
Workflow Usage Examples¶
Running Build Validation Locally¶
To replicate what the build workflow does:
# Build source distribution
uv build --sdist
# Build wheel
uv build --wheel
# Install from built wheel
uv pip install dist/objectory-*.whl
# Validate package metadata
./dev/package/check_metadata.sh
# Check dependency tree
./dev/package/check_dependency_tree.sh
# Validate type annotations
./dev/package/check_type.sh
# Run custom checks
./dev/package/custom_checks.sh
Testing with Different Python Versions¶
The test workflow tests multiple Python versions. To test locally with different versions:
# Using pyenv to test with Python 3.11
pyenv install 3.11
pyenv local 3.11
python -m venv .venv-3.11
source .venv-3.11/bin/activate
uv pip install -e .
inv unit-test
# Test with minimal dependencies
uv pip install -e . --no-optional-deps
inv unit-test
Maintenance Tasks¶
Updating Pre-commit Hooks¶
Happens automatically weekly via pre-commit-autoupdate.yaml, but can be done manually:
pre-commit autoupdate
pre-commit run --all-files
git commit -am "Update pre-commit hooks"
Updating Dependencies¶
Happens automatically weekly via update-deps.yaml, but can be done manually:
inv update
inv install --docs-deps
inv unit-test --cov
Regenerating Package Version Configuration¶
Happens automatically weekly via generate-package-versions.yaml, but can be done manually:
python dev/generate_versions.py
git commit -am "Generate package versions"
Contributing¶
For detailed information about contributing to the project, including how to run tests locally and development setup, see CONTRIBUTING.md.