Русский
Русский
English
Статистика
Реклама

Jetbrains space

Погружение в JetBrains Space Applicaitons

22.03.2021 14:08:01 | Автор: admin

Привет, Хабр.

Недавно JetBrains представили свой новый продукт под названием Space, о чем был своевременный пост на Хабре. Прошло немного времени и уже пора бы попробовать некоторые его особенности как платформы. В этой статье речь пойдет о Space Applications.

Space Applications - это расширения серверной и клиентской частей. Applications позволяют взаимодействовать с разными компонентами платформы и расширять её функциональность.

Первым делом рассмотрим расширения серверной части, которые предоставляет Space. Основное ограничение - Application нельзя запустить непосредственно внутри окружения Space. Для предоставления доступа между Space и Application используется так называемый Endpoint, в котором мы указываем Endpoint URI - адрес нашего плагина, на который Space будет отправлять запросы и коммуницировать с помощью Space HTTP API.

На данный момент известно несколько видов Applications:

Chatbot

Cтандартный чатбот, с которым взаимодействие происходит в приватном с ним чате. На данный момент кастомизация сильно уступает, например, Telegram. Нельзя добавлять бота в канал (групповой чат), а из интерактивного интерфейса пока доступны только кнопки.

Slash commands

Для каждого канала могут быть заданы разные команды, и когда пользователь вводит "/", ему показывается список доступных команд. На данный момент доступны только для чатботов.

Client applications

Используют функционал Space, чтобы получать от него разную информацию или взаимодействовать с разными модулями и компонентами, например, открывать/закрывать issues, писать сообщения, отправлять посты в канал и так далее.

Custom menus

Позволяют расширить стандартные меню новыми элементами. На момент написания статьи api для них еще не доступен.

Также можно свободно комбинировать сразу несколько типов Applications. Например, создать бота, у которого будет кнопка для запуска билда проекта на CI/CD сервере, и результат которого вернется в общий канал.

Для начала Application требуется создать. Делается это через Administration menu. При создании можно указать, какими правами оно будет обладать, чтобы приложение имело доступ только к тем ресурсам, которые нами явно указаны.

После создания в табе Authentication требуется выбрать один из возможных Authentication flows, в зависимости от типа приложения. Кратко каждый из них можно описать так:

  • Client Credentials Flow - самый простой способ. Работает через client id и client secret. Наше приложение будет работать от своего лица и не сможет получить доступ к некоторым компонентам платформы. Используется в полностью серверном приложении.

  • Authorization Code Flow - логинимся в приложение через Space, получаем код авторизации, который приложение использует чтобы из него получить токен и работать от лица пользователя.

  • Implicit Flow - идея таже, что и Authorization Code Flow, только клиент логинится на стороне браузера.

Client applications

В данном разделе мы используем функционал Space, чтобы получить от сервера разную информацию: каналы, приложения, пользователи, проекты, и т.д.

build.gradle.kts
repositories {    mavenCentral()    maven("https://kotlin.bintray.com/kotlinx")    maven("https://maven.pkg.jetbrains.space/public/p/space/maven")}dependencies {    implementation(kotlin("stdlib"))    // Space api sdk    // https://www.jetbrains.com/help/space/space-sdk.html    val space_version = "61400-beta"    implementation("org.jetbrains:space-sdk-jvm:$space_version")    // Ktor (http client)    // https://github.com/ktorio/ktor    val ktor_version = "1.4.3"    implementation("io.ktor:ktor-client-core:$ktor_version")    implementation("io.ktor:ktor-client-core-jvm:$ktor_version")    implementation("io.ktor:ktor-client-cio:$ktor_version")}

Сначала нам требуется создать и настроить клиент. Мы будем использовать Client Credentials Flow:

private const val spaceInstanceUrl = "https://makentoshe.jetbrains.space"val spaceClient = SpaceHttpClient(HttpClient(CIO)).withServiceAccountTokenSource(    ClientCredentialsFlow.clientId, ClientCredentialsFlow.clientSecret, spaceInstanceUrl)object ClientCredentialsFlow {    const val clientId: String = TODO(Put your client_id here)    const val clientSecret: String = TODO(Put your client_secret here)}

Ниже приведены примеры некоторых расширений и запросов.

// There are some examples of retrieving several data from the Space instance.// We can process this info as we want - create analytics, office dashboards, and so on.fun main() = runBlocking {    val channels = spaceClient.chats.channels.listAllChannels("").data    println("Channels: ${channels.map { "${it.name}(${it.channelId})" }}")    // View application rights allows to see all applications    // If rights were not accepted - the application can see only itself.    val applications = spaceClient.applications.getAllApplications("")    println("Applications: ${applications.map { "${it.name}(${it.id})" }}")    // Works only with View member profile rights    val profiles = spaceClient.teamDirectory.profiles.getAllProfiles().data    println("Profiles: ${profiles.map { "${it.username}(${it.id})" }}")    // Works only with View project parameters rights    // These rights can be managed for selected projects or for whole projects at one time.    val projects = spaceClient.projects.getAllProjects().data    println("Projects: ${projects.map { "${it.name}(${it.id})" }}")                // Works only with Project Issues: View issues rights    val issues = projects.firstOrNull()?.let { getProjectIssues(it) }    println("Issues: ${issues?.map { "${it.title}(${it.id})" }} ")}private suspend fun getProjectIssues(project: PR_Project): List<Issue> {    return spaceClient.projects.planning.issues.getAllIssues(        project = ProjectIdentifier.Id(project.id),        assigneeId = emptyList(),        statuses = emptyList(),        sorting = IssuesSorting.CREATED,        descending = true    ).data}
Output
Channels: [Booruchan(4UHs4I3yyno1), general(10xDLp0yqy4w), Habrachan(4HyHLw3SnO9Y), Sipichan(15A2hA1RpAsp)]Applications: [client(2czEkY3AIaV0), chatbot(d3Q8Z0UeVCF)]Profiles: [Makentoshe(2iqI4p3gzufl)]Projects: [Booruchan(qN0K31awqo6), Habrachan(1tJHqn2A76Yf), Sipichan(35BreB35gvdA)]Issues: [Add custom Run Configuration and support ngrok startup(3S09oT4JHvpC), Add Client template for Space plugin with Gradle (atQRe1SIklB), Add Blank template for Space application plugin support for Gradle(4REln04HAo5k)]

В зависимости от настроенных прав полученные данные могут отличаться. Стоит обратить внимание, что почти все данные возвращаются через .data. Изначально возвращается объект Batch, который используется для пагинации и содержит текущий набор данных, ключ к следующему набору, и общее количество элементов. При запросах стоит это учитывать, однако для простоты в данной статье пагинация опущена.

Исходники проекта доступны на github и со временем будут пополняться.

Chatbot + slash command Applications

Серверные Applications, по сравнению с клиентскими, требуют дополнительной подготовки. Первым делом нам нужно серверное приложение, на котором будет хоститься наш бот. Мы уже использовали HTTP клиент Ktor, так что можем создавать на нем и серверную часть. Создание конфигурационных файлов для Ktor здесь будет опущено, но есть документация, на которую можно опереться.

Когда мы поднимем наш сервер, мы сможем получить его URL, чтобы Space мог его использовать. Покупать хост, или искать бесплатный не комильфо, поэтому мы пойдем обходным путем - будем использовать туннельный сервис. В официальной документации используется ngrok, однако лично я предпочитаю localtunnel, из-за его возможности указывать постоянный адрес.

// localtunnelnpx localtunnel --port 8080 --subdomain makentoshe// ngrokngrok http 8080

В любом случае мы получим URL - это как раз то, что нам нужно.


Возвращаемся в настройки Applications в нашем Space. В табе Endpoint в поле Endpoint URI нужно будет указать наш url. Для меня это https://makentoshe.loca.lt/api/chatbot. Про то, зачем нужен /api/chatbot будет дальше.

В том же табе существует два способа верифицировать наши запросы:

  • Verification token - этот токен кладется в каждый запрос от Space. Нам остается сравнить эти токены, и если они совпадают - мы общаемся с нашим Space.

Пример ответа с Verification token
{      "className": "ListCommandsPayload",      "accessToken": "",      "verificationToken": "d415ca5965b37f4f0cac59fd33de7b94e396284e897d0fb8a070d0a5e1b7f2d3",      "userId": "2kawvQ4F6GM6"}
  • Signing key - более продвинутый метод. Для каждого запроса создается хеш, который кладется в его заголовок. Когда мы получаем запрос мы также вычисляем хеш, и если они совпадают - все ок. Подробнее об алгоритме - здесь.

Пример ответа с Signing key
POST /api/chatbot HTTP/1.1Host: 12345abcdef.ngrok.ioUser-Agent: Space (61355) Ktor http-clientContent-Length: 163Accept: */*Accept-Charset: UTF-8Content-Type: application/jsonX-Forwarded-For: 123.456.123.456X-Forwarded-Proto: httpsX-Space-Signature: 2aa8cba6217a28686de0ca8dcfe2a1d0795e343d744a0c5307308e43777593a5X-Space-Timestamp: 1607623492912Accept-Encoding: gzip{"className":"ListCommandsPayload","accessToken":"","verificationToken":"d415ca5965b37f4f0cac59fd33de7b94e396284e897d0fb8a070d0a5e1b7f2d3","userId":"2kawvQ4F6GM6"}

В качестве примера мы возьмем оба варианта и будем сверять и хеши, и токены.

object Endpoint {    const val verificationToken: String = TODO("Place your verification_token")    const val signingKey: String = TODO("Place your signing_key")    fun verify(payload: ApplicationPayload): Boolean {        return payload.verifyWithToken(verificationToken)    }    fun verify(timestamp: String, signature: String, body: String): Boolean {        val hmacSha256 = Mac.getInstance("HmacSHA256")        hmacSha256.init(SecretKeySpec(signingKey.toByteArray(), "HmacSHA256"))        val hash = hmacSha256.doFinal("$timestamp:$body".toByteArray()).toHexString()        return hash == signature    }    private fun ByteArray.toHexString() = joinToString("") { (0xFF and it.toInt()).toString(16).padStart(2, '0') }}

Первым делом для сервера нам нужно указать Routing. Это тот самый Endpoint для Space, который он будет использовать, чтобы обращаться к нашему боту.

@Suppress("unused") // Referenced in application.conf@kotlin.jvm.JvmOverloadsfun Application.module(testing: Boolean = false) {    install(Routing) {        chatbot()    }}fun Routing.chatbot() {    post("api/chatbot") {        val receiveBody = call.receiveText()        val timestamp = call.request.headers["x-space-timestamp"]            ?: return@post call.respond(HttpStatusCode.BadRequest)        val signature = call.request.headers["x-space-signature"]            ?: return@post call.respond(HttpStatusCode.BadRequest)        if (!Endpoint.verify(timestamp, signature, receiveBody)) {            return@post call.respond(HttpStatusCode.Unauthorized)        }        val payload = readPayload(receiveBody)        if (!Endpoint.verify(payload)) {            return@post call.respond(HttpStatusCode.Unauthorized)        }        try {            processChatbotPayload(payload)        } catch (unknownCommand: IllegalStateException) {            LoggerFactory.getLogger("Chatbot").error(unknownCommand.message)        }    }}

Как только к серверу происходит обращение по заданному адресу, первым делом мы проверяем, что запрос пришел именно от нашего Space. Если это не так - возвращаем 401 Unauthorized.

Далее боту следует обработать полученный payload. На момент написания статьи существует 5 имплементаций ApplicationPayload:

  • MessagePayload - передается нам, когда пользователь отправляет обычное сообщение.

  • ListCommandsPayload - передается нам, когда пользователь начинает сообщение с "/" и затем вводит команду посимвольно. Здесь происходит запрос все существующих команд, которые нам нужно будет вернуть в виде json. На ввод каждого символа передается новый Payload.

  • MessageActionPayload - передается, когда пользователь нажимает на интерактивный элемент сообщения, например, на кнопку. Корректно срабатывают только элементы из последнего сообщения. Все предыдущие элементы будут "стерты"(например, их actionId всегда будут пустой строкой).

  • MenuActionPayload - передается, когда пользователь нажимает на кастомный элемент на одном из меню (ProjectMenu, LocationMenu, ChannelMessageMenu, ChannelAttachmentMenu и т.д.). На момент написания статьи все еще не доступен.

  • ListMenuExtensionsPayload - имеет ту же идею, что и ListCommandsPayload, только для меню. На момент написания статьи все еще не доступен.

private suspend fun PipelineContext<*, ApplicationCall>.processChatbotPayload(payload: ApplicationPayload) {    when (payload) {        is MessagePayload -> {            processChatbotMessagePayload(payload)        }        is MessageActionPayload -> {            processChatbotMessageActionPayload(payload)        }        is ListCommandsPayload -> {            processChatbotListCommandsPayload(payload)        }    }}

Когда пользователь отправляет нам сообщение - скорее всего это команда, которую боту надо выполнить. Команду можно описать одним дата классом:

data class Command(    val name: String,    val info: String,    val action: suspend (payload: MessagePayload) -> Unit) {       fun toCommandDetail() = CommandDetail(name, info)}

Предлагаю в качестве примера реализовать три простых команды:

  • help - выводит сообщение со списком всех команд;

  • echo - выводит переданное сообщение обратно пользователю;

  • interactive <type> - выводит пример выбранного типа интерактивного элемента, например, button.

object Commands {    val help = Command(        "help",        "Show this help",    ) { payload ->        val context = HelpContext.from(payload)        printToChat(context, message {            section {                text(                    """Help message:                    name - Show this help                    ${echo.name} - ${echo.info}                    ${interactive.name} - ${interactive.info}                """.trimIndent()                )            }        })    }    val echo = Command(        "echo",        "Echoing the input string",    ) { payload ->        val context = EchoContext.from(payload)        val body = context.message.body        printToChat(context, message = if (body is ChatMessage.Text) {            message { section { text(body.text) } }        } else {            message { section { text("Skip the Block body") } }        })    }    val interactive = Command(        "interactive",        "Displaying available message interactive elements"    ) { payload ->       // TODO finish later    }    val list = listOf(help, echo, interactive)    val commands: Commands        get() = Commands(list.map { it.toCommandDetail() })}

Сначала разберемся, что происходит в командах help и echo. Из ApplicationPayload каждой команды мы можем извлечь нужные данные для обработки и положить их в соответствующий Context, который мы сами определяем. Этот класс помогает нам аккумулировать данные в одном месте.

Context.kt
interface UserContext {    val userId: String}fun userContext(applicationPayload: ApplicationPayload) = object: UserContext {    override val userId = applicationPayload.userId ?: throw IllegalArgumentException("Payload does not contains user id")}data class EchoContext(override val userId: String, val message: MessageContext) : UserContext {    companion object {        fun from(payload: ApplicationPayload): EchoContext? = when (payload) {            is MessagePayload -> from(payload)            else -> null        }        fun from(payload: MessagePayload): EchoContext {            return EchoContext(payload.userId, payload.message)        }    }}data class HelpContext(override val userId: String): UserContext {    companion object {        fun from(payload: ApplicationPayload): HelpContext {            return HelpContext(payload.userId!!)        }    }}data class InteractiveContext(override val userId: String): UserContext {    companion object {        fun from(payload: ApplicationPayload): InteractiveContext {            return InteractiveContext(payload.userId!!)        }    }}

После того, как мы получили наш userId и остальные сопутствующие данные, нам нужно их вывести в чат пользователя, с которым в данный момент взаимодействует бот. Для этого напишем отдельную функцию printToChat.

suspend fun printToChat(context: UserContext, message: ChatMessage) {    val member = ProfileIdentifier.Id(context.userId)    spaceClient.chats.messages.sendMessage(MessageRecipient.Member(member), message)}

Любое сообщение в Space представлено в виде класса ChatMessage. Этот класс является sealed и имеет 2 наследника: ChatMessage.Text и ChatMessage.Block.

ChatMessage.Text является простым текстовым сообщением поддерживающим markdown.

ChatMessage.Text(  """  **bold**  `code`  *italic*  @{2iqI4p3gzufl, Maksim Hvostov}   @{2iqI4p3gzufl, Makentoshe}   @{2iqI4p3gzufl, any string may be replaced with my name}   [\#general](im/group/10xDLp0yqy4w)   >quote  """.trimIndent())
Output

ChatMessage.Block существует для более сложных сообщений, которые могут быть разбиты на секции, иметь разделители, и другие продвинутые элементы форматирования.

Для него существует специальный DSL, который мы и используем. Всё начинается с функции message - это корень нашего сообщения, в котором мы можем указать:

  • MessageOutline - это дополнительная подпись под именем отправителя и, по желанию, иконка, которая задается через строку. Какой именно должна быть эта строка пока не понятно, поэтому вместо иконки передаем null.

  • MessageStyle - изменяет некоторые цвета в сообщении, в соответствии со стилем.

  • Для чего нужна messageData я пока так и не понял. Чтобы не было передано в сообщении нашему боту, это поле всегда будет null.

message {this.outline = MessageOutline(null, "Outline text")  this.style = MessageStyle.PRIMARYsection {this.text("Primary message")}}
Outputs

После этого мы можем либо определить новую секцию методом section, либо поставить разделитель методом divide.

В секции нам доступны:

  • обычное текстовое поле через метод text.

  • текстовое поле с тегом, для которого можно добавить отдельный стиль.

  • текстовое поле с изображением справа от секции.

  • текстовое поле с иконкой, в которую опять же передается строка.

  • footer и header.

  • конструкция поле значение через fields

  • интерактивные элементы, из которых на момент написания статьи доступна только кнопка.

Как это выглядит:

message {    this.outline = MessageOutline(null, "Outline text")    this.style = MessageStyle.PRIMARY    section {        this.header = "Section header"        this.footer = "Section footer"        this.text("Plain text")    }    divider()    section {        header = "This tag may indicate something not good"        this.textWithTag("Text with tag", "error tag", MessageStyle.ERROR)    }    section {        this.text("Plain text just to fill some space.")        this.textWithImage("Text with image", "https://www.jetbrains.com/space/img/feedback-section/video-preview.png")    }    section {        this.textWithIcon("Text with icon", "", MessageStyle.WARNING)    }    section {        header = "Fields"        this.fields {            this.field("field1", "value1")            this.field("field2", "value2")            this.field("field3", "value3")            this.field("field4", "value4")        }        this.controls {            this.button("Disabled button without any action", PostMessageAction("", ""), disabled = true)        }    }}
Output

Осталось реализовать команду interaction и соединить все вместе.

val interactive = Command(        "interactive",        "Displaying available message interactive elements"    ) { payload ->        val context = InteractiveContext.from(payload)        val arguments = payload.commandArguments()        if (arguments == null || arguments.isBlank()) {            return@Command printToChat(context, message {                section {                    text("Specify one of the selected ui elements:\nbutton")                }            })        }        printToChat(context, message {            section {                header = "Available message interactive elements"                controls {                    when (arguments) {                        "button" -> {                            val primaryAction = PostMessageAction("ButtonPrimaryActionId", "InteractiveButtonPayloadPrimary")                            button("Primary", primaryAction, MessageButtonStyle.PRIMARY)                            val secondaryAction = PostMessageAction("ButtonSecondaryActionId", "InteractiveButtonPayloadSecondary")                            button("Secondary", secondaryAction, MessageButtonStyle.SECONDARY)                            val regularAction = PostMessageAction("ButtonRegularActionId", "InteractiveButtonPayloadRegular")                            button("Regular", regularAction, MessageButtonStyle.REGULAR)                            val dangerAction = PostMessageAction("ButtonDangerActionId", "InteractiveButtonPayloadDanger")                            button("Danger", dangerAction, MessageButtonStyle.DANGER)                        }                    }                }            }        })    }

Теперь мы можем подключать обработку разных ApplicationPayload's. Для простого сообщения от пользователя мы ищем команду из списка и выполняем её.

private suspend fun PipelineContext<*, ApplicationCall>.processChatbotMessagePayload(payload: MessagePayload) {    Commands.list.find { it.name == payload.command() }?.action?.invoke(payload)        ?: return call.respond(HttpStatusCode.NotFound)    call.respond(HttpStatusCode.OK)}

Для показа списка команд мы возвращаем список всех команд. Здесь же мы используем подключенный ранее Jackson.

private suspend fun PipelineContext<*, ApplicationCall>.processChatbotListCommandsPayload(payload: ListCommandsPayload) {    call.respondText(ObjectMapper().writeValueAsString(Commands.commands), ContentType.Application.Json)}

Для нажатия на интерактивный элемент мы будем принтить actionId этой команды.

private suspend fun PipelineContext<*, ApplicationCall>.processChatbotMessageActionPayload(payload: MessageActionPayload) {    printToChat(userContext(payload), message { section { text(payload.actionId) } })    call.respond(HttpStatusCode.OK)}

Исходники чатбота доступны по ссылке на github.

Итого

Почти все, что может сделать пользователь используя Space через пользовательский интерфейс, можно сделать и через предоставленный Api(если на то будут предоставлены разрешения).

На самом деле у Space гораздо больше способов расширения функционала. Мы рассмотрели лишь самый продвинутый уровень. Большую часть остальных расширений можно настроить имея вообще минимальные навыки программирования.

Вот остальные способы расширения функционала платформы:

Подробнее..
Категории: Kotlin , Space , Jetbrains space

Перевод Код-ревью в IDE интеграция между Space и IntelliJ IDEA 2021.1

08.04.2021 20:08:42 | Автор: admin

Привет, Хабр!

Вчера вышло обновление IntelliJ IDEA 2021.1. В него вошла интеграция с JetBrains Space, которая позволяет использовать любую IDE на платформе IntelliJ для код-ревью: назначать ревью и управлять ими, просматривать и добавлять комментарии, принимать изменения. Как это работает, мы подробно расскажем в этом посте.

Space предоставляет командам разработчиков удобный способ проверять код друг друга и обсуждать изменения. После внесения изменений вы можете попросить одного или нескольких коллег выполнить ревью вашего кода. При работе над функциональной веткой ее можно заново объединить с базовой веткой прямо из Space.

Доступ к код-ревью и мердж-реквестам можно получить из браузера и десктопного приложения Space. А теперь также из IDE! Нативная интеграция между Space и нашими IDE на базе IntelliJ открывает много новых возможностей, и код-ревью это только первый шаг. Мы планируем развивать и улучшать эту интеграцию.

Видео

Если вы предпочитаете видео, смотрите обзор этой функциональности от Триши Ги:

Space-плагин встроен в свежую версию IntelliJ IDEA 2021.1. Для других наших IDE плагин нужно установить вручную.

Прежде чем приступить к ревью кода, войдите в Space из IDE. Это можно сделать в настройках: Tools | Space. Введите URL-адрес своей организации Space, нажмите Log In, и ваш дефолтный браузер попросит вас предоставить доступ из IDE.

После этого в Get from VCS появится список всех проектов и репозиториев в вашей организации Space. Найдите и выберите Git-репозиторий, с которого вы хотите начать, и нажмите Clone.

У Space-плагина есть свое окно, в котором можно просматривать задания в Space Automation. Плагин также обеспечивает автодополнение и подсветку синтаксиса для файлов .space.kts.

Но мы здесь из-за код-ревью, так что перейдем к делу.

Окно Code Reviews

Окно Space Code Reviews открывается с боковой панели или через меню Tools | Space | Code Reviews. В нем вы увидите все ревью, относящиеся к текущему проекту. В окне работает поиск и фильтры.

Фильтры помогут отсортировать:

  • Открытые и закрытые ревью;

  • Ревью, в которых содержатся ваши изменения;

  • Ревью, требующие вашего внимания;

  • Изменения, которые вам нужно просмотреть;

  • Ревью, назначенные на вас.

Хронология код-ревью

Из списка ревью можно перейти к информации о каждом из них. Вы увидите основные сведения о ревью, например, кто является автором и ревьюером. Вы можете сделать checkout ветки мердж-реквеста, если хотите, чтобы код был у вас под рукой.

Также вы увидите хронологию ревью со всеми комментариями и изменениями. Вы можете отвечать на комментарии, добавлять свои, удалять решенные вопросы.

В Space важное место занимают чаты. Комментарии к код-ревью это тоже чат: оставляйте дополнительные комментарии и отвечайте коллегам в тредах. Все это не выходя из IDE.

Коллеги, использующие браузерное или десктопное приложение Space, увидят ваши комментарии прямо в ревью, если оно открыто, либо в чате.

Ревью кода в IDE

Открыв ревью в IDE, вы увидите список файлов, которые были добавлены, изменены или удалены. Вы можете открыть их и посмотреть, что изменилось, в интерфейсе просмотра различий. В нем можно оставлять комментарии к любым строкам кода.

Комментарии сохраняются как черновик и публикуются, только когда вы завершите код-ревью. При необходимости используйте опцию Post now, чтобы сразу же отправить комментарий.

Принять изменения или дождаться ответа

Когда вы закончите анализировать изменения, можете завершить свой этап код-ревью. На вкладке Details вы можете выбрать:

  • Accept Changes, то есть принять изменения, если на ваш взгляд с кодом все в порядке.

  • Wait for Response, то есть подождать ответа, если вы ознакомились с изменениями, но у вас остались вопросы или в коде есть нерешенные проблемы.

В любом случае ваш этап проверки будет завершен и ваши комментарии будут опубликованы.

Заключение

Команды выполняют ревью кода по многим причинам. Коллеги могут проверять, насколько понятен новый код, легко ли его читать, нет ли в нем серьезных недостатков, прежде чем одобрить слияние с основной веткой. Теперь все это можно делать прямо в IDE.

Space-плагин встроен в IntelliJ IDEA 2021.1, а для других наших IDE его можно установить вручную.

Вы можете бесплатно зарегистрироваться в Space и легко создать зеркало существующего Git-репозитория, чтобы пользоваться всеми возможностями Space для код-ревью в IntelliJ IDEA.

Конечно же, в дальнейшем мы будем расширять функциональность плагина. Что бы вы хотели в нем увидеть? Расскажите нам об этом в комментариях.

Подробнее..

Space публичный релиз командной среды от JetBrains

10.12.2020 18:18:39 | Автор: admin

Привет, Хабр!

Мы рады представить публичную версию Space универсального и расширяемого инструмента для командной работы, разработки ПО, общения, управления проектами и командами.

В этом посте мы расскажем о том, что включает в себя Space на этапе релиза, и поделимся планами на будущее.

Релиз публичной версии Space состоялся 9 декабря, и ниже вы можете посмотреть запись нашей презентации. (Можно выбрать русские субтитры).

Какие проблемы решает Space?

Мы создали Space для того, чтобы улучшить взаимодействие команд, упростить передачу информации внутри всей компании и объединить рабочие инструменты в единую среду.

Space решает проблему разобщенности это единая платформа для общения, обмена информацией и совместной работы над проектами. Space помогает разработчикам, дизайнерам, менеджерам и другим специалистам работать продуктивнее и прозрачно взаимодействовать.

Все для команд в одном инструменте

Space объединяет в себе инструменты, необходимые для поддержки полного цикла разработки ПО любого масштаба:

  • Хостинг Git-репозиториев.

  • Код-ревью с поддержкой merge-реквестов и критериев качества.

  • Автоматизация сборки и развертывания приложений.

  • Инструменты для управления проектами: чеклисты для планирования, баг-трекер и визуальные доски задач.

  • Реестры пакетов и контейнеров для публикации артефактов.

А главное все это идет вкупе с инструментами для эффективной коммуникации и взаимодействия:

Больше пользы. Меньше отвлекающих факторов.

За счет того, что все необходимое для команд собрано в одном инструменте, Space упрощает рабочие процессы: например, объединяет все оповещения в чатах, которые упорядочены по разным вкладкам по типу уведомлений, чтобы вы реже отвлекались, и не позволяет назначать задачи коллегам, когда они болеют или находятся в отпуске.

Объединение целого набора разных инструментов в одном приложении снижает первоначальные расходы и затраты на обслуживание, а также сокращает косвенные затраты при переходе в другую команду люди тратят меньше усилий на освоение новых инструментов.

Адаптация к изменениям

В 2020 году JetBrains, как и миллионам других компаний по всему миру, пришлось быстро адаптироваться к условиям удаленной работы. И Space вовремя доказал свою эффективность на деле.

Одна из важных особенностей инструмента масштабируемость. Вы можете легко начать работу в Space с минимальными затратами, а по мере роста вашей команды и компании Space будет подстраиваться под ваши потребности.

Что говорят наши первые пользователи

С тех пор, как мы открыли программу раннего доступа на KotlinConf в декабре 2019 года, к Space присоединилось около 25 тысяч организаций. Пользователи раннего доступа отправили более 1,5 миллиона сообщений, создали 38+ тысяч задач и 13+ тысяч репозиториев, открыли 12+ тысяч код-ревью.

Мы хотим сказать огромное спасибо всем пользователям ранних версий Space! Без вашей помощи Space не был бы таким, каким вы его видите сегодня.

Вы можете посмотреть, что о нас говорят наши пользователи, а также прочитать их истории.

Что было сделано за 2020

В этом году команда Space приложила много усилий для воплощения нашего видения того, как должна выглядеть интегрированная среда для командной работы.

Вот, что мы внедрили за 2020 год:

Давайте посмотрим на Space в действии!

Space как платформа и экосистема партнеров

С самого начала мы разрабатывали Space как платформу и с точки зрения расширяемости, и с точки зрения бизнес-возможностей. Мы стремимся дать нашим пользователям как можно больше возможностей кастомизации и расширения.

Подробнее о способах расширения Space читайте на нашем сайте. О том, что стоит за нашей концепцией расширяемости Space, и зачем это нужно, мы рассказываем в нашем блоге.

Каждая организация уникальна, поэтому Space есть все необходимое для поддержки самых разных процессов. Наши партнеры могут помогать своим клиентам адаптировать Space к их потребностям и извлечь из продукта максимум пользы. Мы предлагаем три партнерские программы, которые охватывают большинство моделей бизнес-партнерства: партнерство по продажам, сервисное партнерство и технологическое партнерство.

Если вы заинтересованы в сотрудничестве, узнайте больше о наших программах и оставьте свою заявку здесь.

Планы на 2021

В первой публичной версии мы сконцентрировались на поддержке рабочих процессов для команд разработки. Но это только начало.

Мы планируем поддержать рабочие процессы для самых разных команд: дизайнеров, маркетологов, специалистов по продажам, HR, юристов и многих других.

Так как совместная работа над документами один из ключевых процессов для многих команд, в скором времени мы собираемся поработать над ним. Мы планируем поддержать возможность создания и изменения спецификаций, технических требований, кампаний, дорожных карт, юридических документов с поддержкой проверок, подобных процессу код-ревью, и не только.

Вот, что еще входит в наши планы на 2021 год:

  • Локальная версия и удобный переход с облачной на локальную версию Space. Вы можете попробовать облачную версию уже сейчас, а затем плавно перейти на локальную версию.

  • Локализация. Нам важно, чтобы среда, в которой вы работаете, говорила с вами на одном языке.

  • Видеозвонки, как встроенные, так и из внешних инструментов посредством интеграций.

  • Продолжим совершенствовать, корректировать и адаптировать существующую функциональность Space.

  • Добавим больше способов миграции и интеграций, в частности синхронизацию с Outlook/Office 365 и Google Календарем.

  • Сделаем более тесную интеграцию различных частей Space и расширим интеграцию с внешними инструментами с помощью приложений.

Цены

Space доступен бесплатно для неограниченного количества пользователей. Более широкий функционал доступен на платных подписках от 8$ за активного пользователя в месяц. Подробнее о стоимости, разнице подписок и спецпредложениях для образовательных учреждений мы рассказываем на этой странице.

Мы очень благодарны нашим первым пользователям и постараемся обеспечить для них максимально комфортный переход на публичную версию. Все пользователи раннего доступа и бета-версий могут бесплатно оставаться на своем текущем плане на протяжении трех следующих месяцев.

Попробуйте Space бесплатно

Чтобы начать знакомиться с Space, необязательно настраивать инструмент для всей организации. Работайте с репозиториями, отслеживайте задачи, управляйте командами, редактируйте документы вместе с коллегами или просто общайтесь в чате.

Начните использовать Space бесплатно и пригласите всю свою команду.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru