 Welcome. This is Google Summer of Code Jenkins get cash maintenance. It is the 28th of June, 2022. Rishikesh, are there any particular topics you'd like to discuss? Yeah, yeah, can you share the screen so that I can tell you what progress of me this entire week. Yes, absolutely. Here we go. So let's look at this one. Let me bring up, would it be best if I bring up the GitHub repository? Yeah. Okay. And let's look at the open pull request. And here it is. Okay. So this week I added that, you know, getting all the caches from the, you know, on the Jenkins controller that logic has been added, and I am able to run the maintenance tasks on all the caches. Okay. So that's what has been, that's what I've done. And then yesterday I worked on, you know, we have discussed about form validation, like, you know, where we can store incorrect data also into the file and then validate them whenever we are executing the maintenance tasks. So that's what I have worked in this, like in this part in the past. Thank you. That's wonderful. So, so let's, are you okay if we take a look at it? Yeah, sure. Okay. All right. So this one looks like. Oh, okay, so you're intentionally maintaining the ordering by using a linked hash map and the idea there is you want to execute with a particular order. No, the thing is in the UI, right? If I don't use a linked hash map, whenever I refresh the page, all the order of the maintenance task is getting shuffled because I don't have a particular order when I'm iterating through the hash map. I see. Okay, so this, this assures that that makes sense. Good. All right. And then silly scroll bar. Here we go. So, this is for the Chrome syntax validation. This is for the form validation, which, which we have discussed, you know, not to like, which allows saving of incorrect data but it verifies when I'm running, executing the maintenance tasks. So that, that's the logic for this in this comment. Very good. Okay. Now we will. Oh, and this is I assume just a diagnostic thing to help you as your. But you may you may in fact want to use a system or a logging system, because then you can read it and the user if they ever have a question could increase the logging level and see it telling us or decrease the logging level to say oh it's not happening. I had it out regarding logging so that's why I haven't proceeded with that like, how would I implemented each class would have a logger or like how would it would each class would have a logger, and then you use that classes logger that allows the administrator to do very fine control of which things they want to log to see proof that something's happening. So this one might be a an info level or a, let's see I have to have to look at the logger levels. Yeah, so this one could be a debug level even where you say hey, only show this when we're doing debugging debugging level logging. But this, the technique you're using with small commits looks very, very good. That's, that's exactly the right way to do it. So, and, and you've added tests. Excellent. Yeah, I don't know. So, yes, congratulations very okay so so now tell me what you what you learned how did you. What did you have to do in order to allow it to support the the rather Jenkins specific way of describing it. Actually, I didn't do anything I tried it once again and it started working I don't know why it didn't work that day so. Okay, alright so it's, it should be easy to test good very good interest okay now this one. Okay this test I'm not sure is doing what you expect it to do. Yeah, it's throwing an error so that's what I wanted it to do. It is but the problem is, you're iterating over a loop and the first call on the loop will throw the exception and test none of the others. Oh it won't. Oh, okay. Right so I thought it would so. Well and you could you could for instance you could do this if you were instead to switch and use a parameterized test. Then you could make these invalid invalid syntax items each parameters, and then you do the same syntax you say I expect to throw antler exception. And all you do then is in the test you call task scheduler dot get contact list. And it will, it will then use that so so that's this one won't have the behavior you want right now but it's pretty easy. You just split it out into a separate file task scheduler parameterized tests, and then make the parameters your incorrect syntax that has the nicety that then it's, it's easy to see what the test is asserting because all it's asserting is that this exact statement will throw an exception. Okay, I do that I do that I didn't know it would only get the first one so. Good for you, good for you for writing tests well done for sure cash this is really great. All right, so in that and this one, I assume is just an evolution of the earlier file we were looking at. I deleted all of that in the previous one and added it to. So did you want to do you want me to take this for a test drive and show show that it's, it's working should we use that for, or are there more things you would like to show tonight today before, before we finish our session. So actually, there are two ways of like how I want the session to be at the first thing is I never like the maintenance tasks are running okay but I never ran it properly. Like I never run around all the maintenance tasks like I like you know setting it like for one hour, and then setting setting it for like two hours, running every two hours. One thing which I haven't done but the maintenance tasks are running it's getting a lock. It's using that lock running running the maintenance tasks on that cache and then getting unlocked. So that logic has been written but I haven't tested it completely. Okay, the other thing which I wanted in this session was where like regarding legacy get maintenance okay for versions less than 2.30. Where do I write the logic for it, do I write it in the get plugin or the get client plugin, because if I wanted it to, if I want to write it in the get plugin right. I am not getting the get version I'm not able to use the get version underlying get version or CLI version so that that that's something I was not able to proceed. Good, okay that's a very good point so I think what you're noting is get is it get client version. I forget even the name of the function. No, but there's some version thing in it. Let's look for the word version private in the client plugin. Here we go this is at least version. Right, that's the, that's the one thing that knows about version numbers. I thought there was something in in command, you're in the in the get plugin as well. Okay, let's, you okay if I do some quick exploring. Yes. Alright, so. Okay, that's not a whole lot of help. So, version ID, big version, get lab version, get version of that still get that specific unexpected get major version. Oh okay so this thing is doing some work with the get version but it's entirely inside a test. Okay, so, so the get plugin has logic in it but it's right now it's completely inside of a test to determine which version of get and maybe we ought to look at that and see sample repo. Yeah, there's again another test usage. Check out with. Okay. Okay, let's do one more source slash main. Oh, yes, let's use correct syntax. Okay, so. Okay, config version is no help. Temp version all inside the get lab browser is looking at get lab version help files. Okay, yeah so it doesn't. It doesn't have. Any way of getting the. Okay, so the choices are are. Well, do you have a preference because you could for instance, just create a new API somewhere in the get plugin that you can use to determine what version of command line get your is available. You could put it inside the caching mechanism you could put it. Most anywhere you'd like because there's an example right here of how to do it. Right so here is here is code that knows how to do that. And what exactly is wrong. Is it like something. I assume it's a convenience method inside this inside this or inside in another. Inside the parent yeah so it's it's a convenience method that knows how to do a fork, or a fork and exec. Let's see let's look at it and see so abstract sample dbcs repo. This is where I really need a tags file. Okay so it is coming from another place so Jenkins Java doc. Let's see if we can find that SM API plugin. Okay. That doesn't help me at all but let's look at Jenkins GitHub, SM API. Sorry I'm staring in another screen I'll be right there in just a moment. SM API plugin. Here we go. Okay so what does run do here. Let's find the real run the real run is abstract sample repo. So in case you can't tell we have to look at this one. Now here there will be a run yeah so it creates a launcher and then makes the call and and this you certainly could do. And then inside the get plugin it's quite allowed because in your case you I think we are confident that we don't that we always want to use command line get to perform the maintenance operations. Yeah, yeah, because I sent you the link of a forum yesterday right where I asked about Jake it, and they were like they don't have maintenance tasks ready in that thing so. Yeah, right. And I agree with, I don't think we even if they did have it, it would probably only be in the j get six family, and we're not ready to adopt that yet. So, so, for me it's this is too early for us to be forced on to j get six. So even if they had it, it would probably not have arrived until j get six right now I think they're about to release j get six dot three. Okay. So can I call this method directly like wherever I needed to you know get the version of the get, you know, to get a good portion. I think you could right. So I was assuming that the play you would probably want to, to isolate the knowledge of get versions and which things do maintenance inside of your maintenance tasks. I mean it's implementation which whichever one that is inside that class but if you need it in multiple places you could certainly either put it in a, in a utilities class, and use the use the utilities class statically, or copy it if you need to. It's terrible because I wanted to even show the version of which it was being used in the UI. So that's why I wanted it to be in the kit plug in so that I can get the version and you know, it would be useful even in the UI. Well, and I think, I think that's a that's a good thing. I, if we look at this at this code it's doing exactly that right so the knowledge of this thing is it's doing logging to tell us if it couldn't parse the get version into a major version or a minor version and a patch version. And, and if you find this kind of thing helpful you're certainly welcome to make this an API that's somehow available, at least package protected inside the get plugin. I'm not sure we want to make it a publicly accessible API, because I really would rather not have get plug in consumers have any logic about what version of command line get there using. It's, it's, it's bad enough that that the get plug in the get client plug in have to know about command line get versions. Let's not leak that information to our callers if we can avoid it. If, if you would like to make this, this into a package protected method somewhere in the get plug in, you have my full support, it's, I know how important it's been, I'm embarrassed to admit how important it's been to me to see things like here I'll show you the one that that that has mattered to us when the, when the command, when the version of command line get is logged into the Jenkins build log that is actually quite precious information. Oh, here, let's just do CI Jenkins.io that'll be good enough. So for instance, let's look at this plug in here. When it performs a checkout in the log we're going to see Oh, it's even using JGit so that doesn't help me. Okay, let's use something else like this one. But what it does is it reports the command line get version, and by reporting the command line get version. I'm able to diagnose quite a number of problems, much more easily so you have my full support for logging the version of command line get that's being used in the, in the, in the task scheduling logging. Absolutely. Okay, so now I have a doubt regarding, you know, logging. So, like, when I log it, will I be displaying it where where would I be displaying or would I be storing it in a file or would I be displaying it in the terminal. Excellent question. Very good question. Are you okay if I show a demo of how logging works in Jenkins and why I think it's so great. Yeah, sure, sure. Okay, so, so this is my, my Jenkins controller. And, and what I want to show you now, sorry it's running dark mode is dark mode. Okay. Yeah, thanks. Okay. So, so here is my Jenkins controller. And it has some interesting jobs on it. If I go if I want to change what's happened or if I want to see what's happening with logging, I go to manage Jenkins. And now if I scroll downwards there will be a system log thing here. So, the system log gives me access to, to Jenkins log messages from the web page. So when I click all Jenkins logs, it shows me. Oh, here it was upgrading Jenkins last was 356 we're running 357. And it, it talks about oh hey I loaded an attached plugin this thing. And now it's reconnecting agents so so the logging is is already available to me from the web UI so you can see what's happening. Now the, the more elegant thing here is that maybe I need something even more detailed. So I can go to log recorders. And I can add a new log recorder and I'm going to call it get SCM. So I'm going to log something from get that well it's, let's choose a better one maybe we should choose. Let's look for one that will logger. Okay, so Warren tempter value sample. So these are tests. I would like something in Maine, here we go. Yeah, there we go. Okay so in get tool configurator. Let's see if we can find something that it might tell us logged. Now this may be too. Yes, and to I need something much more verbose just a minute. Let's do a quick search. That might be good enough. So let's just turn on the logger for get SCM. And we're going to go so get SCM I'm going to say create a new log a new this is creating a new logger, and it says alright what, what would I like. And I'm going to say I want the class that I'm logging to be this one. So else. Now it will help me along the way and I like that it helps me. So I'm going to say Hudson dot plugins dot. I'm going to say it again it was Hudson dot plugins dot get. Get SCM so here it is prompting me along the way. And I would like finer logging which is as is dangerously close to as verbose as you can get. I haven't run this for a long time because this could potentially slow things down and be rather painful, but now while that's that's set to do logging. I'm going to perform some operation like I'm going to do something that requires a checkout. Maybe hosting providers get hub. And I'm going to build each of these jobs. So now that the build has started, we should see in their logs. Oh, except it's not. Okay, this one's running. And it's performing some operations. Good. Now let's see if anybody else is running. Okay this one's cute so this one has run today. Good. So now if we go back here and look at log records. This is something that it logged it says not adding get tag action to build nine. Likewise to build 24, and it performed a checkout. So that's how I see the logs. So if I were to add new logging statements, the output will appear here or if I want to. Maybe I want to do. Let's look at the log on the maintenance task right so let's check out this one. Okay, so now is there something that we where we might benefit from a log entry. Yeah, for instance, you might choose, hey, to log something at fine. The size of the cash entries, something like that. Hey, returned this many cash entries and you could do that here. That kind of thing and then you would see it by turning on the logging for abstract get a CM source. Okay. So does, does that address your question. One, then I have a doubt like now what do I have to consider like to log, like, what kind of information should I log into the using the log. Like do I have to like log all the procedure whatever is happening or like. I think it's up to you. My, my, my past experience was, I seem to have made the continual mistake of never logging enough. It may sound really terrible but but very frequently when I've, when I'm when someone is reporting a problem that's out in the world and saying hey, I'm running Jenkins in this in some environment. And of course they never tell us all the details of their environment they never tell us nearly enough. They tell us, hey I'm running this and I've got this problem. And if I could have said, hey, turn on to increase the logging level of this class, so that we can see what happens on your system, I would have been, it would have been much easier to diagnose the problem. So, so for me at least I found that the more I do this the more often I'll put simple little statements in that tell me how things are progressing so that I can know it and put them at a relatively fine grain logging level so that they're not on by default. So they're not costing anything, but if I needed to ask someone hey please turn up the logging on this thing, they've already got the code, and I'm not having to deploy have them deploy a new debug build to get it. Okay, so I can use that logging level and then find grain based on what has to be displayed and what doesn't. So, so that one of the techniques that I found for me most recently helpful was, I would put the logging statements in there. And then actually turn the logging on to watch for myself that the code was executing the way I expected, without using a debugger to do it. And it turned out it as it's the result for me was it's easier than for me to know that logging is useful, and it's saying the right thing, and the code is executing the right thing. Okay, so that kind of helps me. Oh, I have another doubt here, like if you go to the task scheduler class. Okay, there's a class task scheduler. There I have a try catch. Okay, and now it was assumed like for some reason there's an error which has been thrown. What do I do with that error do I just log it or because I can't connect it with the UI because the UI is now a separate entity here. So, what do I do with that do I just log it or for now for for now I think yeah you should just log it. Now, ultimately, we may want in in a later part of the project for you to give a location on the UI where we can show that to users, because there certainly are locations in Jenkins where people can see diagnostic information right that that logging page is one example of diagnostics. This support core page is another that can give give diagnostic help. So, so for now, I would just write it to the log. And then in the future, if, if things continue is at the pace you're going, we may have enough time that you'll be able to add that as a feature into the into the page Jenkins page that you're creating. Okay. So, okay, so yeah, so that that was one thing I was like, you know, not sure what to do about. Okay. And does my answer help there or do we need to discuss further. No, no, that thing actually absolutely. Yeah. One more thing. Can you act. So when I am using this incremental build. Okay. My ID is not a supporting, you know, one or two dependencies like the jg dependencies and being supported like only the ID but when I am building the project is running. It is successful, but the ID throws a lot of errors like I'm using IntelliJ right now. It says jagged, you know dependency not found, and then all kind of red files and deadlines everywhere. It doesn't let me run the test. Okay, so you may want to so there if you're willing, post post that as a question to the Jenkins developer list, because there are many, many people who are using IntelliJ. And, and they should they'll probably be able to give you much better guidance that I could. I'm not an IntelliJ user. And because I'm not an IntelliJ user and, and I don't spend nearly enough time in the ID anyway. So, so my problem is, I'm also not a full time developer. I manage professionally and so development is my hobby. And therefore, I'm not a good voice to tell you how to configure IntelliJ but there are lots of people who are using IntelliJ and they should be able to, to answer oh you need to do this magic step or that magic step. I thought there was some, some configuration or some compilation thing that you have to do in order to make it, make it find all the things that you're seeking. So, I think I'll send a mail. And then, you know, I think that could help me out because I wasn't able to test anything then I had to use the previous version of it and comment all these to test the things and then I can then comment it. So, yeah. And I have a doubt or regard, like, if can you open the file, you know, a task executor file, you know, the class. Sure. You bet. So task executor. So here, if you can scroll down the get get client method, the get get client method here, it takes in, you know, get utils dot resolve get tool. So based on this parameter that is default, I get the default, you know, get tool on the Jenkins controller. But now here I only want to get, you know, a CLI get okay. So, what is the parameter I need to pass here only to get a get CLI like CLI command command. Yeah, it's a good question. I'm not sure if there, if there is a way from here to to say please give me command line get because because this thing. Good observation on your part. This thing says, ask the Jenkins controller for its default get implementation, and they default get implementation could be configured to be J get. Yeah, we have, we have CI that Jenkins that IO for instance that I believe is configured exactly that way, where it's intentionally using J get rather than command line get. So, so let's see what we okay so how would we. Let's see. Maybe there's somebody already doing this. Okay, so we're at least doing instance of checks. And we're doing casts. So there are some things that know how to. Yeah, okay. Oh, look. So maybe this is already. The thing that you need without having to put the command line method inside command line get, or inside the get plugin. Look at this thing right here line here, just do it like this line 115. So what it does. Because CLI get API implementation is a. Oh, that's terrifying. CLI get API implementation is a public class. It can be used and that's what it's doing here so it's taking. In this case it's trusting that the get client can be cast in this case safely to a CLI get API implementation. There must be something else elsewhere here that guarantees that that that works. I have no idea. I haven't looked at the code recently to see how it does that but, but this thing is being converted to a command line get implementation. Now is that is that a valid cast. Yeah, the get client know the CLI API, the implementation, you know that implements this interface. Okay, and the get client plugin that I have seen. Okay. All right so then this so this would at least if you if you can if the logic you need to express in your version check can be expressed as a. If you use it at least this version, then you you could probably use this technique so long as you can, you can be assured and, and you could certainly do a right you could do a. Let's put it in here. I actually didn't understand this techniques. Get instance of something like this where you say hey, I'm going to check that get client, or is implementing whatever the whatever the construct is linguistically check to see is it the right type is the cast safe and if it is. Then this thing just cast it and decides yes that's okay. What am I broken here. Apparently, I have lost the ability to write decent code. There we go. Okay. But in my thing I will I would like I am constructing the get client, you know, the get client here whatever the type. Okay, so can I directly, you know, converted to CLI get API. If it is of if it is an instance of CLI get API input yes. Okay. Okay. So so I would be taking the default only then. So, you know, well and that's where we've got to find the answer to your question. Right, how do we how do we ask for, or, or maybe, maybe it's different. Maybe. Well, let's see. Yeah, I mean, if, if, yeah, wait a sec, wait a sec, isn't don't we I think we have the answer here. If the controller is configured to have J get as its default implementation and has no other implementation of get, we can't run maintenance. Right, because we were blocked. So, so I would think what that means is you want to ask for default. And if default is not an instance of CLI get, then we can't run maintenance. Okay, but then on an administrator, you know, wants to set J get as his default but you know, and still has CLI get on his machine. Then what we would need to do is, if it's possible, is it possible to iterate over the, the implementations. I don't remember. I thought there was a facility that would allow iteration over the, the get implementations. Let's see that was get tool wasn't it. Task executor, this one. So if we take a quick look at get utils and is get utils in this cloud. Okay, now I really need my just a minute. Get Alice files. Now I have my index ready. So this one. Okay, so get utils. So here is a constructor resolved by name. And we would need to ask on the built in agent. I use the next next method. Yeah, but I think I think in your case don't you really want to check for it on the built in. Because if you're node agnostic, that may not be available on the controller right. What exactly is not agnostic here. So what what node agnostic is trying to say is list list me a get tool that's available. I don't know which node I'll be on. But you know which node you'll be on because you want to execute on. So here it says, when you know the node you're going to be on and you do because you want to be running on built in you want to be running on the central controller nowhere else. And so in that case it's saying hey you want to use this thing and as the node value you want to get the default, the built in node and there's a, there's a method on the Jenkins object that will tell you give you a node for the built in node. I don't know if that helped but but I think the question we were trying to ask is, is there a way to get the list of all tools and I do. I don't know of a way. Because I've seen in the UI you can set various kinds of, you know, get versions also CLI get version at a 2.3 version at 2.1 version to, you know, 1.8 version so now which version do I use internally. Right exactly well so so and and wouldn't just looking at this code. Wouldn't you want to pass in the get tool as null so that you always call get tool dot get default installation, rather than using the word default rather than using the string default. Like, like you did, why not just allow this method that you're calling. If we call it with null. Interesting yeah and this does the same thing. So if you call it with get tool equals no. Then you're going to. It will call its own get the default installation without you and having to know the string that describes what is the default installation. In this case, as if any administrator uses a default implementation as J get he can't they can't run maintenance tasks right. That that's what that's yeah that I think I would take that as a safe assumption for now. Because we we really cannot do maintenance with J get. And if they're going to choose to use J get as their default implementation, and we the get plug in documentation tells them that the canonical the reference implementation for the get plug in is command line get. It has known limitations, they are welcome to use it but it has no limitations if they use it they choose to accept those limitations compared to command line get. Okay, so, okay, so yeah, okay that that thing answers my question then so I'll be using the default implement you know the default get tool which is used Jenkins and based on that I can schedule the maintenance tasks or throw a log error saying you know update so do right. You're not. I cannot. The message, the message really is I cannot run maintenance with J get. And realistically we can't I don't. I think even though J get implements garbage collection. I'm not ready to take the risk of relying on their garbage collection implementation given that they haven't done the rest of the maintenance tasks. I'd much rather we just use command line get for all of it. So in the gets CLI the get client tool, sorry in the get client plugin, wherever there's a you know I implement the methods maintenance. Okay, do I like just return null or do I just log something there and leave it like in the get client. Yes, I think that makes sense just if someone if someone attempts to perform a maintenance operation using J get just say unsupported. And, and I would do it by logging rather than I think it's better to do it by logging than by than by throwing an exception, but if you look in the get client plugin you'll see both both techniques used. Sometimes when a request to do something is silently ignored. And there are other times where request to do something that J get can't do throws an immediate exception, and I think users have been better satisfied by the silence, then they have by by throwing the exception. Let's see, I think if we look here we can see some examples. Okay, so. Oh, well, yeah these these give us some hints. Now they're only tests. Okay, let's do that maybe there we go. Yeah, here's an example. If you attempt to do a sparse checkout with J get. It will tell you sorry, J get doesn't the J get implementation Jenkins does not support sparse checkout, or here's a I think a more friendly way to do it. This one throws an exception. And that's, that's not very friendly to the user, but it makes sure they know you asked for something that can't be done. This one is I think more friendly to the user it says you asked for large file support, but our J get implementation does not support large file support. Okay. Yeah, yeah that that answered my question. I have another doubt. How is a task listener similar to a logger or how was it different from logger. Yeah, so it's the same. No it has it has some very important differences task listeners are intended for things that might fail. And they are it is a way to log at something lower than the system level for a thing that might fail like a build. So in the case of in the case of the get client, most of the references to a listener are being written directly to the build log. So this message warning J get doesn't support LFS checkout is written to the build log of the job job that attempted to use it. You know now I'm kind of confused should I use the locker or do I have to use a task listener. If, if a task listener is available, you're welcome to use a task listener but the maintenance tasks probably won't have a task listener will there because they're they because I didn't, I didn't think anyway that you had implemented anything that would let it have the concept of a of a task a set of tasks that you're running as separate things right I thought you were just run it and log it and therefore for that you need to use the system Yes, okay so I yeah there's nothing like I am not getting anything like a task listener from any class which I am using so I have nothing like I don't have a task listener, but however I have to pass a task listener to the get, you know, CLI, you know CLI command line get. So I, for now I, you know, parser empty tasks on all tasks listener. So, oh, oh, and, and that's one where you may want to rather than pass an empty task listener, you might want to pass a task listener that would allow you to take the results and send them to a logger. A system level logger. Can you repeat that once again. So, so you've got a task listener. You've so the get client takes task listeners right and it will log to that task listener, and you might want to pass in a task listener that will let you optionally write the results to the system log, so that you can see it because you don't really have a concept of a task yet, at least. And, and so, but writing the information that the get client would be logging to the system log may be helpful. Okay. So basically it would be similar to the log which we were using above rate at the normal log. That was the idea at least that I had you, you probably want to check it to be sure hey does it behave that way. But I think that's, it's worth trying that because having this kind of message appear in your system log for maintenance tasks could be very helpful. And it could be quite quite a good diagnostic to have to say, oops, there was a problem here somehow or other. J get was an attempt was made to call J get during, during a maintenance task, and then the question is why. Okay, so yeah, okay, I understand the flow right now so. Okay, so I think I'll create a task listener which you know, I can logs it back you know uses a system log only so that we can log it. Very good. And then there's another. Okay, these are the major questions for this week. One more thing I had a doubt. Now if I build a project right. I'm running all the test cases successfully on my computer, but on the, you know, on GitHub, the tests are failing as one test which is failing in particular. Okay, well so let's take a look. So this is get plug in me bring it over here and let's take a look at the pull request. So it should be the most recent pull request now right which is. I don't remember it's pull request number just to let's look. So is it 1282. Nope, that's not it. Okay, so it must be the other one. Yes. Okay, good. So this one you say is failing tests. Now the question is why test get caches get a CM maintenance test line 63. So this is saying it didn't find the caches. That's really strange because you did create them right I mean that's what this is doing. My local computer is running. Well, so is it failing on a particular Java version. No, it's failing on all, although it is. Okay, so, so it fails on all three configurations only failing on Linux, or on Java 11 and Java eight but it's failing on Java 17. Let's let's do a quick double check just a moment. I'd like to see this in blue ocean, because I have a thought that it may be. Okay, so it passed on Java 17, but the test fail. Oh, I wonder are these run where these running concurrently on the same agent. It could be that one, one of the tests was running in parallel to another, and they trampled on each other's temporary files. Okay, so this 17 was running on Ubuntu 20 Windows eight. Where's Linux, there was the other one so Ubuntu 20, eight C1640. And I don't have an explanation for that failure either. You're okay if we try to run it from my environment. Yeah, sure. Okay, so where is the test test latest test result. Okay, so the thing we want to run is that thing. It's been forever since I've seen a green check okay where all the tests have been passed so well and that's not a good thing right that's a terrible thing so. Alright, so. Okay, no failure there. Why else would that test fail, and it can't be a concurrent thing because it's failing on Windows and we only ever run once on Windows. There must be something else going on. So you may just have to put some debugging statements some printing some output statements to see what the condition is around the system when that fails because that that surprises me. The thing is the test doesn't failing on my computer so I don't even know like what would be there. Right which which means that means you've really got to put debugging print statements and let it run on CI to see if you can identify what's different between your environment and CI dot Jenkins.io because you're right it should fail on your computer as well I mean if there's a if there's a real failure it shouldn't be somehow tied to CI dot Jenkins.io, and it's certainly passing for me on all three all three Java versions. Now maybe there's something about. Is it regarding the fight path or something something which is different on Windows, could be, although I don't see any Oh look, I wonder. It's saying it's using master so it's okay it's not invoking the other problem. It's possible that this message here. I assume this message is probably not happening on your computer is it. I don't know. It's certainly not happening on mine this is a message you get with the latest release of get and on Windows, we're we're using command line get to dot 36 so very a very recent version on Linux. The Linux version is much older, but it's also failing. So when it fails. What's the message on Linux. It's got the same message because it's using a new and yes, it's using a nice new command line get version on Linux as well. Interesting. And the 1717. Good question. Very good. It's also using a new one. This is 11. Oh, whoops. Did I get that. Let's try this again. 118. Okay, 17 passing. It's using the same version and giving the same message. Hmm. So I think you may just have to add some diagnostic print statements to debug by telegram in this case to debug remotely. So I have to add or print or print statements and push my or or logging statements system logger statements that should if I remember I'd appear in the city. Yeah, so in this case these things. I think if you use the logger they will appear but you can check for yourself when you're running. And I have another few more questions. Yes. So, can you open the, you know, task executor test I guess task executor test. Okay, this one. Yeah. Oops. Okay. Oh, here I wanted to use. Can you scroll a bit. Okay, not the task executor. It was sorry get maintenance SCM I guess I named it like that. Yeah, in this one. So the I added the yeah in this only the test is failing. Okay, I added the logic to run this. Okay. And then I go down. Okay. If you go to the next test. Okay. Yeah, I commented this because it's throwing errors. It's like the tests are failing. So here I wanted to test whether there are no caches present on the Jenkins controller. I wanted to verify whether this thing returns no caches. But in the previous method, the previous test already caches were being made. Okay, like created. So now in this whenever I try to run this it throws an error because already there are caches run present on the. No. Yeah, so couldn't you if if you would like to test like that. Can't you do something like this where put that there and then do an app before public void. Erase or destroy caches. And then in this method destroy all the caches. What this would do is say every every test now has to reconstruct its caches. Okay, so before every method runs I think this method would be running right. That's correct right that's what it before does is it says, I want this test I want this public method to be invoked prior to each test that's running this in this file. Okay, so I look into this I'll add this thing so that you know these tests also start, you know, you know, finished. So now I have the, you know, so now this week I'll have to be working on legacy get maintenance. Okay, but for that I would be needing the versions of you know the one which version. I even sent a mail to the, you know, office to the gift in the guitar. For forms. Okay, and then they have given a response, which was very complicated. Okay, they will like go to the get CLI use some command to find in which version it has been released and all. So I couldn't follow with that so because they were you were trying to determine which versions of command line get implemented portions of maintenance. Yes, yes. Right yeah and, and that if it will help you if had we had I given you access to mark PC. Oh, I forgot about you know sending my public key. So if you want to send your public key to me I can give you access to it, at least then you have, then you can access an assortment of get versions it's not all get versions but it's an interesting assortment. And how would I be using it like after I give you the public, after I send you the public key how would I be using that. Then what you would do is you would, you would do this. I'll show what you, well, the easy way is you would do this you'd say SSH. Okay, I'm going to fake your name by saying mine, you would do that. That logs me in. I like after I log in that then like, you know, then what do I do? Well, so then there's an additional argument you add to the command line here which, which is the thing that creates a tunnel. And now I've got to look it up to see what the command line argument is to create a tunnel and I'll, I would include that in my email to you so it's SSH tunnel. Okay, nope. Define a tunnel with SSH. Okay, there we go. Okay. What is an SSH tunnel. How can you use it. And now configure an example here we go. So, okay, forward apart from the client to the server. What I'm going to do here is minus L source port. So, yeah, so I think we would write it like this. It wasn't minus capital L is that what it said. Yeah, yeah. Okay, good so minus capital so do minus capital L. 8080 colon mark dash PC to mark weight net colon. And what this then says is on my computer or 8080 so local host colon 80 will actually be routed to this thing in behind Mark's firewall. Okay. And then, like, how do I determine the bit like there's so many plugins and so many things on your machine right so. Yeah, so then then what you do is is on my computer, you would go here to Jenkins Jenkins home. Oh, and I think mine's turned off right now so let's let's do it this way home. Is it off it is I need to start it. Just a minute. On that computer, or on that on that Jenkins installation. I have assigned labels to the agents that describe precisely the git version that's installed on each agent. So this UI would be coming on mice. It would be right so when you ran local host colon 8080 like that, you would see Jenkins, just like I'm seeing it here. And here we come. So, here then what you would do is you go to build executor status. And let's look at something that has that shows something other than not applicable. So that this is an agent that's connected this edamame. So when I click on that. I see labels that tell me this thing is labeled get one dot eight plus two dot 11 plus one dot night. Oh, there it is get two dot 17. This is the one without a plus. That's the label that's assigned to this agent. And so this, this agent has git version two dot 17 installed on as do several other agents. Now if I look instead at let's look at some other computer like this one. It has git two dot 35 install lot. And then I have to create a job on this, you know, to check whether maintenance us exists or not right. Correct, right. And so then what you would do is, is you create a job like here I've got one right here. Let me maybe we should just create it for you right now. We can already do that. No, we. Yeah, there is get get maintenance help. This one I think is the job we created. Let's see what it says. And it tells us and figure where is that figure. Yeah, so it's, it's actually attempting to do that for me. So, so maybe we've got it started already so get get maintenance help is right here. What we're trying to do is saying get version GC minus minus help. So it's trying maintenance commands to see if we can get output from them. So any changes have to do it in this file right or or you create a job that does these kinds of that's better because I can I can take this exact text. Let's let's do that. Let's take that exact text and create a new copy of this job that's not using. So, new item, get get maintenance help pipeline. So it's a pipeline, and we're going to paste that text there. And I just want to use this. Okay, so what it's going to do now if I got it correct is it's outputting get help. This is easier than you know going through all the five. Well, it at least it gives you some sampling of, hey, there here are some machines that mark has, and these machines that mark has are reporting this. It also gives you a nice indicator with the red square of things that don't have the get maintenance command. Okay. So which which which versions do I have to target like which all versions are present while looking to all of them. I think so because what you need to know is for for okay here on a to mommy, this agent. It failed the job so if we, if we configure that differently we can make it so it doesn't fail but it will still give us the output we need. So if we instead said something like this. All right now that should not fail. But you'll have to read the output for each of those to decide what did it actually do. It says it failed even so. Now shame on me. Okay, there's get click. And get. Why did. Okay so apparently I'm not really good at shell scripting hang on Russia cash let's fix this figure. Okay, here we'll do it. Sorry if this is terribly painful for you to watch me diagnosing my mistake. Okay, so now we try it. That was more what I expected. However, when we look at the output from this top one, what you'll see is it's going to have a message. Okay it says get GC that worked. So GC is available. Get commit graph. It says, oh, commit graph is not a get command. So you know for this version get 2.17.1. It doesn't have commit dash graph. Yeah, okay. So I'll try this out if I am facing any problems. You know, send a message in the guitar channel. All right. And finally, as I think I'm digging a lot of time of yours. That's what it is. Now, I've written the code for the maintenance. How do we know like it's properly working and all like do we test it like run it on some caches whichever are present so that you know, we can know whether everything is going. Yes, expected. Yes, and that's where Mark PC to is a good choice because here are some get caches. Okay, so I think that this week I'll add the logs log files. Okay, so that we get that thing. Once that's ready, we can start testing, you know, everything on the system and then check whether everything is working as expected. Yeah, that sounds very good to me. I'll also try adding the, you know, get legacy maintenance, you know, for versions less than 2.30. So that would be the agenda for this week. And I can even next week. Yeah. Very good. Yeah, that that that's it from that those are the questions. Sorry for you know, asking too many questions that you know, at the time. I'm delighted that you're asking questions for you guys this is wonderful thank you for the progress you're making. Let's keep going and, and we'll check in. If you need this this coming weekend is a holiday weekend here in the United States it's a public holiday. And so I will, I'm less likely to be available particularly because my grandchildren will be in town. They'll be visiting here from Texas and so so I if you need help, reach out to Rishabh and see if Rishabh can assist. If neither Rishabh nor I are available. You're welcome to ping me on Gitter and I may check occasionally it just I'll be playing with small children and having a lot of fun. You'll be available next week. Yes, yes, I certainly will be available next week. Oh, thank you. All right. Yeah. Thanks Rishabh anything else. Nothing nothing from my thing. All right, have a great day. Thanks again. Thank you.