diff --git a/.github/workflows/update-maintainers.yml b/.github/workflows/update-maintainers.yml new file mode 100644 index 0000000000..b679f158e0 --- /dev/null +++ b/.github/workflows/update-maintainers.yml @@ -0,0 +1,254 @@ +name: Update maintainers list + +on: + push: + branches: + - main + paths: + - lib/maintainers.nix + schedule: + # Update every Monday at 9 AM UTC + - cron: "0 9 * * 1" + workflow_dispatch: + inputs: + create_pr: + description: "Create PR even if no changes" + required: false + default: false + type: boolean + +jobs: + update-maintainers: + runs-on: ubuntu-latest + if: github.repository_owner == 'nix-community' || github.event_name == 'workflow_dispatch' + # Permissions required for workflow + # `contents`: to update maintainers file + # `pull-requests`: to create pr + # `issues`: to label pr + permissions: + contents: write + pull-requests: write + issues: write + env: + pr_branch: update/maintainers-${{ github.ref_name }} + steps: + - name: Create GitHub App token + uses: actions/create-github-app-token@v2 + if: vars.CI_APP_ID + id: app-token + with: + app-id: ${{ vars.CI_APP_ID }} + private-key: ${{ secrets.CI_APP_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write + permission-issues: write + + - name: Get GitHub App user info + id: user-info + if: vars.CI_APP_ID + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + slug: ${{ steps.app-token.outputs.app-slug }} + run: | + name="$slug[bot]" + id=$(gh api "/users/$name" --jq .id) + { + echo "id=$id" + echo "name=$name" + echo "email=$id+$name@users.noreply.github.com" + } >> "$GITHUB_OUTPUT" + + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ steps.app-token.outputs.token || github.token }} + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + github_access_token: ${{ steps.app-token.outputs.token || github.token }} + extra_nix_config: | + allow-import-from-derivation = false + + - name: Setup Git + env: + name: ${{ steps.user-info.outputs.name || 'github-actions[bot]' }} + email: ${{ steps.user-info.outputs.email || '41898282+github-actions[bot]@users.noreply.github.com' }} + run: | + git config user.name "$name" + git config user.email "$email" + + - name: Generate updated maintainers list + run: | + echo "::group::πŸ“‹ Generating updated generated/all-maintainers.nix..." + nix run .#generate-all-maintainers -- --root . --output generated/all-maintainers.nix + echo "::endgroup::" + echo "::group::🎨 Formatting with nixfmt..." + nix fmt generated/all-maintainers.nix + echo "::endgroup::" + + - name: Check for changes + id: check-changes + run: | + if git diff --quiet generated/all-maintainers.nix; then + echo "No changes to generated/all-maintainers.nix" + echo "has_changes=false" >> "$GITHUB_OUTPUT" + else + echo "Changes detected in generated/all-maintainers.nix" + echo "has_changes=true" >> "$GITHUB_OUTPUT" + added=$(git diff --numstat generated/all-maintainers.nix | cut -f1) + removed=$(git diff --numstat generated/all-maintainers.nix | cut -f2) + echo "changes_summary=+$added -$removed lines" >> "$GITHUB_OUTPUT" + fi + + - name: Validate generated file + if: steps.check-changes.outputs.has_changes == 'true' + run: | + echo "πŸ” Validating generated generated/all-maintainers.nix..." + if nix-instantiate --eval generated/all-maintainers.nix --strict > /dev/null; then + echo "βœ… Generated file has valid Nix syntax" + else + echo "❌ Generated file has invalid Nix syntax" + exit 1 + fi + + - name: Create update branch + run: | + git branch -D "$pr_branch" || echo "Nothing to delete" + git switch -c "$pr_branch" + + - name: Get info on the current PR + id: open_pr_info + env: + GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} + run: | + # Query for info about the already open update PR + info=$( + gh api graphql -F owner='{owner}' -F repo='{repo}' -F branch="$pr_branch" -f query=' + query($owner:String!, $repo:String!, $branch:String!) { + repository(owner: $owner, name: $repo) { + pullRequests(first: 1, states: OPEN, headRefName: $branch) { + nodes { + number + url + } + } + } + } + ' | jq --raw-output ' + .data.repository.pullRequests.nodes[] + | to_entries[] + | "\(.key)=\(.value)" + ' + ) + if [[ -n "$info" ]]; then + echo "PR info:" + echo "$info" + echo "$info" >> $GITHUB_OUTPUT + else + echo "No PR is currently open" + fi + + - name: Fetch current PR's branch + if: steps.open_pr_info.outputs.number + run: | + git fetch origin "$pr_branch" + git branch --set-upstream-to "origin/$pr_branch" + + - name: Create Pull Request + id: create-pr + if: steps.check-changes.outputs.has_changes == 'true' || github.event.inputs.create_pr == 'true' + env: + GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} + title: "maintainers: update generated/all-maintainers.nix" + commit_body: | + Automated update of the master maintainers list combining: + - Nixvim specific maintainers from lib/maintainers.nix + - Nixpkgs maintainers referenced in Nixvim modules + + Changes: ${{ steps.check-changes.outputs.changes_summary || 'No content changes' }} + + Generated by: flake/dev/generate-all-maintainers/generate-all-maintainers.py + pr_url: ${{ steps.open_pr_info.outputs.url }} + pr_num: ${{ steps.open_pr_info.outputs.number }} + pr_body: | + ## πŸ“‹ Summary + + This PR updates the master maintainers list (`generated/all-maintainers.nix`) which combines: + - **Nixvim specific maintainers** from `lib/maintainers.nix` + - **Nixpkgs maintainers** referenced in Nixvim modules + + ## πŸ”„ Changes + + **Statistics:** ${{ steps.check-changes.outputs.changes_summary || 'No content changes (format/comment updates only)' }} + + The updated list includes all maintainers needed for review assignments across the Nixvim project. + + ## πŸ€– Automation + + - **Generated by:** `flake/dev/generate-all-maintainers/generate-all-maintainers.py` + - **Trigger:** ${{ github.event_name == 'schedule' && 'Scheduled weekly update' || 'Manual workflow dispatch' }} + - **Validation:** File syntax verified with `nix-instantiate --eval` + + ## πŸ“š Usage + + This file can be imported and used for maintainer lookups: + ```nix + let allMaintainers = import ./generated/all-maintainers.nix; in + # Access any maintainer by name: allMaintainers.username + ``` + + --- + πŸ€– *This PR was automatically created by the [update-maintainers workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})* + run: | + git add generated/all-maintainers.nix + git commit -m "$title" -m "$commit_body" + + echo "Pushing to remote branch $pr_branch" + git push --force --set-upstream origin "$pr_branch" + + if [ -z "$pr_num" ]; then + echo "Creating new pull request." + PR_URL=$( + gh pr create \ + --title "$title" \ + --body "$pr_body" + ) + else + PR_URL=$pr_url + echo "Pull request already exists: $PR_URL" + gh pr edit "$pr_num" --body "$pr_body" + fi + + echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" + + - name: Summary + env: + has_changes: ${{ steps.check-changes.outputs.has_changes }} + changes: ${{ steps.check-changes.outputs.changes_summary }} + pr_url: ${{ steps.create-pr.outputs.pr_url}} + pr_num: ${{ steps.open_pr_info.outputs.number }} + run: | + if [[ "$has_changes" == "true" ]]; then + if [[ -n "$pr_num" ]]; then + echo "βœ… Successfully updated PR with new changes." + echo "$changes" + echo "πŸ”— PR URL: $pr_url" + echo "### βœ… PR Updated" >> $GITHUB_STEP_SUMMARY + echo "[$pr_url]($pr_url)" >> $GITHUB_STEP_SUMMARY + elif [[ -n "$pr_url" ]]; then + echo "βœ… Successfully created PR with maintainer updates." + echo "$changes" + echo "πŸ”— PR URL: $pr_url" + echo "### βœ… PR Created" >> $GITHUB_STEP_SUMMARY + echo "[$pr_url]($pr_url)" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Failed to create or update pull request." + echo "### ❌ PR Operation Failed" >> $GITHUB_STEP_SUMMARY + echo "A pull request was intended but the URL was not captured. Please check the logs." >> $GITHUB_STEP_SUMMARY + fi + else + echo "ℹ️ No changes detected - maintainers list is up to date." + echo "### ℹ️ No Changes" >> $GITHUB_STEP_SUMMARY + echo "The maintainers list is up-to-date. No PR was created." >> $GITHUB_STEP_SUMMARY + fi diff --git a/flake/default.nix b/flake/default.nix index 36875c316d..78560d9921 100644 --- a/flake/default.nix +++ b/flake/default.nix @@ -51,6 +51,7 @@ packages = lib.optionalAttrs (partitionStack == [ ]) { # Propagate `packages` from the `dev` partition: inherit (config.partitions.dev.module.flake.packages.${system}) + generate-all-maintainers list-plugins ; }; diff --git a/flake/dev/default.nix b/flake/dev/default.nix index a2fa309ee0..58ba57d868 100644 --- a/flake/dev/default.nix +++ b/flake/dev/default.nix @@ -2,6 +2,7 @@ { imports = [ ./devshell.nix + ./generate-all-maintainers ./list-plugins ./package-tests.nix ./template-tests.nix diff --git a/flake/dev/generate-all-maintainers/default.nix b/flake/dev/generate-all-maintainers/default.nix new file mode 100644 index 0000000000..1157856a6b --- /dev/null +++ b/flake/dev/generate-all-maintainers/default.nix @@ -0,0 +1,42 @@ +{ self, ... }: +{ + perSystem = + { + lib, + pkgs, + ... + }: + let + package = pkgs.writers.writePython3Bin "generate-all-maintainers" { + # Disable flake8 checks that are incompatible with the ruff ones + flakeIgnore = [ + # Thinks shebang is a block comment + "E265" + # line too long + "E501" + # line break before binary operator + "W503" + ]; + } (builtins.readFile ./generate-all-maintainers.py); + in + { + packages.generate-all-maintainers = package; + + checks.generate-all-maintainers-test = + pkgs.runCommand "generate-all-maintainers-test" + { + nativeBuildInputs = [ package ]; + } + '' + generate-all-maintainers --root ${self} --output $out + ''; + + devshells.default.commands = [ + { + name = "generate-all-maintainers"; + command = ''${lib.getExe package} "$@"''; + help = "Generate a single nix file with all `nixvim` and `nixpkgs` maintainer entries"; + } + ]; + }; +} diff --git a/flake/dev/generate-all-maintainers/extract-maintainers-meta.nix b/flake/dev/generate-all-maintainers/extract-maintainers-meta.nix new file mode 100644 index 0000000000..4b950266c3 --- /dev/null +++ b/flake/dev/generate-all-maintainers/extract-maintainers-meta.nix @@ -0,0 +1,74 @@ +# Extract maintainers from nixvim configuration using meta.maintainers +# This script evaluates an empty nixvimConfiguration and extracts the merged maintainer information +let + nixvim = import ../../..; + lib = nixvim.inputs.nixpkgs.lib.extend nixvim.lib.overlay; + + emptyConfig = lib.nixvim.evalNixvim { + modules = [ { _module.check = false; } ]; + extraSpecialArgs = { + pkgs = null; + }; + }; + + inherit (emptyConfig.config.meta) maintainers; + + extractMaintainerObjects = + maintainerData: + lib.pipe maintainerData [ + lib.attrValues + lib.concatLists + lib.unique + ]; + + allMaintainerObjects = extractMaintainerObjects maintainers; + + allMaintainerNames = lib.filter (name: name != null) ( + map (maintainer: maintainer.github) allMaintainerObjects + ); + + nixvimMaintainers = import ../../../lib/maintainers.nix; + nixvimMaintainerNames = lib.attrNames nixvimMaintainers; + partitionedMaintainers = lib.partition (nameValue: lib.elem nameValue.name nixvimMaintainerNames) ( + lib.attrsToList maintainerDetails + ); + + maintainerDetails = lib.pipe allMaintainerObjects [ + (map (obj: { + name = obj.github; + value = obj // { + source = + if categorizedMaintainers.nixvim ? ${obj.github} then + "nixvim" + else if categorizedMaintainers.nixpkgs ? ${obj.github} then + "nixpkgs" + else + throw "${obj.github} is neither a nixvim or nixpkgs maintainer"; + }; + })) + lib.listToAttrs + ]; + + categorizedMaintainers = { + nixvim = lib.listToAttrs partitionedMaintainers.right; + nixpkgs = lib.listToAttrs partitionedMaintainers.wrong; + }; + + formattedMaintainers = lib.generators.toPretty { + multiline = true; + indent = ""; + } maintainerDetails; +in +{ + raw = maintainers; + names = allMaintainerNames; + details = maintainerDetails; + categorized = categorizedMaintainers; + formatted = formattedMaintainers; + + stats = { + totalMaintainers = lib.length allMaintainerNames; + nixvimMaintainers = lib.length (lib.attrNames categorizedMaintainers.nixvim); + nixpkgsMaintainers = lib.length (lib.attrNames categorizedMaintainers.nixpkgs); + }; +} diff --git a/flake/dev/generate-all-maintainers/generate-all-maintainers.py b/flake/dev/generate-all-maintainers/generate-all-maintainers.py new file mode 100755 index 0000000000..52d923d083 --- /dev/null +++ b/flake/dev/generate-all-maintainers/generate-all-maintainers.py @@ -0,0 +1,210 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i python3 -p python3 +""" +Generate all-maintainers.nix using meta.maintainers as source of truth. + +This script uses the meta.maintainers system to extract maintainer information +by evaluating an empty nixvimConfiguration, which is much simpler and more +reliable than parsing files with regex. +""" + +import argparse +import inspect +import json +import subprocess +import sys +from pathlib import Path + + +def get_project_root() -> Path: + """ + Find the project root directory. + + Tries to find the git repository root. If that fails, falls back to + locating it relative to this script file. + """ + try: + # Ask git for the top-level directory of the current repository. + git_root_bytes = subprocess.check_output( + ["git", "rev-parse", "--show-toplevel"], stderr=subprocess.DEVNULL + ) + return Path(git_root_bytes.decode("utf-8").strip()) + except (subprocess.CalledProcessError, FileNotFoundError): + # Fallback for when not in a git repo or git is not installed. + print( + "Warning: 'git rev-parse --show-toplevel' failed.", + "Falling back to script location to determine root.", + "This may not work correctly with flakes.", + file=sys.stderr, + ) + # Assumes this script is at: /flake/dev/generate-all-maintainers/ + return Path(__file__).parent.parent.parent.parent.resolve() + + +class MetaMaintainerGenerator: + """Generates maintainers list using meta.maintainers from nixvim evaluation.""" + + def __init__(self, nixvim_root: Path): + self.nixvim_root = nixvim_root + self.nixvim_maintainers_file = nixvim_root / "lib" / "maintainers.nix" + self.output_file = nixvim_root / "generated" / "all-maintainers.nix" + self.extractor_script = ( + nixvim_root + / "flake" + / "dev" + / "generate-all-maintainers" + / "extract-maintainers-meta.nix" + ) + + def extract_maintainers_from_meta(self) -> dict: + """Extract maintainer information using meta.maintainers.""" + print("πŸ” Extracting maintainers using meta.maintainers...") + + try: + result = subprocess.run( + [ + "nix", + "eval", + "--file", + str(self.extractor_script), + "--json", + ], + capture_output=True, + text=True, + timeout=60, + ) + + 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: + print(f"❌ Error extracting maintainers: {e}") + sys.exit(1) + + def generate_maintainers_file(self) -> None: + """Generate the complete all-maintainers.nix file.""" + print("πŸ“„ Generating all-maintainers.nix using meta.maintainers...") + + # Extract maintainers using meta.maintainers + maintainer_data = self.extract_maintainers_from_meta() + + nixvim_maintainers = maintainer_data["categorized"]["nixvim"] + nixpkgs_maintainers = maintainer_data["categorized"]["nixpkgs"] + formatted_maintainers = maintainer_data["formatted"] + + print(f"🏠 Nixvim maintainers: {len(nixvim_maintainers)}") + print(f"πŸ“¦ Nixpkgs maintainers: {len(nixpkgs_maintainers)}") + + with open(self.output_file, "w") as f: + f.write(inspect.cleandoc(""" + # Nixvim all maintainers list. + # + # This file lists all referenced maintainers in Nixvim. + # + # This file is automatically generated using meta.maintainers from nixvim evaluation + # DO NOT EDIT MANUALLY + # + # To regenerate: nix run .#generate-all-maintainers + # + """)) + + # Use the formatted maintainers from Nix evaluation + print( + "✨ Serializing formatted maintainers using lib.generators.toPretty..." + ) + f.write("\n") + f.write(formatted_maintainers) + f.write("\n") + + self.validate_generated_file() + self.print_statistics(maintainer_data) + + def validate_generated_file(self) -> bool: + """Validate the generated Nix file syntax.""" + try: + result = subprocess.run( + ["nix-instantiate", "--eval", str(self.output_file), "--strict"], + capture_output=True, + text=True, + timeout=10, + ) + + 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: + print(f"Warning: Could not validate file: {e}") + return False + + def print_statistics(self, maintainer_data: dict) -> None: + """Print generation statistics.""" + stats = maintainer_data["stats"] + + print(f"βœ… Generated {self.output_file}") + print("πŸ“Š Statistics:") + print(f" - Total unique maintainers: {stats['totalMaintainers']}") + print(f" - Nixvim maintainers: {stats['nixvimMaintainers']}") + print(f" - Nixpkgs maintainers: {stats['nixpkgsMaintainers']}") + print() + print("πŸŽ‰ Generation completed successfully using meta.maintainers!") + + +def main(): + parser = argparse.ArgumentParser( + description="Generate Nixvim all-maintainers.nix using meta.maintainers" + ) + parser.add_argument( + "--root", + type=Path, + default=None, + help="Path to Nixvim root (default: auto-detect)", + ) + parser.add_argument( + "--output", + type=Path, + default=None, + help="Output file path (default: /generated/all-maintainers.nix)", + ) + + args = parser.parse_args() + + if args.root: + nixvim_root = args.root + else: + nixvim_root = get_project_root() + + if not (nixvim_root / "lib" / "maintainers.nix").exists(): + print(f"Error: Could not find maintainers.nix in {nixvim_root}") + print("Please specify --root or run from Nixvim directory") + sys.exit(1) + + generator = MetaMaintainerGenerator(nixvim_root) + if args.output: + generator.output_file = args.output + + print("πŸš€ Generating maintainers using meta.maintainers approach...") + + try: + generator.generate_maintainers_file() + except KeyboardInterrupt: + print("\n❌ Generation cancelled by user") + sys.exit(1) + except Exception as e: + print(f"❌ Error generating maintainers file: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/generated/all-maintainers.nix b/generated/all-maintainers.nix new file mode 100644 index 0000000000..d965406fec --- /dev/null +++ b/generated/all-maintainers.nix @@ -0,0 +1,397 @@ +# Nixvim all maintainers list. +# +# This file lists all referenced maintainers in Nixvim. +# +# This file is automatically generated using meta.maintainers from nixvim evaluation +# DO NOT EDIT MANUALLY +# +# To regenerate: nix run .#generate-all-maintainers +# +{ + "347Online" = { + email = "katiejanzen@347online.me"; + github = "347Online"; + githubId = 38228372; + name = "Katie Janzen"; + source = "nixpkgs"; + }; + "4lxs" = { + github = "4lxs"; + githubId = 66408983; + matrix = "@gyn:matrix.org"; + name = "svl"; + source = "nixpkgs"; + }; + AidanWelch = { + email = "aidan@freedwave.com"; + github = "AidanWelch"; + githubId = 35280359; + name = "Aidan Welch"; + source = "nixvim"; + }; + Balssh = { + email = "george.bals25@gmail.com"; + github = "Balssh"; + githubId = 82440615; + name = "George Bals"; + source = "nixpkgs"; + }; + Bodleum = { + email = "daniel@daniellaing.com"; + github = "Bodleum"; + githubId = 60107449; + keys = [ + { + fingerprint = "0821 8B96 DC73 85E5 BB7C A535 D264 3BD2 13BC 0FA8"; + } + ]; + matrix = "@bodleum:matrix.org"; + name = "Daniel Laing"; + source = "nixpkgs"; + }; + DataHearth = { + email = "dev@antoine-langlois.net"; + github = "DataHearth"; + githubId = 28595242; + keys = [ + { + fingerprint = "E8F9 0B80 908E 723D 0EDF 0916 5803 CDA5 9C26 A96A"; + } + ]; + name = "DataHearth"; + source = "nixpkgs"; + }; + Eveeifyeve = { + email = "eveeg1971@gmail.com"; + github = "Eveeifyeve"; + githubId = 88671402; + matrix = "@eveeifyeve:matrix.org"; + name = "Eveeifyeve"; + source = "nixpkgs"; + }; + FKouhai = { + email = "frandres00@gmail.com"; + github = "FKouhai"; + githubId = 24593008; + name = "Fran Cirka"; + source = "nixpkgs"; + }; + GGORG0 = { + email = "GGORG0@protonmail.com"; + github = "GGORG0"; + githubId = 51029895; + matrix = "@ggorg:matrix.org"; + name = "GGORG"; + source = "nixpkgs"; + }; + GaetanLepage = { + email = "gaetan@glepage.com"; + github = "GaetanLepage"; + githubId = 33058747; + name = "Gaetan Lepage"; + source = "nixpkgs"; + }; + HeitorAugustoLN = { + email = "IAm.HeitorALN@proton.me"; + github = "HeitorAugustoLN"; + githubId = 44377258; + name = "Heitor Augusto"; + source = "nixpkgs"; + }; + Kareem-Medhat = { + email = "kareemmedhatnabil@gmail.com"; + github = "Kareem-Medhat"; + githubId = 39652808; + name = "Kareem Medhat"; + source = "nixvim"; + }; + MarcelCoding = { + email = "me@m4rc3l.de"; + github = "MarcelCoding"; + githubId = 34819524; + name = "Marcel"; + source = "nixpkgs"; + }; + MattSturgeon = { + email = "matt@sturgeon.me.uk"; + github = "MattSturgeon"; + githubId = 5046562; + keys = [ + { + fingerprint = "7082 22EA 1808 E39A 83AC 8B18 4F91 844C ED1A 8299"; + } + ]; + matrix = "@mattsturg:matrix.org"; + name = "Matt Sturgeon"; + source = "nixpkgs"; + }; + NickHu = { + email = "me@nickhu.co.uk"; + github = "NickHu"; + githubId = 450276; + name = "Nick Hu"; + source = "nixpkgs"; + }; + alisonjenkins = { + email = "alison.juliet.jenkins@gmail.com"; + github = "alisonjenkins"; + githubId = 1176328; + name = "Alison Jenkins"; + source = "nixvim"; + }; + axelkar = { + email = "axel@axka.fi"; + github = "axelkar"; + githubId = 120189068; + name = "Axel Karjalainen"; + source = "nixpkgs"; + }; + b3nb5n = { + email = "benbaldwin000@gmail.com"; + github = "b3nb5n"; + githubId = 67534814; + name = "Ben"; + source = "nixvim"; + }; + bkp5190 = { + email = "boneypatel37@yahoo.com"; + github = "bkp5190"; + githubId = 60232782; + name = "Boney Patel"; + source = "nixpkgs"; + }; + bpeetz = { + email = "benedikt.peetz@b-peetz.de"; + github = "bpeetz"; + githubId = 140968250; + keys = [ + { + fingerprint = "8321 ED3A 8DB9 99A5 1F3B F80F F268 2914 EA42 DE26"; + } + ]; + matrix = "@soispha:vhack.eu"; + name = "Benedikt Peetz"; + source = "nixpkgs"; + }; + braindefender = { + email = "braindefender@gmail.com"; + github = "braindefender"; + githubId = 4646110; + name = "Nikita Shirokov"; + source = "nixvim"; + }; + elythh = { + email = "gwen@omg.lol"; + github = "elythh"; + githubId = 50964650; + name = "gwen"; + source = "nixvim"; + }; + f4z3r = { + email = "f4z3r-github@pm.me"; + github = "f4z3r"; + githubId = 32326425; + keys = [ + { + fingerprint = "358A 6251 E2ED EDC1 9717 14A7 96A8 BA6E C871 2183"; + } + ]; + name = "Jakob Beckmann"; + source = "nixpkgs"; + }; + foo-dogsquared = { + email = "foodogsquared@foodogsquared.one"; + github = "foo-dogsquared"; + githubId = 34962634; + keys = [ + { + fingerprint = "DDD7 D0BD 602E 564B AA04 FC35 1431 0D91 4115 2B92"; + } + ]; + matrix = "@foodogsquared:matrix.org"; + name = "Gabriel Arazas"; + source = "nixpkgs"; + }; + getchoo = { + email = "getchoo@tuta.io"; + github = "getchoo"; + githubId = 48872998; + matrix = "@getchoo:matrix.org"; + name = "Seth Flynn"; + source = "nixpkgs"; + }; + hmajid2301 = { + email = "hello@haseebmajid.dev"; + github = "hmajid2301"; + githubId = 998807; + keys = [ + { + fingerprint = "A236 785D 59F1 9076 1E9C E8EC 7828 3DB3 D233 E1F9"; + } + ]; + name = "Haseeb Majid"; + source = "nixpkgs"; + }; + insipx = { + email = "github.tech@liquidthink.net"; + github = "insipx"; + githubId = 6452260; + name = "Andrew Plaza"; + source = "nixvim"; + }; + jalil-salame = { + email = "jalil.salame@gmail.com"; + github = "jalil-salame"; + githubId = 60845989; + keys = [ + { + fingerprint = "7D6B 4D8F EBC5 7CBC 09AC 331F DA33 17E7 5BE9 485C"; + } + ]; + name = "Jalil David SalamΓ© Messina"; + source = "nixvim"; + }; + janurskremer = { + email = "mail@jankremer.eu"; + github = "janurskremer"; + githubId = 79042825; + keys = [ + { + fingerprint = "20AF 0A65 9F2B 93AD 9184 15D1 A7DA 689C B3B0 78EC"; + } + ]; + matrix = "@jankremer:matrix.org"; + name = "Jan Kremer"; + source = "nixpkgs"; + }; + jolars = { + email = "jolars@posteo.com"; + github = "jolars"; + githubId = 13087841; + keys = [ + { + fingerprint = "F0D6 BDE7 C7D1 6B3F 7883 73E7 2A41 C0FE DD6F F540"; + } + ]; + matrix = "@jola:mozilla.org"; + name = "Johan Larsson"; + source = "nixpkgs"; + }; + kalbasit = { + email = "wael.nasreddine@gmail.com"; + github = "kalbasit"; + githubId = 87115; + matrix = "@kalbasit:matrix.org"; + name = "Wael Nasreddine"; + source = "nixpkgs"; + }; + khaneliman = { + email = "khaneliman12@gmail.com"; + github = "khaneliman"; + githubId = 1778670; + name = "Austin Horstman"; + source = "nixpkgs"; + }; + loicreynier = { + email = "loic@loicreynier.fr"; + github = "loicreynier"; + githubId = 88983487; + name = "LoΓ―c Reynier"; + source = "nixpkgs"; + }; + mitchmindtree = { + email = "mail@mitchellnordine.com"; + github = "mitchmindtree"; + githubId = 4587373; + name = "Mitchell Nordine"; + source = "nixpkgs"; + }; + nfelber = { + email = "nathan@pascaline.org"; + github = "nfelber"; + githubId = 46248772; + name = "Nathan Felber"; + source = "nixpkgs"; + }; + nwjsmith = { + email = "nate@theinternate.com"; + github = "nwjsmith"; + githubId = 1348; + name = "Nate Smith"; + source = "nixpkgs"; + }; + onemoresuza = { + email = "dev@onemoresuza.com"; + github = "onemoresuza"; + githubId = 106456302; + keys = [ + { + fingerprint = "6FD3 7E64 11C5 C659 2F34 EDBC 4352 D15F B177 F2A8"; + } + ]; + name = "Coutinho de Souza"; + source = "nixpkgs"; + }; + polnio = { + email = "polniolino@gmail.com"; + github = "polnio"; + githubId = 85367527; + name = "Po Co"; + source = "nixpkgs"; + }; + psfloyd = { + email = "peter.racoon@gmail.com"; + github = "psfloyd"; + githubId = 30784060; + name = "Pedro SΓ‘nchez"; + source = "nixvim"; + }; + refaelsh = { + email = "refaelsh@pm.me"; + github = "refaelsh"; + githubId = 2750775; + name = "Refael Sheinker"; + source = "nixvim"; + }; + sheemap = { + github = "sheemap"; + githubId = 1442292; + name = "sheemap"; + source = "nixvim"; + }; + theabm = { + email = "andres_bermeo@outlook.com"; + github = "theabm"; + githubId = 72303015; + name = "Andres Bermeo Marinelli"; + source = "nixpkgs"; + }; + traxys = { + email = "quentin+dev@familleboyer.net"; + github = "traxys"; + githubId = 5623227; + name = "Quentin Boyer"; + source = "nixpkgs"; + }; + wadsaek = { + email = "wadsaek@gmail.com"; + github = "wadsaek"; + githubId = 141351086; + name = "Esther"; + source = "nixvim"; + }; + wvffle = { + email = "nixvim@wvffle.net"; + github = "wvffle"; + githubId = 13330620; + name = "Kasper Seweryn"; + source = "nixvim"; + }; + zainkergaye = { + email = "zain@zkergaye.me"; + github = "zainkergaye"; + githubId = 62440012; + name = "Zain Kergaye"; + source = "nixpkgs"; + }; +}