Skip to content

Commit

Permalink
Merge pull request #14 from Mostafa-wael/master
Browse files Browse the repository at this point in the history
Add changelog template and create a linting pipeline
  • Loading branch information
giarve authored Aug 18, 2024
2 parents 49ab477 + 9b6d366 commit 0ffab51
Show file tree
Hide file tree
Showing 16 changed files with 344 additions and 139 deletions.
3 changes: 3 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 88
exclude = .git,__pycache__,build,dist
35 changes: 35 additions & 0 deletions .github/workflows/lint-and-format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Lint and Format

on:
workflow_dispatch:
pull_request:
branches:
- main

env:
pythonVersion: 3.12

jobs:
lint-and-format:
runs-on: ubuntu-latest

steps:
- name: Check out the code
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.pythonVersion }}

- name: Install dependencies
run: |
pip install flake8 black
apt install flake8
apt install black
- name: Run flake8
run: flake8 .

- name: Run black check
run: black --check .
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- New feature or enhancement descriptions.
- Details about added functionality, modules, or components.

### Changed
- Details about any changes to existing functionality.
- Information about updated dependencies.

### Deprecated
- List any features that are deprecated but still available.

### Removed
- Details about removed features, components, or deprecated functionality.
- Information about dropped support for environments or dependencies.

### Fixed
- List of bug fixes, including references to issue numbers.
- Details about fixed vulnerabilities or security improvements.

### Security
- Descriptions of security-related updates and fixes.

## [Version 1.0.0] - YYYY-MM-DD
### Added
- Initial release of the project.
- Description of the core features and functionality.
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# MetaCall Test Center

![Python](https://img.shields.io/badge/python-3.12-blue.svg)

## Overview

MetaCall Test Center is a comprehensive testing framework designed for MetaCall projects and examples. It provides a structured and efficient way to define, run, and manage test cases across different environments. The primary script, `testing.py`, integrates seamlessly into CI/CD pipelines and supports local testing. This project adheres to best practices, SOLID principles, and design patterns to ensure maintainability, scalability, and ease of contribution.
Expand Down Expand Up @@ -126,9 +128,49 @@ We welcome contributions to the MetaCall Test Center! Here are a few ways you ca
- **Extend Functionality**: Implement support for additional environments or enhance existing ones.
- **Documentation**: Improve and expand the documentation to help new users and contributors.

### Guidelines
To keep the project organized and maintain a clear history, we ask that all contributors follow these guidelines:

### Contribution Process

1. **Fork the Repository**: Create a fork of the repository and make your changes in a new branch.
2. **Write Clear Commit Messages**: Use clear and descriptive commit messages that explain the changes you are making.
3. **Update the Changelog**:
- Before submitting a pull request, make sure to update the `CHANGELOG.md` file.
- Add your changes under the `Unreleased` section, categorizing them under `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, or `Security`.
- Use bullet points to list your changes and include references to related issue numbers if applicable.
4. **Submit a Pull Request**: After making your changes and updating the changelog, submit a pull request. Make sure your pull request includes a description of the changes and why they are necessary.

### Changelog Format

- **Unreleased**: Add any new changes here before a version is released.
- **Version Tags**: When a new version is released, create a new section in the changelog with the version number and date.

### Commit and Pull Request Tips

- **Keep it Simple**: Make small, focused commits and pull requests that address one issue or feature at a time.
- **Explain Your Changes**: Clearly explain the motivation and context for your changes in the pull request description.
- **Run Tests**: Ensure that all tests pass locally before submitting your pull request.

To ensure code quality and consistency, please follow these guidelines:

1. **Linter**: Run `flake8` to check for style violations.
```bash
flake8 .
```

2. **Formatter**: Format your code using `black`.
```bash
black .
```

3. **Pull Requests**: Before submitting a pull request, ensure that your code passes the linter and formatter checks. The CI pipeline will automatically run these checks on your PR.


### General Guidelines

- Follow the existing code style and structure.
- Ensure that all tests pass before submitting a pull request.
- Provide clear and concise commit messages.
- Open an issue to discuss potential changes before submitting significant modifications.

Thank you for contributing to this project! Your efforts help make this project better for everyone.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tool.black]
line-length = 88
4 changes: 0 additions & 4 deletions test-suites/test-time-app-web.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,3 @@ code-files:
- name: Check index.html is fully returned
function-call: index()
expected-pattern: '<html>[\w\W]*</html>'




46 changes: 34 additions & 12 deletions testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,78 @@
from testing.test_runner import TestRunner
from testing.test_suites_extractor import TestSuitesExtractor


def parse_arguments():
''' Parse the command line arguments '''
parser = argparse.ArgumentParser(description="Run test suites in specified environments.")
"""Parse the command line arguments"""
parser = argparse.ArgumentParser(
description="Run test suites in specified environments."
)
parser.add_argument("-f", "--file", required=True, help="The test suite file name.")
parser.add_argument("-V", "--verbose", action="store_true", help="Increase output verbosity.")
parser.add_argument("-e", "--envs", nargs="+", default=["cli"], help="Environments to run the tests on (cli, faas).")
parser.add_argument(
"-V", "--verbose", action="store_true", help="Increase output verbosity."
)
parser.add_argument(
"-e",
"--envs",
nargs="+",
default=["cli"],
help="Environments to run the tests on (cli, faas).",
)
return parser.parse_args()


def setup_logger(verbose):
''' Setup logger with the appropriate logging level '''
"""Setup logger with the appropriate logging level"""
logger = Logger.get_instance()
logger.set_level("DEBUG" if verbose else "INFO")
return logger


def extract_test_suites(file_name):
''' Extract test suites from the test suite file '''
"""Extract test suites from the test suite file"""
try:
test_suites_extractor = TestSuitesExtractor(file_name)
return test_suites_extractor.extract_test_suites()
except Exception as e:
raise RuntimeError(f"Error extracting test suites: {e}")


def clone_repo_if_needed(repo_url):
''' Clone the repository if not already cloned '''
"""Clone the repository if not already cloned"""
try:
repo_manager = RepoManager.get_instance(repo_url)
repo_manager.clone_repo_if_not_exist()
except Exception as e:
raise RuntimeError(f"Error cloning repository: {e}")


def deploy_faas_if_needed(envs, project_path, logger):
''' Deploy the project as a local FaaS if required '''
"""Deploy the project as a local FaaS if required"""
if "faas" in envs:
deploy_manager = DeployManager.get_instance(project_path)
if not deploy_manager.deploy_local_faas():
logger.error("Error deploying the project. Removing 'faas' from environments.")
logger.error(
"Error deploying the project. Removing 'faas' from environments."
)
envs.remove("faas")


def run_tests(envs, test_suites):
''' Run the tests in the specified environments '''
"""Run the tests in the specified environments"""
test_runner = TestRunner(envs)
test_runner.run_tests(test_suites)


def main():
args = parse_arguments()
logger = setup_logger(args.verbose)

try:
project_name, project_path, repo_url, test_suites = extract_test_suites(args.file)
project_name, project_path, repo_url, test_suites = extract_test_suites(
args.file
)
logger.info(f"Testing Project: {project_name}")

clone_repo_if_needed(repo_url)
deploy_faas_if_needed(args.envs, project_path, logger)
run_tests(args.envs, test_suites)
Expand All @@ -65,5 +86,6 @@ def main():
logger.error(e)
exit(1)


if __name__ == "__main__":
main()
41 changes: 25 additions & 16 deletions testing/deploy_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json
from testing.logger import Logger


class DeployManager:
_instance = None

Expand All @@ -17,15 +18,17 @@ def __init__(self, project_path):

@staticmethod
def get_instance(project_path=None):
''' Static access method for singleton '''
"""Static access method for singleton"""
if DeployManager._instance is None:
if project_path is None:
raise ValueError("Project path must be provided for the first instance.")
raise ValueError(
"Project path must be provided for the first instance."
)
DeployManager(project_path)
return DeployManager._instance

def set_environment_variables(self, env_vars):
''' Set environment variables '''
"""Set environment variables"""
try:
for key, value in env_vars.items():
os.environ[key] = value
Expand All @@ -35,30 +38,35 @@ def set_environment_variables(self, env_vars):
return True

def deploy_local_faas(self):
''' Deploy the project as a local FaaS '''
env_vars = {
'NODE_ENV': 'testing',
'METACALL_DEPLOY_INTERACTIVE': 'false'
}
"""Deploy the project as a local FaaS"""
env_vars = {"NODE_ENV": "testing", "METACALL_DEPLOY_INTERACTIVE": "false"}

if not self.set_environment_variables(env_vars):
return False

try:
deploy_command = f"metacall-deploy --dev --workdir {self.project_path}"
subprocess.run(deploy_command, capture_output=True, text=True, shell=True, check=True)
subprocess.run(
deploy_command, capture_output=True, text=True, shell=True, check=True
)
self.logger.debug("Local FaaS deployed successfully.")
return True
except subprocess.CalledProcessError as e:
self.logger.error(f"Error deploying the project: {e}")
return False

def get_local_base_url(self):
''' Get the base URL of the deployed local FaaS '''
"""Get the base URL of the deployed local FaaS"""
inspection_command = "metacall-deploy --inspect OpenAPIv3 --dev"
try:
result = subprocess.run(inspection_command, capture_output=True, text=True, shell=True, check=True)
server_url = json.loads(result.stdout)[0]['servers'][0]['url']
result = subprocess.run(
inspection_command,
capture_output=True,
text=True,
shell=True,
check=True,
)
server_url = json.loads(result.stdout)[0]["servers"][0]["url"]
self.logger.debug(f"Local FaaS base URL: {server_url}")
return server_url
except subprocess.CalledProcessError as e:
Expand All @@ -68,13 +76,14 @@ def get_local_base_url(self):
return None

def deploy_remote_faas(self):
''' Deploy the project as a remote FaaS '''
"""Deploy the project as a remote FaaS"""
pass

def get_remote_base_url(self):
''' Get the base url of the deployed remote faas '''
"""Get the base url of the deployed remote faas"""


'''
"""
Paths: http://localhost:9000/aee940974fd5/examples-testing/v1/call/index
Exmaple output
[
Expand Down Expand Up @@ -128,4 +137,4 @@ def get_remote_base_url(self):
}
]
'''
"""
Loading

0 comments on commit 0ffab51

Please sign in to comment.