All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.octopusden.octopus.infrastructure.gitlab.test.GitlabTestClient.kt Maven / Gradle / Ivy

package org.octopusden.octopus.infrastructure.gitlab.test

import org.gitlab4j.api.GitLabApi
import org.gitlab4j.api.GitLabApiException
import org.gitlab4j.api.models.Group
import org.gitlab4j.api.models.GroupParams
import org.octopusden.octopus.infrastructure.common.test.BaseTestClient
import org.slf4j.LoggerFactory
import java.util.Date
import java.util.concurrent.TimeUnit

class GitlabTestClient(val url: String, username: String, password: String) : BaseTestClient(username, password) {
    private val client = GitLabApi.oauth2Login(url, username, password)
    override fun getLog() = log

    override fun checkActive() {
        client.version
    }

    override fun convertSshToHttp(vcsUrl: String): String = "$url/${vcsUrl.substring(vcsUrl.lastIndexOf(":") + 1)}"

    override fun parseUrl(url: String): ProjectRepo {
        val projectRepoArray = url.substring(url.lastIndexOf(":") + 1, url.indexOf(".git"))
            .split("/")
        if (projectRepoArray.size != 2) {
            throw IllegalArgumentException("Repository '$url' is not a Gitlab repo, current url: '${this.url}'")
        }
        return ProjectRepo(projectRepoArray[0], projectRepoArray[1])
    }

    private fun createProjectIfNotExist(project: String): Group {
        val groupParams = GroupParams()
        groupParams.withPath(project)
        groupParams.withName(project)
        return retryableExecution {
            client.groupApi.getGroups(project).firstOrNull { g -> g.path == project }
                ?: client.groupApi.createGroup(groupParams)
        }
    }

    override fun createRepository(projectRepo: ProjectRepo) {
        if (existRepository(projectRepo)) {
            log.error("Repository ${projectRepo.path} exists (previous test(s) probably crashed)")
            deleteRepository(projectRepo)
        }

        val group = createProjectIfNotExist(projectRepo.project)
        retryableExecution {
            client.projectApi.createProject(group.id, projectRepo.repository)
        }
    }

    override fun deleteRepository(projectRepo: ProjectRepo) {
        log.info("Delete ${projectRepo.path}")
        if (existRepository(projectRepo)) {
            try {
                val projectId = moveProjectForDelete(projectRepo)
                retryableExecution { client.projectApi.deleteProject(projectId) }
            } catch (e: GitLabApiException) {
                log.error(e.message)
            }
        }
    }

    override fun checkCommit(projectRepo: ProjectRepo, sha: String) {
        client.commitsApi.getCommits(projectRepo.path, sha, null, null)
    }

    private fun moveProjectForDelete(projectRepo: ProjectRepo): Long {
        val project = retryableExecution { client.projectApi.getProject(projectRepo.path) }

        val time = Date().time
        project.name = "${project.name}-$time"
        project.path = "${project.path}-$time"
        project.withDefaultBranch(null)

        retryableExecution { client.projectApi.updateProject(project) }

        while (existRepository(projectRepo)) {
            log.warn("Wait when ${projectRepo.path} will be moved for delete")
            TimeUnit.SECONDS.sleep(1)
        }

        return project.id
    }

    private fun existRepository(projectRepo: ProjectRepo): Boolean {
        return try {
            retryableExecution {
                client.projectApi.getProject(projectRepo.path) != null
            }
        } catch (e: GitLabApiException) {
            false
        }
    }

    private fun  retryableExecution(
        attemptLimit: Int = 3,
        attemptIntervalSec: Long = 3,
        skipRetryOnCode: Int = 404,
        func: () -> T
    ): T {
        lateinit var latestException: Exception
        for (attempt in 1..attemptLimit) {
            try {
                return func()
            } catch (e: GitLabApiException) {
                if (e.httpStatus == skipRetryOnCode) {
                    throw e
                }
                getLog().warn("${e.message}, attempt=$attempt:$attemptLimit, retry in $attemptIntervalSec sec")
                latestException = e
                TimeUnit.SECONDS.sleep(attemptIntervalSec)
            }
        }
        throw latestException
    }

    companion object {
        private val log = LoggerFactory.getLogger(GitlabTestClient::class.java)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy