Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
3c6ed12
chore(py): bump version to 0.5.0
yesudeep Feb 3, 2026
c9c14e7
Merge remote-tracking branch 'origin/main' into yesudeep/chore/enchan…
yesudeep Feb 4, 2026
1633d3b
docs(py): add comprehensive changelog and PR description for v0.5.0 r…
yesudeep Feb 4, 2026
f89ddee
docs(py): add Dotprompt integration details, remove session/chat (ref…
yesudeep Feb 4, 2026
1640520
docs(py): add performance section, highlight critical fixes, add links
yesudeep Feb 4, 2026
88e180b
docs(py): add contributor acknowledgments to changelog and PR descrip…
yesudeep Feb 4, 2026
ad3b122
docs(py): add PR counts and convert dotprompt contributors to table
yesudeep Feb 4, 2026
f03f3ae
docs(py): add GitHub links, exhaustive contributions, dotprompt section
yesudeep Feb 4, 2026
4dcac66
docs(py): make contributor tables more exhaustive with PR numbers
yesudeep Feb 4, 2026
46ce52c
docs(py): update GEMINI.md with release PR learnings
yesudeep Feb 4, 2026
c1f7e8e
docs(py): add comprehensive Release PR Checklist to GEMINI.md
yesudeep Feb 4, 2026
7aa793a
docs(py): add blog article for Genkit Python SDK 0.5.0 release
yesudeep Feb 4, 2026
6b0169b
fix(py): correct code examples in blog article
yesudeep Feb 4, 2026
dffe9b4
docs(py): add blog article requirement and code accuracy guidelines
yesudeep Feb 4, 2026
280ba75
docs(py): update branding to 'Genkit' not 'Firebase Genkit'
yesudeep Feb 4, 2026
6727ca8
docs(py): replace DAP section with standard tool calling example
yesudeep Feb 4, 2026
3c439be
docs(py): remove DAP/MCP references - still in development
yesudeep Feb 4, 2026
b95b9b6
docs(py): fix incorrect plugin names and add verification check
yesudeep Feb 4, 2026
f878fa0
docs(py): add blog code syntax verification checks
yesudeep Feb 4, 2026
0a7f7da
docs(py): add automated release documentation validation script
yesudeep Feb 4, 2026
b8a5385
docs(py): remove incorrect AIM references for zarinn3pal
yesudeep Feb 4, 2026
e674e21
docs(py): fix zarinn3pal contribution - use 'GCP telemetry' not 'AIM'
yesudeep Feb 4, 2026
5bfb1b3
docs(py): add zarinn3pal's GCP telemetry work to PR description
yesudeep Feb 4, 2026
c1b1adf
fix(ci): add all 22 plugins to Python publish workflow
yesudeep Feb 4, 2026
dbc539a
feat(ci): add publish-all option to Python release workflow
yesudeep Feb 4, 2026
cf437e7
docs(py): add comprehensive release and publishing documentation
yesudeep Feb 4, 2026
c972db7
feat(py): add create_release script for automated releases
yesudeep Feb 4, 2026
eba9f75
fix(py): fetch PR description from GitHub instead of local file
yesudeep Feb 4, 2026
daa3613
feat(py): add version consistency and shell linting checks
yesudeep Feb 4, 2026
3240266
fix(py): fix publish_pypi.sh shebang location and shellcheck warning
yesudeep Feb 4, 2026
257e94e
fix(py): standardize shell scripts with proper shebang and pipefail
yesudeep Feb 4, 2026
4111e6f
feat(ci): add post-publish verification for Python packages
yesudeep Feb 4, 2026
2f20126
refactor(ci): dynamically generate plugin matrix from py/plugins/
yesudeep Feb 4, 2026
b6454c9
docs: add all plugins to mkdocstrings and update ROADMAP
yesudeep Feb 4, 2026
818d28f
fix(docs): correct import paths in types.md for mkdocstrings
yesudeep Feb 4, 2026
6408d0c
docs: update API docs with all exported types and classes
yesudeep Feb 4, 2026
3b03890
docs: add draft PR descriptions for future reference
yesudeep Feb 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 210 additions & 26 deletions .github/workflows/publish_python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,108 @@ name: Publish Python Package
on:
workflow_dispatch:
inputs:
project_type:
description: Type of project
publish_scope:
description: 'Publish scope (all = release all packages, single = one package)'
type: choice
default: package
default: single
required: true
options:
- all
- single
project_type:
description: 'Type of project (packages for genkit core, plugins for all others). Ignored when publish_scope=all.'
type: choice
default: packages
required: false
options:
- packages
- plugins
project_name:
description: Project name publishing to Pypi
description: 'Project name to publish. Ignored when publish_scope=all.'
type: choice
default: genkit
required: true
required: false
options:
# Core package
- genkit
- compat-oai
- dev-local-vectorstore
- firebase
- flask
- google-cloud
# Model provider plugins
- anthropic
- aws-bedrock
- cf-ai
- deepseek
- google-genai
- huggingface
- mistral
- msfoundry
- ollama
- vertex-ai
- xai
# Telemetry plugins
- aws
- azure
- cf
- google-cloud
- observability
# Framework integration plugins
- flask
# Data and retrieval plugins
- dev-local-vectorstore
- evaluators
- firebase
# OpenAI compatibility
- compat-oai
# MCP (Model Context Protocol)
- mcp

jobs:
# Generate the matrix of packages to build
generate_matrix:
name: Generate build matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v5

- name: Generate matrix
id: set-matrix
run: |
if [ "${{ github.event.inputs.publish_scope }}" == "all" ]; then
# Dynamically discover all plugins from py/plugins/ directory
echo "Discovering plugins from py/plugins/..."

# Start with core package
MATRIX='{"include":[{"project_type":"packages","project_name":"genkit"}'

# Add all plugins dynamically
for plugin_dir in py/plugins/*/; do
if [ -d "$plugin_dir" ]; then
plugin_name=$(basename "$plugin_dir")
# Skip README.md and other non-directory entries
if [ -f "$plugin_dir/pyproject.toml" ]; then
echo " Found plugin: $plugin_name"
MATRIX="$MATRIX,{\"project_type\":\"plugins\",\"project_name\":\"$plugin_name\"}"
fi
fi
done

MATRIX="$MATRIX]}"
echo "Generated matrix with $(echo "$MATRIX" | jq '.include | length') packages"
else
# Build matrix for single package
MATRIX='{"include":[{"project_type":"${{ github.event.inputs.project_type }}","project_name":"${{ github.event.inputs.project_name }}"}]}'
fi
echo "matrix=$(echo $MATRIX | jq -c .)" >> $GITHUB_OUTPUT

jobs:
python_build:
name: Python build packages
name: Build ${{ matrix.project_name }}
needs: [generate_matrix]
runs-on: ubuntu-latest
env:
PATH: ${{ github.workspace }}/.cargo/bin:${{ github.workspace }}/.local/bin:/usr/local/bin:/usr/bin:/bin
strategy:
matrix:
python-version:
- "3.12"
matrix: ${{ fromJson(needs.generate_matrix.outputs.matrix) }}
fail-fast: false
env:
PATH: ${{ github.workspace }}/.cargo/bin:${{ github.workspace }}/.local/bin:/usr/local/bin:/usr/bin:/bin

steps:
- uses: actions/checkout@v5
Expand All @@ -78,43 +143,162 @@ jobs:
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
python-version: "3.12"

- name: Install Python dependencies
run: |
cd py/${{ github.event.inputs.project_type }}/${{ github.event.inputs.project_name }}
uv pip install -e .[dev,test,docs]
cd py/${{ matrix.project_type }}/${{ matrix.project_name }}
uv pip install -e .[dev,test,docs] || uv pip install -e .
uv pip install twine toml

- name: Build package and validate pypi
run: |
cd py
PROJECT_NAME=${{ github.event.inputs.project_name }} PROJECT_TYPE=${{ github.event.inputs.project_type }} ./bin/publish_pypi.sh
PROJECT_NAME=${{ matrix.project_name }} PROJECT_TYPE=${{ matrix.project_type }} ./bin/publish_pypi.sh

- name: Upload build packages
uses: actions/upload-artifact@v4
with:
name: dist
name: dist-${{ matrix.project_name }}
path: py/dist/

pypi_publish:
name: Upload to PyPI
needs: [python_build]
name: Publish ${{ matrix.project_name }} to PyPI
needs: [generate_matrix, python_build]
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJson(needs.generate_matrix.outputs.matrix) }}
fail-fast: false
environment:
# change to publish or similar in productive CI
name: pypi_github_publishing
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v5
with:
name: dist
name: dist-${{ matrix.project_name }}
path: py/dist/

- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
verbose: true
packages-dir: py/dist/

# Post-publish verification: confirm packages are installable and functional
verify_publish:
name: Verify published packages
needs: [generate_matrix, pypi_publish]
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJson(needs.generate_matrix.outputs.matrix) }}
fail-fast: false
steps:
- uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Wait for PyPI propagation
run: |
echo "Waiting 60 seconds for PyPI CDN propagation..."
sleep 60

- name: Get expected version
id: get_version
run: |
VERSION=$(grep '^version' py/${{ matrix.project_type }}/${{ matrix.project_name }}/pyproject.toml | head -1 | sed 's/.*= *"//' | sed 's/".*//')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Expected version: $VERSION"

- name: Determine package name
id: package_name
run: |
if [ "${{ matrix.project_type }}" == "packages" ]; then
PACKAGE="${{ matrix.project_name }}"
else
PACKAGE="genkit-plugin-${{ matrix.project_name }}"
fi
echo "name=$PACKAGE" >> $GITHUB_OUTPUT
echo "Package name: $PACKAGE"

- name: Install from PyPI
run: |
python -m pip install --upgrade pip
pip install "${{ steps.package_name.outputs.name }}==${{ steps.get_version.outputs.version }}"

- name: Verify installation
run: |
PACKAGE="${{ steps.package_name.outputs.name }}"
VERSION="${{ steps.get_version.outputs.version }}"

# Check installed version
INSTALLED=$(pip show "$PACKAGE" | grep "^Version:" | cut -d' ' -f2)
echo "Installed version: $INSTALLED"

if [ "$INSTALLED" != "$VERSION" ]; then
echo "❌ Version mismatch: expected $VERSION, got $INSTALLED"
exit 1
fi
echo "✅ Version match: $VERSION"

- name: Smoke test imports
run: |
PACKAGE="${{ steps.package_name.outputs.name }}"

if [ "$PACKAGE" == "genkit" ]; then
python -c "from genkit.ai import Genkit; print('✅ genkit imports successfully')"
else
# For plugins, just verify the package is importable
# Plugin module names use underscores, not hyphens
MODULE_NAME=$(echo "$PACKAGE" | sed 's/-/_/g')
python -c "import $MODULE_NAME; print('✅ $PACKAGE imports successfully')" || \
echo "⚠️ Import test skipped (plugin may require extra deps)"
fi

# Summary job to report overall status
publish_summary:
name: Publish Summary
needs: [generate_matrix, pypi_publish, verify_publish]
runs-on: ubuntu-latest
if: always()
steps:
- uses: actions/checkout@v5

- name: Get version
id: get_version
run: |
VERSION=$(grep '^version' py/packages/genkit/pyproject.toml | head -1 | sed 's/.*= *"//' | sed 's/".*//')
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Create summary
run: |
echo "## 📦 Python Package Publish Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ steps.get_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**Scope:** ${{ github.event.inputs.publish_scope }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ needs.pypi_publish.result }}" == "success" ]; then
echo "### ✅ Publish Status: Success" >> $GITHUB_STEP_SUMMARY
else
echo "### ❌ Publish Status: Failed" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ needs.verify_publish.result }}" == "success" ]; then
echo "### ✅ Verification: Passed" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.verify_publish.result }}" == "failure" ]; then
echo "### ⚠️ Verification: Some packages failed" >> $GITHUB_STEP_SUMMARY
else
echo "### ⏭️ Verification: Skipped" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY

echo "### Next Steps" >> $GITHUB_STEP_SUMMARY
echo "1. Verify on PyPI: https://pypi.org/project/genkit/${{ steps.get_version.outputs.version }}/" >> $GITHUB_STEP_SUMMARY
echo "2. Test installation: \`pip install genkit==${{ steps.get_version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
echo "3. Update documentation if needed" >> $GITHUB_STEP_SUMMARY
33 changes: 31 additions & 2 deletions bin/lint
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ set -euo pipefail

TOP_DIR=$(git rev-parse --show-toplevel)

GO_DIR="${TOP_DIR}/go"
# shellcheck disable=SC2034
GO_DIR="${TOP_DIR}/go" # Reserved for future Go linting
PY_DIR="${TOP_DIR}/py"
JS_DIR="${TOP_DIR}/js"
# shellcheck disable=SC2034
JS_DIR="${TOP_DIR}/js" # Reserved for future JS linting

uv run --directory "${PY_DIR}" ruff check --fix --preview --unsafe-fixes .
uv run --directory "${PY_DIR}" ruff format --preview .
Expand Down Expand Up @@ -57,6 +59,33 @@ uv run --directory "${PY_DIR}" liccheck -s pyproject.toml
echo "--- 🔍 Running Consistency Checks ---"
"${PY_DIR}/bin/check_consistency"

# Shell script linting
echo "--- 🐚 Running Shell Script Lint (shellcheck) ---"
if command -v shellcheck &> /dev/null; then
shell_errors=0
# Check both top-level bin/ and py/bin/
for script in "${TOP_DIR}"/bin/* "${PY_DIR}"/bin/*; do
if [ -f "$script" ] && file "$script" | grep -qE "shell|bash|sh script" 2>/dev/null; then
script_name=$(basename "$script")
# Skip .py files
if [[ "$script_name" == *.py ]]; then
continue
fi
if ! shellcheck "$script" 2>&1; then
shell_errors=$((shell_errors + 1))
fi
fi
done
if [ $shell_errors -gt 0 ]; then
echo "⚠️ $shell_errors shell script(s) have shellcheck warnings"
exit 1
else
echo "✅ All shell scripts pass shellcheck"
fi
else
echo "⚠️ shellcheck not installed (brew install shellcheck) - skipping"
fi

# Disabled because there are many lint errors.
#pushd "${GO_DIR}" &>/dev/null
#golangci-lint run ./...
Expand Down
Loading
Loading