import utils.LinkedIssueTransitions import utils.FieldCopy final String LINK_TYPE_NAME = "is cloned by" final String TARGET_PROJECT_KEY = "CSD" final String SOURCE_FIELD_ID = "customfield_11501" // ADF final String TARGET_FIELD_ID = "customfield_11501" final String LOG_PREFIX = "[CopyField->LinkedIssue]" def sourceKey = issue?.key?.toString() if (!sourceKey) { logger.warn("${LOG_PREFIX} Kein issue.key im Kontext. Abbruch.") return } // Source laden: Links + Feld def issueResp = get("/rest/api/3/issue/${sourceKey}") .queryString("fields", "issuelinks,${SOURCE_FIELD_ID}") .asObject(Map) if (issueResp.status != 200) { logger.warn("${LOG_PREFIX} Konnte ${sourceKey} nicht laden (${issueResp.status}). Body=${issueResp.body}") return } def sourceJson = issueResp.body // Ziel ermitteln def targetKey = LinkedIssueTransitions.findSingleLinkedTargetKey( sourceJson, LINK_TYPE_NAME, TARGET_PROJECT_KEY ) if (!targetKey) { logger.warn("${LOG_PREFIX} Kein eindeutiges Ziel-Ticket gefunden (erwartet genau 1 Link ins Projekt ${TARGET_PROJECT_KEY}). Abbruch.") return } // Feldwert lesen (ADF) def value = FieldCopy.getFieldValue(sourceJson, SOURCE_FIELD_ID) // Falls leer: Ziel unverändert lassen if (value == null) { logger.warn("${LOG_PREFIX} Source-Feld ${SOURCE_FIELD_ID} ist null/leer in ${sourceKey}. Zielfeld bleibt unverändert.") return } logger.info("${LOG_PREFIX} Kopiere ${SOURCE_FIELD_ID} von ${sourceKey} nach ${targetKey}") def body = FieldCopy.buildSingleFieldUpdateBody(TARGET_FIELD_ID, value) def putResp = put("/rest/api/3/issue/${targetKey}") .header("Content-Type", "application/json") .body(body) .asObject(Map) if (putResp.status == 204) { logger.info("${LOG_PREFIX} OK: Feld ${TARGET_FIELD_ID} in ${targetKey} aktualisiert.") } else { logger.warn("${LOG_PREFIX} Feld-Update fehlgeschlagen: status=${putResp.status}, body=${putResp.body}") }