refactor [gitlab]: show label colors in label chooser

GitOrigin-RevId: 29e5d600478c87e4db6c1b3c52beae485b7a7dad
This commit is contained in:
Ivan Semenov
2026-02-13 14:11:18 +00:00
committed by intellij-monorepo-bot
parent c4cf4f8449
commit ac0ccd89c4
18 changed files with 122 additions and 105 deletions
@@ -17,7 +17,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -17,7 +17,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -16,7 +16,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -17,7 +17,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -16,7 +16,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -16,7 +16,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -1,4 +1,5 @@
fragment label on Label {
title
description
color
}
@@ -15,7 +15,7 @@ fragment mergeRequest on MergeRequest {
}
nodes {
title
...label
}
}
@@ -2,10 +2,12 @@
package org.jetbrains.plugins.gitlab.api.dto
import com.intellij.collaboration.api.dto.GraphQLFragment
import com.intellij.openapi.util.NlsSafe
import org.jetbrains.plugins.gitlab.api.SinceGitLab
@SinceGitLab("12.0")
@GraphQLFragment("/graphql/fragment/label.graphql")
data class GitLabLabelDTO(
val title: String
data class GitLabLabelGQLDTO(
val title: @NlsSafe String,
val color: String,
)
@@ -20,9 +20,8 @@ import org.jetbrains.plugins.gitlab.api.GitLabProjectCoordinates
import org.jetbrains.plugins.gitlab.api.GitLabServerMetadata
import org.jetbrains.plugins.gitlab.api.GitLabVersion
import org.jetbrains.plugins.gitlab.api.SinceGitLab
import org.jetbrains.plugins.gitlab.api.dto.GitLabGraphQLMutationResultDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabGroupDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelGQLDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabNamespaceDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabNamespaceRestDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabProjectDTO
@@ -37,7 +36,6 @@ import org.jetbrains.plugins.gitlab.api.gitLabQuery
import org.jetbrains.plugins.gitlab.api.restApiUri
import org.jetbrains.plugins.gitlab.api.withErrorStats
import org.jetbrains.plugins.gitlab.api.withQuery
import org.jetbrains.plugins.gitlab.mergerequest.api.dto.GitLabMergeRequestDTO
import org.jetbrains.plugins.gitlab.util.GitLabApiRequestName
import java.net.URI
import java.net.http.HttpRequest.BodyPublishers
@@ -102,7 +100,7 @@ suspend fun GitLabApi.isProjectForked(project: GitLabProjectCoordinates): Boolea
@SinceGitLab("13.1", note = "No exact version")
fun GitLabApi.GraphQL.createAllProjectLabelsFlow(project: GitLabProjectCoordinates): Flow<List<GitLabLabelDTO>> =
fun GitLabApi.GraphQL.createAllProjectLabelsFlow(project: GitLabProjectCoordinates): Flow<List<GitLabLabelGQLDTO>> =
ApiPageUtil.createGQLPagesFlow { page ->
val parameters = page.asParameters() + mapOf(
"fullPath" to project.projectPath.fullPath()
@@ -188,8 +186,8 @@ private data class GitLabUserNamespacesResult(
data class CurrentUser(val namespace: GitLabNamespaceDTO)
}
private class LabelConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List<GitLabLabelDTO>)
: GraphQLConnectionDTO<GitLabLabelDTO>(pageInfo, nodes)
private class LabelConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List<GitLabLabelGQLDTO>)
: GraphQLConnectionDTO<GitLabLabelGQLDTO>(pageInfo, nodes)
private class WorkItemConnection(pageInfo: GraphQLCursorPageInfoDTO, nodes: List<GitLabWorkItemDTO>)
: GraphQLConnectionDTO<GitLabWorkItemDTO>(pageInfo, nodes)
@@ -8,7 +8,7 @@ import org.jetbrains.plugins.gitlab.api.GitLabEdition
import org.jetbrains.plugins.gitlab.api.SinceGitLab
import org.jetbrains.plugins.gitlab.api.dto.GitLabCommitDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabDiffRefs
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelGQLDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabMergeRequestPermissionsDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabPipelineDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabProjectDTO
@@ -60,7 +60,7 @@ class GitLabMergeRequestDTO(
@SinceGitLab("14.7")
val commits: List<GitLabCommitDTO>? = commits?.nodes
val labels: List<GitLabLabelDTO> = labels.nodes
val labels: List<GitLabLabelGQLDTO> = labels.nodes
@SinceGitLab("13.5")
class UserCoreConnection(
@@ -89,6 +89,6 @@ class GitLabMergeRequestDTO(
@SinceGitLab("12.4")
class LabelConnection(
pageInfo: GraphQLCursorPageInfoDTO,
nodes: List<GitLabLabelDTO>
) : GraphQLConnectionDTO<GitLabLabelDTO>(pageInfo, nodes)
nodes: List<GitLabLabelGQLDTO>
) : GraphQLConnectionDTO<GitLabLabelGQLDTO>(pageInfo, nodes)
}
@@ -0,0 +1,20 @@
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gitlab.mergerequest.data
class GitLabLabel(
val title: String,
val colorHex: String,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is GitLabLabel) return false
if (title != other.title) return false
return true
}
override fun hashCode(): Int {
return title.hashCode()
}
}
@@ -9,7 +9,7 @@ import git4idea.remote.hosting.HostedGitRepositoryRemote
import git4idea.repo.GitRemote
import org.jetbrains.plugins.gitlab.api.GitLabServerPath
import org.jetbrains.plugins.gitlab.api.dto.GitLabDiffRefs
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelGQLDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabMergeRequestPermissionsDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabPipelineDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabProjectDTO
@@ -19,35 +19,35 @@ import org.jetbrains.plugins.gitlab.mergerequest.api.dto.GitLabMergeRequestDTO
import java.util.Date
data class GitLabMergeRequestFullDetails(
val iid: String,
val title: @NlsSafe String,
val createdAt: Date,
val author: GitLabUserDTO,
val mergeStatus: GitLabMergeStatus,
val isMergeable: Boolean,
val state: GitLabMergeRequestState,
val draft: Boolean,
val assignees: List<GitLabUserDTO>,
val reviewers: List<GitLabReviewerDTO>,
val webUrl: @NlsSafe String,
val detailedLabels: List<GitLabLabelDTO>,
val targetProject: GitLabProjectDTO,
val sourceProject: GitLabProjectDTO?,
val description: String,
val approvedBy: List<GitLabUserDTO>,
val targetBranch: String,
val sourceBranch: String,
val approvalsRequired: Int,
val conflicts: Boolean,
val onlyAllowMergeIfAllDiscussionsAreResolved: Boolean,
val onlyAllowMergeIfPipelineSucceeds: Boolean,
val allowMergeOnSkippedPipeline: Boolean,
val diffRefs: GitLabDiffRefs?,
val headPipeline: GitLabPipelineDTO?,
val userPermissions: GitLabMergeRequestPermissionsDTO,
val shouldRemoveSourceBranch: Boolean?,
val shouldBeRebased: Boolean,
val rebaseInProgress: Boolean
val iid: String,
val title: @NlsSafe String,
val createdAt: Date,
val author: GitLabUserDTO,
val mergeStatus: GitLabMergeStatus,
val isMergeable: Boolean,
val state: GitLabMergeRequestState,
val draft: Boolean,
val assignees: List<GitLabUserDTO>,
val reviewers: List<GitLabReviewerDTO>,
val webUrl: @NlsSafe String,
val detailedLabels: List<GitLabLabelGQLDTO>,
val targetProject: GitLabProjectDTO,
val sourceProject: GitLabProjectDTO?,
val description: String,
val approvedBy: List<GitLabUserDTO>,
val targetBranch: String,
val sourceBranch: String,
val approvalsRequired: Int,
val conflicts: Boolean,
val onlyAllowMergeIfAllDiscussionsAreResolved: Boolean,
val onlyAllowMergeIfPipelineSucceeds: Boolean,
val allowMergeOnSkippedPipeline: Boolean,
val diffRefs: GitLabDiffRefs?,
val headPipeline: GitLabPipelineDTO?,
val userPermissions: GitLabMergeRequestPermissionsDTO,
val shouldRemoveSourceBranch: Boolean?,
val shouldBeRebased: Boolean,
val rebaseInProgress: Boolean
) {
companion object {
@@ -14,18 +14,13 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.transformWhile
import org.jetbrains.plugins.gitlab.api.GitLabApi
import org.jetbrains.plugins.gitlab.api.GitLabGidData
@@ -35,12 +30,10 @@ import org.jetbrains.plugins.gitlab.api.GitLabProjectCoordinates
import org.jetbrains.plugins.gitlab.api.GitLabServerMetadata
import org.jetbrains.plugins.gitlab.api.GitLabVersion
import org.jetbrains.plugins.gitlab.api.data.GitLabPlan
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabProjectDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabWorkItemDTO.GitLabWidgetDTO.WorkItemWidgetAssignees
import org.jetbrains.plugins.gitlab.api.dto.GitLabWorkItemDTO.WorkItemType
import org.jetbrains.plugins.gitlab.api.getResultOrThrow
import org.jetbrains.plugins.gitlab.api.request.createAllProjectLabelsFlow
import org.jetbrains.plugins.gitlab.api.request.createAllWorkItemsFlow
import org.jetbrains.plugins.gitlab.api.request.getProjectNamespace
@@ -72,7 +65,7 @@ interface GitLabProject {
suspend fun getEmojis(): List<GitLabReaction>
fun getLabelsBatches(): Flow<List<GitLabLabelDTO>>
fun getLabelsBatches(): Flow<List<GitLabLabel>>
fun getMembersBatches(): Flow<List<GitLabUserDTO>>
val defaultBranch: String?
@@ -135,7 +128,12 @@ class GitLabLazyProject(
CachingGitLabProjectMergeRequestsStore(project, cs, api, glMetadata, projectMapping, currentUser, tokenRefreshFlow)
}
private val labelsLoader = BatchesLoader(cs, api.graphQL.createAllProjectLabelsFlow(projectMapping.repository))
private val labelsLoader = BatchesLoader(cs,
api.graphQL.createAllProjectLabelsFlow(projectMapping.repository).map { labels ->
labels.map {
GitLabLabel(it.title, it.color)
}
})
private val membersLoader = BatchesLoader(cs,
ApiPageUtil.createPagesFlowByLinkHeader(getProjectUsersURI(projectMapping.repository)) {
api.rest.getProjectUsers(it)
@@ -144,7 +142,7 @@ class GitLabLazyProject(
override suspend fun getEmojis(): List<GitLabReaction> = emojisRequest.await()
override val defaultBranch: String? = initialData.repository?.rootRef
override suspend fun isMultipleReviewersAllowed(): Boolean = multipleReviewersAllowedRequest.await()
override fun getLabelsBatches(): Flow<List<GitLabLabelDTO>> = labelsLoader.getBatches()
override fun getLabelsBatches(): Flow<List<GitLabLabel>> = labelsLoader.getBatches()
override fun getMembersBatches(): Flow<List<GitLabUserDTO>> = membersLoader.getBatches()
private suspend fun loadMultipleReviewersAllowed(project: GitLabProjectDTO): Boolean {
@@ -1,7 +1,6 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gitlab.mergerequest.ui.filters
import com.intellij.collaboration.ui.codereview.avatar.Avatar
import com.intellij.collaboration.ui.codereview.list.error.ErrorStatusPresenter
import com.intellij.collaboration.ui.codereview.list.search.ChooserPopupUtil
import com.intellij.collaboration.ui.codereview.list.search.DropDownComponentFactory
@@ -13,7 +12,6 @@ import com.intellij.ui.awt.RelativePoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
import org.jetbrains.annotations.Nls
import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO
import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.LabelFilterValue
@@ -22,6 +20,7 @@ import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsF
import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.MergeRequestsMemberFilterValue.MergeRequestsAssigneeFilterValue
import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.MergeRequestsMemberFilterValue.MergeRequestsAuthorFilterValue
import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.MergeRequestsMemberFilterValue.MergeRequestsReviewerFilterValue
import org.jetbrains.plugins.gitlab.mergerequest.util.GitLabMergeRequestChoosersUtil
import org.jetbrains.plugins.gitlab.util.GitLabBundle
import javax.swing.JComponent
@@ -94,11 +93,13 @@ internal class GitLabFiltersPanelFactory(
filterName = GitLabBundle.message("merge.request.list.filter.category.label"),
valuePresenter = { labelFilterValue -> labelFilterValue.title },
chooseValue = { point ->
ChooserPopupUtil.showAsyncChooserPopup<LabelFilterValue>(
ChooserPopupUtil.showAsyncChooserPopup(
point,
itemsLoader = vm.labels.mapResultList { label -> LabelFilterValue(label.title) },
presenter = { labelFilterValue -> PopupItemPresentation.Simple(shortText = labelFilterValue.title) }
)
itemsLoader = vm.labels,
presenter = GitLabMergeRequestChoosersUtil.getLabelPresenter()
)?.let {
LabelFilterValue(it.title)
}
}
)
@@ -121,13 +122,7 @@ internal class GitLabFiltersPanelFactory(
participantsLoader: Flow<Result<List<GitLabUserDTO>>>
): GitLabUserDTO? = ChooserPopupUtil.showAsyncChooserPopup(
point, itemsLoader = participantsLoader,
presenter = { user ->
PopupItemPresentation.Simple(
user.username,
vm.avatarIconsProvider.getIcon(user, Avatar.Sizes.BASE),
user.name
)
},
presenter = GitLabMergeRequestChoosersUtil.getUserPresenter(vm.avatarIconsProvider),
popupConfig = PopupConfig(errorPresenter = ErrorStatusPresenter.simple(
GitLabBundle.message("merge.request.list.filter.error"),
descriptionProvider = { null },
@@ -146,15 +141,4 @@ internal class GitLabFiltersPanelFactory(
MergeRequestStateFilterValue.CLOSED -> GitLabBundle.message("merge.request.list.filter.state.closed")
}
}
}
private fun <T, R> Flow<Result<List<T>>>.mapResultList(mapper: (T) -> R): Flow<Result<List<R>>> {
val flow = this
return flow.map { result: Result<List<T>> ->
result.map { list: List<T> ->
list.map { item: T ->
mapper(item)
}
}
}
}
@@ -13,8 +13,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.drop
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO
import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabLabel
import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabProject
import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.MergeRequestStateFilterValue
import org.jetbrains.plugins.gitlab.mergerequest.ui.filters.GitLabMergeRequestsFiltersValue.MergeRequestsMemberFilterValue
@@ -33,7 +33,7 @@ interface GitLabMergeRequestsFiltersViewModel : ReviewListSearchPanelViewModel<G
val labelFilterState: MutableStateFlow<GitLabMergeRequestsFiltersValue.LabelFilterValue?>
val mergeRequestMembers: Flow<Result<List<GitLabUserDTO>>>
val labels: Flow<Result<List<GitLabLabelDTO>>>
val labels: Flow<Result<List<GitLabLabel>>>
fun reloadData()
}
@@ -87,7 +87,7 @@ internal class GitLabMergeRequestsFiltersViewModelImpl(
override val mergeRequestMembers: Flow<Result<List<GitLabUserDTO>>> =
GitLabCoroutineUtil.batchesResultsFlow(projectData.dataReloadSignal, projectData::getMembersBatches)
override val labels: Flow<Result<List<GitLabLabelDTO>>> =
override val labels: Flow<Result<List<GitLabLabel>>> =
GitLabCoroutineUtil.batchesResultsFlow(projectData.dataReloadSignal, projectData::getLabelsBatches)
override fun reloadData() {
@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gitlab.mergerequest.util
import com.intellij.collaboration.ui.CollaborationToolsUIUtil
import com.intellij.collaboration.ui.codereview.avatar.Avatar
import com.intellij.collaboration.ui.codereview.list.search.ChooserPopupUtil
import com.intellij.collaboration.ui.codereview.list.search.PopupConfig
@@ -9,8 +10,10 @@ import com.intellij.collaboration.ui.icon.IconsProvider
import com.intellij.collaboration.ui.util.popup.PopupItemPresentation
import com.intellij.collaboration.util.IncrementallyComputedValue
import com.intellij.ui.awt.RelativePoint
import com.intellij.util.ui.ColorIcon
import kotlinx.coroutines.flow.StateFlow
import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO
import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabLabel
internal object GitLabMergeRequestChoosersUtil {
suspend fun chooseUser(
@@ -22,13 +25,7 @@ internal object GitLabMergeRequestChoosersUtil {
ChooserPopupUtil.showChooserPopupWithIncrementalLoading(
point,
users,
presenter = { reviewer ->
PopupItemPresentation.Simple(
reviewer.username,
avatarIconsProvider.getIcon(reviewer, Avatar.Sizes.BASE),
reviewer.name,
)
},
getUserPresenter(avatarIconsProvider),
PopupConfig.DEFAULT.copy(showDirection = showDirection)
)
@@ -43,13 +40,30 @@ internal object GitLabMergeRequestChoosersUtil {
point,
choseUsers,
users,
presenter = { reviewer ->
PopupItemPresentation.Simple(
reviewer.username,
avatarIconsProvider.getIcon(reviewer, Avatar.Sizes.BASE),
reviewer.name,
)
},
getUserPresenter(avatarIconsProvider),
PopupConfig.DEFAULT.copy(showDirection = showDirection)
)
fun getUserPresenter(avatarIconsProvider: IconsProvider<GitLabUserDTO>): (GitLabUserDTO) -> PopupItemPresentation {
return {
PopupItemPresentation.Simple(
it.username,
avatarIconsProvider.getIcon(it, Avatar.Sizes.BASE),
it.name,
)
}
}
fun getLabelPresenter(): (GitLabLabel) -> PopupItemPresentation {
return {
val icon = runCatching {
val color = CollaborationToolsUIUtil.getLabelBackground(it.colorHex)
ColorIcon(16, color)
}
PopupItemPresentation.Simple(
it.title,
icon.getOrNull(),
)
}
}
}
@@ -14,7 +14,7 @@ import org.jetbrains.plugins.gitlab.api.GitLabServerMetadata
import org.jetbrains.plugins.gitlab.api.GitLabServerPath
import org.jetbrains.plugins.gitlab.api.GitLabVersion
import org.jetbrains.plugins.gitlab.api.dto.GitLabGraphQLMutationResultDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelDTO
import org.jetbrains.plugins.gitlab.api.dto.GitLabLabelGQLDTO
import org.jetbrains.plugins.gitlab.apitests.GitLabApiTestCase.Companion.IDEA_TEST_GITLAB_API_DATA_PATH
import org.jetbrains.plugins.gitlab.apitests.GitLabApiTestCase.Companion.IDEA_TEST_GITLAB_API_EDITION
import org.jetbrains.plugins.gitlab.apitests.GitLabApiTestCase.Companion.IDEA_TEST_GITLAB_API_TOKEN
@@ -61,13 +61,13 @@ abstract class GitLabApiTestCase {
class GitLabDataConstants {
val rootUsername = "root"
val testsGroupLabel1 = GitLabLabelDTO("grouplabel1")
val testsGroupLabel2 = GitLabLabelDTO("grouplabel2")
val testsGroupLabel1 = GitLabLabelGQLDTO("grouplabel1", "#FFFFFF")
val testsGroupLabel2 = GitLabLabelGQLDTO("grouplabel2", "#FFFFFF")
val glTests2Project = GitLabProjectPath("tests", "gl-tests-2")
val glTests2Coordinates = GitLabProjectCoordinates(server, glTests2Project)
val glTests2Label1 = GitLabLabelDTO("label1")
val glTests2Label2 = GitLabLabelDTO("label2")
val glTests2Label1 = GitLabLabelGQLDTO("label1", "#FFFFFF")
val glTests2Label2 = GitLabLabelGQLDTO("label2", "#FFFFFF")
val glTest1Project = GitLabProjectPath("root", "gl-test-1")
val glTest1Coordinates = GitLabProjectCoordinates(server, glTest1Project)