diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 8d3dfcb..362b9d2 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.0.3 +current_version = 1.0.7 commit = True tag = False diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 43bf04d..c41e14d 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,9 +3,9 @@ blank_issues_enabled: false contact_links: - - name: GitHub CICD Template Community Support - url: https://github.com/JuanVilla424/github-cicd-template/discussions + - name: GitHub Scripts Community Support + url: https://github.com/JuanVilla424/scripts/discussions about: Please ask and answer questions here. - - name: GitHub CICD Template Security Reports - url: https://juanvilla424.github.io/github-cicd-template/SECURITY + - name: GitHub Scripts Security Reports + url: https://juanvilla424.github.io/scripts/SECURITY about: Please report security vulnerabilities here. diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 7da64ac..81af031 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -26,7 +26,7 @@ jobs: - name: Format check with Black run: | source venv/bin/activate - black --check scripts/ + black --check . - name: Lint with Pylint run: | source venv/bin/activate diff --git a/.github/workflows/version-controller.yml b/.github/workflows/version-controller.yml index d0e6dea..79fa3f8 100644 --- a/.github/workflows/version-controller.yml +++ b/.github/workflows/version-controller.yml @@ -59,10 +59,8 @@ jobs: - name: Add Modules id: add_modules run: | - rm -rf scripts - git rm -r --cached scripts ls -la - git submodule add -b ${{ steps.determine_branch.outputs.current_branch }} https://github.com/JuanVilla424/scripts.git + git submodule add --force -b ${{ steps.determine_branch.outputs.current_branch }} https://github.com/JuanVilla424/scripts.git # - name: Run Changelog Generator # id: run_changelog # run: | diff --git a/.gitignore b/.gitignore index 7a8cd55..660ff39 100644 --- a/.gitignore +++ b/.gitignore @@ -132,3 +132,5 @@ $RECYCLE.BIN/ *.njsproj *.sln *.sw? + +scripts diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 6e9f323..21ff02c 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -23,7 +23,7 @@ We are committed to fostering an open and welcoming environment for all contribu ## 📢 Reporting Misconduct -If you encounter any behavior that violates this code of conduct, please report it by contacting [email@dominio.com](mailto:email@dominio.com). All complaints will be reviewed and handled appropriately. +If you encounter any behavior that violates this code of conduct, please report it by contacting [r6ty5r296it6tl4eg5m.constant214@passinbox.com](mailto:r6ty5r296it6tl4eg5m.constant214@passinbox.com). All complaints will be reviewed and handled appropriately. ## ⚖️ Enforcement diff --git a/SECURITY.md b/SECURITY.md index 7d8f778..6b42226 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -28,7 +28,7 @@ If you discover a security vulnerability within this project, please follow thes 1. **Do not create a public issue.** Instead, contact us directly to responsibly disclose the vulnerability. -2. **Email** [juan.villa@quipux.com](mailto:juan.villa@quipux.com) with the following information: +2. **Email** [r6ty5r296it6tl4eg5m.constant214@passinbox.com](mailto:r6ty5r296it6tl4eg5m.constant214@passinbox.com) with the following information: - A description of the vulnerability. - Steps to reproduce the issue. diff --git a/pyproject.toml b/pyproject.toml index 3199f87..3977e56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "scripts" -version = "1.0.3" +version = "1.0.7" description = "CICD Core Scripts" authors = ["B "] license = "Apache 2.0" @@ -41,6 +41,7 @@ exclude = ''' | \.mypy_cache | \.tox | \.venv + | venv | _build | buck-out | build @@ -67,5 +68,5 @@ ensure_newline_before_comments = true rcfile = ".pylintrc" [build-system] -requires = ["poetry-core>=1.0.4"] +requires = ["poetry-core>=1.0.7"] build-backend = "poetry.core.masonry.api" diff --git a/scripts/bump_year/main.py b/scripts/bump_year/main.py deleted file mode 100644 index 1138b1a..0000000 --- a/scripts/bump_year/main.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3 -""" -bump_year.py - -A script to bump the year part of the version in pyproject.toml. -Resets major and minor versions to 0 when the year is incremented. - -Usage: - bump_year.py -""" - -import datetime -import toml -import sys - - -def bump_year() -> None: - """ - Bumps the year in pyproject.toml and resets major and minor versions to 0. - """ - current_year = datetime.datetime.now().year - pyproject_path = "pyproject.toml" - - try: - with open(pyproject_path, "r", encoding="utf-8") as file: - data = toml.load(file) - except FileNotFoundError: - print(f"Error: {pyproject_path} not found.") - sys.exit(1) - except toml.TomlDecodeError: - print(f"Error: Failed to parse {pyproject_path}.") - sys.exit(1) - - try: - version = data["tool"]["poetry"]["version"] - year, major, minor = version.split(".") - except (KeyError, ValueError): - print("Error: Version format is incorrect in pyproject.toml.") - sys.exit(1) - - if int(year) < current_year: - print(f"Updating year from {year} to {current_year}") - year = str(current_year) - major = "0" - minor = "0" - new_version = f"{year}.{major}.{minor}" - data["tool"]["poetry"]["version"] = new_version - try: - with open(pyproject_path, "w", encoding="utf-8") as file: - toml.dump(data, file) - print(f"Year bumped to {new_version}") - except Exception as e: - print(f"Error writing to {pyproject_path}: {e}") - sys.exit(1) - else: - print("Year is up-to-date. No need to bump.") - - -def main() -> None: - """ - Main function to execute the year bumping process. - """ - bump_year() - - -if __name__ == "__main__": - main() diff --git a/scripts/commit_msg_version_bump/main.py b/scripts/commit_msg_version_bump/main.py deleted file mode 100644 index 053e541..0000000 --- a/scripts/commit_msg_version_bump/main.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env python3 -""" -commit_msg_version_bump.py - -A script to bump the version in pyproject.toml based on commit message keywords. -Handles major, minor, and patch releases. - -Usage: - commit_msg_version_bump.py -""" - -import sys -import re -import subprocess -import toml - -DEBUG = False - - -def bump_version(part: str) -> None: - """ - Bumps the specified part of the version using bump2version and commits the change. - - Args: - part (str): The part of the version to bump ('major', 'minor', 'patch'). - - Raises: - subprocess.CalledProcessError: If bump2version or git commands fail. - """ - try: - subprocess.run(["bump2version", part], check=True) - print(f"Successfully bumped the {part} version.") - except subprocess.CalledProcessError: - print(f"Failed to bump the {part} version.") - sys.exit(1) - - # Retrieve the new version from pyproject.toml - new_version = get_new_version() - - if DEBUG: - print(f"Target version {new_version}") - - # Stage the changed pyproject.toml - try: - subprocess.run(["git", "add", "pyproject.toml"], check=True) - except subprocess.CalledProcessError: - print("Failed to stage pyproject.toml.") - sys.exit(1) - - # Commit the change - try: - subprocess.run(["git", "commit", "-m", f"Bump {part} version to {new_version}"], check=True) - print(f"Committed the bumped {part} version to {new_version}.") - except subprocess.CalledProcessError: - print(f"Failed to commit the bumped {part} version.") - sys.exit(1) - - -def get_new_version() -> str: - """ - Retrieves the new version from pyproject.toml. - - Returns: - str: The new version string. - - Raises: - SystemExit: If the version cannot be retrieved. - """ - pyproject_path = "pyproject.toml" - try: - with open(pyproject_path, "r", encoding="utf-8") as file: - data = toml.load(file) - version = data["tool"]["poetry"]["version"] - return version - except (FileNotFoundError, KeyError, ValueError, toml.TomlDecodeError): - print(f"Error: Unable to retrieve the version from {pyproject_path}.") - sys.exit(1) - - -def main() -> None: - """ - Main function to parse the commit message and perform version bumping. - """ - if DEBUG: - print(f"Sys: {sys}") - - if len(sys.argv) < 2: - print("Usage: commit_msg_version_bump.py ") - sys.exit(1) - - commit_msg_file = sys.argv[1] - - try: - with open(commit_msg_file, "r", encoding="utf-8") as file: - commit_msg = file.read().strip() - except FileNotFoundError: - print(f"Commit message file not found: {commit_msg_file}") - sys.exit(1) - - if DEBUG: - print(f"Commit message file: {commit_msg_file}") - print(f"commit_msg: {commit_msg}") - - # Define patterns for candidate types - major_pattern = re.compile(r"\bmajor candidate\b", re.IGNORECASE) - minor_pattern = re.compile(r"\bminor candidate\b", re.IGNORECASE) - patch_pattern = re.compile(r"\bpatch candidate\b", re.IGNORECASE) - - if major_pattern.search(commit_msg): - print("Major candidate release detected. Bumping major version...") - bump_version("major") - elif minor_pattern.search(commit_msg): - print("Minor candidate release detected. Bumping minor version...") - bump_version("minor") - elif patch_pattern.search(commit_msg): - print("Patch candidate release detected. Bumping patch version...") - bump_version("patch") - else: - print("No version bump detected in commit message.") - - -if __name__ == "__main__": - main() diff --git a/scripts/format_yaml/main.py b/scripts/format_yaml/main.py deleted file mode 100644 index 5860645..0000000 --- a/scripts/format_yaml/main.py +++ /dev/null @@ -1,101 +0,0 @@ -# scripts/validate_docker_compose.py -import re -import sys -import os - -DEBUG = False - - -def format_yaml_file(file_path): - """ - Format a yaml file - - Args: - :param file_path: - """ - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() - - lines = content.splitlines() - - if not lines or not lines[0].strip().startswith("---"): - lines.insert(0, "---") - print(f"[FORMAT] Added '---' at the beginning of {file_path}.") - - for i, line in enumerate(lines): - original_line = line - line = re.sub(r"\[\s+", "[", line) - line = re.sub(r"\s+]", "]", line) - line = re.sub(r"\(\s+", "(", line) - line = re.sub(r"\s+\)", ")", line) - if line != original_line: - lines[i] = line - print(f"[FORMAT] Removed extra spaces inside brackets in line {i+1} of {file_path}.") - - inside_run_block = False - new_lines = [] - for i, line in enumerate(lines): - if re.match(r"^run:\s*\|", line): - inside_run_block = True - new_lines.append(line) - continue - if inside_run_block and re.match(r"^\S", line): - inside_run_block = False - - if inside_run_block and len(line) > 120: - split_pos = line.rfind(" ", 0, 120) - if split_pos != -1: - split_line1 = line[:split_pos] - split_line2 = " " + line[split_pos + 1 :].lstrip() - new_lines.append(split_line1) - new_lines.append(split_line2) - print(f"[FORMAT] Split long line in 'run' block at line {i+1} of {file_path}.") - continue - if not split_pos != -1: - split_line1 = line[:120] - split_line2 = " " + line[120:].lstrip() - new_lines.append(split_line1) - new_lines.append(split_line2) - print(f"[FORMAT] Split long line in 'run' block at line {i+1} of {file_path}.") - continue - - new_lines.append(line) - - formatted_content = "\n".join(lines) + "\n" - - with open(file_path, "w", newline="\n", encoding="utf-8") as f: - f.write(formatted_content) - - print(f"[FORMAT] Formatted {file_path} with LF line endings.") - sys.exit(0) - - -def main(): - """Main void function to format yaml files.""" - - if len(sys.argv) < 2: - print("[ERROR] Incorrect usage. Must specify at least one file.") - sys.exit(1) - - files_to_validate = sys.argv[1:] - for file in files_to_validate: - file_path = os.path.abspath(file) - if os.path.isfile(file_path): - format_yaml_file(file_path) - else: - print(f"[ERROR] File {file_path} does not exist.") - sys.exit(1) - - print("[OK] All checks passed successfully.") - sys.exit(0) - - -if __name__ == "__main__": - if sys.stdout.encoding.lower() != "utf-8": - try: - sys.stdout.reconfigure(encoding="utf-8") - except AttributeError: - import io - - sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") - main() diff --git a/scripts/format_yml/main.py b/scripts/format_yml/main.py deleted file mode 100644 index 417d169..0000000 --- a/scripts/format_yml/main.py +++ /dev/null @@ -1,88 +0,0 @@ -# scripts/validate_docker_compose.py -import re -import sys -import os - -DEBUG = False - - -def format_yml_file(file_path): - """ - Function to format yml files - - Args: - file_path (str): - """ - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() - - lines = content.splitlines() - new_lines = [] - - if not lines or not lines[0].strip().startswith("---"): - lines.insert(0, "---") - print(f"[FORMAT] Added '---' at the beginning of {file_path}.") - - for i, line in enumerate(lines): - original_line = line - line = re.sub(r"\[\s+", "[", line) - line = re.sub(r"\s+]", "]", line) - line = re.sub(r"\(\s+", "(", line) - line = re.sub(r"\s+\)", ")", line) - if line != original_line: - lines[i] = line - print(f"[FORMAT] Removed extra spaces inside brackets in line {i+1} of {file_path}.") - - for i, line in enumerate(lines, start=1): - current_indent = len(line) - len(line.lstrip(" ")) - - while len(line) > 120: - split_pos = line.rfind(" ", 0, 120) - if split_pos != -1: - split_line1 = line[:split_pos] + " \\" - split_line2 = " " * current_indent + " " + line[split_pos + 1 :].lstrip() - new_lines.append(split_line1) - new_lines.append(split_line2) - print(f"[FORMAT] Split long line at line {i} in {file_path}.") - continue - if not split_pos != -1: - split_line1 = line[:120] + " \\" - split_line2 = " " * current_indent + " " + line[120 + 1 :].lstrip() - new_lines.append(split_line1) - new_lines.append(split_line2) - print(f"[FORMAT] Force split long line at line {i} in {file_path}.") - continue - - new_lines.append(line) - - formatted_content = "\n".join(new_lines) + "\n" - - with open(file_path, "w", newline="\n", encoding="utf-8") as f: - f.write(formatted_content) - - print(f"[FORMAT] Formatted {file_path} with LF line endings.") - sys.exit(0) - - -def main(): - """Main void function to format yml files.""" - - if len(sys.argv) < 2: - print("[ERROR] Incorrect usage. Must specify at least one file.") - sys.exit(1) - - files_to_validate = sys.argv[1:] - for file in files_to_validate: - file_path = os.path.abspath(file) - if os.path.isfile(file_path): - format_yml_file(file_path) - else: - print(f"[ERROR] File {file_path} does not exist.") - sys.exit(1) - - print("[OK] All checks passed successfully.") - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/scripts/generate_changelog/main.py b/scripts/generate_changelog/main.py deleted file mode 100644 index 0777dfa..0000000 --- a/scripts/generate_changelog/main.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python3 -""" -generate_changelog.py - -This script automatically generates or updates the CHANGELOG.md file based on commit messages. -It processes all commit history and categorizes commits into features, fixes, etc., while -grouping non-conforming commits under a separate section. - -Usage: - python generate_changelog.py -""" - -import subprocess -import re -from datetime import datetime, timezone -from typing import List, Dict, Tuple - -DEBUG = False - -# Define the path to the CHANGELOG.md -CHANGELOG_PATH = "CHANGELOG.md" - -# Define the commit message regex pattern -# Example: feat(authentication): add OAuth2 support [minor candidate] -COMMIT_REGEX = re.compile( - r"^(?Pfeat|fix|docs|style|refactor|perf|test|chore)" - r"(?:\((?P[^)]+)\))?:\s+(?P.+?)\s+\[(?Pminor candidate|major " - r"candidate|patch candidate)]$", - re.IGNORECASE, -) - -# Mapping of commit types to changelog sections -TYPE_MAPPING = { - "feat": "### Features", - "fix": "### Bug Fixes", - "docs": "### Documentation", - "style": "### Styles", - "refactor": "### Refactors", - "perf": "### Performance Improvements", - "test": "### Tests", - "chore": "### Chores", -} - - -def get_latest_version_from_changelog() -> str: - """ - Retrieves the latest version from the CHANGELOG.md file. - - Returns: - str: The latest version number or an empty string if not found. - """ - try: - with open(CHANGELOG_PATH, "r", encoding="utf-8") as f: - for line in f: - match = re.match(r"^## \[(\d+\.\d+\.\d+)]", line) - if match: - return match.group(1) - except FileNotFoundError: - return "" - return "" - - -def get_commits_since_version(version: str) -> List[str]: - """ - Retrieves commit messages since the specified version. - - Args: - version (str): The version number to retrieve commits since. - - Returns: - List[str]: A list of commit messages. - """ - try: - if version: - commits = ( - subprocess.check_output(["git", "log", f"v{version}..HEAD", "--pretty=format:%s"]) - .decode() - .split("\n") - ) - else: - # If no version found in CHANGELOG, get all commits - commits = ( - subprocess.check_output(["git", "log", "--pretty=format:%s"]).decode().split("\n") - ) - return commits - except subprocess.CalledProcessError: - return [] - - -def parse_commits(commits: List[str]) -> Tuple[Dict[str, List[str]], List[str]]: - """ - Parses commit messages and categorizes them based on type. - - Args: - commits (List[str]): A list of commit messages. - - Returns: - Tuple[Dict[str, List[str]], List[str]]: A dictionary categorizing commits and a list of non-conforming commits. - """ - changelog = {section: [] for section in TYPE_MAPPING.values()} - non_conforming_commits = [] - - for commit in commits: - match = COMMIT_REGEX.match(commit) - if match: - commit_type = match.group("type").lower() - scope = match.group("scope") - description = match.group("description").strip() - versioning_keyword = match.group("versioning_keyword").lower() - - section = TYPE_MAPPING.get(commit_type) - if section: - if scope: - entry = f"- **{scope}**: {description} (`{versioning_keyword}`)" - else: - entry = f"- {description} (`{versioning_keyword}`)" - changelog[section].append(entry) - else: - non_conforming_commits.append(commit) - else: - non_conforming_commits.append(commit) - - # Remove empty sections - changelog = {k: v for k, v in changelog.items() if v} - return changelog, non_conforming_commits - - -def generate_changelog_entry( - version: str, changelog: Dict[str, List[str]], non_conforming: List[str] -) -> str: - """ - Generates a changelog entry for a specific version. - - Args: - version (str): The version number. - changelog (Dict[str, List[str]]): The categorized changelog entries. - non_conforming (List[str]): List of non-conforming commit messages. - - Returns: - str: The formatted changelog entry. - """ - date = datetime.now(timezone.utc).strftime("%Y-%m-%d") - entry = f"## [{version}] - {date}\n\n" - for section, items in changelog.items(): - entry += f"{section}\n" - for item in items: - entry += f"{item}\n" - entry += "\n" - - if non_conforming: - entry += "### Other Changes\n" - for commit in non_conforming: - entry += f"- {commit}\n" - entry += "\n" - - return entry - - -def update_changelog(version: str, new_entry: str): - """ - Updates the CHANGELOG.md file by prepending the new entry. - - Args: - version (str): The version number. - new_entry (str): The new changelog entry to add. - """ - if DEBUG: - print(f"Updating version... {version}") - try: - with open(CHANGELOG_PATH, "r", encoding="utf-8") as f: - existing_content = f.read() - except FileNotFoundError: - existing_content = "" - - with open(CHANGELOG_PATH, "w", encoding="utf-8") as f: - f.write(new_entry + "\n" + existing_content) - - -def get_next_version(latest_version: str, version_bump: str) -> str: - """ - Calculates the next version based on the current version and the type of version bump. - - Args: - latest_version (str): The latest version number. - version_bump (str): The type of version bump ('major', 'minor', 'patch'). - - Returns: - str: The next version string. - """ - if not latest_version: - # Default initial version if no changelog exists - return "1.0.0" - - major, minor, patch = map(int, latest_version.split(".")) - - if version_bump == "major": - major += 1 - minor = 0 - patch = 0 - elif version_bump == "minor": - minor += 1 - patch = 0 - elif version_bump == "patch": - patch += 1 - - return f"{major}.{minor}.{patch}" - - -def get_version_bump(commits: List[str]) -> str: - """ - Determines the type of version bump based on commit messages. - - Args: - commits (List[str]): A list of commit messages. - - Returns: - str: The type of version bump ('major', 'minor', 'patch') or an empty string if none. - """ - # Priority: major > minor > patch - bump = "" - - for commit in commits: - match = COMMIT_REGEX.match(commit) - if match: - keyword = match.group("versioning_keyword").lower() - if keyword == "major candidate": - bump = "major" - elif keyword == "minor candidate" and bump != "major": - bump = "minor" - elif keyword == "patch candidate" and not bump: - bump = "patch" - - return bump - - -def main(): - """ - Main function to generate or update the CHANGELOG.md. - """ - latest_version = get_latest_version_from_changelog() - print(f"Latest version in CHANGELOG.md: {latest_version}") - commits = get_commits_since_version(latest_version) - if not commits: - print("No new commits to include in the changelog.") - return - - changelog, non_conforming = parse_commits(commits) - if not changelog and not non_conforming: - print("No valid commits found for changelog generation.") - return - - # Determine the next version based on the highest priority keyword - version_bump = get_version_bump(commits) - - if not version_bump and non_conforming: - # Assign a patch bump if there are non-conforming commits but no version bump keywords - version_bump = "patch" - - if not version_bump and not non_conforming: - print("No versioning keyword found in commits.") - return - - # Get the next version - next_version = get_next_version(latest_version, version_bump) - print(f"Bumping version: {version_bump} to {next_version}") - - # Generate changelog entry - changelog_entry = generate_changelog_entry(next_version, changelog, non_conforming) - - # Update CHANGELOG.md - update_changelog(next_version, changelog_entry) - print(f"CHANGELOG.md updated with version {next_version}.") - - -if __name__ == "__main__": - main() diff --git a/scripts/validate_docker_compose/main.py b/scripts/validate_docker_compose/main.py deleted file mode 100644 index 0cacdbb..0000000 --- a/scripts/validate_docker_compose/main.py +++ /dev/null @@ -1,90 +0,0 @@ -# scripts/validate_docker_compose.py - -import subprocess -import sys -import os - -DEBUG = False - - -def format_docker_compose(file_path): - """ - Format a docker compose file - - Args: - :param file_path: - """ - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() - - lines = content.splitlines() - - if not lines or not lines[0].strip().startswith("---"): - lines.insert(0, "---") - print(f"[FORMAT] Added '---' at the beginning of {file_path}.") - - formatted_content = "\n".join(lines) + "\n" - - with open(file_path, "w", newline="\n", encoding="utf-8") as f: - f.write(formatted_content) - - print(f"[FORMAT] Formatted {file_path} with LF line endings.") - - -def validate_docker_compose(file_path): - """ - Validate a Docker compose file. - - Args: - :param file_path: - """ - try: - result = subprocess.run( - ["docker-compose", "-f", file_path, "config"], - check=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - ) - print(f"[OK] {file_path} is valid.") - if DEBUG: - print(f"[DEBUG] Result response: {result}") - except subprocess.CalledProcessError as e: - print(f"[ERROR] Error in file {file_path}:") - print(e.stderr) - sys.exit(1) - except FileNotFoundError: - print("[ERROR] docker-compose not found.") - sys.exit(1) - - -def main(): - """Main void function for validating Docker compose files.""" - - if len(sys.argv) < 2: - print("[ERROR] Incorrect usage. Must specify at least one file.") - sys.exit(1) - - files_to_validate = sys.argv[1:] - for file in files_to_validate: - file_path = os.path.abspath(file) - if os.path.isfile(file_path): - format_docker_compose(file_path) - validate_docker_compose(file_path) - else: - print(f"[ERROR] File {file_path} does not exist.") - sys.exit(1) - - print("[OK] All checks passed successfully.") - sys.exit(0) - - -if __name__ == "__main__": - if sys.stdout.encoding.lower() != "utf-8": - try: - sys.stdout.reconfigure(encoding="utf-8") - except AttributeError: - import io - - sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") - main()