Regenerate Client #38
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Regenerate Client | |
| on: | |
| workflow_dispatch: | |
| jobs: | |
| regenerate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Generate GitHub App token | |
| id: app-token | |
| uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3 | |
| with: | |
| app-id: 3060111 | |
| private-key: ${{ secrets.HOTDATA_AUTOMATION_PRIVATE_KEY }} | |
| owner: hotdata-dev | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Fetch merged OpenAPI spec | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: | | |
| curl -sS -f -L \ | |
| -H "Accept: application/vnd.github.v3.raw" \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| https://api.github.com/repos/hotdata-dev/www.hotdata.dev/contents/api/openapi.yaml \ | |
| -o openapi.yaml | |
| - name: Clean existing source | |
| run: rm -rf src/ | |
| - name: Read package version from pyproject.toml | |
| id: pkg | |
| run: | | |
| version=$(python3 -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])") | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| - name: Generate client | |
| run: | | |
| npx @openapitools/openapi-generator-cli generate \ | |
| -i openapi.yaml \ | |
| -g python \ | |
| -o . \ | |
| -t .openapi-generator-templates \ | |
| --additional-properties=packageName=hotdata,projectName=hotdata,packageVersion=${{ steps.pkg.outputs.version }},gitUserId=hotdata-dev,gitRepoId=sdk-python \ | |
| --skip-validate-spec | |
| - name: Patch generated __version__ to read from package metadata | |
| run: | | |
| python3 - <<'PY' | |
| import re, pathlib, sys | |
| p = pathlib.Path("hotdata/__init__.py") | |
| src = p.read_text() | |
| replacement = ( | |
| 'from importlib.metadata import PackageNotFoundError, version as _pkg_version\n' | |
| '\n' | |
| 'try:\n' | |
| ' __version__ = _pkg_version("hotdata")\n' | |
| 'except PackageNotFoundError: # running from a source checkout without install\n' | |
| ' __version__ = "0.0.0+unknown"\n' | |
| ) | |
| new, n = re.subn(r'^__version__ = "[^"]*"\n', replacement, src, count=1, flags=re.MULTILINE) | |
| if n != 1: | |
| sys.exit("Failed to patch __version__ line in hotdata/__init__.py") | |
| p.write_text(new) | |
| PY | |
| - name: Patch generated pyproject.toml metadata | |
| run: | | |
| python3 - <<'PY' | |
| import re, pathlib, sys | |
| p = pathlib.Path("pyproject.toml") | |
| src = p.read_text() | |
| patches = [ | |
| ( | |
| r'^keywords = \[.*\]$', | |
| 'keywords = ["hotdata", "api-client", "data-platform"]', | |
| re.MULTILINE, | |
| ), | |
| ( | |
| r'\[project\.urls\]\nRepository = "[^"]*"\n', | |
| '[project.urls]\nHomepage = "https://www.hotdata.dev"\nRepository = "https://github.com/hotdata-dev/sdk-python"\n', | |
| 0, | |
| ), | |
| ] | |
| for pattern, replacement, flags in patches: | |
| src, n = re.subn(pattern, replacement, src, count=1, flags=flags) | |
| if n != 1: | |
| sys.exit(f"Failed to patch pyproject.toml: pattern {pattern!r}") | |
| p.write_text(src) | |
| PY | |
| - name: Clean up generated artifacts | |
| run: | | |
| rm -f openapi.yaml | |
| rm -f .github/workflows/python.yml | |
| - name: Verify built wheel installs and imports | |
| run: | | |
| python -m pip install --upgrade build | |
| python -m build | |
| python -m pip install dist/*.whl | |
| # cd away from the source tree so the import resolves against the installed wheel. | |
| cd /tmp && python -c "import hotdata; print(hotdata.__version__)" | |
| - name: Check integration test scenario parity | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: | | |
| curl -sS -f -L \ | |
| -H "Accept: application/vnd.github.v3.raw" \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| https://api.github.com/repos/hotdata-dev/www.hotdata.dev/contents/api/test-scenarios.yaml \ | |
| -o test-scenarios.yaml | |
| pip install --quiet pyyaml | |
| python3 - <<'PY' | |
| import sys, pathlib, yaml | |
| scenarios = yaml.safe_load(pathlib.Path("test-scenarios.yaml").read_text())["scenarios"] | |
| missing = [] | |
| for s in scenarios: | |
| if "python" in (s.get("optional_for") or []): | |
| continue | |
| expected = pathlib.Path("tests/integration") / f"test_{s['name']}.py" | |
| if not expected.exists(): | |
| missing.append(str(expected)) | |
| if missing: | |
| print(f"::warning::sdk-python is missing tests for {len(missing)} scenarios after regen:") | |
| for m in missing: | |
| print(f" - {m}") | |
| else: | |
| print(f"All {len(scenarios)} scenarios have corresponding test files.") | |
| PY | |
| rm -f test-scenarios.yaml | |
| - name: Create PR | |
| uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| title: "chore: regenerate client from updated OpenAPI spec" | |
| branch: openapi-update-${{ github.run_id }} | |
| commit-message: "chore: regenerate client from OpenAPI spec" | |
| body: "Auto-generated from updated HotData OpenAPI spec." |