 Okay, so in real life the meeting has been recorded, John, the floor is yours? I think, I think, the screen share somewhere, there it is. I was thinking that we'd go through the agenda as soon as we figure out where to press the fine button. There it is. If you screen share your screen it's not working right now. Exactly. So if you want I can screen share for you? No, I just, I can't remember how to do it. Okay, just a second. Okay, do you see my screen? Yeah. Anyway, that was the part that I wanted to show. We just proposed the agenda that the plastic put in the Gitter yesterday, I think. Yes. Yeah. Then we just talk it through basically. I think about the last part about breaking down tasks, it should be somewhat easy to do it offline. So there's no need to use your time or like for this. So I say that's why we should take it at last. There's just the road and example of one of the issues we should break down. Anyway. So like, Should I start on with the questions? Yes, sure. Oleg, hello. Yeah, hello. Okay, so first question is like the compatibility issue that you mentioned yesterday. Like how can it be resolved? Do you remember our previous knowledge transfer where we actually discussed it? Yes, you showed it. Yeah, because I have shown some code samples, etc. Yes, yes. So do you want me to do that again? Or do you have enough information? No, like just that part, that particular code. Okay, promotion badge, right? Yes, yes. Yeah, I think that we can just take a look at the code. I think for this, you have to, okay, okay. Okay, I'll probably just launch a vintage idea. So yeah, we can take a look. In a while. I believe that there is some documentation in pipeline plugin before. Let's take a look. So yeah, I'm just putting links, but yeah, there is information about pipeline development. That's my idea. Oh yeah, now it's starting. Okay, good. So yeah, there is a document for pipeline integration and there is also a document for, I believe, from Eclipse about compatibility. Yeah, evolving Java-based APIs. So yeah, you remember we have already seen this page together with you. Yeah, these documents are rather two main guidelines describing how you could do that. So yeah, this documentation is probably not enough, but yeah, but it addresses some topics. So yeah, let's take a look at our particular example. I believe it's loading promoted builds here. So yeah, when I run Hangouts on Air, my laptop is too slow. If you want, I can hear the tune. I have the good. No, I think that it would be more convenient if I do that because how to make today's promotion page appear binary compatible. So I think that we can just have a short show and tell session. So yeah, let's go to my depository so that I just do it on the clean branch. Yeah, I can just mute one particular channel. So sorry. I disconnected from Hangouts. Sorry, from Gitter for a while. Okay, let's go to the master branch. Okay. So yeah, we have a quote and yeah, there is a promotion page. Promotion page. Okay, so yeah, it's here. And we have a method which takes abstract build. So yes, we discussed that the previous session when you see abstract build abstract project and other types. It should be a red flag for you that it's not compatible with pipeline. And we have a problem here because we have a method and we already have extension points which implement this method. Probably we have extension points outside the plugin. So if you just change here from abstract build to run, as you did in your pull request, then if you go to this guideline, you may see that there is parameters. Change of type of form of parameter. It's actually a break in compatibility, even if you upstream the type. So it might not be obvious sometimes because yeah, there are some documentation below. So you retain source compatibility here by changing the type, but you do not retain binary compatibility. So what we do instead, so something like that. So yeah, we keep this method as this, but we start creating a new method. So for example, now it will be run. So firstly, what you need to keep in mind here that even if you have a new method here, you can get into source code and be greedy. So you cannot retain the same method. Usually how it's being done. For example, you can pass built listener here. Wow, it's still in the configuration listener. So you have a new method because actually built listener is not passed. So it would have been a necessary change anyway. I think running listener is used for pipelines. No. Well, yeah, it's run listener. Just a second. So there is a thing here because the run listener is a method for checking the completion of the new runs. So API may be a bit confusing here. What's going on? It still cannot open the project properly. Okay. Oh, yeah, but actually after the build, built listener. Oh, maybe not. Just a second. Built listener. Okay. Let's start from task listener. So task listener is a top level endpoint. Well, there should be a method there, by the way. Maybe get... Yeah, I just forgot the method, but yeah, so it should be built listener here. We will get to it later. So if we take a look, yeah, sorry, I really forgot the code. Yeah, so built listener is what we need, even if we work for pipeline, on pipeline. So here what we can do is, yeah, there is a new method. Here we can call it run to make it more specific. I never know. So instead of that, we just put an annotation to make the code... None, none. Yeah, none now. So yeah, we are using standard annotations, environment variables. Yeah, it's not documented, but we can check usages of this method. Okay, and this makes it compatible. Yeah, for now it's compatible. Okay. So yeah, we will see how to refactor the entire code. Yeah, but yeah. So here what we need to do is, yeah, we have a new method. This one, we say it's a deprecated. Because we want all codebases to use the new method. Okay, use... Yeah, there is a lot of background noises coming. So yeah, sorry if I'm distracted sometimes. That's fine, I can listen to you. Yeah, I am distracted and also my ID HENX, which also doesn't help a lot. Yeah, so let's see. Currently the branch targets very old version core, but still we have this method here. So yeah, well, it should be this method though. Yeah, there is a more simple implementation. So promoted. So what we need to do here, promotion. Okay, so what we need here, we introduced a new method. And we need to ensure that since not every new implementation has already written that, we can say that if run instance of abstract build. So yeah, if a new implementation ever writes this method, then it's fine. Okay. Okay, if the method is not ever written. Okay. If it is a classical build, this run instance of abstract build means if it is a classical build, then what do we do? So if it's a classic build, the simplest approach is to just invoke the existing methods. So yeah, here we just convert it to abstract build. Okay. So if it's not required. Yeah. And then what else do we need to pass environment? That's it. So here we invoke the old method. So it means that when this method is involved to be a full back to the old implementation. Then here. Yeah, we can keep a disease. We have invocation here, which comes from status. So you may see that it also uses all KPI. And we have to do pretty much the same here. So we create a deprecated method. It uses abstract build here, but we can still pass this in there. So yeah, we use new API in old method. So that it still invokes new API space where possible, but we basically deprecate this existing method. And here we also have run run. And yeah, we use build listener. Build listener. So something like that. So here we also retained compatibility. Built and worse. Okay. Okay. So yeah, you will be able to polish this implementation later. I'm just showing how it works. So yeah, we have a new method. But then what we need to do, we need to see who uses this old method. And there is one method, which is get environment. So, and you may see that it actually already receives a task listener. So what we discovered here that we have a method which already has login engine, which you haven't been using before. So we pass the listener here. But yeah, if you do that, there is type conflicts because we assume that all listeners are actually built listeners. So the most simple way to fix that and to retain value, you actually go to definition, declaration, just say that okay, it will be task listener. It doesn't really matter for us because this is just an abstraction class. But here we just say task listener. Okay. I'm washing the page fix Java doc here. Okay. So now this good status thing should be able. Yeah, it's able to invoke the thing correctly. So let's take a look what it takes in the code. So yeah, you may see that target he is abstract build. So we won't be touching it right now. So the factor to run. So yeah, I'm leaving it for you so that we do not go much forward. But we did only one part of the implementation because what is our problem that we have promotion page. We have a new method here. But implementation still use this method. So we need to find implementations. So you may see that there are two implementations and that's again, groovy condition and one condition. So what we do here that it uses new old API. Let's use new APIs. Task listener. Okay. So here, there is no sense to invoke this method to be honest. So I will just keep it because it was no up. And this is for historical reasons. So yeah, this method is fixed and there is also manual condition, which also has a self promotion, but you can see it's not. But in manual condition, you also have batch I believe he he was the batch. And here in this batch. So here we do the same. Listener. Here we checked to run. And here you can see that there are some tricky things here because the others. So, the class. And here you can see a problem which is going here because we're running his instance of promotion. The fact that support pipeline promotion types. So again, I just want to do so that we don't touch it now. So what you can do here just to give you a hint. You have promotion as an implementation. So yeah, you already started refactoring this class. But you have already discovered that it's a kind of uphill battle. So what you could do is you can. So here we can say that it's promotion for abstract projects. Yeah, we can do what we can say that here they will be a new interface. So yeah, I'll create just in the hats package for now but it's better to move it. Yeah, okay, let's do it. Let's keep it as is. Okay. Okay, let's say that it's a promotion run or something like that. Okay. Yeah, I just make up the thing for now. So we create a new let's say interface for now. So this is a promotion. We will implement our interface. So we have one implementation for abstract projects. Okay. This interface was made though the previous promotion class that is for abstract build. Yeah. So because yes, we discussed before refactoring this class is uphill battle. Just do something like that. Okay. So only the needed methods from promotion would be used in this new interface Exactly. And you can also make it parameterizable. I'm not sure whether it's needed or not to do the generics. Okay, so I'm not sure what they will need it. I'm not touching it. So yeah, let's go back to our mental condition. Okay, and now we have that if it's not a promotion run. I expected a promotion run but got whatever. So here we have promotion run. And now we know that this method needs to have parameter values in order to support this promotion. Okay. So yeah, what we do. Yep. Is it fine that I probably consume too much time at the call. It's fine. This isn't needed. So it is fine. Built. Okay. There should be public method here. Okay. I'm going to stop something. Yeah, too many classes open. Oh, good parameter values. I was looking for the wrong thing. So yeah, we know that there is method, good parameter values. So here what do you say. Yeah. I'm not sure what you can move this implementation upstairs. It looks like so for promotion, bitch. I'm not sure. Yeah. I'll just move it for now so that we keep it simple. Okay. Yeah, we say that. Yeah, so. Yeah, we just have a method. To do. Move implementation. Okay. Yeah. I'm not sure how it would be finally done. So we need to do more crunching to get it right. So I just leave it to do comment behind me through this line. And our next problem is about parameter values. So there is a method for building environment variables. It's a part of Jenkins. For actually, but you may see that this method is actually is already deprecated and we have a new method for runs. So what it means firstly that if you want to make efficient, we would need to provide to build environment for promote that run. But since we are not fully sure what would be the interface of promotion run, for example, yeah, one of the ways is to say that promotion run is always run. But yeah, we can say it. So for me right now it doesn't look like 100% condition. So here we can say that. So we can just say that there will be a new method. Something like run get promoted run. And here if you follow such approach, it already looks like we might need generics here. Are you familiar with generics in Java? Yes, yes, yes. Yeah, so if you had generics, we could have added some static type check in here. But yeah, let's move on again. So now we broke compatibility of this method because yeah, now we do not have the thing. And here it's already... So maybe we actually need two methods because yeah, this is already different because promoted run, promotion run. Yeah, so it's quite complicated. So yeah, you will like to need to rename this method. Run which we try to promote. And this is execution which does the promotion. So yeah, you may see that which does the promotion. Because this may be two separate jobs. And yeah, even in existing implementation, these jobs are separate. But for example, in your new implementation for pipeline, it might be different. Get promoted run and get promotion run. So we implemented these two interfaces here. But now we need to understand what we actually return here because null is obviously not an option. But yeah, here we have promotion. Here we have a get target. So get target is the built that this promotion promoted. So yeah, my interface is just get target here. Well, yeah, you can rename it later. Maybe it should be just a get target or get source, whatever. And here get promotion run, we just return this actually. Because yeah, it's here. So let's take a look here. In this method, we actually retrieve built for this. So it's actually a promotion run. And there are some run conditions which... So yeah, there is some magic which you may refactor later. Yeah, because here it definitely makes sense to move to a default method. But yeah, let's go back to our manual condition. So here we can say that we can again apply refactoring. So now we have promotion run. So probably this code is not longer required because we can say that actually it's a promotion run. So instead of having this Luzi check, we just enforce it into the API. Well, so yeah, I'll keep it as is. But you can refactor it to do the effect of API to promotion run. So yeah, it's just a question in there. But yeah, here what we do, promotion run, promotion, we just convert the type run. And yeah, here promotion, we just actually put it here, built in first. And here we know that it's a good promotion run. So one which actually executes the thing. And now we see that actually it wasn't enough because I probably messed up the interface. The method is called built environment. So again, you may see that there is method name change and it has been all done for binary compatibility in the core. I added additional parameter task listener because it was more reasonable. But when the core was refactored instead of that, there was a method renaming which is also fine. Okay. So yeah, we updated the manual condition. And then firstly, we fixed all the port issues. So our port will compile and our port will work for all existing pages we touched at the same time. Yep. But testing if it is like pipeline compatible is if it compile successfully after change, we can assume that it is done. Yeah, we cannot assume that it's done because, well, you have no test automation for that. So that's why when we were discussing it before in the chat, I proposed to have a promotion step. So something like, well, I cannot easily do it here because I don't have classes, but what we could do is say that there is a new class like something at batch at a motion which step. So instead of doing full implementation of the plugin to test that you can have a small step, which actually does the promotion. So I won't be able to actually write anything here because the core dependencies are too old. But yeah, you can. Yeah, if you take a look at this method of pipeline integration. So yeah, there are descriptions about steps. Step. Okay, so yeah, one of the ways is to just implement simple build step. But the simple build step actually requires works, workspace. So it's better to use a pipeline step API. This step means what does this step mean like in the pipeline script steps in the pipeline script. Yep. Okay. So this is a pipeline step so that you can spot check the logic. Yeah, so I can show you where you can find this API. Because, yeah, so this guy actually. So, it's probably not the best guide. You can find compatible plugins, finding symbols. Yes, everything is important. So you will have to go through this guide. But the entry point for you here, there's, there is a build step thing. Okay. And yeah, this build step thing actually recommends using simple build step, because simple build step is really simple. Simple build step for quickly. The problem that it will require workspace. So yeah, it's probably okay for now. So let's see whether I can accept simple build step. Yeah, so it's probably the most straightforward way. Yeah, use pipeline step API for advanced fields. So for me, it would be fine if you start from simple build step, though it has its own limitations but the advantage that it's really simple. Okay. So something like, oh, why does it have so many methods. I think that the most of them are default funds. Okay, if not, yeah, I think you can figure it out what is needed, but yeah, basically, you will end up with implementing this one simple method plus some descriptors in order to implement a descriptor. Yes, and one question is descriptors for a new instance, when a new class is made, are descriptors like mandatory like I learned that it is a global configuration to make instance available throughout the plugin. Yeah, so the purpose of descriptors is to make extension points and other UI elements configurable. So if you do not want the extension point to be configurable, then you do not need descriptors. Okay. Yeah, so, yeah, I just added some sample code, but yeah, it's basically what would you need to do. So you just somehow define base. Okay. Take And for what. So, yeah, we have this. Yeah, and then to run action. So you can do implementation on your own. I suppose we just leave stop here for now. But yeah, it could be a good start point for you. Okay, so I'll quickly move on to next questions. Like in promotion condition like promotion condition. Yeah. In that, I guess that is the main entry point of this plugin right because it extends the extension point. Promotion condition. Yeah, it's one of the extension points. Ask like in this conventional method of passing the promotion parameters through the web UI. I guess there's something called a descriptor list in the promotion condition that registers the input, the desired input right. How is it passed? How is it passed from the UI with parameters or which variables are through which these inputs are being passed. Okay, so let's take a look. When you go through UI, there is a manual condition, which you have already touched. So you might see that there is actually a bunch of code. But what you can see that there are parameter definitions there. So it means that promotion condition, manual condition stores its own definitions. And these definitions actually get retrieved by promotion when you start the code. So yeah, let's go here. Yeah, you may see that there are such things like manual conditions. Yeah, when somebody requests parameters for promotion, the code checks what the manual condition is enabled. And if manual condition is enabled, the parameters are propagated from there. In promotion, there is manual condition, right? But for self-promotion, there's no method called self-promotion in promotion. So how does it happen for others like self-promotion, parameterized promotion? Well, let's take a look. For self-promotion, let's look for self-promotion. Okay, what is it? Inside conditions. Conditions, self-promotion. Okay, so yeah, it's self-promotion bench, self-promotion condition. Yes. So here, let's see. So promotion bench just consults this, well, condition that promotes a built as soon as it's done. So first thing here that actually doesn't return any parameters like manual condition. Yeah. So what it means that self-promotion condition is not parameterizable. Let's take a look at its implementation. So here, it's almost nothing except on completed handler, which does promotion. But you may see that it retrieves promotion and just does the execution. Let's take a look at the web UI. So it's resources, conditions, self-promotion condition, configuration. And again, there is no parameterization here at all. So what it means that self-promotion has no parameterization. It has no parameterization in the code in the web UI and it will just execute a promotion with default parameters. I mean, how are these parameters then put into self-promotion? I didn't understand. Manual, I understood it is parameterized. But how does the modules in this plugin know that self-promotion is being called? And how are those inputs? How self-promotion is being called? Let's try to investigate the code again. So I'll just close other code passes. Okay. So here, we have self-promotion condition. Once it's all down, you can see that there is a run listener. So the listener is extension point, which actually monitors completions of jobs. So here the monitor completions of abstract builds. So obviously in your code, you will have to rework it for pipeline. But this extension point, probably it's okay to just rename it here and call it minor compatibility breakage. There's nothing to discuss later. But here, once job completes, this handler receives a notification from Jenkins core. Then what it does, it checks whether, so when any job completes, then it retrieves job property. So to ensure, so this job property is promotion job property. And when it exists, we assume that this is a job which has promotion logic defined. Then we go to promotion processes. And for each process, we check conditions. And if any process has a condition with self-promotion condition, then we need a whole self-promotion. So it's promotion process, consider promotion. And here we go to this code, actually it just goes through all approvals. So yeah, if all other approvals are passed, whether it's minor approvals or whatever, then we just execute promotion. That's it. Okay. But this future promotion is for after it has been built. This is for after like before this. Yeah, so this condition gets invoked only when the build is completed, whether it's passed or failed, but then it's completed. Okay. This is fine. And badges or like badges, one confusion about badges is how are badges assigned like before promotion, like in this self-promotion, what we can see is it gives up an approval badge to that build. Okay. So how is that done? Badging is how is it done? Let's see. So there is no magic there, so we can get to that using the code. So here the only code related to promotion is consider promotion. Here we process all the conditions. So I would assume that, yeah, then there is a method here, which is considered. Sorry. There is a method to consider promotion. Here we can use it to promote and build actions. Action A. Okay. So yeah, if there is no promotion, we just go forward and yeah, there is a method called promote to. So yeah, let's go further in the code implementation promote to then there is action. And here we actually have that there is a code called status qualification. So we need to return back because yeah, the method was actually. So the code comes from qualifications for promotion. So it might be here or might be here. But we need to go back to consider promotion. So and consider the promotion there is qualification code status qualification is met. So I guess that it's actually somewhere inside. In promotion conditions. Yeah. Yeah, it's in promotion condition or whatever. So yeah, this status would be generated when promotion conditions are met. And now we need to understand where the bed is just injected. I focused that it's gets involved here, but let's try to find where it comes from in the code. So go to declaration. Here we have addiction or whatever. So promote action. And I believe that it contains badges, right? Yes. Okay, so actually it's not. Let's take a look where the badges come from. There's another class promotion. There's one batch in the promotion builds only the promotion batch dot Java. Oh, yeah, right. So the one we will patching. So let's take a look where it actually gets used. But yeah, again, it will be everything around status. You may see that badges are stored in status as we discussed. So what it means that when we had a qualification in this code. So here we're here. We actually had a qualification with badges to the action. So it means that the system formation about badges. Let's, let's take a look where the badges actually get generated for these status. So you can just look for usages of this parameter. And here, let's see. Yeah, well, you're right. We have only one execution. Right. It's in the constructor. So when we construct a status, we put all badges here. It's the only way to modify badges. And let's take a look where this logic is made. Yeah, we come again to this is my method. So, yeah. So here is made for promotion process. So we pass through conditions. This can each condition. It's a bridge here. We accumulate bridges and then return the status. So this way we get all the pages and then they get to the action. Okay, we get, okay. Badges are assigned from this. Okay, okay, okay. Okay, so like that is pretty much it. And like, I had, like he defined one task in zero that I will be making at least. And yes, yes. The next question is, okay, this is done. Okay, badges is done since we're working for pipelines. For promotion trigger this class promotion trigger. How would we implement this in pipeline because we'll be triggering a new job. Okay, so how now badges have been assigned badges have been assigned. Now how is triggering done. Okay, let's talk about triggering. So here what we have a trigger that starts a build when a promotion happens. So you may say that. So let's firstly see where this trigger gets involved because I believe this trigger is a part of promotion process definition right. Yes, I guess so. So promotion rather implementation. So yeah, it's basically this is a trigger only for post execution. So for pollution, we handle promotion figures. And yeah, this promotion triggers. So let's see where it gets from. And you suggest. Okay. So yeah, let's go to the super method. You may see that it's part of abstract build, but effectively it gets executed after execution of the build. So yeah, we can just find usages. But yeah, basically when the build finishes in abstract build, then we go through this code in order to invoke promotion triggers. So I think we don't need this, do we? Probably we need that, but not in this implementation, because this implementation was likely created in ancient times. And now what we have already seen with you that there is run this year. And for the implementation, it's enough to have run this in it, which actually checks promotion triggers. So run this in it just verifies that the build is completed. And once it's completed, it can consult this promotion triggers and trigger other builds. Okay, like it's notifications from the build. That is what I read in Java. So it means that you won't need to implement the logic like you have in a promotion process. Instead of that, you just subscribe to run this year. So for this promotion process also, I need to make a new interface. And like taking important methods into the new interface, right? Yeah, right. Okay. Yeah, so one of the things that you can do, I can just push this piece of code. Yes, yes. You can probably just start from it so that you have a small pull request, which just addresses these badges. And you can just take my code and build from the top of it. Okay. Like push that code. Okay, like, I think you have to go. Like it is pretty much up. Thank you, Oleg. And like last question, one question is, you said in GitHub that you suggest having separate PRs and separate JIRA tickets. What did you mean by that? Yeah, right. Because for example, if you take a look, we have created a pre-insulated logic for promotion batch. So if there was a separate ticket for promotion batch, we could have reviewed this pull request separately. And we could have delivered this pull request separately before you touch other things. So then you can deliver things incrementally in smaller chunks. Part of the thing I was talking about for the last bullet point for our agenda to split up that one issue into smaller issues. Okay. So, yeah. Yeah, what I will do, I will just submit this code. Oh, yeah. I'm not really using can tell this idea. So you may see that there are some things like that, which is not a good practice. So yeah, I'll have to revert it later. But okay, I'll just submit it as is. And then. Okay. Okay, just mute the other. Okay. Yeah. Just a second. I'll see what they can reverse it from the. Okay. I'll, I can do it in source three. So it would be better if I reverse it before pushing the change. So yeah, let's agree that I will just submit a new change maybe in 20 to 30 minutes. Okay. Okay. Like no more questions from me. Like you have a meeting. I guess. And John and me will talk for a little long. So if John is available. I have a meeting you're coming up right now, but it's just a short one. So I'll get back to your prestige right, right after I've done the other meeting. Okay. Okay. Okay. Then I'll stop the broadcast for now. And then as a next step, you agree how to break down the thing. Okay. As a pre test for promotion, bitch, I will just push the code with this ID. Okay. And also ship, please share the YouTube channel as like. Yeah, sure. Okay. Okay. This time it will be done quickly because I don't need to cut. I did it. Okay. Okay. So yeah, thank you all. Thank you like a presentation. Yeah. Well, it was rather life coding. If it helps you guys consider doing coding sometimes because it's a really helpful practice. Hey, it helps me to get a better look too. So see what hide the curtains magic Jenkins is. Okay. Yeah. Bye. Bye. Bye. Bye. Bye. Bye. Bye. Bye. Bye. Bye. Bye. Bye.