Sciak Flow for Gitlab latest Help

Development

Commit

I try to follow Karma commit, based on the Angular project convention, this is the reference Karma Commit Msg. The version is calculated automatically using a semver plugin for gradle: Git.SemVersioning.Gradle

Release

Releasing is done using gradle task and gitlab pipeline. The version is calculated by the semver plugin and a tag is created, in order to release see Release page.

Run test in IntelliJ

We are using a gradle plugin to show the status of each test during the build, the plugin is configured to use Mocha style but this create problem in the IntelliJ console, in order to fix them add the following parameter in the gradle template:

-Dtestlogger.theme=plain

this one remove all the formatting from the plugin, just showing the status of the test.

Feature flags

In order to allow feature development and release version to test, a feature flag is introduced, the code can be wrapped around a withFeatureFlag function. The feature flag can be overridden by a System Properties at startup.

withFeatureFlag(FeatureFlags.TRACE_CALL) { val requestLogged = serializeRequest(request) LOGGER.info(requestLogged) }

UI Testing

The plugin is UI intensive and rely on 3rd party data to display the right data. Build an UI automation test in this scenario is quite complicated and in the end doesn't really serve the big purpose of see how the plugin looks like.

More effective are the test on connection, at least will recognize if some setting or change in the connectivity destroy the system, and visual smoke test are needed in any case.

Coroutines

The plugin use coroutines in an extensive way, mainly with the injected CoroutineScope and the additional layer of define the scope name as the class using the coroutine scope.

There are 3 different way to get the coroutine scope:

  1. Service - In this scenario Intellij inject the coroutine scope bounded with the service scope lifecycle

  2. Normal Class - In this scenario the class require the coroutine scope during instantiation

  3. AnAction - There is no way to get the coroutine scope injected in an Action, therefore we get it from the PluginScheduler class, that is a Project Service coroutine.

Most of the code is build using the MVVM pattern, and with an extensive use of MutableStateFlow variable that represent the current state. In a nutshell: action -> MV -> API -> Mutable State -> Change in the Model -> UI revalidation

This looks complicated but make easier to define the boundary of the context and use the right Dispatcher for the operation, avoiding UI code with a background thread and blocking code in the EDT.

Dispatchers

Pooled

This is a custom dispatcher based on Application Thread Pool, use the same thread pool of AppExecutorUtil#getAppExecutorService that is the global Intellij thread pool

EDT/Main

EDT is the dispatcher provided by Intellij and must be used for UI related work. In case of modal dialog the right ModalityState must be added to the coroutine context using the following pattern:

coroutineScope.launch(Dispatchers.Default + ModalityState.current().asContextElement()) { // your async code withContext(Dispatcher.EDT) { //UI code } }

Starting from 2025.1 EDT is considered legacy and should be used Main

28 April 2025