diff --git a/.github/workflows/validate-maintainers.yml b/.github/workflows/validate-maintainers.yml index a4564ace5..27f3ab298 100644 --- a/.github/workflows/validate-maintainers.yml +++ b/.github/workflows/validate-maintainers.yml @@ -25,96 +25,11 @@ jobs: with: nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/${{ steps.get-nixpkgs.outputs.rev }}.tar.gz - name: Validate Nix syntax - run: | - echo "🔍 Validating maintainers.nix syntax..." - if nix eval --file modules/lib/maintainers.nix --json > /dev/null; then - echo "✅ Valid Nix syntax" - else - echo "❌ Invalid Nix syntax" - exit 1 - fi + run: ./lib/python/validate-maintainers-syntax.py - name: Validate maintainer entries - run: | - echo "🔍 Validating maintainer entries..." - python3 -c " - import json - import re - import subprocess - import sys - - # Get the maintainers data from the Nix file - result = subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'], - capture_output=True, text=True, check=True) - maintainers = json.loads(result.stdout) - errors = [] - - for name, data in maintainers.items(): - # Check REQUIRED fields - github and githubId are mandatory - if 'github' not in data: - errors.append(f'{name}: Missing required field \"github\"') - if 'githubId' not in data: - errors.append(f'{name}: Missing required field \"githubId\"') - - # Validate GitHub ID is a positive integer (NOT a string) - if 'githubId' in data: - github_id = data['githubId'] - if not isinstance(github_id, int): - errors.append(f'{name}: githubId must be a number, not a string: {github_id} (type: {type(github_id).__name__})') - elif github_id <= 0: - errors.append(f'{name}: githubId must be positive: {github_id}') - - if errors: - print('❌ Validation errors found:') - for error in errors: - print(f' - {error}') - sys.exit(1) - else: - print('✅ All maintainer entries are valid') - print(f'✅ Validated {len(maintainers)} maintainer entries') - " + run: ./lib/python/validate-maintainer-entries.py - name: Check for duplicate maintainers - run: | - echo "🔍 Checking for duplicate maintainers between HM and nixpkgs..." - python3 -c " - import json - import subprocess - import sys - - hm_result = subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'], - capture_output=True, text=True, check=True) - hm_maintainers = json.loads(hm_result.stdout) - hm_github_users = set() - for name, data in hm_maintainers.items(): - if 'github' in data: - hm_github_users.add(data['github']) - - nixpkgs_result = subprocess.run(['nix', 'eval', 'nixpkgs#lib.maintainers', '--json'], - capture_output=True, text=True, check=True) - nixpkgs_maintainers = json.loads(nixpkgs_result.stdout) - nixpkgs_github_users = set() - for name, data in nixpkgs_maintainers.items(): - if isinstance(data, dict) and 'github' in data: - nixpkgs_github_users.add(data['github']) - - duplicates = hm_github_users.intersection(nixpkgs_github_users) - - if duplicates: - print(f'❌ Found {len(duplicates)} duplicate maintainers between HM and nixpkgs:') - for github_user in sorted(duplicates): - # Find the HM attribute name for this github user - hm_attr = None - for attr_name, data in hm_maintainers.items(): - if data.get('github') == github_user: - hm_attr = attr_name - break - print(f' - {github_user} (HM attribute: {hm_attr})') - print() - print('These maintainers should be removed from HM maintainers file to avoid duplication.') - print('They can be referenced directly from nixpkgs instead.') - sys.exit(1) - else: - print('✅ No duplicate maintainers found') - " + run: ./lib/python/check-duplicate-maintainers.py - name: Test generation if: inputs.run_tests == true run: | diff --git a/lib/python/check-duplicate-maintainers.py b/lib/python/check-duplicate-maintainers.py new file mode 100755 index 000000000..5421f4625 --- /dev/null +++ b/lib/python/check-duplicate-maintainers.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +""" +Check for duplicate maintainers between home-manager and nixpkgs + +This script compares the maintainers in home-manager with those in nixpkgs +to identify duplicates that should be removed from home-manager. +""" + +import json +import subprocess +import sys + + +def main(): + print("🔍 Checking for duplicate maintainers between HM and nixpkgs...") + + # Get home-manager maintainers + hm_result = subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'], + capture_output=True, text=True, check=True) + hm_maintainers = json.loads(hm_result.stdout) + hm_github_users = set() + for name, data in hm_maintainers.items(): + if 'github' in data: + hm_github_users.add(data['github']) + + # Get nixpkgs maintainers + nixpkgs_result = subprocess.run(['nix', 'eval', 'nixpkgs#lib.maintainers', '--json'], + capture_output=True, text=True, check=True) + nixpkgs_maintainers = json.loads(nixpkgs_result.stdout) + nixpkgs_github_users = set() + for name, data in nixpkgs_maintainers.items(): + if isinstance(data, dict) and 'github' in data: + nixpkgs_github_users.add(data['github']) + + # Find duplicates + duplicates = hm_github_users.intersection(nixpkgs_github_users) + + if duplicates: + print(f'❌ Found {len(duplicates)} duplicate maintainers between HM and nixpkgs:') + for github_user in sorted(duplicates): + # Find the HM attribute name for this github user + hm_attr = None + for attr_name, data in hm_maintainers.items(): + if data.get('github') == github_user: + hm_attr = attr_name + break + print(f' - {github_user} (HM attribute: {hm_attr})') + print() + print('These maintainers should be removed from HM maintainers file to avoid duplication.') + print('They can be referenced directly from nixpkgs instead.') + sys.exit(1) + else: + print('✅ No duplicate maintainers found') + + +if __name__ == "__main__": + main() diff --git a/lib/python/validate-maintainer-entries.py b/lib/python/validate-maintainer-entries.py new file mode 100755 index 000000000..7d4c5c8e3 --- /dev/null +++ b/lib/python/validate-maintainer-entries.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +""" +Validate maintainer entries in modules/lib/maintainers.nix + +This script validates that all maintainer entries have required fields +and that the data types are correct. +""" + +import json +import subprocess +import sys + + +def main(): + print("🔍 Validating maintainer entries...") + + result = subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'], + capture_output=True, text=True, check=True) + maintainers = json.loads(result.stdout) + errors = [] + + for name, data in maintainers.items(): + if 'github' not in data: + errors.append(f'{name}: Missing required field "github"') + if 'githubId' not in data: + errors.append(f'{name}: Missing required field "githubId"') + + if 'githubId' in data: + github_id = data['githubId'] + if not isinstance(github_id, int): + errors.append(f'{name}: githubId must be a number, not a string: {github_id} (type: {type(github_id).__name__})') + elif github_id <= 0: + errors.append(f'{name}: githubId must be positive: {github_id}') + + if errors: + print('❌ Validation errors found:') + for error in errors: + print(f' - {error}') + sys.exit(1) + else: + print('✅ All maintainer entries are valid') + print(f'✅ Validated {len(maintainers)} maintainer entries') + + +if __name__ == "__main__": + main() diff --git a/lib/python/validate-maintainers-syntax.py b/lib/python/validate-maintainers-syntax.py new file mode 100755 index 000000000..d1d65a39f --- /dev/null +++ b/lib/python/validate-maintainers-syntax.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +""" +Validate maintainers.nix syntax + +This script validates that the maintainers.nix file has valid Nix syntax. +""" + +import subprocess +import sys + + +def main(): + print("🔍 Validating maintainers.nix syntax...") + + try: + subprocess.run(['nix', 'eval', '--file', 'modules/lib/maintainers.nix', '--json'], + capture_output=True, text=True, check=True) + print("✅ Valid Nix syntax") + except subprocess.CalledProcessError: + print("❌ Invalid Nix syntax") + sys.exit(1) + + +if __name__ == "__main__": + main()