Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
39 changes: 39 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
root = true

# All files
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

# Python files
[*.py]
indent_style = space
indent_size = 4

# YAML files - maintain 2-space indentation
[*.{yaml,yml}]
indent_style = space
indent_size = 2

# JSON files
[*.json]
indent_style = space
indent_size = 2

# Markdown files
[*.md]
trim_trailing_whitespace = false
indent_style = space
indent_size = 2

# Toml files
[*.toml]
indent_style = space
indent_size = 2

# GitHub Actions workflows
[.github/workflows/*.{yaml,yml}]
indent_style = space
indent_size = 2
6 changes: 6 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Mock server URLs for local development
# Copy this file to .env and uncomment the URLs you need

# MOCK_ALGOD_URL=http://localhost:18000
# MOCK_INDEXER_URL=http://localhost:18002
# MOCK_KMD_URL=http://localhost:18001
31 changes: 31 additions & 0 deletions .github/actions/publish-docs/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "Build Documentation"
description: "Generate API docs via Sphinx and build Starlight site"

runs:
using: "composite"
steps:
- name: Setup Python environment
uses: algorandfoundation/algokit-shared-config/.github/actions/setup-algokit-python@main
with:
install-algokit: "false"

- name: Set up Node.js 22
uses: actions/setup-node@v4
with:
node-version: "22"

- uses: pnpm/action-setup@v4
with:
package_json_file: docs/package.json

- name: Install docs dependencies
shell: bash
run: pnpm install --frozen-lockfile --dir docs

- name: Generate API docs
shell: bash
run: uv run poe docs-api

- name: Build Starlight site
shell: bash
run: pnpm --dir docs build
40 changes: 0 additions & 40 deletions .github/actions/setup-poetry/action.yaml

This file was deleted.

20 changes: 17 additions & 3 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
## Proposed Changes

-
-
-
This pull request introduces optional runtime validation schemas for API client responses using Pydantic models, and adds automation and documentation to support their use and maintenance. The main themes are: adding schema generation and usage, updating developer workflow and dependencies, and documenting the new feature.

### Validation schema generation and usage

- Added a script (`scripts/generate_schemas.py`) that generates Pydantic validation schemas from OpenAPI specs for algod, kmd, and indexer clients, producing 208 schema files in total. These schemas enable runtime type and bounds validation of API responses.
- Added and exported all generated schemas in `src/algokit_algod_client/schemas/__init__.py` for easy import and usage in client code.

### Developer workflow and automation

- Introduced a new `poe` task (`generate-schemas`) in `pyproject.toml` to automate schema generation, and updated the CI workflow to generate schemas and check for uncommitted changes to ensure schema files remain in sync with OpenAPI specs.
- Added `pydantic>=2.0.0,<3` as a development dependency, and excluded generated schemas from mypy type checking in `pyproject.toml`.
- Updated linting configuration to ignore specific rules for generated API client and schema files.

### Documentation

- Added a new documentation file (`api/oas-generator/VALIDATION.md`) detailing the purpose, usage, features, and maintenance of the validation schemas.
- Updated `README.md` with a section introducing validation schemas, installation requirements, usage examples, and links to further documentation.
83 changes: 72 additions & 11 deletions .github/workflows/build-python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,78 @@ jobs:
- name: Checkout source code
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v5
- name: Setup Python environment
uses: algorandfoundation/algokit-shared-config/.github/actions/setup-algokit-python@main
with:
python-version: ${{ matrix.python }}
install-algokit: "false"

- name: Set up Poetry
uses: ./.github/actions/setup-poetry
- name: Install extra dependency groups
run: uv sync --group api-generator

- name: Install dependencies
run: poetry install --no-interaction
- name: Setup Polytest
uses: algorandfoundation/algokit-polytest/.github/actions/setup-polytest@main

- name: Generate all polytest files
shell: bash
run: uv run poe polytest-generate-all

- name: Start algod mock server
uses: algorandfoundation/algokit-polytest/.github/actions/run-mock-server@main
with:
client: algod

- name: Start indexer mock server
uses: algorandfoundation/algokit-polytest/.github/actions/run-mock-server@main
with:
client: indexer

- name: Start kmd mock server
uses: algorandfoundation/algokit-polytest/.github/actions/run-mock-server@main
with:
client: kmd

- name: Generate API clients
run: uv run poe generate-api-clients

- name: Check API output stability
shell: bash
run: |
git status --porcelain src > /tmp/post_api_status.txt
if [ -s /tmp/post_api_status.txt ]; then
echo "❌ API OpenAPI sync needed!"
git status --porcelain src
git diff -- src
echo "🔧 Run 'uv run poe generate-api-clients' locally and commit the results."
exit 1
else
echo "✅ API OpenAPI sync passed"
fi

- name: Generate validation schemas
run: uv run poe generate-schemas

- name: Check schema output stability
shell: bash
run: |
git status --porcelain tests/fixtures/schemas > /tmp/post_schema_status.txt
if [ -s /tmp/post_schema_status.txt ]; then
echo "❌ Validation schema sync needed!"
git status --porcelain tests/fixtures/schemas
git diff -- tests/fixtures/schemas
echo "🔧 Run 'uv run poe generate-schemas' locally and commit the results."
exit 1
else
echo "✅ Validation schema sync passed"
fi

- name: pytest + coverage
shell: bash
run: |
set -o pipefail
pipx install algokit
algokit localnet start
poetry run pytest -n auto --junitxml=pytest-junit.xml --cov-report=term-missing:skip-covered --cov=src | tee pytest-coverage.txt
algokit localnet stop
uvx algokit localnet start
uv run poe test-ci 2>&1 | tee pytest-coverage.txt
uvx algokit localnet stop

- name: pytest coverage comment - using Python 3.10 on ubuntu-latest
if: matrix.python == '3.10' && matrix.os == 'ubuntu-latest'
Expand All @@ -41,5 +94,13 @@ jobs:
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest-junit.xml

- name: Upload test results and coverage artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-python-${{ matrix.python }}
path: pytest-junit.xml
retention-days: 30

- name: Build Wheel
run: poetry build --format wheel
run: uv build
94 changes: 64 additions & 30 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ on:
push:
branches:
- main
- alpha
paths-ignore:
- "docs/**"
- ".github/**"
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -39,6 +39,9 @@ jobs:
name: Release Library
needs: ci-build-python
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write

steps:
- name: Generate bot token
Expand All @@ -54,16 +57,10 @@ jobs:
fetch-depth: 0
token: ${{ steps.app_token.outputs.token }}

- name: Set up Python
uses: actions/setup-python@v5
- name: Setup Python environment
uses: algorandfoundation/algokit-shared-config/.github/actions/setup-algokit-python@main
with:
python-version: "3.10"

- name: Set up Poetry
uses: ./.github/actions/setup-poetry

- name: Install dependencies
run: poetry install --no-interaction --no-root
install-algokit: "false"

- name: Get branch name
shell: bash
Expand All @@ -73,32 +70,69 @@ jobs:
- name: Set Git user as GitHub actions
run: git config --global user.email "179917785+engineering-ci[bot]@users.noreply.github.com" && git config --global user.name "engineering-ci[bot]"

- name: Create Continuous Deployment - Alpha
id: release-alpha
if: steps.get_branch.outputs.branch == 'alpha'
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
run: |
uv run semantic-release -v version --as-prerelease --prerelease-token alpha
uv run semantic-release publish

- name: Create Continuous Deployment - Beta (non-prod)
id: release-beta
if: steps.get_branch.outputs.branch == 'main' && !inputs.production_release
run: |
poetry run semantic-release \
-v DEBUG \
--prerelease \
--define=branch=main \
--define=upload_to_repository=true \
publish
gh release edit --prerelease "v$(poetry run semantic-release print-version --current)"
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
REPOSITORY_USERNAME: __token__
REPOSITORY_PASSWORD: ${{ secrets.PYPI_API_KEY }}
run: |
uv run semantic-release -v version --as-prerelease
uv run semantic-release publish

- name: Create Continuous Deployment - Production
id: release-prod
if: steps.get_branch.outputs.branch == 'main' && inputs.production_release
run: |
poetry run semantic-release \
-v DEBUG \
--define=version_source="commit" \
--define=patch_without_tag=true \
--define=upload_to_repository=true \
--define=branch=main \
publish
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
REPOSITORY_USERNAME: __token__
REPOSITORY_PASSWORD: ${{ secrets.PYPI_API_KEY }}
run: |
uv run semantic-release -v version
uv run semantic-release publish

- name: Publish package distributions to PyPI
if: |
(steps.release-alpha.outputs.released == 'true') ||
(steps.release-beta.outputs.released == 'true') ||
(steps.release-prod.outputs.released == 'true')
uses: pypa/gh-action-pypi-publish@release/v1
with:
verbose: true

deploy-docs:
name: Deploy Documentation
needs: ci-build-python
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
concurrency:
group: deploy-docs
cancel-in-progress: true
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Build documentation
uses: ./.github/actions/publish-docs

- name: Upload to GitHub Pages
uses: actions/upload-pages-artifact@v3
with:
path: docs/dist

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Loading
Loading