 Hello, everyone, and welcome to the Closure Buff. This buff is going to be led by Alana Hashman, who's going to... Sure, I will kick it off. So, hi, everyone. I am the Debian Closure Team de facto lead. I have been working on the team since 2017, since I revived it. And I have also a few members from the team with me on the call, as well as some folks from the Puppet Team who might be asking questions, as will become relevant later in the buff. So, I have Rob Browning from the Closure Team, and I also have Udkarsh and Zigo. So, let's kick it off. If everybody can see the pad, you should see what I'm going to go through in the session. I'm going to just start with a quick introduction of, you know, closure for those who are not familiar with closure. The state of, you know, the current closure packages in Debian, and then what work needs to be done in the upcoming months. So, and I'm going to share my screen. So, okay. So, what is closure? Closure is a Lisp that runs on the JVM. So, some folks may call it a dialect of Lisp. I would call it my favorite dialect of Java. So, all of the various closure programs in Debian, the source code is distributed in, you know, closure source code format. And if it needs to be compiled, it is compiled down to Java bytecode, which makes it architecture all, which is kind of handy. So, there are many packages that are currently maintained by the closure team. You can see some of them here on the DDPO page. Not all of them have been updated recently. For example, many of them are, you know, the same in stable as they are in testing. And unstable currently. And let's see. What else do we have on the agenda? So, goals. What work needs to be done? So, I have recently updated the Wiki page on the closure Wiki. And as far as goals for the upcoming release, we probably want to update closure to 111. However, that's not yet available. So, as soon as that's available, we should do that update. We probably want to update some of the other closure packages. They haven't necessarily been uploaded in a while. We may have some policy updates that we can apply. We probably want to, if possible, package some of the new CLI tools that have been out for a number of years, but just haven't been included in Debian, and we can talk a little bit more about that later. And then potentially anything else that can be accomplished in the sections below that go into a little bit more detail. So, closure itself was targeted initially at the JVM, but also targets other runtimes such as the CLR, such as the node runtime for JavaScript. So, one of the potential goals for missing closure tools in Debian would be to target closure script. There is a CLI provided by upstream, as opposed to the CLI provided by the Debian packages, which was introduced as a Debian script and does not match the upstream because it predates it. But there are a bunch of dependencies that make adding these new upstream scripts relatively complicated, as well as a package transition to potentially use the new scripts. Boot is a closure build runtime that we currently don't have packaged in Debian, but could potentially be including. And then there's some talk about potentially writing a line again helper to allow packages to be able to line again, which is the most popular Debian build tool outside of like the upstream depth scripts to make this a little bit easier than using like some of the templating that I have currently provided. We may also want to work on policy. There's also a big question of reproducibility. So, closure, the language itself is not currently reproducible, which means that any binaries distributed in Debian are also not reproducible. There is a bug sort of tracking this and a discussion on it. And what else do we have? There's some, you know, sort of general packaging hygiene stuff. And there's also stuff that we've done since the Buster release. I think the last time that I held one of these box was at DebConf in Montreal in 2017 because that was the last DebConf I was able to attend. And I think that's probably all I need to share in terms of screen. So, I guess, back to video. So, let's see, what do we have on the pad? I am happy to hold the discussion and discuss any of these, you know, potential goals for the team. One of the other things that I mentioned was that we potentially have some work to be done in Puppet because Puppet, it turns out, these days uses large components of closure. So, in order to package, you know, the various Puppet stuff, we will need to do that. So, yeah, I think that's a good overview. Yeah, I think Zigo, Akash, and I, maybe not Akash entirely, but please, Zigo and I are interested in trying to package Puppet Server. Indeed, in Puppet Server 6, well, Puppet Server was previously written in Ruby and now it's written in Clojure. And we have a large amount of dependencies to write. So, that's why we're here. Yeah, awesome. So, I mean, thanks for joining. There's many things that we can potentially discuss during today's talk, but hopefully that's a decent overview of kind of all of the things that are happening in the world of Clojure. So, any questions? I mean, you're talking about the reproducibility bug. Is it like a really hard bug? No, that is a really good question. So, let's see, let me pull up the bug and I'll share my screen again. Yeah, I think I was going to talk about this as well. Generally, I've seen upstream to be very helpful in making these things reproducible. So, okay, I mean, let's read the bug and see. I mean, I don't know what's going on. So, yeah, so this was a bug filed against line again as opposed to the core language runtime. But if you take a look at the DDPO page, like the core language is not reproducible as well. So, this was mostly a symptom as opposed to a root cause here. We actually, we removed strip non-determinism on this one because it was doing weird things to performance due to strange things about how Clojure bytecode compilation works. So, if we look at, let's see, this is probably very old because Clojure 1.8 doesn't exist anymore. But let me pull up one of these reproducibility reports and I can see if I can try to show you. I mean, it's not reproducible across the board for the most part. And it's because of non-deterministic Java bytecode. Now, that is for, let's see, it's strange that it says this is unstable but it's actually pointing at stretch. So, here, let's take a look at like in cluster. And let me see if I can find the differences. Like, there's specific ordering things in terms of like how this code is generated. And from what I can see, it's mostly like, I've seen a number of instances. I mean, this is just ordering stuff and I'm not sure necessarily how to fix that. But it's pretty like, it's not a trivial thing in terms of the differences here. It's not like a small and obvious thing. I think it would take a decent amount of time to try to determine, because like there are so many things that are just kind of moved around. One of the things that I had previously identified was that it looked like there were, for example, anonymous functions, lambdas that were being generated. And those would have like an identifier which would be like a numeric string. And sometimes those would change between builds. And I don't know if there was like a way to set the random seed for those to be generated from, but yeah, fundamentally, I think that this is like non-trivial to fix. And so I suspect it would be best if someone from like the reproducible build team actually went and took like a deep look at this. I don't think that this is an easy thing to patch downstream. I think this needs to be addressed upstream. Can y'all hear me now? Yes. Excellent. I have no idea what I did. So I poked around a little bit yesterday and saw that at least the obvious uses of the RAM number generator were using the same seed. My best guess is that it might be exactly what you said and concurrency. Like that number may well be coming from an atom that they're incrementing and they're actually generating the code in parallel. And so it's a race to see who gets number 12 on any given run. But that's just a guess. And I agree with you that somebody will have to dig into this. But I also have some people I can, I may be able to ask who, they're not Clojure developers directly, but they might have a clue. So I'll badger them. Awesome. That would be great. Did you try to report this upstream? And I'm not sure how helpful they are or how kind they are. That's a good question. So previously, so it kind of depends. Sometimes Clojure upstream is really quite amenable to various suggestions. Frequently they'll say, this doesn't matter to us therefore. Clothes won't fix. So it's unclear. I can't remember. I feel like maybe this was reported at some point, but it's been so long and the Clojure Jira is hard to trawl through. So I don't think I'll be able to give you an answer on this plot. But if there has been a discussion, I cannot imagine that necessarily the Clojure core team would want to be doing the majority of the heavy lifting. I suspect that we might be pushing that effort in Debian. Okay. Well, thanks. That's nice to know and a little bit sad to hear. Language is not producible as a whole. There's always a big thing, especially if we're going to be packaging a bunch of stuff. Yeah. So one of the good news is that only binary pre-compiled Java bytecode has this problem. Library packages like the recommendation from upstream is that you package those basically just a source code and do compilation on the fly as needed. And there are reasons for this, namely that like between different versions of potentially the JVM as well as different versions of the Clojure runtime, there are no bytecode compatibility guarantees. So without us doing like this massive matrix of like bytecode generation to pre-distribute, it would be kind of moved. So rather than bothering to pre-compile most of the library code, which then solves the reproducibility problem because you're just basically getting text. What we do is we have auto package tests that check to make sure that everything builds with the class path with the current runtime of Clojure as specified in Debian. I actually, sorry, go ahead. Does that mean that the bytecode is being compiled in the postage? Sorry, can you repeat that? Your audio is a little garbled. Does that mean that the bytecode is being built when we install the package? The bytecode is being built at runtime. So we are not like, for example, if I go and I install lib pomegranate Clojure, I do not build any bytecode until I try to use that package with Clojure. Like Clojure will automatically do the just-in-time compilation. OK, thank you. One question I had about that was we had an experience where doing AOT compilation can have a pretty big effect on performance, especially startup performance in some of the work that I've done. And I wondered, I'm not volunteering for this necessarily, but I'm wondering if there has been a discussion or maybe even any interest in. On the Emacs side, for a long time, we've had dependency-based compilation in install time, the Debian Emacs policy infrastructure. We could probably do the same thing for Clojure if we wanted to and might even be able to steal some code from there if we wanted to. But I'm wondering, has that been discussed and do we think it's of interest? And of course, the key thing there is it not only rebuilds all the add-on packages in the right order whenever the packages are installed or upgraded, but it also rebuilds them all whenever Emacs changes because Emacs, we don't know for sure about the bytecode either, so we could do a similar trick whenever the OpenJDK changes, a new version gets installed, we just rebuild the world. Again, not volunteering, just wondering. Yeah, I would not be volunteering for that either. Personally, I suspect it would be a lot of work for not a lot of benefit. Clojure is expected to constantly be recompiling bytecode basically every time you make a change. So if, for example, you have, I don't know, some project that you're working on, on your local Debian system and you're linking it against the system Clojure libraries, every time you make a change to that code, you're recompiling it anyways. Having the bytecode available on your system doesn't matter, Clojure will just go and say, I've got the source, I'm going to redo it again. Sure, but like for PuppyDB in particular, ahead of time compilation could change the start-up time by more than order of magnitude. So we do ahead of time compilation for line again. Of course, if you are, for example, like using line again against a different runtime of Clojure. So for example, if you're like using line run with say a newer version of Clojure than is currently available on Debian or even an older version of Clojure, that will go and be like, ah, this is old. I must go and do these new recompilation things. I think is the kind of thing maybe we can look at once we've been packaging large things like a puppet or a PuppyDB, if we ever get a packaged PuppyDB correctly in Debian. Once that's done, we can actually run benchmarks and see what the hit is, because I guess that upstream PuppyDB compiles this ahead and just pushes a binary, right? Yes, I can tell you it is on the order of seconds in terms of overhead. Like it will be very, very painful. No, potentially that's not as much of a worry for something like puppet where you have like, you know, you kind of run it once and that's that. But for say like the Clojure language runtime or line again where you're frequently running the command over and over again, you absolutely want something pre-compiled available. But then we run into these reproducibility issues. So there are lots of comments in the etherpad. Do you want me to address any of those? Yes, so the blue ones are mine. So that's things I wrote because I have a cranky internet connection here. Mm-hmm. Okay, well, I will just go ahead and I will respond to some of these. Oh, I see that there is a comment that I should speak more slowly. I will try to speak more slowly. My apologies. Okay, so the first question. I didn't have a question before you proceed. I'm sorry. No problem. Yeah. Okay. So in the to do in the wiki that you shared, there was a task, a to do task that, you know, we want to update the Clojure packages that are in the dating archive. Do we do we just want to update as in, I mean, for instance, there are some packages that might depend on it and we don't want to bump their version. So that is why they're like, sometimes the reason to have outdated packages because the main package, the main thing, which is why the other packages were packaged, does not currently support the latest package of their reverse dependencies. I'm not sure if you're, if you get that one. That's right. So most of the packages in Debian under the Clojure language ecosystem, they're not packaged specifically for you to, for example, like, you know, apt install random package so that you can do system development against that package. You can do that. It's not particularly well integrated with the standard Clojure workflow. And so typically Clojure tools are going to be pulling dependencies externally from, for example, like Maven Central or Clojars or other repositories. And so generally my position is that any Clojure package in Debian should be there in order to facilitate some tool available on the system that happens to be written in Clojure. So whether that's line again, whether that's the core Clojure language, whether that's say like Puppet, my goal would be to ensure that the packages are, the corresponding versions for those dependency trees rather than always just trying to ship the latest. Clojure is I think sort of guilty to some extent of often holding really outdated dependencies because the language runtime is very stable. So there's not necessarily like a culture of like constantly updating packages and dependencies to latest. So as a result of that, I would say it's quite safe to leave them kind of where they are mostly like for hygiene, I'm thinking of updating packages. So for example, ensuring that they all are compliant with the latest standards policy ensuring that, you know, like the packaging all looks good and is up to date not necessarily pulling down new versions from upstream. All right. If I'm a VI breakage between let's say, we're trying to package Puppet server, which has a huge list of dependencies. Do you know if a new version of a dependency might break something? Is that something that is common or? So yeah, that is potentially a risk. I would not be super worried about that. And the reason that I would not be super worried about that is I would recommend probably the way that we should package Puppet is the same way that we package line again, which is that we do a big ahead of time what upstream calls an uber jar where basically like you take all of the dependencies like all the things there's no like, you know, the Java equivalent of dynamic linking going on. You take everything you compile all the bytecode that you need you get one single static executable and that's kind of the end of that. And so basically the only thing you would need to worry about in terms of breakage is if you had say like a new version come into the archive and then you can't build Puppet then that might like, you know, we would need to go and fix that in order for the next binary published to the archive to work properly. Okay, anything else before I dive into the etherpad? One quick question. Are we allowing uber jars? If we are, then some of my concerns may not as well apply. Yes. So I mean currently there is one uber jar and it is a line again. I have no concerns with shipping uber jars. That's the upstream policy. Like that is how I think many other teams are now sort of moving to ship things as various language run times sort of move in that direction. At this point, I'm not super worried about it because you know, one of the concerns of doing that is potentially outdated things in terms of dependencies and like duplication on the system. Right now we don't have enough things. I think that would result in large amounts of duplication. So I don't think it's a serious risk for any of that. There will be a good chunk between PuppetServer and PuppetDB, but I don't know if that matters. Yeah, I don't think that that would matter that much. If it was like dozens or hundreds of packages there might be more concern than like... It may be. But that's the thing. If we don't have so many packages then probably we can figure out how to package them separately. Thanks for Puppet. We counted around 20 to 25. That's manageable. But the whole tree is much larger than that. So if you were to install PuppetServer on a machine you'd get something like 200 closure dependencies. Or as if we're only using the Uberjar version then you just install PuppetServer which is a large binary and then you can run that easily. I think that might be more performant and give us less headaches maybe having something more stable with Puppet. And as for the size, I think you don't care if you're running Puppet on a server anyway that machine is powerful. Not running Puppet on a machine with 250 megs of RAM. Yeah, and that's what we're doing for a line again as well. And I mean like the file sizes we're talking about here are not particularly large. Let me pull up quickly. Let me see what the actual file sizes for like a line again are in the binary package. Because I don't think they're really not that big. So shall we stop doing what we wrote on the wiki? No, that's still relevant because we need those dependencies to build PuppetServer in Deepian. Yeah, you need to upload all of the dependencies. Instead of having all these dependencies as runtime dependencies we're going to have them as build time dependencies. Yes. Okay, so the ubersure that you're thinking about is PuppetServer is tough then. All right, thank you. Now I get it. Exactly. Okay, I'm just checking right now to see if I can see... That's the source package. Binary package. Okay, so the binary package for a line again is like 14 megabytes. So we're not talking about like really anything substantial here, right? Okay, any other questions? Yes, before we move on to the questions that are in the pad I just have a quick thing to ask. So I guess we started the discussion that there are a lot of packages, closure packages that are in the Java team. I discussed this in the Puppet team buff as well. Do we intend to move those closure packages from the Java team to the Clojure team? I would like to do that. I proposed that in like 2017. The reasoning behind that proposal being that for all of the closure packages that are just closure source code that they're not Java source code, there's no real need to have any understanding of Java in order to package them. So I think it makes sense to move them because it'll be easier. The Java packaging is much more complicated, I think, than closure packaging, particularly for something like a library that's kind of like, here's a tar ball of the source code. I think it makes sense because there might be dependencies which we'd need to update or something. Then we'll need to go to Java team to do that. And I think it's better if all the Clojure stuff is inside the Clojure team that makes this thing easier. And did you manage to have access right to move them on Celsa directly? So I should have access now to do the migration. I have not sat down and done that on mass. We'll have to probably also... I mean, all of the sim links should be in place, but we'll still probably have to update the home pages of all of the packages or the packaging links. So... The thing was to do it on Celsa on clicking on the repository tab. And then that way you move it to the Clojure team and you have a redirection which is not impacting anyone then. Yes. Yeah, that is the hope. That should make it much easier. But yeah, just have them sat down and had a chance to do it. There's like a bunch of them that we need to identify, and I would rather not go the pointy clicky route for like, you know, 30 packages. I can write you a script and start the API. I think that supposedly the Celsa team already has scripts for this. So I just need to reach out to them. Rob, I see that there's a bunch of backscroll in IRC from Alex Miller, who is one of the, like, core members of Upstream Clojure. Do you want to speak to a little bit of that for the livestream? Well, I think one of the things we were talking about was just that my original suggestion about whether or question about whether or not we wanted automatic rebuilding and install time. We were talking a little bit about that and maybe completely irrelevant if we're going to allow UberJarves. So I think we probably already covered that. But he also mentioned direct linking, which, yeah, that's a thing I think we probably, if we're not already, we probably want to enable for the final packages and maybe for everything. It basically, I'd have to go refresh in the tails, but it avoids a level of indirection at the top level for all references in Clojure. So it can get rid of overhead. It also means it's less dynamic. You can't go in and mess around with things at runtime as easily, but that's not relevant. And I think it can have an entrepreneurial effect depending on the use case in performance. It's pretty much just performance related. Yeah, I'm taking a look right now at the link that was provided in IRC. And I'll make sure to add that to the ether pads. I believe it's just a line again option. So for those who don't know, there's some plug in. I forget if they're built in or not for line again where you can do update in on the project file to make some minor modifications to a project file automatically without having to, you know, do something uglier when you're wanting to mess with it. Yeah, I definitely wouldn't mind adding that to, for example, like the line again build parameters. Now granted, if it's just like a thing that we can stick in the project.close file, then that should make it easy. But hopefully it will be, I mean, if it's a straightforward as like a single build parameter then yeah, we should just do it. If it's already happening, according to this doc link that I pasted in the ether pad, it already should be enabled on Clojure 1.8 and higher. And so if that's the case, we don't do any modification to the upstream build, we just use their scripts. So that should be happening already for that binary. So it would just be line again and potentially puppet server that we would need to enable that on. I should probably also call out that he mentioned with, I assume, his upstream hat on that they definitely do encourage users to just distribute the source libs. I assume meaning, you know, libs not compiled. Yeah, that's been my understanding from, like that's just the upstream practice in Clojure, both for like my understanding working with the line again folks, my understanding working with Clojure upstream. That's just the recommendation. So that's mostly why I've been trying to save us like pain and suffering there. It should be, it's much more straightforward to just distribute the source and that is the recommendation. All right, maybe we should have a look at the ether pad and the question because we have only 15 minutes left. Great, I am happy to do so. So I'm just going to go through the questions in the order that they have been put in the doc. So first question is how does one tell if a dependency in a project.close is a Java or Clojure dependency? That's a hard question. There's no obvious way to know without like going and looking at the package itself. You can guess? What's happening is that I look at the project.clg and trying to figure out which package is matching or not and it's not very easy to do so. No, it's not. It's, you know, it might be helpful if for example, like we had some sort of mapping in Debian between like this is the upstream Maven central artifacts name and this is the package in Debian's name. As far as I'm aware, we don't have that. If we did have something like that, I would be very happy to also contribute Clojure package names to that as well. But there's no way to tell just from the name. We do it works in the Python world. Sorry. Do you know how it works with Python? Like we have a dhpyton embed file which has precisely that a kind of dictionary. I see. Yeah. I mean, I don't have strong opinions on what that metadata should look like. That's certainly an option. But I think the problem right now is that Clojure is like a pretty small portion of the wider Java ecosystem and there's really no way to tell. And if we were to implement this at the Java team level, that would be quite a lot of work, I think, if it's not been done. So that would be potentially a good question to bring to the Java team mailing list. But I agree with Zigo that mapping the dependencies for puppet server was a pain in the ass. It took me like two days of work. And even there I made a bunch of errors that people corrected me on. So it was a very manual and tedious process. I talked with the people in the Java team and there has been interest in doing that. Somebody, I don't remember their name. It was Subin maybe, started doing some work on that and it had something working. But it wasn't working perfectly. But I think, yeah, since we're using Maven anyway, it should be done in the Java theme. It would be more... Yeah, that sounds totally fine to me. And if, for example, like either the Maven repo helper or if it's like an actual Maven package then the Maven Debian helper can help us write that information then all the better. It'll make it easy to standardize across the board. Currently, all of the packages in Debian, all of the Java packages, build a Java or a Maven repository within the system. So, and all of the closure packages add this metadata as well and get registered there. So you can basically point at your Debian system with all of these Java packages to treat it like you would any other Maven repo source. Let's see, what else we have for questions in the pad? There's a question on what are the causes of non-reproducibility in Clojure. I think we covered that one already. Yeah, and Alex just, I talked to him about it for just a second and he mentioned it. Yeah, Jinsim names, the integer names, that kind of thing might be a problem. And he suggested that we could ask a question on ask.clojure.org and he monitors that and can make a ticket. Great. Yeah, then I think that potentially that is something we should do. Next question is, can you explain how the Debian palms.xml gets generated by Clojhelper? Well, I think I would have to talk about Clojhelper in order to discuss that. So, let's see. I'm going to look through just the rest of the questions before I jump into that that's probably a more extended subject. What would you suggest to check on a freshly new package? What should I do to make sure my package is in shape for uploading? That's a good question. You can ask me for a review for the Clojure ones. There are some reference packages that I would look to to see like, hey, what should a Clojure package look like? But I don't have any like examples of the top of my head. Yeah, but that would be a shame to give you so many things to review. That's a problem. Yes. Well, certainly if there are other folks from the Clojure team who would be willing to step up and assist with that, I think that would be awesome too. Right now, it's always great like to have more volunteers and that's definitely an area that, you know, we could have more volunteers get involved. I think we're going to review for the first few packages, maybe, and then once we're going to be, once we have done a bit of them, we'll have more experience and we shouldn't need everything. And I think what Cashman mentioned with the auto package test is important. It's a good way to test if something is working, if you can call the Clojure package, the Clojure library. Yeah. So the next question is, this is a good question. Why do we have to specify all of the dot jars in the Debian slash package dot class path? Can't this be found out of dependencies? So Clojure currently does not do that like automatically in the Clojure runtime. It doesn't have like a dependency resolver. So the options are, you could use a dependency resolver like Maven to generate the class path. You can use a tool like the upstream Cloj depths alpha script, which could potentially generate your class path. Basically, there are many tools, most of which ultimately rely on Maven code to generate a class path. But if you don't have one already, you need a way to provide one. So what we do in most of these packages is we just go and say, hey, here's the class path. We know what it is. We don't need to use all these tools in order to specify it. That's something that we can do at packaging time. Is it time to write this file by hand? Yes, assuming it works. But there's some automation available to help with that. And then how do I check that? What I wrote there is correct. You can check that by trying to run the package. But invoking it basically with the Clojure runtime and see if it works. So we're just modifying only that particular jar on the class path to Clojure. I think the newer upstream CLJ stuff has a way to actually print the class path that it generates now, too. I don't know if Liningan does. Yeah, but both of them. Yeah, LINE also has a class path sub command that you can use. And I think that's actually how we generate that when we build LINE itself since it's a bootstrapping build. And then the class path file will end up in the jar of the library, right? Yes. Okay. Okay, so we have two more questions. One is about the team's Git tag workflow. I am not particularly attached to any particular workflow. I think you're referring to the workflow on the Wiki in a tutorial. That's obviously not the only way to do things. It is simply a tutorial guide. And it's also quite a few years out of date. So there are potentially lots of improvements to be made there. So I would not accept that as the law of the land or something. That's just, you know, here's one way you can do this. But I think we should maybe jump into this question about Cloj Helper. And I will go ahead and share my screen to give a bit of context. So Cloj Helper. So Cloj Helper is a small Clojure package that I wrote in order to assist with templating out Clojure packaging. There had previously been a script that had been written in Python way back in like 2014 that did not do a lot of things. It kind of fell out of use. I also know that Poicos had written some bash scripts to help automating in Clojure packaging. But this is what I ended up writing to assist with my own packaging. This is not like a, you know, this isn't like my name space on Salsa. It's not like in the team name space. I mean, I'd be happy to donate it to the team. But I'd say it's more like beta. It's certainly not in Debian currently. But so we had done a little bit of work on this today earlier in like addressing some of the problems, outdated stuff, CI, that kind of thing. And so effectively what this package does is you can basically run the standalone jar and it will ask you a bunch of questions and then it will go and generate a bunch of scaffolding for a Debian package, for a Clojure package. And so this is just, you can take a look. There's a link in the etherpad if you want to pull this up. But the specific question was how does this generate a POM? And I can just pull up the code for that because I believe that is in here. Yeah, because it's all like magic to me. And I just wonder the rest of it, I think I can figure it out. But that was a whoa. Yes. So it's not actually that. It's not very sophisticated. It just shells out to line and calls line POM. So it uses line again to generate the POM. It doesn't do that directly. And in particular, it shells out to a line. It's not added as a dependency in the Clojure package. So it's not like that's part of the source code here that you would get in a standalone jar. You would still have a system dependency on line again. But given that you need line again to build and run this anyways, that didn't seem like something excessive to ask for. While I have this open, any questions about Clojhelper other than that one? I think it would be a good idea if you could move it. And then the team's path would make certainly making merge requests easier since we wouldn't have to fork it and then we could just use branches. And I agree that I think if we're going to use that a lot, it would be a good idea to try to package it and deep into it. Yeah. I have no objection to that. I did not expect anyone to use this other than me. So I did not really write this for anyone to use other than me. So if you want to use this, by all means, I would be happy to move it to the team for falsetory. OK. Stop sharing the screen. I've got another question. Probably a simple one. Do the auto-PKG tests, the tests that we write, are kind of similar for all packages, like a quick smoke test or something? In case, if it is, can we add this in the Clojhelper and just which will generate the test by default and maybe we can run it. And if it fails, maybe we can just debug this. In case, it's similar for all kind of modules. I would love that. I think that would be a great idea. And I think somebody mentioned something about AutoDep 8 as well. Yeah, I did. I think a bunch of these tests are very similar and it could be an easy AutoDep 8 test. And when it fails, you can just remove the AutoDep test command. I don't have any experience with AutoDep 8 or talking with the even CIT from what I've seen from the Python scripts to use, because I've been looking at the Python scripts. It doesn't seem that hard. And I think it would make things a lot easier and we could add tests like this in a mass. Yep. So something like you need to add test suite and auto-PKG tests, Clojhelper, something like that. And that should be a depate test. And maybe you can just integrate. You just need to then mention a line in the D control file, the test suite, auto-PKG tests, PKG CLJ. And that should run the tests by default. Yeah, that would be awesome. The only caveat that I mentioned earlier as I think some folks ran into is the specific like namespaces that you need to test if you're doing a smoke test. They're not necessarily obvious or easily discoverable. So that might be something that we need to take account of. OK. Maybe you can just give it a try. If it doesn't work out, we can just remove. I mean, I don't want to break things and then be like, oh, that didn't work. I guess we'll take it out. I'd rather not break things. So we can see. We have one minute left. Maybe let's let Zigo talk and on that. Yeah. So if I understand well, the project.clj is some bunch of closure codes as well, right? So the best way to to parse it would be in closure so that maybe we could extend closure helper to read that file and pick up some information from it, like the dependencies, the IC test, the license name and such. So that closure helper would ask less things. I wouldn't. I'd be careful about parsing it depending on what you want because, for example, PuppetDBs is code that runs and you don't know what the right answer is until it finishes running. But you can, by extension, you can add, we could add code to project.clj sometimes to print out what we want or do whatever. Yeah. I'd echo what Rob says there. It can be because essentially like there's a macro that's been defined by Lining in called project in that file. But it's just a bunch of code. So potentially you could have a bunch of other code and some projects do have this. So it's not an I and I format or something like that. It's not just data. And in fact, like folks will potentially use this to like swap in or out different dependency profiles based on environment variables set other things like that. It's sort of the risk of having something that's very extensible. But sadly, we're going to have to end the stream on there. If you still want to talk, we can continue talking here or an IRC, but the stream part of the box is going to happen. Just to wrap up on that subject and then maybe you can say goodbye. So it's comparable to a set up by in fact, right? It's like a make file kind of. I mean, in the abstract, it's touring complete. You can do whatever you want in there. The but tools like line depths, line depth tree, line P print, line update in, or we could write our own plugins for lining, which is one of the things I was wondering about. I guess we didn't get to unless I'll talk about it first. Was the, I think you brought it up. A lot of the discussion about using line again more. And I don't know exactly what the plans were there or what we were thinking. Yeah, I don't know, but I think we got to wrap it up so we can just continue the discussion on IRC. Thank you so much. Yeah, thanks for the buff and all the help. It's super nice. Thanks everyone.