 OK, we are live. Hi everybody, today we have a knowledge transfer for all strategy plug-in. It's one of the most popular plug-in in Jenkins, managing authorization for various use cases. And since we have a number of newcomer contributors, maintainers, and those students who are interested in Google Summer project ideas, we decided that it's better to have a knowledge transfer earlier than it usually happens. In Google Summer, of course, we usually have knowledge transfers during the community bonding period. But if you're interested to get information for another project, you're more than welcome to just reach out to potential mentors and ask for more information. So that's the approach. Today, we will just review the architecture for all strategy plug-in, how it operates, and how to start contributing to this plug-in. It's a real-time discussion. So if you have a question, just feel free to interrupt me and I'll try to answer that. And my objective here is to just provide you as much information as needed. And if you need a follow-up session, you can definitely do that. So that's the plan. I'm going to share my screen. OK, do you see my screen? Yeah, just a question. Would somebody be interested to make notes for the session? I mean, just if yes, I can just create a Google document for that. Yeah, I will help you to record it. OK, so what's going on with my network? OK, OK, so let's create a Google doc. I will just share it with everybody. OK, it seems one of the students is unable to join. So Martin, if you could do that, it would be much appreciated. For students, it's better to actually participate in live, especially if they have questions. Yeah, if anybody is watching this as a recording or if you want to have more information, we have a role strategy plug-in chat. It's in Gitter. I posted the link to the meeting notes here. So everybody is welcome to just put some comments and information. OK, I believe we cannot do much about that. So if anybody else wants to join, I propose that we use YouTube and chat for questions as a plan B, because I didn't expect so many people on the call. Otherwise, we would have found other options. So let's proceed with the kitty itself. So if you have never seen a role strategy plug-in before, there is a plug-in. Yeah, it has 48,000 installations. So it means that it's installed on around 25% of instances. It's a pretty good number. And actually, this is the second most popular authorization management plug-in after matrix authorization. But matrix authorization was a part of the Jenkins core. You may see that it's installed almost every way because it's detached plug-in. We don't know how many actual dosages of this configuration. But yeah, this is the second most popular plug-in anyway. So what this plug-in does? In Jenkins, there are actually authorization and authentication parts. I'll probably just start with the instance. So if you have already checked out the code base, maybe an HPI run is a command which allows to run a development instance from a Pomex ML. I'm just starting to show how it's actually configured to Jenkins. OK, Jenkins is fully up and running. Now we can go here. For example, localhost 8080 Jenkins. And here, we get my development instance. It doesn't have so many things configured. But yeah, what I wanted to show you that this plug-in actually, yeah, let's start from Jenkins architecture. You may see that I'm running with all the Jenkins core because it's a baseline for the plug-in. So there is a number of security vulnerabilities, et cetera. But it doesn't matter for the context of this talk. Here, what we need to know is that there are security configurations in Jenkins. And here, you can configure security realm, which is actually the authentication. So you can set up various sources of authentication. It means that ability to understand who is the user. So it may be internal user database. You can connect LDAP. You can connect Unix and these other plugins that are dozens of various ways to identify users in the system. But then, even if you know that there is a user that this user has logged in, we still need to rise it. So we can understand which permissions user has on the instance and which actions he can execute. And this is managed by authorization. Naturalization, there are also many plugins. Currently, I'm using a whole strategy plug-in. But you may see that even on my instance, there is a number of various extension point implementations configured. How a whole strategy plug-in looks like from a user perspective, I hope that everybody on this call has already tried that. Here, you may see that there is Manage and Assign Roles page, which is available when you enable it as a authorization engine. And what you can do, you can configure multiple roles. For example, project roles and agent roles. Why does it write slaves here? I will show a fix to that, maybe not. But yeah, what you can do in this plug-in, you can actually create multiple roles using regular expressions. For example, we can say Job Developer, let's say Project A Developer. We know that there is a folder A Jenkins. And we say that anything under this folder is accessible by this developer. And we can say that he's able to configure jobs there, delete them, read, of course. Oh, sorry. I'm editing another project. Yeah, we had this role. Here, we can, yeah, this is a new feature which was released yesterday. We know that there is no matching projects so far, but we will create some later. And here, we can just set some check boxes. Each check box is managing one of Jenkins permissions. Permissions are also extensible in Jenkins. So depending on the plugins you have here, you will get different sets of permissions. Anyway, I configured something. It doesn't really matter for this call. I saved that. And then once roles are configured, we also can assign roles. So you may see that I have a number of non-existent users here. And actually, I only have user, I believe. So let's see whether we have user account, like not, maybe yes. And here, we say that user is actually a Project A developer. I hope I have a user from the instance. No, I don't. So we can always create our user. Okay, user, okay. So now we have another user, and you may see that this user has permissions to browse jobs, but he has no permissions to launch anything because admin didn't grant him permissions. I mean admin. So now as admin, we can save it. Let's create folder A. Okay, and folder A, we can create a job. Let's say full. So I just created an empty configuration. It doesn't really matter for the discussion. So here, we may see that it's executed. Now if we log in as user, we should also have permissions to at least access this job. So job A, full. And here you may see that we now have permissions to delete the project because it's what admin granted. Due to whatever reason, this admin didn't grant permissions to actually run the jobs, but yeah, it's how I configured that. It doesn't really matter in this case. So this is what the plugin does. Actually you can just configure roles and this plugin is pretty scalable in terms of how many roles you can configure, how you can configure them. It's not that scalable in terms of performance and in terms of web UIs. And it's one of the GSOC project ideas to improve user experience of these pages. But yeah, what we're really interested to know today is how it's organized internally. And before we proceed to that, are there any questions? Okay. Questions, anybody? Okay. No questions. So then yeah, we'll probably just proceed. Let's take a look at the architecture. The entire code base is located in GitHub for almost any other Jenkins plugin. There is a role strategy plugin. And actually it's the common structure of Jenkins plugin. It's a Maven project. It's a Maven project which uses Jenkins plugin form and yeah, the most of configuration is defined there. So in the plugin form you will only declare some dependencies. For example, on other plugins and also on some test tools which are not included in the base package. So that's it. And the rest is managed by a parent form. And then if you're familiar with Maven projects it's a common Maven structure. And what we need to know here that there are Java classes, there are resources which implement the user web UIs. And there is also a web app because a web app is an old way to manage resources. In the newest plugins you will unlikely see web app. But here there are some contents here, also new contents. So for example, CSS files located here also JavaScript components. This is the UI content. But the rest and the most interesting part for us today is Java code base. And it's easier to show this Java code base actually is in IDE because due to historical reasons the code is scattered across multiple namespaces or packages. Why it happened originally, this project has started by contributors from Michelin. So they created a base architecture for the plugin. They created this class which is a herter of the plugin. We will talk about it later. Then yeah, this plugin was created in 2008. Then in 2011 I have taken ownership of this plugin. I was working for my previous company. We were using our own company package. So you may see that there is a number of classes here as well and finally now there is a recommendation to actually use or JNPCI plugins for strategy package for new development. So if you create new features, it's better to put them here. It may seem it would be a bit complex but that's how it's implemented now. But yeah, for the starters, we still need to begin from this class because it's the main JNPCI extension point. If you scroll here, you may see that there is a role-based authorization strategy which extends authorization strategy. Authorization strategy is an extension point in Jenkins Core which effectively defines UIs. So if we go back to manage security configuration, this is actually it. So authorization, this drop down is a list of extension points implemented with authorization strategy. And there is actually other implementations. So we can go, for example, Jenkins extension points. I usually forget what is the location of this page but yeah, there is extension points defined in Jenkins Core. You may see that there is a pretty long list of extension points, but one of the first ones is authorization strategy. And here you may see that there is a number of implementations available in open source, three implementations in Jenkins Core, then there is GitHub authorization, GitLab, matrix authorization, and also role strategy. There are more implementations available, but today we are talking about these ones. And here is our plugin. So yeah, it's one of the implementations. It is organized as a classic Jenkins extension point. So if you have already seen plugin developer guidelines and recordings which describe how Jenkins is developed, it's one of the classic implementations, but yeah, this implementation is a bit old. So the code was created in 2008 or later, but yeah, you may still see the descriptor. So the descriptor is content holder for all UI implementation for static methods. And yeah, when we talk about extension point we use UI, it includes part, which is a base class and the descriptor. And yeah, as I said, this is a bit old style and if you develop new plugins, there may be better ways to do data binding or whatever. So here, for example, when we configure the project, there is a method called new instance. It's currently located in the descriptor. In new implementations, it would be just a data-bound constructor or something like that. But here you may see that there is a bunch of code here because we manually process form data in order to retrieve entities and then to submit them. And there is same logic for reading data for the disk, from the disk. So yeah, everything is implemented manually. There are some advantages of that, but yeah, there is also a lot of disadvantages. For example, there is ongoing project to implement a configuration as code support, but yeah, it's not there yet. Okay, do you still follow me? I assume yes. So if you have any questions, just stop me at any point because I may be jumping from one topic to another and the code may be quite complicated, especially if you didn't take a look at it before the meeting. So please feel free to interrupt me. Okay, back to the main class. So yeah, main class includes a lot of the stuff. For configuration as code compatibility, likely there will be serious refactoring applied here, but as an extension point, extension point is relatively simple. What we need to implement, let's take a look. So there is authorization strategy. We can click here and we actually learnt in the Java doc for this extension point. You may see that there is a number of methods which are abstract, and these methods get the ACL for something. And ACL is just a common permission management entity in Jenkins, and you can receive ACL objects for jobs, for computers, for nodes, for users, views, et cetera. And this thing is actually used to retrieve permissions. So when you navigate through UI, for example, let's go here. You may see that there is a number of controls here, just to access this web interface, you need Jenkins read permission, then to manage Jenkins, you need the Jenkins administer permission to manage credentials. Yeah, you likely do not need anything for jobs in order to see the job you need for this interface, you need job discover and job heat permissions. In order to launch the job, you also need the job build permission. So every time you open Jenkins web interface, there is a number of permission checks being performed. Each time you reload this page, each time you access particular components, for example, we can go to test here, there is a more buttons, there is build, then there is delete project, there is a permission to delete project. If we have a build history for builds, you can also delete things, you can mark them as keep forever. And all of that is managed by permissions. And there is also move button. So move button comes from folders plugin. But even if a role strategy doesn't have direct integration with these folders, since the plugin and the role strategy use common APIs, you still can manage permissions for that. So everything is managed, everything has a lot of permission checks and all of that passes through this class. So if you want to get a permission list for computer, we get this ACL for jobs, this ACL, et cetera, et cetera. In the plugin, as we've seen in the web interface, there are three types of permissions right now. Let's take a look, manage and assign nodes, manage roles. So here, global roles, project roles and slave roles, which effectively means agent roles or not roles. What it means, we manage data only for three entities. For example, there is no view permission management. There was a pull request, but it has never been completed. There is also no user-specific permission management. Probably it doesn't matter, but it could be done in this plugin. But yeah, we have three entities. These three entities, if you go back to the code, they're actually visible right here. So there is a global project slave, which are string values. There is also an iteration in another package role type, which actually does the same, but yeah, as an iteration, which improves the performance of some APIs, but yeah, still the main cause, due to compatibility reasons, mostly uses strings to access the data. And what is this data is? Actually, it's what the display in web UIs. So we have roll maps for each type of global project slave. For each type, global project slave, we have a roll map, which is stored in the container. It's persisted on the disk. And each time the plugin needs to provide ACL for permissions, it goes through the methods. For example, if you want to get a permission for the project, for example, our test job, you may see that actually we request ACL for abstract item, it's here. And for abstract item, it includes not only job, but various components. Actually, it's not widely used in Jenkins right now. Here you can retrieve ACL. And this method actually goes here. This is a default roll map implementation. So it takes which roll map to take, which item name to retrieve, and then it receives all the information. So how this roll map is organized? There were some changes in the recent release, but effectively for each roll map, since we have global permissions and we have local permissions, what we do here is that there is also way to inherit data. So for example, inherit ACL, what it does is actually combines root ACL and also roll specific ACL. So it means that if you request permission for a project, so I clicked some bits here and some bits here. And our user, if we identify them, what he will get if he accesses a project, he gets permissions here and gets permission here always if he belongs to this group. So it's combined at this level. But yeah, in any case, we try to build this ACL and actually here we rely on the roll map. Roll map is a relatively simple entity, which just implements roll map. So for each roll name, you have there is a granted rolls container. So for each roll, you have a set of modifications or seats, which actually associated with this roll and this map is stored here. Effectively, it's a combination of multiple entities. So roll is what you configure here. So for example, a roll admin, it has some permissions and the roll entity is located here as well, but you may see that it has name, it has pattern, it has some description, which is not publicly used in a web UI right now. And there is also a set of permissions. Then we map it to the container here. So set of strings. Effectively, this set of strings is assignments we have in another control. Okay, manage and assign rolls, assign rolls. Yeah, so you may see that, yeah, I should have created a better configuration for the demo today. I didn't prepare to that, but yeah, whatever. We are taking a look at the hierarchy section. So here, this is set of seats. It may be either users. So for example, here we have a user user, user admin, we have also anonymous. We could add authenticated. So these are also seats defined in Jenkins directly. And if our authentication engine supports groups, then we can also add the groups here. For example, if you use old app or if you use GitHub as an authentication engine, you can manage groups and the plugin also supports that because in Jenkins, actually each group will be a set of seats which you can manage via these assignments. So that's how it works. And yeah, they are stored here. And you may see that the results cache because the plugin needs to provide good performance and what it means that we need some caching. So here we use standard caching complementation and do not recall which one. Yeah, it's cache builder from Guava if I recall correctly. And yeah, here we just use this default construction cache. So when we access roles, et cetera, it's been fetched relatively quickly but you may see that cache has some expiration time. And it means that during the breaking modifications, the cache also needs to be flushed which is a kind of security concern for the plugin because if you have cache, you are responsible to properly manage its validation to keep your plugin secure. Okay, what is the main method? And if we go back to role based authorization strategy, you may see that we operate with ACLs here. So what is ACL in Jenkins? Let's take a look at that finally. So ACL is actually an abstract class. This abstract class, yeah, you need to download sources. Yeah, I did have sources for this version in my main repository, but yeah, let's just go to Jenkins Java doc. Yeah, Jenkins project posts Java doc for all companies. So here you may see that there is our security entity. Actually it just controls access to the data and here you may see a number of methods. And the only method which is abstract is this method has permission. It means that whatever ACL entity we produce, it should be able to answer whether this ACL has permission for particular authentication. So authentication may be, for example, my current user or Jenkins admin, permission that may be, for example, job build or job execute or whatever. And this particular permission entity should be able to answer these two questions. So ACL is being retrieved for particular item. And it means that if here, for example, we have got ACL which retrieves data for the project, it means that if there are different permission configurations, we should return different ACL objects here. And that's why actually the plugin creates ACLs each time on its own, especially when it inherits the data. So here you may see that, yeah, we create a new ACL on each request, which is definitely not good from the performance side and it would be one of the potential topics for performance polishing. But yeah, that's how the plugin works now. And you may see that actually here just combines permission from child. And then if child has no permission, it takes permission from parent. What it means that child for us, it's always root ACL. So if you take here, here's a child, if I recall correctly, I mean, maybe not. Let's take a look. No, it's parent. So what it means here, that firstly, we consult with child ACL. And it means that we consult with role permissions. Just a second. It's here. So firstly, we consult with project permissions. So then we consult with global roles. And if it doesn't work, then we just return false. So this is the default behavior. It's done because this one may be a non-conclusive because we can return permissions, but sometimes it may be better to even invert this logic, which could be also a potential performance improvement. Anyway, this how it works. So let's just repeat that. So when we need ACL, we provide ACL for particular objects Jenkins requests that. And then it uses this ACL for performance checks. Then here, ACL is retrieved. Yeah, you may see that there is a query here, but effectively what it does, it queries a roll map for item names. And then it gets ACL, which would operate with this roll map and which would also combine with root ACL. So effectively it will be mesh all this permission graph for particular fetch. So item name, for example, for job or for agent, we built this map and then return this ACL as a result. And Jenkins will use this ACL as many times as it wishes to render to their web UI. That's how it works. It's not the, well, it works. Obviously there is a lot of performance improvements can be done there, but on the plugins, actually, our main objective is to build this object in a quick way. So here, there was some enhancement in the last release. And thanks a lot for that. So here you may see that we actually go through all roles and verify that our regular expression patterns are matching and after that we do this permission checks. Obviously not for all permissions we needed at all, so some preemptive caching could be also helpful, but yeah, finally we just produce a map of whatever roles and permissions accessible for this particular user and for this particular object. And it's returned back to ACL, which will fetch that. And yeah, actually this is how it works. So yeah, it's just one method, which goes with the first all patterns, it will build us a roll map and then roll map. Here we can see that there is also a ACL constructor here. You get ACL. Effectively for roll map it just creates a ACL implementation which takes controlled item, we will be verifying and roll type because we need it for some permission checks and logging. And yeah, pretty much that's it. So it's a big map with some object conversion, but at the time we need to fetch permissions, we just go through all this logic, built map and then for this map we determine which permission actually granted to the user. This is how permission check logic works. And if you don't have questions now, then probably I'll have questions to you. I have a question. Okay. What exactly is a root ACL and how does it differ from a normal ACL? Okay, so root ACL, let's take a look. Root ACL is effectively ACL for global. What is specific here? Global ACL has no regular expressions. So it relies only on assignments. It will never check patterns. So it operates much faster than project rolls. But yeah, here, it's just a roll assignments. So if you're admin, you're admin everywhere. If you're authenticated, you're authenticated everywhere. And we append this configuration to project rolls when we produce the final ACL. So these global rolls will be used as addition to what project-specific rolls or agent-specific rolls you have configured in these configurations. Does it answer your question? Yeah, yeah, thank you. Yeah, so if you have a question, yeah. I have a question, John. Yeah? Can you please explain those three types of rolls, global, slave, and another one in bit more detail? Okay, so global rolls is this configuration. Actually, it's global rolls. It applies everywhere across Jenkins instance. And here you may see that you actually can manage all permission groups. So there are permission groups for credentials, for agents, for jobs. Here you can configure everything and it will apply globally. So for example, here administrator has actually Jenkins administrator permission. All other check boxes are not really required in this configuration because this permission in the current setup gives you all permissions across the Jenkins instance. And then if I assign this permission in AscendRolls, so here you may see that user admin is actually AscendRollAdmin. And it means that I will get these global rolls everywhere. So everywhere across Jenkins, I get admin permission. This is the first roll. And the two other ones is Project and Slave. And the two other ones is Project and Slave. So Project, well, it uses obsolete terminology. But yeah, what it really means that project rolls is any kind of item within the system. So for example, folder, job, and anything else you can actually create from here. So new item, you may see that there are multiple project types. Everything is controlled by this permission. Moreover, builds are also controlled by this roll. So for example, if we take test, you may see that there is a build. And the Jenkins technically allows to configure different permissions for different builds. It's supported by its architecture. It's not supported by the roll strategy plugin, but still all permissions you define actually come from this table. And last but not least is about agents. So currently we don't have agents in Jenkins, but actually we could have one. So for example, there is built executor status. There is only one agent master. But we can create another agent. It's something like that. So yeah, there is also some configuration to be done, but we are not really going to launch the same agent. So we can just put something like that and label, for example, Linux, even though a run with macOS, okay. Let's say it's macOS to be fair. Okay, so this is an agent. What we can do, we can configure different permissions for master and agent. And yeah, let's take a look at these permissions. Manage and assign roles, manage roles. So here you may see that we have whatever I think. So here, let's just look here, but okay. So let's say agent team A. And we say that my agent, it's a regular expression pattern, but name is a valid regular expression name. And then here, we have that A also let's say team B. So I think that here we created two teams for my agent and we can say that for team A, for example, can configure agents, can connect agents, can delete, disconnect, build, whatever. So this is management for owners. But for team B, we can say that the user can only build on the agent. What it actually means, I wanted to talk about it a bit later because it's a complicated topic, but in Jenkins, there is also a queue authentication. So it's not only about the web UI, when you launch a build, for example, if you click here, you also run some execution on the queue. And this execution can actually land on a master on an agent and it's possible to protect agents. So for example, by this permission, if I have authorized a project plugin installed, I can say that on the team B can execute builds on a particular agent. It requires some configuration, but it's possible. And the demo I was showing, it's a demo Jenkins configuration as code. Actually, it does that if you take a look at plugin stick, there is a plugin called AutoRaceProject is here. So effectively queue security is configured here and this is an engine, how we do that. So the Roll Stretch plugin allows managing that and it's just one of the ways. Okay. Yeah, thank you. Okay. Any other questions before we press it? Hi. Yeah, hi. Hi, Oleg, the third knob. So I wanted to ask, will we have such KT's and deep dive sessions for all the other project ideas as well? Well, I believe if I answer to this question in the beginning, but it depends on the projects. So as mentors or as students, students are welcome to request knowledge transfers from mentors. We ask mentors to do it during the community bonding. When the projects are actually selected. But yeah, doing it before the project application or during the project application is also a good idea because it gives students some information on what to do. So if you're a mentor and if you have some time, if you have an interest student, of course it would be nice to have a KT. Okay, cool, thanks. Okay. So let me just finish the code dive. There are some interesting bits in this plugin. For example, there are some dangerous permission handling logic. It actually has been done due to historical reasons because there are some combinations of permissions which are not actually recommended in Jenkins. I won't be able to show you it in the web UI because we have protection from that. But so currently dangerous permissions are disabled. For example, there was a permission to manage plugins and it was possible to configure plugin management before, without a given code administrative permissions. But effectively it almost the same in Jenkins terms because if you're able to install a plugin, you're able to install any plugin, including a plugin which does some malicious code execution. So at some point in the security team, it was decided to limit a number of permissions by default and there is a dangerous permission engine which actually hides these permissions or prints administrative warnings if they're configured and if they're not advised. So currently it's hidden so we didn't see it in web UI. Another topic you may need to know about is about mattress. So what mattress do actually they provide some additional integrations. Story behind that at my previous company, we had some issues with performance of raw threat to the plugin and we decided to have another engine based on ownership plugin. So ownership plugin is just a separate plugin but it integrates with role strategy and some other plugins and the security engine is called Orange Base Security. So you may see that it includes role-based strategy, also job restrictions, plugin and rise project which I was referencing today. And what it does instead of configuring multiple roles, actually it configures only two roles. Current user is owner, is primary owner, et cetera. And then you can configure roles not by this matrix as you may see, there is for example, matrix with assigned roles but by managing permissions directly as owner. So if you have access to this demo it's something you can see there but you effectively able as Jenkins administrator to assign owners to each job or to each folder and then this owner configurations it will grant you some permissions. And on the role strategy side, it was done by macros. So you may see that it starts from special symbol and then it's considered as a macro in role strategy plugin. So macro roles are being handled a bit differently because when you have macros it's actually being created dynamically. So it's not like a regular expression it's an invocation of extension point. So here you may see that actually there are two kinds of macros, one is role macro extension. So this is what we have here. There is also a user macro extension but it's not really implemented and it's not really used anyway. But yeah, for macros, what it does it's a separate extension point which has its own caching. And yeah, this macro engine allows to somehow calculate which users match this permission dynamically. So for example, here you may see that just second macro extension, I believe it should be here. Yeah, so it checks, it actually has this method has permission. So you may see it here. And effectively it means that this macro makes a final decision whether a user has permission or not. It comes at some performance overhead but on the other hand, you do not need to compare multiple regular expressions each time you fetch the data. So at some point I implemented it as my solution for performance issues in the plugin. It's not an ideal solution but yeah, it came from advanced user management features. But if you work on the performance plugin that yeah, it's something you need to keep in mind. Okay, I was talking about performance a lot today. Probably we should talk a bit about user experience. So how it's organized. Jenkins has its own engine, it's based on Jella. So you may see that WebUIs are mostly written in Jella for this plugin. Jella is a weird combination of XML, HTML and Java code. Actually not even Java, Groovy. But yeah, you may see how it works in real. For example, this is an index page which offers you controls, talks, the data. So effectively this is a configuration for this page. And yeah, there are ways to create macros. There are ways, for example, there is a reusable tech library and then we have two hyperrings. And yeah, there are also tables. For example, a server in global roles. Yeah, you may see that, yeah, there is some magic behind that and you may also see that there is embedded JavaScript logic which does something for management of these WebUIs. So it's how the current interface is configured in this plugin. It's far from ideal. It would be great to completely rework it to be honest. So now there is a trend to actually split the management part. So we could have REST APIs and we could have, for example, JavaScript based engine which would interact with this REST API to configure that. So for me, one of the interests in this project would be to actually completely to write this layouts and to do something in modern languages. So yeah, you may see that now it's a mix of whatever. Jelly JavaScript doesn't help, but yeah. I mean, it makes the code more complex, especially things like that. So by using an existing web framework, for example, to react or something like that, you can just rework these pages and simplify them. So yeah, it would be one of the foundation bits for the user experience project in a role strategy plugin. Yeah, you may see that there is a number of such pages here which could be reworked and completely replaced according to your proposal. Okay, so we have some minutes left. Do we have any more questions? And then we have one, do you know what we have there? Just to understand, so we have two projects. One is about performance, another one is about user experience. Is everybody on the call interested in the performance project? Or is somebody interested in their web UIs? I'm interested in the web UI project. Mm-hmm, okay. So yeah, for web UIs, yeah. I think that the work of this mess would be actually an interesting thing for everybody who uses this plugin because these configurations, yeah, it's difficult to maintain that, it's difficult to extend that. The UI is really difficult to use when you have hundreds of roles because there is no pagination there. Then just switching to another interface would help, yeah, thousands of users of the plugin out of the box. Here is just a sketch, but imagine these pages if you have 100 roles here, for example, it's just a matrix. There are some things, for example, you may see that there is highlighting, but yeah, obviously it's possible to do much better with modern web UI frameworks. Yeah. Mm-hmm. Okay, what else do you need to know about this plugin? As I said, development of this plugin is just development of any other Jenkins plugin. So there are guidelines for that. Maybe in HPI run actually does the run, you can call maybe in debug in order to run in the debug mode. So you may see that now it exposes a debug port. So you can connect your ID as a remote debugger and start developing. If you use NetBeans, it's even more easy because there are specific plugins for NetBeans, which save time, but yeah, it's like any other plugin. And once you create something, you can create pull requests. Actually, we already had a lot of pull requests over the last weeks and you're more than welcome to contribute more. So you may see that we have continuous integration instance configured. So every time you configure, create a pull request, actually the build will be completed and you will get test results. So for example, there is a pull request from DeepAunch, one of once related to performance. So it has been tested, it has been integrated and already released. That's cool. And yeah, speaking of tests, all the tests which we run in the plugin now, they're located in this directory test and here you may see that there is actually only some plugins and yeah, obviously it could be improved a lot. So you may see that there are actually few plugins, few tests in this plugin. And for new functionality, I try to develop a test automation and everybody is welcome to contribute more to test because now there is almost no web UI test automation. There is limited functional test automation. So yeah, we can always do more. And regarding test utilities, so right now I do not plan to do a particular knowledge transfer for that. We usually do a dedicated knowledge transfer for test utilities when we get closer to community bonding so that everybody is able to contribute and listen because it's shared between multiple projects. And if you're interested to know more about tests now, we also have some keyties and demos recorded. So if you need more information, just ping me or any other G-Socumenter and hopefully they will be able to send you links if not just a score, that means we have a list of links. Okay, that's it from me. Any new questions? Any newcomer issues so sort of we can start, but... Sorry. What to start from? Any newcomer issues for new issues, right? So we have some issues in the project ideas. Project, I think it's your project's JSOC. So you may see that there are some issues here and some of them are still not addressed. But yeah, my advice to you would be to actually, if you don't have any issues to start from here, firstly you can, if you already contributed some tickets, you can remove newbie friendly and you can take a look at particular issues related to performance or you can just do some exploration. Because yeah, performance in this plugin can be improved a lot, web UIS could be improved a lot. So maybe at some point, if you don't see any other new issues, you could can just find your own ones, diagnose the code base and propose your own patches. And if needed, I'll do my best to report more newbie friendly tickets here. So, yeah, if you need more newbie friendly tickets, so we start from something like 12, I believe. So all of them are closed and yeah, we definitely need to think about more. But yeah, so just ping us in chats and you have taken an extra item, I'll try to create more on this weekend. Sure. Okay. Any other questions? I had a question somewhat unrelated. In the code, some methods have been annotated with noexternaluse.class. And so just let me get the Java doc for that. Mm-hmm. Yeah, so the purpose of this method is to actually prevent usages of APIs in other plugins. So it's a Jenkins internal mechanism which allows to restrict public methods to particular plugins. Because there is no other means available in Java to permit a method from one package in another package without permitting it for other plugins, at least until we use Java 11 and models or other simple solutions. So restriction is our internally tooling for that. Yeah, so basically when I wrote some groovy scripts, I used a method which was annotated with the noexternaluse, but it was working. So I don't know if that's a bug or if that's a feature. Well, it's neither feature nor bug. Groovy actually does not recognize Java annotations because groovy is the label to access many things, including private methods, private fields, like reflection in Java. So it's not a bug. It's how it works. And when you access private method from groovy scripts, it usually means that the API of the plugin is not ideal and could be improved. If you need that. We do not restrict that. So the purpose of annotations is to prevent plugins, at least from including the code directly in the code base. Yeah, it's limited. Okay. So groovy calls are not protected. Okay. Yeah. Okay. If there is no more questions, I propose to close down the recording for now because I have another meeting starting. But yeah, if there are any questions, we can proceed in the chat. And if needed, I'm happy to organize another session. For example, if somebody wants to talk about web UI specifically, how it's organized, most probably you know more about web UI than me, but I'll do my best to help. Okay. Any questions? Yes. I hope that this kitty gives you some information about how the plugin is organized. Yeah. And yeah, I'll make sure to post this session to link it to previous kitties about the plugin structure in general and about the plugin development. And I hope that it will help you with some contributions. And if needed, just reach out to us in the Gitter chat and we will provide all the necessary assistance. Okay. Thanks everybody. I'll stop with it. Yeah, I'll stop with the broadcast there then. Okay.