Skip to content
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
29 changes: 29 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Lint

on:
pull_request:
branches: [main]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3

- name: Set up Python
run: uv python install 3.11

- name: Install dependencies
run: uv sync --group dev

- name: Run ruff check
run: uv run ruff check src/ tests/

- name: Run ruff format check
run: uv run ruff format --check src/ tests/

- name: Run mypy
run: uv run mypy src/ tests/
26 changes: 26 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Tests

on:
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v3

- name: Set up Python
run: uv python install 3.11

- name: Install dependencies
run: uv sync --group dev

- name: Run tests
run: uv run pytest tests/ -v

- name: Check coverage
run: uv run coverage run -m pytest tests/ && uv run coverage report --fail-under=85
19 changes: 7 additions & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ repos:
hooks:
- id: ruff
args: [--fix]
exclude: ^(client/|tests/|src/workato_platform/client/)
exclude: ^(client/|src/workato_platform/client/)
- id: ruff-format
exclude: ^(client/|tests/|src/workato_platform/client/)
exclude: ^(client/|src/workato_platform/client/)

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.18.1
hooks:
- id: mypy
args: [--explicit-package-bases]
additional_dependencies:
[
types-requests,
Expand All @@ -38,17 +39,11 @@ repos:
aiohttp>=3.8.0,
python-dateutil>=2.8.0,
typing-extensions>=4.0.0,
pytest>=7.0.0,
pytest-asyncio>=0.21.0,
pytest-mock>=3.10.0,
]
exclude: ^(client/|tests/|src/workato_platform/client/)

# Bandit for security linting
- repo: https://github.com/PyCQA/bandit
rev: 1.8.6
hooks:
- id: bandit
args: [-c, pyproject.toml]
additional_dependencies: ["bandit[toml]"]
exclude: ^(client/|tests/|src/workato_platform/client/)
exclude: ^(client/|src/workato_platform/client/)

# pip-audit for dependency security auditing
- repo: https://github.com/pypa/pip-audit
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ help:
@echo " test Run all tests"
@echo " test-unit Run unit tests only"
@echo " test-integration Run integration tests only"
@echo " test-client Run generated client tests only"
@echo " test-cov Run tests with coverage report"
@echo " test-watch Run tests in watch mode"
@echo " lint Run linting checks"
Expand Down Expand Up @@ -43,8 +44,11 @@ test-unit:
test-integration:
uv run pytest tests/integration/ -v

test-client:
uv run pytest src/workato_platform/client/workato_api/test/ -v

test-cov:
uv run pytest tests/ --cov=src/workato --cov-report=html --cov-report=term --cov-report=xml
uv run pytest tests/ --cov=src/workato_platform --cov-report=html --cov-report=term --cov-report=xml

test-watch:
uv run pytest tests/ -v --tb=short -x --lf
Expand All @@ -58,7 +62,7 @@ format:
check:
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv run mypy src/
uv run mypy --explicit-package-bases src/ tests/

clean:
rm -rf build/
Expand Down
37 changes: 18 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,12 @@ select = [
"T20", # flake8-print
"SIM", # flake8-simplify
]
ignore = []
ignore = [
"S101", # Skip assert_used test (used in generated client code)
]

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"**/test_*.py" = ["B011", "S101", "S105", "S106"]
"**/*_test.py" = ["B011", "S101", "S105", "S106"]
"tests/**/*.py" = ["S101", "S105", "S106"]
"tests/**/*.py" = ["B011", "S101", "S105", "S106"]

# Ruff isort configuration
[tool.ruff.lint.isort]
Expand Down Expand Up @@ -158,10 +157,13 @@ strict_equality = true
namespace_packages = true
explicit_package_bases = true
mypy_path = "src"
files = [
"src/workato_platform",
"tests",
]
plugins = ["pydantic.mypy"]
exclude = [
"src/workato_platform/client/workato_api/.*",
"test/*"
"src/workato_platform/client/*",
]

[[tool.mypy.overrides]]
Expand All @@ -177,6 +179,12 @@ module = [
]
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = [
"certifi",
]
ignore_missing_imports = true

# Pytest configuration
[tool.pytest.ini_options]
minversion = "7.0"
Expand All @@ -191,9 +199,8 @@ pythonpath = ["src"]
[tool.coverage.run]
source = ["src/workato_platform"]
omit = [
"*/tests/*",
"*/test_*",
"client/*",
"tests/*",
"src/workato_platform/client/*",
]

[tool.coverage.report]
Expand All @@ -216,25 +223,17 @@ source = "vcs"
[tool.hatch.build.hooks.vcs]
version-file = "src/workato_platform/_version.py"

# Bandit configuration for security linting
[tool.bandit]
exclude_dirs = [
"tests",
"client",
"src/workato_platform/client",
]
skips = ["B101"] # Skip assert_used test

[dependency-groups]
dev = [
"bandit>=1.8.6",
"build>=1.3.0",
"hatch-vcs>=0.5.0",
"mypy>=1.17.1",
"pip-audit>=2.9.0",
"pre-commit>=4.3.0",
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=7.0.0",
"pytest-mock>=3.10.0",
"ruff>=0.12.11",
"types-click>=7.0.0",
Expand Down
4 changes: 2 additions & 2 deletions src/workato_platform/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
commit_id: COMMIT_ID
__commit_id__: COMMIT_ID

__version__ = version = '0.1.dev5+gbd0aba595.d20250917'
__version_tuple__ = version_tuple = (0, 1, 'dev5', 'gbd0aba595.d20250917')
__version__ = version = '0.1.dev19+g3ca2449bf.d20250920'
__version_tuple__ = version_tuple = (0, 1, 'dev19', 'g3ca2449bf.d20250920')

__commit_id__ = commit_id = None
11 changes: 7 additions & 4 deletions src/workato_platform/cli/commands/api_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ async def create(
async with aiohttp.ClientSession() as session:
response = await session.get(content)
openapi_spec["content"] = await response.text()
openapi_spec["format"] = "json"

# Create API collection
spinner = Spinner(f"Creating API collection '{name}'")
Expand Down Expand Up @@ -222,14 +223,15 @@ async def list_endpoints(
endpoints: list[ApiEndpoint] = []
page = 1
while True:
endpoints.extend(
page_endpoints = (
await workato_api_client.api_platform_api.list_api_endpoints(
api_collection_id=api_collection_id,
page=page,
per_page=100,
)
)
if len(endpoints) < 100:
endpoints.extend(page_endpoints)
if len(page_endpoints) < 100:
break
page += 1

Expand Down Expand Up @@ -325,14 +327,15 @@ async def enable_all_endpoints_in_collection(
endpoints: list[ApiEndpoint] = []
page = 1
while True:
endpoints.extend(
page_endpoints = (
await workato_api_client.api_platform_api.list_api_endpoints(
api_collection_id=api_collection_id,
page=page,
per_page=100,
)
)
if len(endpoints) < 100:
endpoints.extend(page_endpoints)
if len(page_endpoints) < 100:
break
page += 1

Expand Down
6 changes: 2 additions & 4 deletions src/workato_platform/cli/commands/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,10 +674,8 @@ def group_connections_by_provider(
grouped: dict[str, list[Connection]] = {}

for connection in connections:
provider = connection.provider
if not provider:
provider = "unknown"
provider_display = provider.replace("_", " ").title()
application = connection.application
provider_display = application.replace("_", " ").title()

if provider_display not in grouped:
grouped[provider_display] = []
Expand Down
14 changes: 11 additions & 3 deletions src/workato_platform/cli/commands/projects/project_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""ProjectManager for handling Workato project operations"""

import os
import subprocess
import shutil
import subprocess # noqa: S404
import time
import zipfile

Expand Down Expand Up @@ -256,8 +257,15 @@ async def handle_post_api_sync(
click.echo()
click.echo("🔄 Auto-syncing project files...")
try:
result = subprocess.run(
["workato", "pull"], # noqa: S607, S603
# Find the workato executable to use full path for security
workato_exe = shutil.which("workato")
if workato_exe is None:
click.echo("⚠️ Could not find workato executable for auto-sync")
return

# Secure subprocess call: hardcoded command, validated executable path
result = subprocess.run( # noqa: S603
[workato_exe, "pull"],
capture_output=True,
text=True,
timeout=30,
Expand Down
2 changes: 1 addition & 1 deletion src/workato_platform/cli/commands/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from workato_platform.cli.utils import Spinner
from workato_platform.cli.utils.config import ConfigManager
from workato_platform.cli.utils.exception_handler import handle_api_exceptions
from workato_platform.client.workato_api.models.upsert_project_properties_request import (
from workato_platform.client.workato_api.models.upsert_project_properties_request import ( # noqa: E501
UpsertProjectPropertiesRequest,
)

Expand Down
4 changes: 3 additions & 1 deletion src/workato_platform/cli/commands/pull.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ async def _pull_project(
folder_id=meta_data.folder_id,
profile=meta_data.profile, # Keep profile reference for this project
)
project_config_manager = ConfigManager(project_workato_dir)
project_config_manager = ConfigManager(
project_workato_dir, skip_validation=True
)
project_config_manager.save_config(project_config_data)

# Ensure .workato/ is in workspace root .gitignore
Expand Down
4 changes: 2 additions & 2 deletions src/workato_platform/cli/commands/recipes/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from workato_platform.cli.utils.exception_handler import handle_api_exceptions
from workato_platform.client.workato_api.models.asset import Asset
from workato_platform.client.workato_api.models.recipe import Recipe
from workato_platform.client.workato_api.models.recipe_connection_update_request import (
from workato_platform.client.workato_api.models.recipe_connection_update_request import ( # noqa: E501
RecipeConnectionUpdateRequest,
)
from workato_platform.client.workato_api.models.recipe_start_response import (
Expand Down Expand Up @@ -231,7 +231,7 @@ async def validate(
spinner.start()

try:
result = recipe_validator.validate_recipe(recipe_data)
result = await recipe_validator.validate_recipe(recipe_data)
finally:
elapsed = spinner.stop()

Expand Down
Loading