Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add workflows for testing / linting #17

Merged
merged 12 commits into from
Dec 3, 2024
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: pip
directory: /
schedule:
interval: monthly
groups:
dependencies:
dependency-type: production
dev-dependencies:
dependency-type: development
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
24 changes: 24 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Lint

on:
push:
branches:
- master
pull_request:
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- uses: pre-commit/[email protected]
- uses: pre-commit-ci/[email protected]
if: always()
with:
msg: Apply code formatting with pre-commit
6 changes: 3 additions & 3 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ name: Release Package
# secrets.TESTPYPI_API_TOKEN (See: https://test.pypi.org/help/#apitoken)

on:
schedule:
- cron: '0 0 * * *'
# schedule:
# - cron: 0 0 * * *
workflow_dispatch:

jobs:
Expand All @@ -27,4 +27,4 @@ jobs:
poetry config pypi-token.testpypi '${{ secrets.TESTPYPI_API_TOKEN }}'
poetry config pypi-token.pypi '${{ secrets.PYPI_API_TOKEN }}'
- name: Publish package
run: python publish.py
run: poetry run task publish
43 changes: 43 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Test

on:
push:
branches:
- master
pull_request:
workflow_dispatch:

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
python-version:
- '3.9'
- '3.13'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Install poetry
run: pipx install poetry
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: poetry
- name: Setup
shell: bash
run: |
poetry install --no-interaction
export DOWNLOAD_LATEST_ONLY=1
poetry run task publish
- name: Test
run: |
poetry run task test
50 changes: 50 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# How to develop

## Requirement

- `python>=3.9`
- `java`

## Setup

```bash
pip install pipx
pipx install poetry

poetry install
poetry run pre-commit install
```

## Activate virtual environment (venv) for development

```bash
poetry shell
```

## Lint

```bash
# in venv:
task lint
```

## Fetch latest jar file

```bash
# in venv:
task download-latest-jar
```

## Run tests for all unpublished versions without publishing

```bash
# in venv:
task test-unpublished-versions
```

## Publish all unpublished versuibs to PyPI (for CI)

```bash
# in venv:
task publish
```
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<https://img.shields.io/badge/Slack-Join%20the%20chat%20room-orange>
)](
<https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g>
) [![PyPI version](
<https://badge.fury.io/py/openapi-generator-cli.svg>
)](
<https://badge.fury.io/py/openapi-generator-cli>
) [![Code style: black](
<https://img.shields.io/badge/code%20style-black-000000.svg>
)](
Expand Down
21 changes: 18 additions & 3 deletions openapi_generator_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""A Python wrapper for the OpenAPI Generator CLI."""

from __future__ import annotations

import importlib.resources
Expand All @@ -6,7 +8,19 @@
import sys


def run(args: list[str] | None = None) -> None:
def run(args: list[str] | None = None) -> subprocess.CompletedProcess[bytes]:
"""Run the OpenAPI Generator CLI with the given arguments.

Args:
args (list[str], optional):
The list of arguments to pass to the Open
API Generator CLI. If not provided, the CLI will
be run without any arguments.

Returns:
subprocess.CompletedProcess[bytes]: The result of running the OpenAPI Generator CLI.

"""
arguments = ["java"]

java_opts = os.getenv("JAVA_OPTS")
Expand All @@ -18,13 +32,14 @@ def run(args: list[str] | None = None) -> None:
jar_path = importlib.resources.files("openapi_generator_cli") / "openapi-generator.jar"
arguments.append(str(jar_path))

if args and type(args) == list:
if args and isinstance(args, list):
arguments.extend(args)

subprocess.call(arguments) # noqa: S603
return subprocess.run(arguments, check=False) # noqa: S603


def cli() -> None:
"""Run the OpenAPI Generator CLI with the arguments provided on the command line."""
args = []
if len(sys.argv) > 1:
args = sys.argv[1:]
Expand Down
17 changes: 16 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 41 additions & 17 deletions publish.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from __future__ import annotations

import json
import os
import shutil
import subprocess
from pathlib import Path
from typing import TYPE_CHECKING
from urllib.request import urlopen

from natsort import natsorted

if TYPE_CHECKING:
from collections.abc import KeysView

Expand All @@ -18,22 +21,18 @@ def download_openapi_generator_jar(version: str) -> None:
MVN_BASE_URL
+ "/remotecontent?filepath=org/openapitools/openapi-generator-cli/"
+ version
+ "/openapi-generator-cli-"
+ version
+ ".jar"
+ f"/openapi-generator-cli-{version}.jar"
)

Path("openapi-generator.jar").unlink(missing_ok=True)

print(download_url)
print(f"[{version}] URL: {download_url!r}")
response = urlopen(download_url) # noqa: S310

if response.status != 200: # noqa: PLR2004
msg = f"{response.status}: {download_url}"
raise RuntimeError(msg)

print("Downloading complete")

with Path("openapi_generator_cli/openapi-generator.jar").open("wb") as openapi_generator_jar:
openapi_generator_jar.write(response.read())
openapi_generator_jar.close()
Expand Down Expand Up @@ -78,18 +77,43 @@ def get_published_vesions() -> KeysView[str]:
return published_releases.keys()


def publish() -> None:
latest_version = get_available_versions()[0]
published_versions = get_published_vesions()
def download_latest_jar_for_test() -> None:
latest_version = natsorted(get_available_versions())[-1]
print(f"[{latest_version}] Downloading...")
download_openapi_generator_jar(latest_version)
print(f"[{latest_version}] Downloaded!")


def publish(*, dryrun: bool = False) -> None:
pytest_path = shutil.which("pytest")
poetry_path = shutil.which("poetry")

unpublished_versions = natsorted(set(get_available_versions()) - set(get_published_vesions()))

for publishing_version in unpublished_versions:
print(f"[{publishing_version}] Downloading...")
download_openapi_generator_jar(publishing_version)

print(f"[{publishing_version}] Testing...")
subprocess.check_call([pytest_path])

if dryrun:
continue

print(f"[{publishing_version}] Building...")
subprocess.check_call([poetry_path, "build", "-v"])

print(f"[{publishing_version}] Publishing to TestPyPI...")
subprocess.check_call([poetry_path, "publish", "-r", "testpypi", "-v"])

print(f"[{publishing_version}] Publishing to PyPI...")
subprocess.check_call([poetry_path, "publish", "-v"])

if latest_version not in published_versions:
print("Publishing version " + latest_version)
download_openapi_generator_jar(latest_version)
poetry_path = shutil.which("poetry")
subprocess.check_call([poetry_path, "build"]) # noqa: S603
subprocess.check_call([poetry_path, "publish", "-r", "testpypi"]) # noqa: S603
subprocess.check_call([poetry_path, "publish"]) # noqa: S603
print(f"[{publishing_version}] Published!")


if __name__ == "__main__":
publish()
if os.getenv("DOWNLOAD_LATEST_ONLY") == "1":
download_latest_jar_for_test()
else:
publish(dryrun=os.getenv("DRYRUN") == "1")
13 changes: 12 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ mypy = ">=0.991,<1.14"
pre-commit = ">=2.20,<4.0"
taskipy = "^1.10.3"
pytest = ">=7.2.2,<9.0.0"
natsort = "^8.4.0"

[tool.poetry.scripts]
openapi-generator-cli = "openapi_generator_cli:cli"
Expand All @@ -61,11 +62,18 @@ lint.select = [
"ALL",
]
lint.ignore = [
"D",
"D211", # No blank lines allowed before class docstring
"D213", # Multi-line docstring summary should start at the second line
]
lint.per-file-ignores."publish.py" = [
"D",
"S603", # `subprocess` call: check for execution of untrusted input
"T201", # `print` found
]
lint.per-file-ignores."tests/*" = [
"D",
"S101", # Use of `assert` detected
]

[tool.mypy]
pretty = true
Expand All @@ -74,6 +82,9 @@ show_error_codes = true
strict = true

[tool.taskipy.tasks]
download-latest-jar = "DOWNLOAD_LATEST_ONLY=1 task publish"
test = "pytest"
test-unpublished-versions = "DRYRUN=1 task publish"
lint = "pre-commit run -a"
publish = "python publish.py"
profile = "python -m cProfile"
Empty file added tests/__init__.py
Empty file.
Loading
Loading