Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TeamCity CI config files #203

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .teamcity/asteroid/AsteroidProject.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package asteroid

import asteroid.devices.DevicesProject
import asteroid.packages.PackagesProject
import asteroid.thirdparty.ThirdPartyProject
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
import jetbrains.buildServer.configs.kotlin.v2019_2.projectFeatures.activeStorage

object AsteroidProject : Project({
description = "Base Asteroid Project"

// Attach vcsRoots from CoreVCS
for (vcs in CoreVCS.allVcs)
vcsRoot(vcs)

// TODO: Remove when have common base
vcsRoot(DevicesProject.vcs)

// Attach InitWorkspace build
buildType(InitWorkspace)

// Attach the subProjects
// TODO: Link to subprojects externally
subProjects(
DevicesProject,
PackagesProject,
ThirdPartyProject
)

// Define the build parameters inherited by the subprojects
params {
text(
"system.sstate.server.address",
Settings.sstateServer.url,
label = "SState server public address",
description = "Public address serving sstate-cache",
readOnly = true,
allowEmpty = false
)
if (Settings.deploySstate) {
text(
"system.sstate.server.location",
Settings.sstateServer.location,
label = "Sstate server location",
description = "Path location of the sstate-cache",
readOnly = true, allowEmpty = true
)
text(
"system.sstate.server.user",
Settings.sstateServer.user,
label = "SState server user",
description = "Username used to upload sstate-cache",
readOnly = true, allowEmpty = true
)
text(
"system.sstate.server.upload_address",
Settings.sstateServer.backendUrl,
label = "SState server backend address",
description = "Backend address to upload the sstate-cache",
readOnly = true, allowEmpty = false
)
}
}
features {
activeStorage {
activeStorageID = "DefaultStorage"
}
}
})
147 changes: 147 additions & 0 deletions .teamcity/asteroid/CoreVCS.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package asteroid

import asteroid.devices.DevicesProject
import asteroid.packages.CommunityAppsProject
import com.github.kittinunf.fuel.Fuel
import jetbrains.buildServer.configs.kotlin.v2019_2.VcsSettings
import jetbrains.buildServer.configs.kotlin.v2019_2.vcs.GitVcsRoot
import org.json.JSONObject

object CoreVCS : CoreVCSDefault() {
init {
// Override default values with thise in overrides.json
val json = Settings.overrides?.optJSONObject("coreVCS")
val vcsList = allVcs.toMutableList()
vcsList.add(DevicesProject.vcs)
vcsList.add(CommunityAppsProject.vcs)
if (json != null)
for (vcs in vcsList) {
val json2 = json.optJSONObject(vcs.name)
if (json2 != null)
checkVcsOverride(vcs,json2)
}
}
}

fun checkVcsOverride(vcs: GitVcsRoot, json: JSONObject) {
val branchRegex = "\\((.*?)\\)".toRegex()
val branch = json.optString("branch", branchRegex.find(vcs.branch!!)!!.value)
val url = json.optString("url", vcs.url)
vcs.branch = "refs/heads/($branch)"
vcs.url = url
}

open class CoreVCSDefault {
val Asteroid: GitVcsRoot
val OpenEmbeddedCore: GitVcsRoot
val Bitbake: GitVcsRoot
val MetaOpenEmbedded: GitVcsRoot
val MetaQt5: GitVcsRoot
val MetaSmartphone: GitVcsRoot
val MetaAsteroid: GitVcsRoot

fun attachVCS(init: VcsSettings, forDevice: Boolean = false) {
init.root(OpenEmbeddedCore, "+:.=>src/oe-core")
init.root(Bitbake, "+:.=>src/oe-core/bitbake")
init.root(MetaOpenEmbedded, "+:.=>src/meta-openembedded")
init.root(MetaQt5, "+:.=>src/meta-qt5")
init.root(MetaSmartphone, "+:.=>src/meta-smartphone")
init.root(MetaAsteroid, "+:.=>src/meta-asteroid")
if (forDevice)
init.root(DevicesProject.vcs, "+:.=>src/meta-smartwatch")

init.cleanCheckout = true
}

init {
Asteroid = GitVcsRoot_fallback {
id("AsteroidVCS")
name = "Asteroid"
gitBase = "https://github.com/"
url = "${Settings.fork}/asteroid.git"
fallback_url = "${Settings.upstream}/asteroid.git"
branch = "refs/heads/(master)"
}
OpenEmbeddedCore = GitVcsRoot {
id("OpenEmbeddedVCS")
name = "OpenEmbedded Core"
url = "https://github.com/openembedded/openembedded-core.git"
branch = "refs/heads/(honister)"
}
Bitbake = GitVcsRoot {
id("BitBakeVCS")
name = "Bitbake"
url = "https://github.com/openembedded/bitbake.git"
branch = "refs/heads/(1.52)"
}
MetaOpenEmbedded = GitVcsRoot {
id("MetaOpenEmbeddedVCS")
name = "Meta OpenEmbedded"
url = "https://github.com/openembedded/meta-openembedded.git"
branch = "refs/heads/(honister)"
}
MetaQt5 = GitVcsRoot {
id("MetaQt5VCS")
name = "Meta Qt5"
url = "https://github.com/meta-qt5/meta-qt5"
branch = "refs/heads/(master)"
}
MetaSmartphone = GitVcsRoot {
id("MetaSmartphoneVCS")
name = "Meta Smartphone"
url = "https://github.com/shr-distribution/meta-smartphone"
branch = "refs/heads/(honister)"
}
MetaAsteroid = GitVcsRoot_fallback {
id("MetaAsteroidVCS")
name = "Meta Asteroid"
gitBase = "https://github.com/"
url = "${Settings.fork}/meta-asteroid"
fallback_url = "${Settings.upstream}/meta-asteroid"
branch = "refs/heads/(master)"
}
}
val allVcs = listOf<GitVcsRoot>(
Asteroid,
OpenEmbeddedCore,
Bitbake,
MetaOpenEmbedded,
MetaQt5,
MetaSmartphone,
MetaAsteroid
)
}

class GitVcsRoot_fallback(init: GitVcsRoot_fallback.() -> Unit) : GitVcsRoot() {
var gitBase: String? = null
var fallback_url: String? = null

init {
init.invoke(this)
val json = Settings.overrides?.optJSONObject("coreVCS")?.optJSONObject(name)
if (json != null){
checkVcsOverride(this,json)
} else {
if (!gitBase.isNullOrEmpty()) {
url = gitBase + url
if (!fallback_url.isNullOrEmpty())
fallback_url = gitBase + fallback_url
}
if (!fallback_url.isNullOrEmpty()) {
if (Settings.canHttp) {
var testURL: String = url ?: ""
var code = Fuel.get(testURL).response().second.statusCode
if (code == 404) {
testURL = fallback_url ?: ""
code = Fuel.get(testURL).response().second.statusCode
}
if (code != 200) {
// TODO: Resolve other excetions
}
url = testURL
} else
url = fallback_url
}
}
}
}
134 changes: 134 additions & 0 deletions .teamcity/asteroid/GitAPIChecker.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package asteroid

import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.core.Headers
import com.github.kittinunf.fuel.core.extensions.jsonBody
import com.github.kittinunf.fuel.json.responseJson

enum class GitRepoHubType {
Github
}

interface GitAPIChecker {
val repo: String
val token: String
val hubType: GitRepoHubType
val commitUser: String
fun checkCommitStatus(): Boolean
fun checkPR(): Boolean
fun checkToken(): Boolean

companion object {
fun Create(repo: String, token: String): GitAPIChecker? {
with(repo) {
when {
contains("https://github.com") -> return GithubAPIChecker(repo, token)
else -> return null
}
}
}
}
}

class GithubAPIChecker(override val repo: String, override val token: String) : GitAPIChecker {
override val hubType = GitRepoHubType.Github
override val commitUser = Settings.commitUser
val repoAPIBase = repo.removeSuffix(".git")
.replace("https://github.com", "https://api.github.com/repos")

override fun checkToken(): Boolean {
// Cannot check if sandboxing is enabled or the token is not plain-text
if (!Settings.canHttp || token.startsWith("credentialsJSON:"))
return false
val request = Fuel.get("https://api.github.com")
.appendHeader(Headers.AUTHORIZATION, "token $token")
return when (request.response().second.statusCode) {
401 -> false
200 -> true
else -> {
// TODO: Add warning
false
}
}
}

override fun checkCommitStatus(): Boolean {
// Cannot check if sandboxing is enabled or the token is not plain-text
if (!Settings.canHttp || token.startsWith("credentialsJSON:"))
return true
// If token is invalid throw warning
if (!checkToken()) {
// TODO: add warning
return false
}

var request = Fuel.get("$repoAPIBase/commits/HEAD/status")
.appendHeader(Headers.AUTHORIZATION, "token $token")
var response = request.responseJson()
when (response.second.statusCode) {
// Token cannot access private repo
404 -> return false
// Token does not have repo:status:read access to the repo
403 -> return false
// Token has at least repo:status:read access to the repo
200 -> {}
else -> {
// Unknown states
// TODO: Add warning
return false
}
}
val sha = response.third.component1()!!.obj()["sha"].toString()
request = Fuel.post("$repoAPIBase/commits/$sha/statuses")
.appendHeader(Headers.AUTHORIZATION, "token $token")
.jsonBody(
"""
{
"context": "test-connection",
"state": "dummy"
}
""".trimIndent()
)
response = request.responseJson()
return when (response.second.statusCode) {
// Token does not have repo:status:write access to the repo
403 -> false
// Token has repo:status:write access but we made ill-formed content
422 -> true
// Created status. This should not have occured
201 -> {
// TODO: Add warning
true
}
// Unknown
else -> false
}
}

override fun checkPR(): Boolean {
// Cannot check if sandboxing is enabled or the token is not plain-text
if (!Settings.canHttp || token.startsWith("credentialsJSON:"))
return true
// If token is invalid throw warning
if (!checkToken()) {
// TODO: add warning
return false
}

val request = Fuel.get("$repoAPIBase/pulls")
.appendHeader(Headers.AUTHORIZATION, "token $token")
return when (request.response().second.statusCode) {
// Token cannot access private repo
404 -> false
// Token does not have repo:status:read access to the repo
403 -> false
// Token has at least repo:status:read access to the repo
200 -> true
else -> {
// Unknown states
// TODO: Add warning
false
}
}
}
}
Loading