diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..19106084 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,41 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +--- +name: Pre-commit Checks + +on: + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Run pre-commit checks + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + uv tool install pre-commit + uv tool ensurepath + pre-commit run --all-files --color always --show-diff-on-failure diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..346aa0bb --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +--- +default_stages: [pre-commit] +default_language_version: + python: python3 +minimum_pre_commit_version: '3.2.0' +repos: + - repo: local + hooks: + - id: sort-actions-yml + name: Sort actions.yml + entry: ./scripts/sort_yml.py + language: python + additional_dependencies: ['rich>=12.4.4', 'ruamel.yaml'] + require_serial: true + files: ^actions\.yml$ \ No newline at end of file diff --git a/scripts/sort_yml.py b/scripts/sort_yml.py new file mode 100755 index 00000000..307b8b8f --- /dev/null +++ b/scripts/sort_yml.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "rich", +# "ruamel.yaml", +# ] +# /// + +from ruamel.yaml import YAML +from ruamel.yaml.comments import CommentedMap +import sys +from pathlib import Path +from rich.console import Console + +console = Console(width=400, color_system="standard") + + +def sort_yaml_file(input_file: str): + """Sorts the keys of a YAML file in alphabetical order""" + + yaml = YAML() + yaml.preserve_quotes = True + + input_path = Path(input_file) + + if not input_path.exists(): + raise FileNotFoundError(f"File '{input_file}' not found.") + + with open(input_path, 'r', encoding='utf-8') as f: + data = yaml.load(f) + + sorted_data = CommentedMap() + + sorted_keys: list[str] = sorted(data.keys(), key=str.lower) + + # Copy data in sorted order + for key in sorted_keys: + sorted_data[key] = data[key] + + # Preserve any comment at the beginning of the file + if hasattr(data, 'ca') and hasattr(data.ca, 'comment'): + if not hasattr(sorted_data, 'ca'): + sorted_data.ca = data.ca.__class__() + sorted_data.ca.comment = data.ca.comment + + with open(input_path, 'w', encoding='utf-8') as f: + yaml.dump(sorted_data, f) + + +errors = [] +def main(): + files = sys.argv[1:] + for file in files: + console.print(f"[blue]Sorting YAML file {file}") + try: + sort_yaml_file(file) + console.print(f"[blue]✅ YAML file sorted successfully {file}!") + except FileNotFoundError as e: + errors.append((file, str(e))) + except Exception as e: + errors.append((file, str(e))) + + if errors: + console.print("[red]Errors occurred while sorting YAML files:") + for file, error in errors: + console.print(f"[red]File: {file} - Error: {error}") + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file