Skip to content

Commit

Permalink
Merge pull request #150 from ccims/working/fullmerge
Browse files Browse the repository at this point in the history
Working on combined merge of most open PRs
  • Loading branch information
chriku authored Oct 18, 2024
2 parents 49d932e + 2a61cf5 commit 80f2f32
Show file tree
Hide file tree
Showing 13 changed files with 602 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,10 @@ fragment IssueData on Issue {
}
query CurrentMetaData {
...MetaData
}
query FindUser($login: String!) {
...MetaData
user(login: $login) {
...UserData
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,32 @@ mutation MutateCreateIssue($id: ID!, $title: String!, $body: String!) {
...IssueDataExtensive
}
}
}
}
mutation MutateAssignUser($id: ID!, $user: ID!) {
addAssigneesToAssignable(input:{assignableId: $id, assigneeIds: [$user]}){
assignable {
...on Issue {
timelineItems(itemTypes: [ASSIGNED_EVENT], last: 1) {
nodes {
...TimelineItemData
}
}
}
}
clientMutationId
}
}
mutation MutateUnassignUser($id: ID!, $user: ID!) {
removeAssigneesFromAssignable(input:{assignableId: $id, assigneeIds: [$user]}){
assignable {
...on Issue {
timelineItems(itemTypes: [UNASSIGNED_EVENT], last: 1) {
nodes {
...TimelineItemData
}
}
}
}
clientMutationId
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import gropius.sync.github.config.IMSConfig
import gropius.sync.github.config.IMSProjectConfig
import gropius.sync.github.generated.fragment.LabelData
import gropius.sync.github.generated.fragment.UserData
import gropius.sync.github.generated.fragment.UserData.Companion.asNode
import gropius.sync.github.generated.fragment.UserData.Companion.asUser
import gropius.sync.model.LabelInfo
import gropius.sync.repository.LabelInfoRepository
Expand Down Expand Up @@ -115,6 +116,12 @@ class GithubDataService(
val databaseId = userData?.asUser()?.databaseId
val encodedAccountId =
jsonNodeMapper.jsonNodeToDeterministicString(objectMapper.valueToTree<JsonNode>(databaseId ?: 0))
val encodedUserId =
jsonNodeMapper.jsonNodeToDeterministicString(
objectMapper.valueToTree<JsonNode>(
userData?.asNode()?.id ?: ""
)
)
val username = userData?.login ?: FALLBACK_USER_NAME
val ims = neoOperations.findById<IMS>(imsProject.ims().value.rawId!!)!!
if (databaseId != null) {
Expand All @@ -133,7 +140,7 @@ class GithubDataService(
userData?.asUser()?.email,
null,
username,
mutableMapOf("github_id" to encodedAccountId)
mutableMapOf("github_id" to encodedAccountId, "github_node_id" to encodedUserId)
)
imsUser.ims().value = imsProject.ims().value
imsUser.template().value = imsUser.ims().value.template().value.imsUserTemplate().value
Expand Down
78 changes: 78 additions & 0 deletions sync-github/src/main/kotlin/gropius/sync/github/GithubSync.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@ package gropius.sync.github
import gropius.model.architecture.IMSProject
import gropius.model.issue.Issue
import gropius.model.issue.Label
import gropius.model.issue.timeline.Assignment
import gropius.model.issue.timeline.IssueComment
import gropius.model.issue.timeline.TimelineItem
import gropius.model.template.IMSTemplate
import gropius.model.template.IssueState
import gropius.model.user.GropiusUser
import gropius.model.user.IMSUser
import gropius.model.user.User
import gropius.sync.*
import gropius.sync.github.config.IMSConfigManager
import gropius.sync.github.config.IMSProjectConfig
import gropius.sync.github.generated.*
import gropius.sync.github.generated.MutateAddLabelMutation.Data.AddLabelsToLabelable.Labelable.Companion.asIssue
import gropius.sync.github.generated.MutateAssignUserMutation.Data.AddAssigneesToAssignable.Assignable.Companion.asIssue
import gropius.sync.github.generated.MutateCreateCommentMutation.Data.AddComment.CommentEdge.Node.Companion.asIssueTimelineItems
import gropius.sync.github.generated.MutateRemoveLabelMutation.Data.RemoveLabelsFromLabelable.Labelable.Companion.asIssue
import gropius.sync.github.generated.MutateUnassignUserMutation.Data.RemoveAssigneesFromAssignable.Assignable.Companion.asIssue
import gropius.sync.github.generated.fragment.TimelineItemData.Companion.asNode
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
Expand Down Expand Up @@ -80,6 +86,10 @@ final class GithubSync(
return imsProjectConfig.enableOutgoingComments
}

override suspend fun isOutgoingTemplatedFieldsEnabled(imsProject: IMSProject): Boolean {
return false
}

override suspend fun isOutgoingTitleChangedEnabled(imsProject: IMSProject): Boolean {
val imsProjectConfig = IMSProjectConfig(helper, imsProject)
return imsProjectConfig.enableOutgoingTitleChanges
Expand Down Expand Up @@ -172,6 +182,74 @@ final class GithubSync(
return null
}

override suspend fun syncSingleAssigned(
imsProject: IMSProject, issueId: String, assignment: Assignment, users: List<User>
): TimelineItemConversionInformation? {
val assignedUser = assignment.user().value
val imsUsers =
if (assignedUser as? IMSUser != null) listOf(assignedUser) else if (assignedUser as? GropiusUser != null) assignedUser.imsUsers()
.filter { it.ims().value == imsProject.ims().value } else emptyList()
val ids = imsUsers.map {
githubDataService.objectMapper.readTree(it.templatedFields["github_node_id"]!!).textValue()
}
if (ids.isEmpty()) {
return null
}
val response = githubDataService.mutation(
imsProject, users, MutateAssignUserMutation(issueId, ids.first()), gropiusUserList(users)
).second
val item =
response.data?.addAssigneesToAssignable?.assignable?.asIssue()?.timelineItems?.nodes?.lastOrNull()?.asNode()
if (item != null) {
return TODOTimelineItemConversionInformation(imsProject.rawId!!, item.id)
}
logger.error("${response.data} ${response.errors}")
//TODO("ERROR HANDLING")
return null
}

override suspend fun syncSingleUnassigned(
imsProject: IMSProject, issueId: String, assignment: Assignment, users: List<User>
): TimelineItemConversionInformation? {
val assignedUser = assignment.user().value
val imsUsers =
if (assignedUser as? IMSUser != null) listOf(assignedUser) else if (assignedUser as? GropiusUser != null) assignedUser.imsUsers()
.filter { it.ims().value == imsProject.ims().value } else emptyList()
val ids = imsUsers.map {
githubDataService.objectMapper.readTree(it.templatedFields["github_node_id"]!!).textValue()
}
if (ids.isEmpty()) {
return null
}
val response = githubDataService.mutation(
imsProject, users, MutateUnassignUserMutation(issueId, ids.first()), gropiusUserList(users)
).second
val item =
response.data?.removeAssigneesFromAssignable?.assignable?.asIssue()?.timelineItems?.nodes?.lastOrNull()
?.asNode()
if (item != null) {
return TODOTimelineItemConversionInformation(imsProject.rawId!!, item.id)
}
logger.error("${response.data} ${response.errors}")
//TODO("ERROR HANDLING")
return null
}

override suspend fun syncFallbackComment(
imsProject: IMSProject, issueId: String, comment: String, original: TimelineItem?, users: List<User>
): TimelineItemConversionInformation? {
val response = githubDataService.mutation(
imsProject, users, MutateCreateCommentMutation(issueId, comment), gropiusUserList(users)
).second
val item = response.data?.addComment?.commentEdge?.node?.asIssueTimelineItems()
if (item != null) {
return TODOTimelineItemConversionInformation(imsProject.rawId!!, item.id)
}
logger.error("${response.data} ${response.errors}")
//TODO("ERROR HANDLING")
return null
}

override suspend fun syncAddedLabel(
imsProject: IMSProject, issueId: String, label: Label, users: List<User>
): TimelineItemConversionInformation? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ class UnassignedTimelineItem(
gropiusId
) else RemovedAssignmentEvent(createdAt, createdAt)
val opposite = issue.timelineItems().filterIsInstance<Assignment>().sortedBy { it.createdAt }
.lastOrNull { it.user().value.username == user }
.lastOrNull { it.user().value.username == user } // TODO: Catch multiple
if ((event == null) || (opposite == null)) {
return listOf<TimelineItem>() to convInfo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ class IMSConfigManager(
"github_id" to obj {
"nullable" to true
"type" to "int32"
}.toString(),
"github_node_id" to obj {
"nullable" to true
"type" to "string"
}.toString()
)
}
Expand Down
28 changes: 20 additions & 8 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 @@ -108,11 +111,16 @@ class JiraDataService(
/**
* Find and ensure the IMSIssueTemplate in the database
* @param imsProject The IMSProject to work with
* @param name name of the type to look for, if known
* @return the IssueType
*/
suspend fun issueType(imsProject: IMSProject): IssueType {
suspend fun issueType(imsProject: IMSProject, name: String): IssueType {
val template = issueTemplate(imsProject)
val imsProjectConfig = IMSProjectConfig(helper, imsProject)
val namedType = template.issueTypes().firstOrNull { it.name == name }
if (namedType != null) {
return namedType
}
if (imsProjectConfig.defaultType != null) {
val type = neoOperations.findById<IssueType>(imsProjectConfig.defaultType)
if ((type != null) && (type.partOf().contains(template))) {
Expand Down Expand Up @@ -269,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 @@ -289,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 @@ -319,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
Loading

0 comments on commit 80f2f32

Please sign in to comment.