mirror of
https://github.com/nix-community/nixvim.git
synced 2025-07-12 02:04:31 +02:00
ci: tag-maintainers extract maintainers in a separate script
Make it easier to test the workflow by moving logic out into separate script.
This commit is contained in:
parent
860754350d
commit
405132bab3
2 changed files with 119 additions and 46 deletions
49
.github/workflows/tag-maintainers.yml
vendored
49
.github/workflows/tag-maintainers.yml
vendored
|
@ -67,52 +67,9 @@ jobs:
|
||||||
PR_AUTHOR: "${{ github.event.pull_request.user.login }}"
|
PR_AUTHOR: "${{ github.event.pull_request.user.login }}"
|
||||||
CHANGED_FILES: '${{ steps.changed-files.outputs.changed_files }}'
|
CHANGED_FILES: '${{ steps.changed-files.outputs.changed_files }}'
|
||||||
run: |
|
run: |
|
||||||
if [[ -z "$CHANGED_FILES" ]]; then
|
MAINTAINERS_LIST=$(./ci/tag-maintainers/extract-maintainers.py \
|
||||||
echo "No plugin files changed. No maintainers to tag."
|
--changed-files "$CHANGED_FILES" \
|
||||||
echo "maintainers=" >> "$GITHUB_OUTPUT"
|
--pr-author "$PR_AUTHOR")
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Evaluating nixvim meta system for all maintainers..."
|
|
||||||
# Get a JSON object mapping plugin paths to maintainer data.
|
|
||||||
ALL_MAINTAINERS=$(nix eval --impure --expr "
|
|
||||||
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;
|
|
||||||
in
|
|
||||||
maintainers
|
|
||||||
" --json 2>/dev/null || echo "{}")
|
|
||||||
|
|
||||||
echo "Finding maintainers for changed files..."
|
|
||||||
FOUND_MAINTAINERS=$(
|
|
||||||
echo "$CHANGED_FILES" | while IFS= read -r FILE; do
|
|
||||||
[[ -z "$FILE" ]] && continue
|
|
||||||
PLUGIN_DIR=$(dirname "$FILE")
|
|
||||||
|
|
||||||
# Use jq to find maintainers whose path key ends with the plugin directory.
|
|
||||||
echo "$ALL_MAINTAINERS" | jq -r --arg plugindir "$PLUGIN_DIR" '
|
|
||||||
to_entries[] |
|
|
||||||
select(.key | endswith($plugindir)) |
|
|
||||||
.value[] |
|
|
||||||
select(has("github")) |
|
|
||||||
.github
|
|
||||||
' 2>/dev/null
|
|
||||||
done
|
|
||||||
)
|
|
||||||
|
|
||||||
# De-duplicate the list, remove the PR author, and format as a space-separated string.
|
|
||||||
MAINTAINERS_LIST=$(echo "$FOUND_MAINTAINERS" | grep -v -w -F "$PR_AUTHOR" | sort -u | tr '\n' ' ' | sed 's/ *$//')
|
|
||||||
|
|
||||||
if [[ -z "$MAINTAINERS_LIST" ]]; then
|
|
||||||
echo "No maintainers found for changed files (or only the PR author is a maintainer)."
|
|
||||||
else
|
|
||||||
echo "Found maintainers to notify: $MAINTAINERS_LIST"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "maintainers=$MAINTAINERS_LIST" >> "$GITHUB_OUTPUT"
|
echo "maintainers=$MAINTAINERS_LIST" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
|
116
ci/tag-maintainers/extract-maintainers.py
Executable file
116
ci/tag-maintainers/extract-maintainers.py
Executable file
|
@ -0,0 +1,116 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Extract maintainers from changed plugin files.
|
||||||
|
|
||||||
|
This script extracts the maintainer extraction logic from the tag-maintainers workflow
|
||||||
|
for easier testing and validation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
def run_nix_eval(expr: str) -> str:
|
||||||
|
"""Run a Nix evaluation expression and return the result."""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["nix", "eval", "--impure", "--json", "--expr", expr],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return result.stdout.strip()
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error running Nix evaluation: {e}", file=sys.stderr)
|
||||||
|
print(f"Stderr: {e.stderr}", file=sys.stderr)
|
||||||
|
return "[]"
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
return []
|
||||||
|
|
||||||
|
print("Finding maintainers for changed files...", file=sys.stderr)
|
||||||
|
|
||||||
|
changed_files_nix = '[ ' + ' '.join(f'"{f}"' for f in changed_files) + ' ]'
|
||||||
|
|
||||||
|
nix_expr = f"""
|
||||||
|
let
|
||||||
|
nixvim = import ./.;
|
||||||
|
lib = nixvim.inputs.nixpkgs.lib;
|
||||||
|
emptyConfig = nixvim.lib.nixvim.evalNixvim {{
|
||||||
|
modules = [ {{ _module.check = false; }} ];
|
||||||
|
extraSpecialArgs.pkgs = null;
|
||||||
|
}};
|
||||||
|
inherit (emptyConfig.config.meta) maintainers;
|
||||||
|
|
||||||
|
changedFiles = {changed_files_nix};
|
||||||
|
|
||||||
|
# Find maintainers for files that match changed plugin directories
|
||||||
|
relevantMaintainers = lib.concatLists (
|
||||||
|
lib.mapAttrsToList (path: maintainerList:
|
||||||
|
let
|
||||||
|
matchingFiles = lib.filter (file:
|
||||||
|
lib.hasSuffix (dirOf file) path
|
||||||
|
) changedFiles;
|
||||||
|
in
|
||||||
|
if matchingFiles != [] then maintainerList else []
|
||||||
|
) maintainers
|
||||||
|
);
|
||||||
|
|
||||||
|
# Extract GitHub usernames
|
||||||
|
githubUsers = lib.concatMap (maintainer:
|
||||||
|
if maintainer ? github then [ maintainer.github ] else []
|
||||||
|
) relevantMaintainers;
|
||||||
|
|
||||||
|
in
|
||||||
|
lib.unique githubUsers
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_nix_eval(nix_expr)
|
||||||
|
|
||||||
|
try:
|
||||||
|
maintainers = json.loads(result)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(f"Error parsing Nix evaluation result: {result}", file=sys.stderr)
|
||||||
|
return []
|
||||||
|
|
||||||
|
filtered_maintainers = [m for m in maintainers if m != pr_author]
|
||||||
|
|
||||||
|
if not filtered_maintainers:
|
||||||
|
print("No maintainers found for changed files (or only the PR author is a maintainer).", file=sys.stderr)
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
print(f"Found maintainers to notify: {' '.join(filtered_maintainers)}", file=sys.stderr)
|
||||||
|
return filtered_maintainers
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Main function to handle command line arguments and run the extraction."""
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Extract maintainers from changed plugin files"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--changed-files",
|
||||||
|
help="Newline-separated list of changed files",
|
||||||
|
default="",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--pr-author",
|
||||||
|
required=True,
|
||||||
|
help="GitHub username of the PR author",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
changed_files = [f.strip() for f in args.changed_files.split('\n') if f.strip()]
|
||||||
|
maintainers = extract_maintainers(changed_files, args.pr_author)
|
||||||
|
print(' '.join(maintainers))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Add table
Add a link
Reference in a new issue