From 9cdd979953a47b7e9565a21c66764476d1c2b477 Mon Sep 17 00:00:00 2001 From: Gaetan Lepage Date: Sun, 2 Aug 2026 16:00:32 +0200 Subject: [PATCH] misc: address new ruff requirements in python script --- ci/tag-maintainers/extract-maintainers.py | 3 +- ci/tag-maintainers/manage-reviewers.py | 46 +++++++++---------- .../generate-all-maintainers.py | 46 ++++++++++--------- ruff.toml | 7 +++ 4 files changed, 55 insertions(+), 47 deletions(-) create mode 100644 ruff.toml diff --git a/ci/tag-maintainers/extract-maintainers.py b/ci/tag-maintainers/extract-maintainers.py index 5eb84e10..6c97bbe8 100755 --- a/ci/tag-maintainers/extract-maintainers.py +++ b/ci/tag-maintainers/extract-maintainers.py @@ -11,7 +11,6 @@ import json import subprocess import sys from pathlib import Path -from typing import List def run_nix_eval(file: str, *args: str) -> str: @@ -30,7 +29,7 @@ def run_nix_eval(file: str, *args: str) -> str: sys.exit() -def extract_maintainers(changed_files: List[str], pr_author: str) -> List[str]: +def extract_maintainers(changed_files: list[str], pr_author: str) -> list[str]: """Extract maintainers from changed plugin files.""" if not changed_files: print("No plugin files changed. No maintainers to tag.", file=sys.stderr) diff --git a/ci/tag-maintainers/manage-reviewers.py b/ci/tag-maintainers/manage-reviewers.py index 7e791411..49acac01 100755 --- a/ci/tag-maintainers/manage-reviewers.py +++ b/ci/tag-maintainers/manage-reviewers.py @@ -19,6 +19,8 @@ logging.basicConfig( stream=sys.stderr, ) +logger = logging.getLogger(__name__) + MANUAL_REVIEW_REQUEST_QUERY: Final[str] = """ query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { @@ -46,8 +48,6 @@ query($owner: String!, $repo: String!, $prNumber: Int!) { class GHError(Exception): """Custom exception for errors related to 'gh' CLI commands.""" - pass - def run_gh_command( args: list[str], @@ -66,8 +66,8 @@ def run_gh_command( ) return result except subprocess.CalledProcessError as e: - logging.error("Error running command: %s", " ".join(command)) - logging.error("Stderr: %s", e.stderr.strip()) + logger.error("Error running command: %s", " ".join(command)) + logger.error("Stderr: %s", e.stderr.strip()) raise GHError(f"Failed to execute gh command: {e}") from e @@ -108,7 +108,7 @@ def get_manually_requested_reviewers( } return manually_requested except (GHError, json.JSONDecodeError, KeyError) as e: - logging.error("Could not determine manually requested reviewers: %s", e) + logger.error("Could not determine manually requested reviewers: %s", e) return set() @@ -118,7 +118,7 @@ def get_users_from_gh(args: list[str], error_message: str) -> set[str]: result = run_gh_command(args) return {user.strip() for user in result.stdout.split("\n") if user.strip()} except GHError as e: - logging.error("%s: %s", error_message, e) + logger.error("%s: %s", error_message, e) return set() @@ -164,13 +164,13 @@ def is_collaborator(owner: str, repo: str, username: str) -> bool: return True if "HTTP 404" in result.stderr: - logging.error("'%s' is not a collaborator in this repository.", username) + logger.error("'%s' is not a collaborator in this repository.", username) return False else: - logging.error( + logger.error( "Unexpected error checking collaborator status for '%s'.", username ) - logging.error("Stderr: %s", result.stderr.strip()) + logger.error("Stderr: %s", result.stderr.strip()) raise GHError( f"Unexpected API error for user '{username}': {result.stderr.strip()}" ) @@ -185,7 +185,7 @@ def update_reviewers( ) -> None: """Adds or removes reviewers from a PR in a single operation per action.""" if reviewers_to_add: - logging.info("Requesting reviews from: %s", ", ".join(reviewers_to_add)) + logger.info("Requesting reviews from: %s", ", ".join(reviewers_to_add)) try: run_gh_command( [ @@ -197,12 +197,10 @@ def update_reviewers( ] ) except GHError as e: - logging.error("Failed to add reviewers: %s", e) + logger.error("Failed to add reviewers: %s", e) if reviewers_to_remove and owner and repo: - logging.info( - "Removing review requests from: %s", ", ".join(reviewers_to_remove) - ) + logger.info("Removing review requests from: %s", ", ".join(reviewers_to_remove)) payload = json.dumps({"reviewers": list(reviewers_to_remove)}) try: run_gh_command( @@ -217,7 +215,7 @@ def update_reviewers( input_data=payload, ) except GHError as e: - logging.error("Failed to remove reviewers: %s", e) + logger.error("Failed to remove reviewers: %s", e) def main() -> None: @@ -256,20 +254,20 @@ def main() -> None: args.owner, args.repo, args.pr_number, args.bot_user_name ) - logging.info("Current Maintainers: %s", " ".join(maintainers) or "None") - logging.info("Pending Reviewers: %s", " ".join(pending_reviewers) or "None") - logging.info("Past Reviewers: %s", " ".join(past_reviewers) or "None") - logging.info("Manually Requested: %s", " ".join(manually_requested) or "None") + logger.info("Current Maintainers: %s", " ".join(maintainers) or "None") + logger.info("Pending Reviewers: %s", " ".join(pending_reviewers) or "None") + logger.info("Past Reviewers: %s", " ".join(past_reviewers) or "None") + logger.info("Manually Requested: %s", " ".join(manually_requested) or "None") # --- 2. Determine reviewers to remove --- reviewers_to_remove: set[str] = set() if no_plugin_files: reviewers_to_remove = pending_reviewers - manually_requested - logging.info("No plugin files changed. Removing bot-requested reviewers.") + logger.info("No plugin files changed. Removing bot-requested reviewers.") else: outdated_reviewers = pending_reviewers - maintainers reviewers_to_remove = outdated_reviewers - manually_requested - logging.info("Removing outdated bot-requested reviewers.") + logger.info("Removing outdated bot-requested reviewers.") if reviewers_to_remove: update_reviewers( @@ -279,7 +277,7 @@ def main() -> None: reviewers_to_remove=reviewers_to_remove, ) else: - logging.info("No reviewers to remove.") + logger.info("No reviewers to remove.") # --- 3. Determine new reviewers to add --- reviewers_to_add: set[str] = set() @@ -295,14 +293,14 @@ def main() -> None: non_collaborators = potential_reviewers - reviewers_to_add if non_collaborators: - logging.warning( + logger.warning( "Ignoring non-collaborators: %s", ", ".join(non_collaborators) ) if reviewers_to_add: update_reviewers(args.pr_number, reviewers_to_add=reviewers_to_add) else: - logging.info("No new reviewers to add.") + logger.info("No new reviewers to add.") if __name__ == "__main__": diff --git a/flake/dev/generate-all-maintainers/generate-all-maintainers.py b/flake/dev/generate-all-maintainers/generate-all-maintainers.py index d9ea6564..42c86185 100755 --- a/flake/dev/generate-all-maintainers/generate-all-maintainers.py +++ b/flake/dev/generate-all-maintainers/generate-all-maintainers.py @@ -72,23 +72,27 @@ class MetaMaintainerGenerator: capture_output=True, text=True, timeout=60, + check=True, ) - - if result.returncode == 0: - data = json.loads(result.stdout) - print("✅ Successfully extracted maintainers using meta.maintainers") - return data - else: - print(f"❌ Failed to extract maintainers: {result.stderr}") - sys.exit(1) - except subprocess.TimeoutExpired: print("❌ Timeout while extracting maintainers") sys.exit(1) - except Exception as e: + except subprocess.CalledProcessError as e: + print(f"❌ Failed to extract maintainers: {e.stderr}") + sys.exit(1) + except OSError as e: print(f"❌ Error extracting maintainers: {e}") sys.exit(1) + try: + data = json.loads(result.stdout) + except json.JSONDecodeError as e: + print(f"❌ Error parsing extracted maintainers: {e}") + sys.exit(1) + + print("✅ Successfully extracted maintainers using meta.maintainers") + return data + def generate_maintainers_file(self) -> None: """Generate the complete all-maintainers.nix file.""" print("📄 Generating all-maintainers.nix using meta.maintainers...") @@ -132,24 +136,24 @@ class MetaMaintainerGenerator: def validate_generated_file(self) -> bool: """Validate the generated Nix file syntax.""" try: - result = subprocess.run( + subprocess.run( ["nix-instantiate", "--eval", str(self.output_file), "--strict"], capture_output=True, text=True, timeout=10, + check=True, ) - - if result.returncode == 0: - print("✅ Generated file has valid Nix syntax") - return True - else: - print("❌ Warning: Generated file has Nix syntax errors") - print(result.stderr[:500]) - return False - except Exception as e: + except subprocess.CalledProcessError as e: + print("❌ Warning: Generated file has Nix syntax errors") + print(e.stderr[:500]) + return False + except (OSError, subprocess.TimeoutExpired) as e: print(f"Warning: Could not validate file: {e}") return False + print("✅ Generated file has valid Nix syntax") + return True + def print_statistics(self, maintainer_data: dict) -> None: """Print generation statistics.""" stats = maintainer_data["stats"] @@ -203,7 +207,7 @@ def main(): except KeyboardInterrupt: print("\n❌ Generation cancelled by user") sys.exit(1) - except Exception as e: + except (OSError, KeyError) as e: print(f"❌ Error generating maintainers file: {e}") sys.exit(1) diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..727fb28c --- /dev/null +++ b/ruff.toml @@ -0,0 +1,7 @@ +[lint] +ignore = [ + # Some of our scripts are run through `nix-shell` as an interpreter, which + # requires a second `#!nix-shell ...` line right after the shebang. + # See https://nix.dev/manual/nix/latest/command-ref/nix-shell#use-as-a-interpreter + "EXE005", +]