Coverage for little_loops/cli/sprint/create.py: 17%

1"""ll-sprint create subcommand."""

2

3 from __future__ import annotations

4

5 import argparse

6

7 from little_loops.cli_args import parse_issue_ids, parse_issue_types

8 from little_loops.logger import Logger

9 from little_loops.sprint import SprintManager, SprintOptions

10

11

12 def _cmd_sprint_create(args: argparse.Namespace, manager: SprintManager) -> int:

13 """Create a new sprint."""

14 logger = Logger()

15 issues = [i.strip().upper() for i in args.issues.split(",")]

16

17 # Apply skip filter if provided

18 skip_ids = parse_issue_ids(args.skip)

19 if skip_ids:

20 original_count = len(issues)

21 issues = [i for i in issues if i not in skip_ids]

22 skipped = original_count - len(issues)

23 if skipped > 0:

24 logger.info(

25 f"Skipping {skipped} issue(s): "

26 f"{', '.join(sorted(skip_ids & set(issues) | skip_ids))}"

27 )

28

29 # Apply type filter if provided

30 type_prefixes = parse_issue_types(getattr(args, "type", None))

31 if type_prefixes:

32 original_count = len(issues)

33 issues = [i for i in issues if i.split("-", 1)[0] in type_prefixes]

34 filtered = original_count - len(issues)

35 if filtered > 0:

36 logger.info(f"Filtered {filtered} issue(s) by type: {', '.join(sorted(type_prefixes))}")

37

38 # Validate issues exist

39 valid = manager.validate_issues(issues)

40 invalid = set(issues) - set(valid.keys())

41

42 if invalid:

43 logger.warning(f"Issue IDs not found: {', '.join(sorted(invalid))}")

44

45 options = SprintOptions(

46 max_workers=args.max_workers,

47 timeout=args.timeout,

48 )

49

50 sprint = manager.create(

51 name=args.name,

52 issues=issues,

53 description=args.description,

54 options=options,

55 )

56

57 logger.success(f"Created sprint: {sprint.name}")

58 logger.info(f" Description: {sprint.description or '(none)'}")

59 logger.info(f" Issues: {', '.join(sprint.issues)}")

60 logger.info(f" File: .sprints/{sprint.name}.yaml")

61

62 if invalid:

63 logger.warning(f" Invalid issues: {', '.join(sorted(invalid))}")

64

65 return 0