Development Guide
This guide covers everything you need to know to develop in the grizzly repository.
Repository Structure
This is a monorepo for all Grizzly-related projects, managed as a uv workspace.
- Language: Python
- Package Manager: uv
- Build System: hatchling
- Linting & Formatting: ruff
- Testing: pytest
Packages
- grizzly-loadtester-common - Shared code between packages (exceptions, constants, utilities)
- grizzly-loadtester - Core framework with locust messages, test data producer/consumer, gherkin parser, and load users
- grizzly-loadtester-cli - Command line interface for running tests, Azure Keyvault integration, TOTP generator, project scaffolding
- grizzly-loadtester-ls - Language server implementation using LSP protocol
- vscode extension - Visual Studio Code extension integrating the language server
- grizzly-docs - MkDocs-based documentation hosted on GitHub Pages
Setting Up Development Environment
Prerequisites
- Python 3.10 or higher
- uv package manager
- Node.js 24 (for VS Code extension development)
- Git
Installing Dependencies
Install all dependencies for all packages (preserving the lock file):
Important: Always use
--lockedto ensure reproducible builds by preserving the dependency lock file.
Development Container
This repository includes a dev container configuration for VS Code, which provides a pre-configured development environment with all necessary tools.
Running Tests
The repository uses hatch environments for running tests across different Python versions.
Unit Tests
Run unit tests for a specific package:
# Framework
hatch run test:framework-unit
# CLI
hatch run test:cli-unit
# Language Server
hatch run test:ls-unit
# Common
hatch run test:common-unit
# Docs
hatch run test:docs-unit
End-to-End Tests
Run e2e tests for packages that support them:
# Framework (local mode)
hatch run test:framework-e2e-local
# Framework (distributed mode)
hatch run test:framework-e2e-dist
# Framework (example tests)
hatch run test:framework-e2e-example
# CLI
hatch run test:cli-e2e
# Language Server
hatch run test:ls-e2e
All Tests
Run all tests (unit + e2e) for a package:
Test Matrix
Tests run across multiple Python versions (3.10, 3.11, 3.12, 3.13). Use the matrix syntax:
Code Quality
Formatting
Format all code using ruff:
Type Checking
Run mypy type checking:
Linting
Run ruff linting checks:
Development Patterns
Code Style
- All code should be Pythonic and follow PEP-8
- Use type hints where appropriate
- Write descriptive docstrings for public functions and classes
Package Dependencies
- Keep shared code in
grizzly-loadtester-common - Don't duplicate code across packages
-
Move common utilities to the common package
-
Use workspace dependencies in
pyproject.toml -
Always preserve
uv.lock - Use
uv sync --lockedwhen installing - Commit the lock file to ensure reproducible builds
Testing Strategy
- Unit Tests: Mock external dependencies, fast execution
- E2E Tests: Run against real services, validate full functionality
- Coverage: All code must be covered with unit tests
- Group Tests: Organize tests by functionality
Adding a New Package
When adding a new package to the workspace:
- Create the package directory with
pyproject.toml - Update root
pyproject.toml: tool.pytest.ini_optionstool.coverage.pathtool.mypy- Add test scripts to
tool.hatch.envs.test.scripts - Run
uv sync --lockedto update the lock file
Release Process
Releases are automated via the .github/workflows/release.yaml workflow.
Release Triggers
The release workflow can be triggered in two ways:
- Automatic (PR Merge): When a PR is merged to
mainwith one of these labels: major- Breaking changes (X.0.0)minor- New features (0.X.0)-
patch- Bug fixes (0.0.X) -
Manual (Workflow Dispatch): Manually trigger the workflow from GitHub Actions UI
- Specify the PR number
- Optionally enable dry-run mode (no actual release)
Release Workflow Steps
- Prerequisites Job
- Validates the PR and checks for the version bump label
- Detects which packages changed using
.github/changes-filter.yaml -
Maps changes to packages and their dependencies
-
UV Release Job (Python packages)
- Builds packages using
uv build --package <package> --sdist --wheel - Creates a git tag (e.g.,
framework@v1.2.3) - Publishes to PyPI using trusted publishing (OIDC)
-
Pushes the tag only if all steps succeed
-
NPM Release Job (VS Code extension)
- Builds the extension using
@vscode/vsce package - Creates a git tag (e.g.,
vscode-extension@v1.2.3) - Publishes to VS Code Marketplace
-
Pushes the tag only if all steps succeed
-
Documentation Job
- Builds and deploys documentation to GitHub Pages
- Only runs if previous jobs succeed
Version Management
Versions are managed automatically using:
-
Python packages:
hatch-vcswith git tags matching pattern inpyproject.toml -
NPM packages:
package.local.jsondefines the tag pattern
Release Requirements
For a package to be releasable:
- Python packages must have:
-
tool.hatch.version.raw-options.scm.git.describe_commandinpyproject.toml -
NPM packages must have:
-
tag.patterninpackage.local.json -
Workflow files (.github/workflows/) cannot be modified in the same PR
- The
map-changes.pyscript will fail if workflow changes are detected during release - This prevents permission issues with
GITHUB_TOKENwhen pushing tags
Tag Management
The setup-release action creates tags during the job and manages them in a cleanup phase:
- Success: Tag is pushed to the repository
- Failure: Tag is deleted locally (not pushed)
- Dry-run: Tag is deleted (no push)
Secrets Required
Configure these secrets in your GitHub repository:
VSCE_TOKEN: Personal Access Token for VS Code Marketplace- Required for publishing the VS Code extension
-
Get from Azure DevOps
-
GITHUB_TOKEN: Automatically provided by GitHub Actions - Used for API access and documentation deployment
Manual Release Example
# Trigger via GitHub Actions UI
# 1. Go to Actions → Release
# 2. Click "Run workflow"
# 3. Select branch: main
# 4. Enter PR number: 123
# 5. Enable dry-run: true (optional)
# 6. Click "Run workflow"
Dry-Run Mode
Test the release process without actually publishing:
This will: - Create and validate tags - Build packages - Skip actual publishing to PyPI/VS Code Marketplace - Delete tags at the end
VS Code Extension Development
Building the Extension
Watch Mode
For active development with auto-rebuild:
Or use the VS Code task:
Testing the Extension
- Open the extension project in VS Code
- Press
F5to launch Extension Development Host - The extension will be loaded in a new VS Code window
Important Notes
- VS Code extension requires rebuild after language server changes
- Always run tests after modifying language server code
- Extension source is in TypeScript, compiled to JavaScript in
dist/
Documentation
The documentation is built using MkDocs with a custom plugin for API reference generation.
Building Documentation
Serving Documentation Locally
Then visit http://localhost:8000
Documentation Structure
docs/site/- Static markdown pagesdocs/build/- Generated output (deployed to GitHub Pages)- Custom MkDocs plugin generates API reference from code
Common Gotchas
- Always use
uv sync --locked - Preserves dependency locks
-
Ensures reproducible builds
-
E2E tests require additional setup
- See package-specific READMEs
-
May need external services (IBM MQ, Azure services, etc.)
-
VS Code extension rebuild
- Required after language server changes
-
Run
npm run compileor use watch mode -
Python version compatibility
- Test across all supported versions (3.10-3.13)
-
Use
hatchmatrix environments -
Workflow file changes
- Cannot be released in the same PR as package changes
- Will cause the release workflow to fail
- Create separate PRs for workflow and package changes
Troubleshooting
Dependency Issues
If you encounter dependency conflicts:
Test Failures
- Check if dependencies are installed:
uv sync --locked - Verify Python version:
python --version - Check for environment-specific issues in package READMEs
- Run with verbose output:
pytest -vv
Release Failures
- Check PR has correct version label (major/minor/patch)
- Verify secrets are configured (VSCE_TOKEN)
- Ensure workflow files aren't modified in the PR
- Check GitHub Actions logs for detailed error messages
- Verify package has release configuration (tag pattern in pyproject.toml or package.local.json)
Contributing
- Create a feature branch from
main - Make your changes following the development patterns
- Write tests for new functionality
- Run linting and type checking
- Create a PR with appropriate labels (major/minor/patch for releases)
- Ensure all CI checks pass