Skip to content

Commit

Permalink
Merge pull request #48 from derek10cloud/add-lint
Browse files Browse the repository at this point in the history
Add ruff linter to improve code quality and maintainability
  • Loading branch information
jeffreyaven authored Nov 9, 2024
2 parents 49e93ac + b3d9e4a commit d50e1c7
Show file tree
Hide file tree
Showing 13 changed files with 649 additions and 175 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/lint-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Lint Check

on:
push:
branches:
- main
pull_request:

jobs:
check_lint:
defaults:
run:
working-directory: "stackql_deploy"
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
strategy:
max-parallel: 1
matrix:
python-version: ["3.11"]
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: pip install ruff

- name: Lint check with ruff
run: ruff check .
49 changes: 35 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
<!-- web assets -->

[logo]: https://stackql.io/img/stackql-logo-bold.png "stackql logo"
[deploylogo]: https://stackql.io/img/stackql-deploy-logo.png "stackql-deploy logo"
[stackqlrepo]: https://github.com/stackql/stackql
[homepage]: https://stackql.io/
[docs]: https://stackql.io/docs
[blog]: https://stackql.io/blog
[registry]: https://github.com/stackql/stackql-provider-registry

<!-- [readthedocs]: -->

[pypi]: https://pypi.org/project/stackql-deploy/

<!-- badges -->

[badge1]: https://img.shields.io/badge/platform-windows%20macos%20linux-brightgreen "Platforms"
[badge2]: https://img.shields.io/pypi/v/stackql-deploy "PyPi Version"
[badge3]: https://img.shields.io/pypi/dm/stackql-deploy "PyPi Downloads"
[badge4]: https://img.shields.io/github/license/stackql/stackql "License"

<!-- github links -->

[discussions]: https://github.com/orgs/stackql/discussions
[issues]: https://github.com/stackql/stackql-deploy/issues/new/choose

<!-- misc links -->

[twitter]: https://twitter.com/stackql

<!-- language: lang-none -->
Expand All @@ -36,23 +45,25 @@
<p align="center">

<!-- [__Read the docs »__][readthedocs] -->
[__PyPi__][pypi]
[__Raise an Issue__][issues]

[**PyPi**][pypi]
[**Raise an Issue**][issues]

</p>
</div>

## About The Project

[__`stackql-deploy`__][pypi] is an open-source command line utility which implements a declarative, model driven framework to deploy and manage multi cloud stacks using [__`stackql`__][stackqlrepo]. [__`stackql-deploy`__][pypi] is distributed as a Python script to be used as a CLI tool, do the following to get started:
[**`stackql-deploy`**][pypi] is an open-source command line utility which implements a declarative, model driven framework to deploy and manage multi cloud stacks using [**`stackql`**][stackqlrepo]. [**`stackql-deploy`**][pypi] is distributed as a Python script to be used as a CLI tool, do the following to get started:
<br />

```bash
pip install stackql-deploy
```

> __Note for macOS users__
> to install `stackql-deploy` in a virtual environment (which may be necessary on __macOS__), use the following:
> **Note for macOS users**
> to install `stackql-deploy` in a virtual environment (which may be necessary on **macOS**), use the following:
>
> ```bash
> python3 -m venv myenv
> source myenv/bin/activate
Expand All @@ -61,15 +72,15 @@ pip install stackql-deploy
## About StackQL
StackQL is a utility which allows you to query and interact with cloud and SaaS resources in real time using SQL grammar. StackQL supports a full set of SQL query/DML grammar, including `JOIN`, `UNION` adn subquery functionality and supports mutation operations on cloud and SaaS resources such as `create`, `update` and `delete`, implemented as `INSERT`, `UPDATE` and `DELETE` respectively. StackQL also supports grammar for performing lifecycle operations such as starting or stopping a VM using the `EXEC` statement.
StackQL is a utility which allows you to query and interact with cloud and SaaS resources in real time using SQL grammar. StackQL supports a full set of SQL query/DML grammar, including `JOIN`, `UNION` adn subquery functionality and supports mutation operations on cloud and SaaS resources such as `create`, `update` and `delete`, implemented as `INSERT`, `UPDATE` and `DELETE` respectively. StackQL also supports grammar for performing lifecycle operations such as starting or stopping a VM using the `EXEC` statement.
StackQL provider definitions are defined in plaintext OpenAPI extensions to the providers specification. These definitions are then used to generate the SQL schema and the API client. The source for the provider definitions are stored in the [__StackQL Registry__][registry].
StackQL provider definitions are defined in plaintext OpenAPI extensions to the providers specification. These definitions are then used to generate the SQL schema and the API client. The source for the provider definitions are stored in the [**StackQL Registry**][registry].
## How it works
<!-- > see [__readthedocs__]() for more detailed documentation -->
A __`stackql-deploy`__ project is a directory containing StackQL scripts with a manifest file at the root of the directory, for example:
A **`stackql-deploy`** project is a directory containing StackQL scripts with a manifest file at the root of the directory, for example:
```
├── example_stack
Expand Down Expand Up @@ -115,9 +126,9 @@ resources:
Deployment orchestration using `stackql-deploy` includes:
- __*pre-flight*__ checks, which are StackQL queries that check for the existence or current configuration state of a resource
- __*deployment*__ scripts, which are StackQL queries to create or update resoruces (or delete in the case of de-provisioning)
- __*post-deployment*__ tests, which are StackQL queries to confirm that resources were deployed and have the desired state
- **_pre-flight_** checks, which are StackQL queries that check for the existence or current configuration state of a resource
- **_deployment_** scripts, which are StackQL queries to create or update resoruces (or delete in the case of de-provisioning)
- **_post-deployment_** tests, which are StackQL queries to confirm that resources were deployed and have the desired state
This process is described here:
Expand Down Expand Up @@ -278,16 +289,26 @@ Navigate to your `docs` directory and build the Sphinx documentation:
```
cd docs
make html
```
```
## Code Linting
To maintain code quality and consistency, we use `ruff` as the linter for this project. `ruff` offers fast performance and a comprehensive set of linting rules suitable for `stackql-deploy`. You can run the lint check as follows:
```bash
ruff check .
```
Note: If you need to install ruff, you can do so with `pip install ruff`.
## Contributing
Contributions are welcome and encouraged.
Contributions are welcome and encouraged.
## License
Distributed under the MIT License. See [`LICENSE`](https://github.com/stackql/stackql-deploy/blob/main/LICENSE) for more information.
## Contact
Get in touch with us via Twitter at [__@stackql__][twitter], email us at [__info@stackql.io__]([email protected]) or start a conversation using [__discussions__][discussions].
Get in touch with us via Twitter at [**@stackql**][twitter], email us at [**info@stackql.io**]([email protected]) or start a conversation using [**discussions**][discussions].
38 changes: 38 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[tool.poetry.group.dev.dependencies]
ruff = "^0.6.9"

# Tool-specific configurations

# Ruff configuration (linter)
[tool.ruff]
line-length = 120 # Maximum allowed line length
exclude = [
"docs",
"examples",
"images",
"website",
]

[tool.ruff.format]
quote-style = "preserve" # Preserve existing quote style (single or double)

[tool.ruff.lint]
select = ["E", "F", "W"] # Select specific linting rules (E: Errors, F: Pyflakes, W: Warnings)
ignore = [
"F405", # Ignore 'import *' warnings
]

[tool.ruff.lint.isort]
force-single-line = true # Force single-line imports for better readability

# Black configuration (code formatter)
[tool.black]
line-length = 120 # Same line length limit as Ruff for consistency
target-version = ['py38'] # Target Python version for formatting

# Flake8 configuration (for additional linting, if needed)
[tool.flake8]
max-line-length = 120 # Align with Ruff's line length setting
ignore = [
"E501", # Ignore long line warnings
]
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
'stackql_deploy': [
'templates/**/*.template', # Include template files recursively
],
},
},
include_package_data=True,
install_requires=[
'click',
'click',
'python-dotenv',
'jinja2',
'pystackql>=3.6.1',
Expand Down
47 changes: 33 additions & 14 deletions stackql_deploy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
def print_unicode_box(message):
border_color = '\033[93m' # Yellow color
reset_color = '\033[0m'

lines = message.split('\n')
max_length = max(len(line) for line in lines)
top_border = border_color + '┌' + '─' * (max_length + 2) + '┐' + reset_color
bottom_border = border_color + '└' + '─' * (max_length + 2) + '┘' + reset_color

click.echo(top_border)
for line in lines:
click.echo(border_color + '│ ' + line.ljust(max_length) + ' │' + reset_color)
Expand Down Expand Up @@ -88,10 +88,21 @@ def add_common_options(command):
common_options = [
click.option('--log-level', default='INFO', help='set the logging level.'),
click.option('--env-file', default='.env', help='environment variables file.'),
click.option('-e', '--env', multiple=True, callback=parse_env_var, help='set additional environment variables.'),
click.option(
'-e',
'--env',
multiple=True,
callback=parse_env_var,
help='set additional environment variables.'
),
click.option('--dry-run', is_flag=True, help='perform a dry run of the operation.'),
click.option('--show-queries', is_flag=True, help='show queries run in the output logs.'),
click.option('--on-failure', type=click.Choice(['rollback', 'ignore', 'error']), default='error', help='action on failure.')
click.option(
"--on-failure",
type=click.Choice(["rollback", "ignore", "error"]),
default="error",
help="action on failure.",
)
]
for option in common_options:
command = option(command)
Expand Down Expand Up @@ -240,7 +251,7 @@ def info(ctx):
)

click.echo(click.style("stackql-deploy CLI", fg="green", bold=True))
click.echo(f" Version: {deploy_version}\n")
click.echo(f" Version: {deploy_version}\n")

click.echo(click.style("StackQL Library", fg="green", bold=True))
click.echo(f" Version: {stackql.version}")
Expand Down Expand Up @@ -270,7 +281,7 @@ def shell(ctx):
custom_registry=ctx.obj.get('custom_registry'),
download_dir=ctx.obj.get('download_dir')
)

# Find the stackql binary path
stackql_binary_path = find_stackql_binary(stackql.bin_path, ctx.obj.get('download_dir'))

Expand All @@ -280,7 +291,7 @@ def shell(ctx):
sys.exit(1)

click.echo(f"Launching stackql shell from: {stackql_binary_path}")

# Launch the stackql shell as a subprocess
try:
subprocess.run([stackql_binary_path, "shell", "--colorscheme", "null"], check=True)
Expand All @@ -297,7 +308,7 @@ def shell(ctx):
@click.pass_context
def upgrade(ctx):
"""Upgrade the pystackql package and stackql binary to the latest version."""

stackql = get_stackql_instance()
orig_pkg_version = stackql.package_version
orig_stackql_version = stackql.version
Expand All @@ -306,7 +317,7 @@ def upgrade(ctx):
click.echo("upgrading pystackql package...")
try:
# Run the pip install command to upgrade pystackql
result = subprocess.run(
subprocess.run(
[sys.executable, "-m", "pip", "install", "--upgrade", "--quiet", "pystackql"],
check=True,
stdout=subprocess.PIPE,
Expand Down Expand Up @@ -341,18 +352,22 @@ def create_project_structure(stack_name, provider=None):
base_path = os.path.join(os.getcwd(), stack_name)
if os.path.exists(base_path):
raise click.ClickException(f"directory '{stack_name}' already exists.")

directories = ['resources']
for directory in directories:
os.makedirs(os.path.join(base_path, directory), exist_ok=True)

# Check if provider is supported
if provider is None:
logger.debug(f"provider not supplied, defaulting to `{DEFAULT_PROVIDER}`")
provider = DEFAULT_PROVIDER
elif provider not in SUPPORTED_PROVIDERS:
provider = DEFAULT_PROVIDER
message = f"provider '{provider}' is not supported for `init`, supported providers are: {', '.join(SUPPORTED_PROVIDERS)}, defaulting to `{DEFAULT_PROVIDER}`"
message = (
f"provider '{provider}' is not supported for `init`, "
f"supported providers are: {', '.join(SUPPORTED_PROVIDERS)}, "
f"defaulting to `{DEFAULT_PROVIDER}`"
)
click.secho(message, fg='yellow', err=False)

# set template files
Expand All @@ -373,7 +388,7 @@ def create_project_structure(stack_name, provider=None):
'README.md.template': os.path.join(base_path, 'README.md'),
f'resources/{sample_res_name}.iql.template': os.path.join(base_path,'resources', f'{sample_res_name}.iql'),
}

for template_name, output_name in template_files.items():
logger.debug(f"template name: {template_name}")
logger.debug(f"template output name: {output_name}")
Expand All @@ -384,7 +399,11 @@ def create_project_structure(stack_name, provider=None):

@cli.command()
@click.argument('stack_name')
@click.option('--provider', default=None, help='[OPTIONAL] specify a provider to start your project, supported values: aws, azure, google')
@click.option(
"--provider",
default=None,
help="[OPTIONAL] specify a provider to start your project, supported values: aws, azure, google",
)
def init(stack_name, provider):
"""Initialize a new stackql-deploy project structure."""
setup_logger("init", locals())
Expand Down
Loading

0 comments on commit d50e1c7

Please sign in to comment.