 Okay. We're live. Okay. Hello, everyone. My name is Martin D'Angiot. And today, this meeting is the Google Summer of Code Evaluation Presentations Part 2. So we had evaluation presentations Part 1 a couple days ago, and now we're doing Part 2. This is the Summer of Code week evaluation. So we're done with the coding phase, coding phase one. And I want to thank all the students for their participation in coding phase one. And today we have three presentations. So let me share my screen. Can you see my screen? Can you see the Not yet. Okay, sorry. Okay, I think it works now. Yeah, it does. Okay, so we have three presentations today. So we are June 26, 2019. And the first presentation will be the Plugins Installation Manager CLI 2 library by Natasha. The second presentation will be Remoting over Apache Kafka with Kubernetes features. This will be presented by Long. And the third presentation will be the Working Hours Plugin UI improvements by Jack. Okay, so before we start, I would like to ask anybody who is attending that I want to say that we're going to be taking questions during the presentations and after. And you can post your questions to this Gitter Chat. That's jenkinsci slash jsoc-sig. Okay. And yeah, one topic to it that we start from presentation by Natasha, then it will be Jack and then it will belong. Sorry for my mistake. The order in YouTube announcement was different from the Google look. Okay, so the second will be Jack. Yes. Okay, we'll do that. Last thing I want to say is, okay, so the way this goes, the student will present their presentation and then mentors will have a chance to comment or ask questions. And then we move on to the next presentation. So I would like to now we'll stop my screen share. Okay. And now I would like Natasha to present us the plugin installation manager with the CLI, which is your project. Natasha, the floor is yours. Thanks. All right. Yeah, I'll go ahead and get started. So hi, my name is Natasha Stopa and my Jenkins Google Summer of Code project is the plugin installation manager library slash CLI tool. Just a quick overview of my project. There are sort of two main parts. There's the CLI tool, which will allow users to have more control over which plugins they want to download and use for Jenkins instance and more easily see information about specific plugins. And then there's the library, which will sort of serve as this unified way to do plugin management. And then, yeah, some of the key features will be that we can download plugins before Jenkins starts. And then it'll also offer better plugin tooling. So first I want to just motivate my project a little bit. This quote was taken from the offer plugin management tooling epic that this project is based off of. So everyone is reinventing the wheel, partially implementing the quote unquote details of plugin management, signed metadata, artifact checksums, plugins detached from core dot dot dot becomes obvious Jenkins should provide adequate tooling for plugin installation outside Jenkins live instance. So plugins are key to the extensibility of Jenkins and plugin management has been somewhat of a pain point. There's currently lots of different ways of doing this, each which has their own strengths and weaknesses. A lot of people have been trying to do the same thing multiple different times. So the goal of this project is to really streamline plugin management across the different components, and then also offer additional features such as viewing security warnings and available updates. So the first part of my project, we kind of started by trying to pull out plugin management from core, which ended up being pretty difficult. So you probably can't really see this visual, that's okay, it's more just for visual purposes. But each box represents a class related to plugin management. And then each line in that box represents some method and all the red lines are dependencies that would also have to get pulled in or refactored. And then additional boxes, same thing, are just related classes or things that would also have to get pulled in. So this ended up being a much more difficult approach to kind of start with. So we ended up changing gears a little bit and trying to go about this a different way. But I just wanted to bring this up because we did look at this, but it ended up just being very complex with the dependencies. So a large part of phase one has been focused on converting the install plugins, bash script to Java. And we wanted to start here because there's a lot of limitations with this bash script. It's difficult to maintain and extend. It doesn't get all of the current up to date data from the update center. So there's kind of two portions, as I mentioned to this. There's the CLI options. And then also the library. I'll go over each of these and what I've implemented so far in a little bit more detail. So currently, these are the available CLI options if you were to download and try out the tool today. So the user can input a list of plugins either through the CLI or through a .txt file that just contains a list of these plugins and their versions. The user can specify which directory they want their plugins to be downloaded to. They can also include a Jenkins core file. And then they can also view security warnings for all plugins. The library so far works like this. Basically, first it tries to find when installing plugins, which plugins are already installed or downloaded. So first it'll check the plugins that are in the war file. Then it will look at plugins if there are any plugins installed in the specified directory. Then it will go ahead and actually download those plugins and their dependencies. And it'll ignore them if they're already downloaded or installed or upgrade them if there's an existing version but what's required is a higher version than that. And then it'll download those plugins from the URL either based off of the plugin version or if the user can specify also a version specific specifiers such as latest or experimental. So go ahead and download those and their dependencies and put them in a folder. So I have just a quick demo of kind of how that works. Okay. So I have my jar file. I can go ahead and specify a list of plugins here. I'm just specifying one right now. And then I've also included my Jenkins war file. So as you can see, the plugins will actually start downloading. We'll go ahead and check and see what plugins are installed in our war file. Right now I just use kind of the default plugin directory. And if there isn't one, this library will go ahead and create it. So right now we don't have anything in our plugin directory. And then for each plugin, we'll go ahead and grab it from the URL and download it. And then for each of the dependencies, go ahead and do the same thing. Okay. So I think downloading all of these does take a little while. But yeah, you can see that basically if we have an installed version that's less than what's required, we'll go ahead and upgrade that. And then if we have an already installed plugin, we'll go ahead and ignore that or skip that too. And then I guess I also want to add, I did present this on the platform SIG meeting last week. And we had some issues with recursively resolving dependencies. And that has since been fixed. Okay. So while this is downloading, I have a couple other things I'll go ahead and share. So let's see. So we just recently released an alpha version. So feel free to go ahead and try it out and give me feedback. Looking forward to hearing more about what you guys think. And then just in terms of next steps, so far, it's very much a work in progress. So there's a lot of work to be done yet. So we want to make parsing more robust. We want to add full support for actually viewing all the security issues and available updates. We want to support different input formats and incorporate into Jenkins Soccer. So I did just see somebody asked a question about how compatible it is right now with Jenkins Soccer. So that's something I was actually working on last night. And it's not quite there yet. So I think some of the defaults that I've set for specifically if there are plugins that fail to download, I have a default set right in there right now to just create a file in the current working directory. And I know that that fails with Jenkins Soccer. And then there's also a couple other issues with right now in the current installation script, you can basically getting the update centers is set via environment variable. And I have a hard coded right now. So those aren't changeable. But that's something that we're aware of. And we have a jura ticket for so that should be resolved sometime in the near future. Okay, so let's see, I think that those are probably done downloading now. So yep, so I just wanted to go ahead and show you we have all of our plugins installed. And then I did forget to show you in my plugins dot txt I did also include a failed plugin that should fail as well. So this is the part that I was talking about that currently there was an error in Docker. Basically, we create this text file that includes like the failed plugin. And I know there are some issues with that. So yeah, I think that's pretty much all I was going to show today. Yeah, we have meetings twice a week at 6 p.m. UTC, you can check out the repository and our Gitter channel. Yeah, so are there any other questions or feedback? Actually, I have one technical question. Yeah, what happens when the download center stops responding in the middle of the operation? Are you talking about like if the plugin is downloaded like halfway or are you talking about like if the URL can't be resolved? Sometimes the download center goes offline for uncontrollable reasons, or maybe let's say I'm on an unreliable internet connection. How does this script behave in that case? Or how do you plan to make it behave? Yeah, so I think in a case where you can't actually access the download center right now or say if there's some error with actually downloading those, we'll just print that there was an error. I think that we probably in the future might want to create a couple different options on how to deal with that. So one problem would be say you are downloading a plugin that is a dependency for another plugin. Obviously, it's going to be problematic if you can't download those dependencies appropriately. But in some cases where you just want to say view the information about what those dependencies are or available updates, maybe in that case, we wouldn't necessarily want to stop the whole procedure. Maybe we just want to say oh look, we can't access this right now and carry on. So I think the goal is to make that configurable where the way that would be handled might be different based off of the different use cases. Does that answer your question? Yes, thanks. Okay. And then I think there was at least, sorry, one other question. Yeah, so it'd be nice to support Maven Repository as an installation source. Yeah, I think that's something that we can probably do. And I can go ahead and create a Jira ticket or that's something you guys can do too. And then we also had talked previously talked about I think on a different call about supporting caches. That's something that also there's a ticket for we just haven't quite gotten there yet. Okay, so if there's no more questions, I'll go ahead and pass it off. But again, really want feedback. Feel free to try out that alpha and just let us know what we can do to make this tool really usable, something that people really want to use. Okay. Thank you Natasha for this presentation. So, Christian, would you like to have a few comments? You are the lead mentor on this project. Would you like to make a few comments? Sure, I guess the project has been going well so far. I think it's really good to be able to see the downloads that are happening, like being all around the tool and at least build the plugin folder locally. Again, if you have anyone has any suggestions or looking to see anything, please feel free to add it to the Jenkins Jira. We'll maybe look at the potential phase two or phase three, but I think it's been good so far. Good job, Natasha. Thanks. I have one more comment too. I just wanted to thank all the mentors and org admins. Thank you guys so far for all the support and I look forward to continuing to work with you. Thank you. Thank you. Okay. All right, so let's move on to the second presentation, which is the Working Hours plugin UI improvements. And this will be presented by Jack Cheng. Okay, so I'm going to move it to you, Jack. It's all right. You have the floor. Yeah, thanks, Martin. Okay, I'm going to share my screen. Okay. For the first code phase, and I've been working on working hours, plugging with Jeff and introduction. The Working Hours plugin is a plugin which can help people set allowable build times and set excluded days and which could schedule our build. And we have control of the times of the days and the build will be executed. But the plugin needs more improvements, like you know, currently some plugins are using Jali. I don't know, maybe most are using Jali to write the configure page. And so if we want to import a date, there is no provided components for us to import a date. At least we could not select a selected date. We just can import a hard-coded date like a number with slash. And so we are actually thinking about using some components, some third-party components to have a selected date. And also in setting time ranges, and the time ranges is just the allowable build times. So in order to find some usable UI components, some hyperlibraries, and we are thinking about using React. And why using React? Because using React, we got some powerful data picker and we could pick data, pick date like a magic, and we can have a slider to choose time ranges. And also we got some ability on designing a flexible responsive UI. And should I show some part of my demo? And maybe that would make it clear. And here is what it looks right now. And for time range part, we can have a slider, we can use a slider to select a date, and people could import data just type in. But also we could use a slider just to that time. And for excluded dates, we can select the date, use the time picker, and this is a React component. And we can select date or yeah, so she has such a mouse to like this. And we needn't to type a hardcoded data string. And you know, sometimes it's easy to type a round date. And yeah, let's go back. Also, if we use React, we also could take advantage of Webpack. And if we use Webpack, the user interface we rotate, you know, in common ways of develop some JavaScript projects. Some of your functions will be used to pollute the global namespace and like something if you import some libraries with a script. And for example, you import jQuery and in the global namespace, all the plays could use jQuery, but we actually that's not expected. But if we write a React project with Webpack, the output will be wrapped in a function and that is executed instantly. Yeah, so our project won't pollute the global namespace. We won't affect the other plugins. Also, if we want to use React, we are not using, so we are not using jelly and sometimes stapler anymore. And we need to split our front end with back end, no, separate them. So we found a solution to divide the front end and the back end. And we just doing this by setting a mountain point in the jelly file. And usually it's a it's a simple tag with a unique ID. And then in the block below, we got a script tag and it will import the file with Webpack. And by doing this, we got our React app mounted into the place into the mount point. Also, we are not taking advantage of some stapler hyperfunction. We are not using it anymore. And we may need to define our own backend service. And I'm doing this, learning from the blue ocean. Although it's just using stapler, but it helps me a lot. So we got a function called geodynamic and it will receive the request and we will add its parent URL and relate it to the process function. And then it will be returned to the front end. And yeah, set HTTP request and this is from the front end. It's just using an XLS to send a post request. Okay. And actually, I'm thinking about building a common way to develop plug-in with React. And I don't know, maybe the working hours plug-in may be the first one to develop common plug-in with React. So I'm thinking about if people want to design a more custom UI, if he wants to use some maybe more than frameworks like React, like some other headmaster JS frameworks, we could produce a way to build a plug-in with them. And this is what I'm trying to do. But for the difficulties, it's just a problem I found during my attempts if you know or not, Jenkins is using prototype.js to provide the JS functionality. And it's maybe a little bit old. It has some incompatibility with some React packages. And yeah, so maybe not all the packages, but we should be careful. And currently, we don't know how many packages it will have incompatibilities, but React is okay. And for next phase, yeah, I will complete the backend service and data validation. For now, the backend service is just a function to store data and return data. And maybe we need to do more things like data validation and excluded data check. And also, we could do something like workflow refinement and also for the things before we could make a scaffold, maybe a boiler plate or more common way to develop a plug-in with React. And I think that will be kind of useful. Okay, as I see more on the user interface, yeah, I see the excluded dates. For now, we could select the base time zone because if excluded, the date was set. And if the people who use the system is divided all over the world and the date starts in their local time zone will be different. Yeah, and so we need to define a base time zone to put date to start the excluded dates and then to make it consistent. Also, there is a preset we could select the date. Like if we set the rigoring calendar, we could select the next gaming day and we apply the choice. We apply the choice and it will be automatically set to the fourth Thursday of November and it will infer the next occurrence. Like it's on the Thursday, November 20th. This is one of the new features called presets. Also, there is a dynamic date. We could select a dynamic date, which means the date is not static. It depends on the order of the day you set. Some hard days, it's not static and maybe it's on some Sunday, some Saturday. And this is what is useful. Also, we could select a static date. And the effect if we integrate it into a plugin development, it will be something like that here. And for this part, we will make another build script and we will generate the files into a plugins web app directory and write it right under the just directory and we could inject the files using this script. And so in that time, we could provide a way to how to reload the web app in Jenkins web page. Okay. I think maybe there are a lot of questions I need to answer. Okay. Sorry. So, we are at the screen. So, one of them is that one of four can mean suggest us questions. Yeah. Okay. Okay. So, okay. Have you reviewed Jenkins design language and Jenkins JS bundle? Yeah. I know them but Jenkins design language is it's styling is different with classical Jenkins styling and maybe I think we, I think the plugin we wrote for now should be better consistent in the style with the other plugins. So, although the plugin I wrote here is not it's not using jelly components but I, but I still set the style of the components to the Jenkins styling and yeah, I think that's more comfortable. Maybe that's more consistent with Jenkins. Thank you. Okay. And sorry, Jeff. Should we embed the name of the plugin to make yeah, yeah, yeah. Yeah, we could embed the name and maybe we could have some hushed the number and to make it unique and the other, the other, the other scripts won't be, won't affect us. Okay. Do we have a plan to adjust the potential prototypes? Yeah. The prototype, the prototype.js, this library, uh, uh, yes, was effective once inference, though, my development while I, while I am using a library called entity and the, called and, called entity and the sum of its, uh, usability of, of the map function has conflicts and I, so I gave up using the entity library and I choose to write it in, in simple CSS. No, we actually, and we don't have a plan for now, but um, oh, yeah, uh, maybe there are some, or maybe there are some, uh, solutions for that. Well, let's talk about that. But, uh, I will, I will post the data later, maybe in the, in the, in the, in the GitHub chat is a, is a poster. It, it's a poster wrote by, uh, some other people. Is it? Okay. And is there a plan to embed into, uh, in case we have a UI, yeah, ifrim or do you plan to make it look a little bit closer? No, no, no, no, we are, we are not using ifrim because I, because I think, uh, React provided us with some ability called mountability and we could mount our application to a certain point. Yeah. And I don't know, I don't know, uh, for other pro, for other approaches, like, like what approaches? I don't know. Oh, sorry. Yeah, no worries. If the question is not comfortable to you, we can just take a top line. Yeah, the purpose is to start the discussion. We can come up on the questions later. Hey, Oleg, are there any people either in the community or, or CloudBees that can, can give us sort of design help? Well, we can ask around. That's for sure. Okay. So I definitely know a couple of names. So if such help needed, I can try sending a demo to them and maybe we will get some feedback. Yeah. Just, just regarding like, like, look and feel and, and styling and stuff. I would probably feel more comfortable just having somebody do a review of the whole thing when we're a little bit closer, if we could find somebody. Okay. Yeah, I'll try to help. So if you follow up on the developer mailing list, we can just discuss it there because the best advice for such cases, if you want feedback, just send something to the developer mailing list. For example, you can send it into this demo, you can send it to the court and you can ask for feedback and it would be a good starting point for all kinds of such discussion. Okay. Well, thank you, Jack, for presenting. I wanted to ask if Jeff wanted to comment on or, or has questions, but you've already spoken, Jeff, but you want to add a couple of things or? Yeah, I just want to say, I'm kind of pleased with this project overall. I think if you just look at the features that we want to implement, it seems like deceptively not a lot, but there's a lot of things like breaking new ground with using React, so we can make use of these third-party components. There's a lot of tons and tons of React components, so that takes some extra time. Just working with dates and times is often harder than you would think, and so that adds some complexity. And I like the approach that Jack is taking towards thinking about with the problems that he's found, figuring out how to make those things easier for other projects in the future. So I'm really pleased with that, and thank you for your work on them. I'm looking forward to the rest of GSOC. Okay, thank you. Let's move on to our third presentation. Okay, so just a moment. First, I want to check that I'm properly sharing and presenting so that the video is recorded properly. So far, you're not presenting. Okay, so I should be hitting the present to everyone button. Is that right? No, you should. Do you want to share the screen? If yes, you should click the share the screen button, because I can make you a presenter, but now we just see a Jenkins logo talking to us. Okay, so here's my screen. Yeah, now we see it. Okay, except it's the loop. Wait a minute. Okay, obviously, I'm sorry, I'm not familiar with this. I'm going to stop. And let's move on to our third presentation. So third presentation is remoting over Apache Kafka with Kubernetes feature by Long. And so Long, I invite you to start now. Okay, thank you. Hi, everyone. I'm going to share my screen. Okay, so today I would like to demo my GSO project. Remoting over Apache Kafka with Kubernetes feature. And yeah, I'm Long, I'm from FPD University in Vietnam. And this is my first time participating in GSO and contributing for Jenkins. And five mentors, Andrea and Kate are left. And so on. And okay, so sorry, I thought I lost connection. Yeah, we see your screen. Yeah, yeah, can you see my screen? Yeah, because my connection is a bit laggy, so I feel that I'm lost connection. So remoting over Kafka plugin is a successful GSO project from last year. And but it has some problems. First, it requires user to manually configure the entire system, which you will have to start their own GSO keeper cluster, Kafka cluster, then start their own remoting agents. And the second thing is it doesn't support dynamic agent provisioning. So scalability is hard to achieve. And that's why this project, it is to solve two problems. The first one is out the box solution to provision Kafka cluster. The second one is dynamic agent provisioning in Kubernetes cluster. Let's move on. So the original proposal is our first one is Kafka provisioning in Kubernetes cluster. Okay, sorry. And dynamic agent provisioning in Kubernetes connected logic using Kubernetes credential, a ham chart to start the whole system. And finally, the version tool release. And what I have done is the first thing I have implemented a Kubernetes factory adapter class to connect to Kubernetes cluster using different kinds of credential. The second thing is a function to launch Kafka and to keep in Kubernetes using Gmail spec files. And after launching Kafka, it will automatically update the URL field. And I also investigated compatibility with Kubernetes plugin, whether we could reduce the code in Kubernetes plugin, so we don't have to implement Cloud API. And the end result is we cannot reduce the code. So we will implement Cloud API in phase two. The last thing is I have written a ham chart to start the whole system in a Kubernetes cluster. Okay, so let's move on to our first feature, Kafka provisioning in Kubernetes. So in global Kafka configuration class, there is a button. And when a user can fill out the Kubernetes information and press the button to start the Kafka and Zookeeper. And when user press the button, it will instantiate a Kubernetes factory adapter and reduce the HTML spec file from resources. Then the Kubernetes factory adapter will pass the credential to create a Kubernetes client and then start them on Kafka and Zookeeper to start Kafka and Zookeeper on Kubernetes. So let's demo, let's move on to the demos. I have started a Jenkins server on my local host. Okay, yeah, as you can see, this is the Zookeeper and Kafka URL. So in the previous, before user have to start their own Zookeeper and Kafka, then input the URL here. And this feature, we can use Kubernetes and input the Kubernetes information. So I used MiniCube on my local machine. And this is the IP as a part. And the next space is demo Kafka. Okay, so let's start the connection. It's success. And I will press the button. And it will start Zookeeper and Kafka on this namespace. And it might take a while to download images. It's the first time. And I preload the images. So you guys don't have to wait in demo namespace. Zookeeper is already up and Kafka initializing. Let's see Kafka look. Okay, so it's opening port. It's success. So why we wait for Zookeeper and Kafka Jenkins server with constantly ping for the port? And after the Zookeeper and Kafka started, it will print the URL here. And the URL will be automatically updated here. And why we can do this is because I have a JavaScript on the jelly page. So here. So what this JavaScript does is it will observe every azure mutation of the API. And it will watch it will watch this element. And if it's element change to success, we will pause the URL here and then update it here. So you don't have to reload the page. Okay, that's it. Let's move on to the next one, which is Hemchart. I will tear down the Jenkins and Kafka to free up some memory, delete all the service and port. So the next one is Hemchart. And Hemchart. Okay, thank you. And Hemchart. Our Hemchart have two dependencies. The first one is stable slash Jenkins. The second one is incubator slash Kafka. And for this demo, I will also start a part in Kubernetes to an agent part to connect to the Jenkins master. Okay. So I have a script to demo Hemchart. What this script does is it will install the Hemchart, then wait for Jenkins to come up by using netcard to bring the part and then copy the password to clipboard. And then it will use configuration escort to launch an Asian computer on the master side. And then it will launch a remote in Kafka, a remote in Kafka Asian part to connect to the computer master side. And then it will open the URL in the browser. And this, the whole thing might take about three to four minutes. And while we wait for Jenkins to come up, I will get all so you guys can see all the service. So we have Kafka, we have ZooKeeper, we have Jenkins, and Kafka and ZooKeeper are already online. Jenkins takes a while to initialize because it has to download all the plugins and configuration. Okay, so here's the dependencies. Kafka and Jenkins. And I overwrite some value for the demo. For Kafka, it will already start a standalone cluster, only one replica. And for the Jenkins, I also inject some plugin and some init script. This is the script for agent part. Okay, so Jenkins is up. And this group will open the empty master on the browser. And because I have a script to copy the password to the port, I can paste it here inside. Okay, so this is the agent computer on the master side. So as you can see, agent part is up. And it might take about one minutes to initiate handshake and fully connect. Okay, so now the agent part can connect, have connected successfully to the master. And we can run a job. Let's run the hello world job. I don't know why. This error is uninspirated. Basically, the agent connects successfully, but there's some work. I cannot run the job. Okay, let's move on. So that's it, the two demo. And the next phase, the plan for the next phase is Implement Cloud API to provision remote in Kafka agent dynamically, so we don't have to start in part. We can create as many as many as we want, depending on the workload. And the second thing is Implement Cloud API implementation with Handchart. And probably more unit has documentation and fix some bugs, like the last one we see, and release version two. And here's the links to the repo, the the channel for project is slash remote. And the project space, and the blog post is I'm drafting the blog post, and it will probably come out at the end of phase one. Okay, so Q&A. Does the configuration support GCSC plugin? In my proposal, I have planned to implement GCSC support in phase three. So in phase three, I might demo some GCSC support. And that's it, do you guys have any questions? Okay, thank you, Long. Is there any questions? Yeah, maybe one additional question is which Handchart do you use as a base? As a base Handchart. I don't think there is maybe the official agent Keynes Handchart from Google. So this Handchart is very stable and extensible, so we can use it. And I also use Kafka Handchart. So the Kafka Handchart is still in incubating period, and it still has many things to improve. So I've got new Handchart. I also have contributed some PR to those two Handcharts as well, because it has some work. Okay, I actually have a question. It's about the configuration as code. I'm wondering if it's wise to wait until coding phase three to start thinking about supporting GCSC. Should it be considered sooner to make sure it's compatible from the start? What do you think? Yeah, that's a very nice idea. I think it makes sense to start considering it now. Okay, thank you very much. Goodbye. Okay. Vutuan, would you like to make some comments? Okay, so I think the overall demo is good. I said we have some bugs in the final demo, but I think long in the dry run before this, long good if well. I mean, I think there's some unexpected, maybe I guess it's some network or some version conflict problem. So for the overall of this project, I think Long reached out to us quite early, like from the beginning of diesel, and he's very active to ask the question. And so he's very active to sell learning about the concept, about the plug-in, about Kafka on communities. So actually, I quite appreciate all the effort that he made until now, and I'm looking forward to working with him in the second phase. Yeah. Okay, thank you. All right. Well, thanks everyone for participating today. I just have some couple of closing remarks. First of all, I would like to remind all the mentors to please submit your evaluations. As soon as possible, we do not want to miss the deadline. I want to thank all the students for submitting their own evaluation. So that's very nice. I think they are all in. So thank you. And thank you, everyone, for your contribution during, contributions during phase one. And best of luck for the next phases. All right. So does anyone have any further questions or comments? Okay. So on this, I will conclude this series of three presentations. Thanks, people, for watching. And I will now stop the broadcast. Thank you, Martin, for running it. Thank you.