Update fields
This commit is contained in:
@ -40,6 +40,30 @@ from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any, Callable
|
||||
|
||||
from jira import Issue
|
||||
from jira.resources import CustomFieldOption, User
|
||||
|
||||
|
||||
class DeploymentRequirements(Enum):
|
||||
"""Checklist of deployment requirements for the Jira 'Deployment Requirements' multi-select field."""
|
||||
CODE_REVIEW_COMPLETED = "Code Review Completed"
|
||||
UNIT_TESTS_PASSED = "Unit Tests Passed"
|
||||
QA_SIGN_OFF = "QA Sign-off"
|
||||
DOCUMENTATION_UPDATED = "Documentation Updated"
|
||||
SECURITY_SCAN_APPROVED = "Security Scan Approved"
|
||||
CHANGE_MANAGEMENT_TICKET_LINKED = "Change Management Ticket Linked"
|
||||
|
||||
|
||||
class ReleaseTrain(Enum):
|
||||
"""Valid release train options for the Jira 'Release Train' single-select field."""
|
||||
ALPHA_TRAIN = "Alpha Train"
|
||||
BETA_TRAIN = "Beta Train"
|
||||
GAMMA_TRAIN = "Gamma Train"
|
||||
STABLE_TRAIN = "Stable Train"
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class FieldType(Enum):
|
||||
"""
|
||||
@ -68,9 +92,13 @@ class FieldType(Enum):
|
||||
LABELS = "labels"
|
||||
|
||||
def single_select_formatter(value: Any):
|
||||
if isinstance(value, Enum):
|
||||
return {"value": value.value}
|
||||
return {"value": value}
|
||||
|
||||
def multi_select_formatter(values: Any):
|
||||
if all(isinstance(v, Enum) for v in values):
|
||||
return [{"value": v.value} for v in values]
|
||||
return [{"value": value} for value in (values if isinstance(values, list) else [values])]
|
||||
|
||||
def user_formatter(value: Any):
|
||||
@ -91,6 +119,35 @@ FIELD_FORMATTERS = {
|
||||
}
|
||||
|
||||
|
||||
def get_single_select_formatter(value: CustomFieldOption) -> str:
|
||||
if not isinstance(value, CustomFieldOption):
|
||||
raise ValueError(f"Expected CustomFieldOption, got {type(value)}")
|
||||
return value.value
|
||||
|
||||
|
||||
def get_multi_select_formatter(values: list[CustomFieldOption]) -> list[str]:
|
||||
if not isinstance(values, list):
|
||||
raise ValueError(f"Expected list of CustomFieldOption, got {type(values)}")
|
||||
if not all(isinstance(v, CustomFieldOption) for v in values):
|
||||
raise ValueError("All items in the list must be CustomFieldOption instances")
|
||||
return [get_single_select_formatter(v) for v in values]
|
||||
|
||||
|
||||
def get_user_formatter(user: User) -> dict:
|
||||
if not isinstance(user, User):
|
||||
raise ValueError(f"Expected User, got {type(user)}")
|
||||
return user.name
|
||||
|
||||
|
||||
GET_FIELD_FORMATTERS = {
|
||||
FieldType.TEXT: lambda v: v,
|
||||
FieldType.SINGLE_SELECT: get_single_select_formatter,
|
||||
FieldType.MULTI_SELECT: get_multi_select_formatter,
|
||||
FieldType.USER: get_user_formatter,
|
||||
FieldType.LABELS: lambda v: v,
|
||||
}
|
||||
|
||||
|
||||
class JiraFields(Enum):
|
||||
"""
|
||||
Enumeration of high-level Jira field names used in the CLI.
|
||||
@ -154,6 +211,10 @@ class JiraFieldInfo:
|
||||
def formatter(self) -> Callable[[Any], Any]:
|
||||
return FIELD_FORMATTERS[self.field_type]
|
||||
|
||||
@property
|
||||
def get_field_formatter(self) -> Callable[[Any], Any]:
|
||||
return GET_FIELD_FORMATTERS[self.field_type]
|
||||
|
||||
|
||||
FIELD_REGISTRY = {
|
||||
JiraFields.RELEASE_TRAIN: JiraFieldInfo(
|
||||
@ -171,6 +232,34 @@ FIELD_REGISTRY = {
|
||||
}
|
||||
|
||||
|
||||
def get_field(issue: Issue, name: JiraFields) -> JiraFieldInfo:
|
||||
"""
|
||||
Retrieve a field from a Jira issue and format it according to FieldType.
|
||||
|
||||
Args:
|
||||
issue (Issue): Jira issue instance (from jira-python).
|
||||
name (JiraFields): Logical Jira field enum member.
|
||||
|
||||
Returns:
|
||||
Any: The formatted field data (e.g. str, list, dict) appropriate to the type.
|
||||
|
||||
Raises:
|
||||
ValueError: If the field name is not a valid JiraFields enum member
|
||||
AttributeError: If the issue does not have the field
|
||||
"""
|
||||
if not isinstance(name, JiraFields):
|
||||
raise ValueError(f"Expected JiraFields enum, got {type(name)}")
|
||||
try:
|
||||
info = FIELD_REGISTRY[name]
|
||||
except KeyError:
|
||||
raise ValueError(f"Field {name} is not registered in FIELD_REGISTRY")
|
||||
try:
|
||||
data = getattr(issue.fields, info.field_id)
|
||||
except AttributeError:
|
||||
raise ValueError(f"Issue does not have field {name} ({FIELD_REGISTRY[name].field_id})")
|
||||
return info.get_field_formatter(data)
|
||||
|
||||
|
||||
class UpdateFields:
|
||||
"""
|
||||
Builder class for constructing Jira issue field update payloads.
|
||||
|
30
cli/fields_test.py
Normal file
30
cli/fields_test.py
Normal file
@ -0,0 +1,30 @@
|
||||
from jira import JIRA
|
||||
from rich.console import Console
|
||||
|
||||
from fields import JiraFields as jf
|
||||
from fields import DeploymentRequirements as dr
|
||||
from fields import ReleaseTrain as rt
|
||||
from fields import UpdateFields, get_field
|
||||
from jql_utils import load_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
console = Console(color_system="truecolor")
|
||||
jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"]))
|
||||
|
||||
|
||||
tick = jira.issue("AETHER-1")
|
||||
|
||||
deployment_requirements = get_field(tick, jf.DEPLOYMENT_REQUIREMENTS)
|
||||
reporter = get_field(tick, jf.REPORTER)
|
||||
|
||||
update_fields = UpdateFields()
|
||||
update_fields.add_field(jf.RELEASE_TRAIN, rt.GAMMA_TRAIN)
|
||||
update_fields.add_field(
|
||||
jf.DEPLOYMENT_REQUIREMENTS, [dr.CODE_REVIEW_COMPLETED, dr.QA_SIGN_OFF]
|
||||
)
|
||||
|
||||
tick.update(fields=update_fields.as_dict())
|
||||
|
||||
for name, value in tick.raw["fields"].items():
|
||||
console.print(f"[bold green]{name}[/bold green]: {value}")
|
Reference in New Issue
Block a user