![JAR search and dependency download from the Maven repository](/logo.png)
com.jetbrains.plugin.structure.teamcity.action.TeamCityActionPluginManager.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of structure-teamcity-actions Show documentation
Show all versions of structure-teamcity-actions Show documentation
Library for parsing JetBrains TeamCity actions. Can be used to verify that plugin complies with JetBrains Marketplace requirements.
The newest version!
package com.jetbrains.plugin.structure.teamcity.action
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.jetbrains.plugin.structure.base.decompress.DecompressorSizeLimitExceededException
import com.jetbrains.plugin.structure.base.plugin.*
import com.jetbrains.plugin.structure.base.plugin.Settings.EXTRACT_DIRECTORY
import com.jetbrains.plugin.structure.base.problems.*
import com.jetbrains.plugin.structure.base.utils.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.file.Files
import java.nio.file.Files.createTempDirectory
import java.nio.file.Path
import java.nio.file.Paths
class TeamCityActionPluginManager
private constructor(private val extractDirectory: Path) : PluginManager {
private val objectMapper = ObjectMapper(YAMLFactory()).registerKotlinModule()
companion object {
private val LOG: Logger = LoggerFactory.getLogger(TeamCityActionPluginManager::class.java)
fun createManager(extractDirectory: Path = Paths.get(EXTRACT_DIRECTORY.get())) =
TeamCityActionPluginManager(extractDirectory.createDir())
}
override fun createPlugin(pluginFile: Path): PluginCreationResult {
require(pluginFile.exists()) { "TeamCity Action file ${pluginFile.toAbsolutePath()} does not exist" }
return when {
pluginFile.isZip() || pluginFile.isYaml() -> createPluginFrom(pluginFile)
else -> fileFormatError(pluginFile)
}
}
private fun createPluginFrom(actionPath: Path): PluginCreationResult {
val sizeLimit = Settings.TEAM_CITY_ACTION_SIZE_LIMIT.getAsLong()
if (Files.size(actionPath) > sizeLimit) {
return PluginCreationFail(FileTooBig(actionPath.simpleName, sizeLimit))
}
return when {
actionPath.isZip() -> extractActionFromZip(actionPath, sizeLimit)
actionPath.isYaml() -> parseYaml(actionPath)
else -> fileFormatError(actionPath)
}
}
private fun extractActionFromZip(zipPath: Path, sizeLimit: Long): PluginCreationResult {
val tempDirectory = createTempDirectory(extractDirectory, "teamcity_action_extracted_${zipPath.simpleName}_")
return try {
extractZip(zipPath, tempDirectory, sizeLimit)
val yaml = Files.walk(tempDirectory)
.filter { item -> item.isYaml() }
.findFirst()
if (yaml.isEmpty) {
return PluginCreationFail(MissedFile("action.yaml"))
}
parseYaml(yaml.get())
} catch (e: DecompressorSizeLimitExceededException) {
return PluginCreationFail(PluginFileSizeIsTooLarge(e.sizeLimit))
} finally {
tempDirectory.deleteLogged()
}
}
private fun parseYaml(yamlPath: Path): PluginCreationResult {
try {
return parse(yamlPath)
} catch (e: Exception) {
e.rethrowIfInterrupted()
val errorMessage = "An unexpected error occurred while parsing the TeamCity Action descriptor"
LOG.warn(errorMessage, e)
return PluginCreationFail(UnableToReadDescriptor(yamlPath.toAbsolutePath().toString(), errorMessage))
}
}
private fun parse(yamlPath: Path): PluginCreationResult {
val descriptor = try {
val yamlContent = yamlPath.readText()
objectMapper.readValue(yamlContent, TeamCityActionDescriptor::class.java)
} catch (e: Exception) {
LOG.warn("Failed to parse TeamCity Action", e)
return PluginCreationFail(ParseYamlProblem)
}
val validationResult = validateTeamCityAction(descriptor)
if (validationResult.any { it.isError }) {
return PluginCreationFail(validationResult)
}
val plugin = with(descriptor) {
TeamCityActionPlugin(
// All the fields are expected to be non-null due to the validations above
pluginId = this.name!!, // composite id
pluginName = this.name,
description = this.description!!,
pluginVersion = this.version!!,
specVersion = this.specVersion!!,
yamlFile = PluginFile(yamlPath.fileName.toString(), yamlPath.readBytes()),
namespace = TeamCityActionSpec.ActionCompositeName.getNamespace(this.name)!!
)
}
return PluginCreationSuccess(plugin, validationResult)
}
}
private fun fileFormatError(pluginFile: Path): PluginCreationResult =
PluginCreationFail(IncorrectPluginFile(pluginFile.simpleName, "ZIP archive or YAML file"))
private fun Path.isYaml(): Boolean = this.hasExtension("yaml") || this.hasExtension("yml")
© 2015 - 2025 Weber Informatics LLC | Privacy Policy