Skip to content

Commit

Permalink
fix assingments
Browse files Browse the repository at this point in the history
  • Loading branch information
chriku committed Oct 18, 2024
1 parent ab2987e commit 7fd2574
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 21 deletions.
21 changes: 14 additions & 7 deletions sync-jira/src/main/kotlin/gropius/sync/jira/JiraDataService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import gropius.sync.JsonHelper
import gropius.sync.SyncDataService
import gropius.sync.jira.config.IMSConfig
import gropius.sync.jira.config.IMSProjectConfig
import gropius.sync.jira.model.IssueDataRepository
import gropius.util.JsonNodeMapper
import io.ktor.client.*
import io.ktor.client.call.*
Expand Down Expand Up @@ -46,6 +47,7 @@ import java.util.*
* @param objectMapper Reference for the spring instance of ObjectMapper
* @param jsonNodeMapper Reference for the spring instance of JsonNodeMapper
* @param gropiusUserRepository Reference for the spring instance of GropiusUserRepository
* @param issueDataRepository Reference for the spring instance of IssueDataRepository
*/
@Component
class JiraDataService(
Expand All @@ -55,7 +57,8 @@ class JiraDataService(
val helper: JsonHelper,
val objectMapper: ObjectMapper,
val jsonNodeMapper: JsonNodeMapper,
val gropiusUserRepository: GropiusUserRepository
val gropiusUserRepository: GropiusUserRepository,
val issueDataRepository: IssueDataRepository
) : SyncDataService {

companion object {
Expand Down Expand Up @@ -274,8 +277,7 @@ class JiraDataService(
): Optional<HttpResponse> {
val imsConfig = IMSConfig(helper, imsProject.ims().value, imsProject.ims().value.template().value)
val cloudId =
token.cloudIds?.filter { URI(it.url + "/rest/api/2") == URI(imsConfig.rootUrl.toString()) }?.map { it.id }
?.firstOrNull()
token.cloudIds?.filter { URI(it.url) == URI(imsConfig.rootUrl.toString()) }?.map { it.id }?.firstOrNull()
if (token.type == "PAT") {
try {
val res = client.request(imsConfig.rootUrl.toString()) {
Expand All @@ -294,15 +296,15 @@ class JiraDataService(
setBody(body)
}
}
logger.info("Response Code for request with token token is ${res.status}(${res.status.isSuccess()}): $body is ${res.bodyAsText()}")
return if (res.status.isSuccess()) {
logger.debug("Response for {} {}", res.request.url, res.bodyAsText())
Optional.of(res)
} else {
logger.info("Response Code for request with token token is ${res.status}(${res.status.isSuccess()}): $body is ${res.bodyAsText()}")
Optional.empty()
}
} catch (e: ClientRequestException) {
e.printStackTrace()
logger.warn("Request failed with token $token", e)
return Optional.empty()
}
} else if (cloudId != null) {
Expand All @@ -324,18 +326,23 @@ class JiraDataService(
setBody(body)
}
}
logger.info("Response Code for request with token token is ${res.status}(${res.status.isSuccess()}): $body is ${res.bodyAsText()}")
return if (res.status.isSuccess()) {
logger.debug("Response for {} {}", res.request.url, res.bodyAsText())
Optional.of(res)
} else {
logger.info("Response Code for request with token token is ${res.status}(${res.status.isSuccess()}): $body is ${res.bodyAsText()}")
Optional.empty()
}
} catch (e: ClientRequestException) {
e.printStackTrace()
logger.warn("Request failed with token $token", e)
return Optional.empty()
}
} else {
logger.error("Invalid value for token type: ${token.type} and cloudId: ${token.cloudIds} with ${
token.cloudIds?.map {
URI(it.url) to URI(imsConfig.rootUrl.toString())
}
}")
return Optional.empty()
}
}
Expand Down
26 changes: 18 additions & 8 deletions sync-jira/src/main/kotlin/gropius/sync/jira/JiraSync.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import java.time.OffsetDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import kotlin.io.encoding.ExperimentalEncodingApi
import kotlin.jvm.optionals.getOrNull

/**
* Details of the issue status after the transition.
Expand Down Expand Up @@ -270,13 +271,13 @@ final class JiraSync(
val issueList = mutableListOf<IssueData>()
val times = mutableListOf<OffsetDateTime>()
val issueResponse = jiraDataService.tokenManager.executeUntilWorking(imsProject, userList, listOf()) {
val userTimeZone = ZoneId.of(
jiraDataService.sendRequest<Unit>(
imsProject, HttpMethod.Get, null, {
appendPathSegments("myself")
}, it
).get().body<UserQuery>().timeZone
)
val requestData = jiraDataService.sendRequest<Unit>(
imsProject, HttpMethod.Get, null, {
appendPathSegments("myself")
}, it
).getOrNull() ?: TODO("Timezone bad")
logger.trace("TIME ZONE RESPONSE ${requestData.bodyAsText()}")
val userTimeZone = ZoneId.of(requestData.body<UserQuery>().timeZone)
var query = "project=${imsProjectConfig.repo} ORDER BY updated ASC"
if (lastSuccessfulSync != null) {
query = "project=${imsProjectConfig.repo} AND updated > ${
Expand Down Expand Up @@ -474,12 +475,21 @@ final class JiraSync(
override suspend fun syncTemplatedField(
imsProject: IMSProject, issueId: String, fieldChangedEvent: TemplatedFieldChangedEvent, users: List<User>
): TimelineItemConversionInformation? {
val customName = jiraDataService.issueDataRepository.findByImsProject(imsProject.rawId!!).map {
it.names.map { it.value.jsonPrimitive.content to it.key }.toMap()[fieldChangedEvent.fieldName]
}.filterNotNull().firstOrNull()
logger.trace("Writing ${fieldChangedEvent.fieldName} to $customName with ${fieldChangedEvent.newValue}")
if (customName == null) {
return null
}
val response = jiraDataService.request(
imsProject, users, HttpMethod.Put, gropiusUserList(users), JsonObject(
mapOf(
"fields" to JsonObject(
mapOf(
fieldChangedEvent.fieldName to JsonPrimitive(fieldChangedEvent.newValue)
customName to JsonPrimitive(
jiraDataService.objectMapper.readTree(fieldChangedEvent.newValue).textValue()
)
)
)
)
Expand Down
69 changes: 66 additions & 3 deletions sync-jira/src/main/kotlin/gropius/sync/jira/model/IssueData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package gropius.sync.jira.model

import com.fasterxml.jackson.databind.JsonNode
import gropius.model.architecture.IMSProject
import gropius.model.architecture.Project
import gropius.model.issue.Issue
import gropius.model.issue.timeline.*
import gropius.sync.IncomingIssue
Expand All @@ -13,7 +12,6 @@ import gropius.sync.jira.JiraDataService
import gropius.util.schema.Schema
import gropius.util.schema.Type
import jakarta.transaction.Transactional
import kotlinx.coroutines.reactive.awaitFirst
import kotlinx.coroutines.reactor.awaitSingle
import kotlinx.serialization.json.*
import org.bson.*
Expand Down Expand Up @@ -77,6 +75,10 @@ class JiraTimelineItem(val id: String, val created: String, val author: JsonObje
return gropiusLabels(
timelineItemConversionInformation, imsProject, service, jiraService
)
} else if (fieldId == "assignee") {
return gropiusAssignment(
timelineItemConversionInformation, imsProject, service, jiraService, issue
)
}
if (issue.template().value.templateFieldSpecifications.containsKey(data.field)) {
val schema = issue.template().value.templateFieldSpecifications[data.field]!!
Expand Down Expand Up @@ -218,6 +220,67 @@ class JiraTimelineItem(val id: String, val created: String, val author: JsonObje
return listOf<TimelineItem>(titleChangedEvent) to convInfo;
}

/**
* Convert a single assignment change to a Gropius TimelineItem
* @param timelineItemConversionInformation the timeline item conversion information
* @param imsProject the ims project
* @param service the service
* @param jiraService the jira service
* @param issue the issue to work on (sometimes not yet saved or complete)
* @return the pair of timeline items and conversion information
*/
private suspend fun gropiusAssignment(
timelineItemConversionInformation: TimelineItemConversionInformation?,
imsProject: IMSProject,
service: JiraDataService,
jiraService: JiraDataService,
issue: Issue
): Pair<List<TimelineItem>, TimelineItemConversionInformation> {
val convInfo =
timelineItemConversionInformation ?: JiraTimelineItemConversionInformation(imsProject.rawId!!, id);
val timelineId = timelineItemConversionInformation?.gropiusId
val encodedAccountId = service.jsonNodeMapper.jsonNodeToDeterministicString(
service.objectMapper.valueToTree<JsonNode>(data.to)
)
val newUser = if (data.to != null) imsProject.ims().value.users()
.firstOrNull { (it.username == data.to) or (it.templatedFields["jira_id"] == encodedAccountId) } else null
if (newUser != null) {
val titleChangedEvent = (if (timelineId != null) service.neoOperations.findById<Assignment>(
timelineId
) else null) ?: Assignment(
OffsetDateTime.parse(
created, IssueData.formatter
).minusNanos(1), OffsetDateTime.parse(
created, IssueData.formatter
).minusNanos(1)
)
titleChangedEvent.createdBy().value = jiraService.mapUser(imsProject, author)
titleChangedEvent.lastModifiedBy().value = jiraService.mapUser(imsProject, author)
titleChangedEvent.user().value = newUser
return listOf<TimelineItem>(titleChangedEvent) to convInfo;
} else if (data.to != null) {
logger.warn("Cannot find user for ${data.to} ${data.toString}")
}
val oldAssignment =
issue.assignments().lastOrNull { it.user().value.username == data.from } ?: issue.assignments().lastOrNull()
if (oldAssignment != null) {//TODO: Replace with robuster logic once handling of multiple timeline items works
val titleChangedEvent = (if (timelineId != null) service.neoOperations.findById<RemovedAssignmentEvent>(
timelineId
) else null) ?: RemovedAssignmentEvent(
OffsetDateTime.parse(
created, IssueData.formatter
).minusNanos(1), OffsetDateTime.parse(
created, IssueData.formatter
).minusNanos(1)
)
titleChangedEvent.createdBy().value = jiraService.mapUser(imsProject, author)
titleChangedEvent.lastModifiedBy().value = jiraService.mapUser(imsProject, author)
titleChangedEvent.removedAssignment().value = oldAssignment
return listOf<TimelineItem>(titleChangedEvent) to convInfo
}
return listOf<TimelineItem>() to convInfo
}

/**
* Convert a single state change to a Gropius StateChangedEvent
* @param timelineItemConversionInformation the timeline item conversion information
Expand Down Expand Up @@ -427,7 +490,7 @@ data class IssueData(
issue.body().value.issue().value = issue
issue.state().value = jiraService.issueState(imsProject, null, true)
issue.template().value = jiraService.issueTemplate(imsProject)
issue.trackables() += jiraService.neoOperations.findAll(Project::class.java).awaitFirst()
issue.trackables() += imsProject.trackable().value
issue.type().value =
jiraService.issueType(imsProject, fields["issuetype"]?.jsonObject?.get("name")?.jsonPrimitive?.content!!)
return issue
Expand Down
10 changes: 7 additions & 3 deletions sync/src/main/kotlin/gropius/sync/IssueCleaner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ class IssueCleaner(
if (item is Assignment) {
issue.assignments() += item
}
if (item is RemovedAssignmentEvent) {
issue.assignments() -= item.removedAssignment().value
}
}
for (item in issue.timelineItems().sortedBy { it.createdAt }) {
if (item is AssignmentTypeChangedEvent) {
TODO()
}
}
for (item in issue.timelineItems().sortedBy { it.createdAt }) {
if (item is RemovedAssignmentEvent) {
issue.assignments() -= item.removedAssignment().value
}
}
}

/**
Expand Down

0 comments on commit 7fd2574

Please sign in to comment.