 Welcome everybody. This was last minute exercise on Arduino CLI. So Arduino CLI is a technology preview by Arduino, which basically replaced the Arduino IDE. So who here has never used the Arduino IDE? Okay. And who here has never used Docker? Okay. So what I'm going to show, I hope at the end, if the internet connection is fine, is how to use GitLab CI. So GitLab CI, the original plan was to connect GitLab CI, build the container with the SDK, blink a LED, and package everything, put that into a Docker registry of GitLab, and then tell Raspberry Pi connected to the ESP8266 board that you can see here. So I don't know from far if you can see the LED blinking. So the typical way is to use the Arduino IDE. So the interesting thing is why use Docker in this setup is to be able to do caching. So one of the advantages of Docker is it does when you are developing, when you try to rebuild your Docker image, it uses layers of caching. And so previously I worked in a company like 10 years ago where I was scripting containers. And when Docker came out, the Docker file was very similar to the scripts I was doing. One of the disadvantages of my approach was if you had to change one comma, it was a 45 minutes rebuild. While with Docker, if the comma you change is at the end of the Docker file, then it would cache everything and just use the cache way faster. So here I have a simple, I use a simple blink. So I'm not going to, the code is very simple. So everybody knows that. So I took the Arduino CLI project and added the Docker file. So I've separated the structure in two layers. So the Arduino CLI is basically a Go application. It's a Go application, so I took the examples and basically in the first lines I compiled the Arduino CLI binary as a static and then in the second step, so this is called in Docker multi stage build. Basically I want to take the Arduino CLI binary and put it in another Alpine layer. So this is, I copy the Arduino CLI binary into my user bin. And then in order to use the support for the Wemos D1, which is an ESP8266, I have to specify CLI config.yaml, which contains the link to the, when you have to add a new type of board, you have to specify which URL, JSON URL, which will fetch the SDK. And then do an Arduino CLI core update, install the SDK, and then one thing I found during my development is that I tried to put that part into the second Docker file, but then it was pulling the SDK again. So I just put a blink example so that everything is cached. And then in the second example, I create a blink tool where I don't have this pulling of the SDK anymore. So I measured it was, this whole thing is 500 megabytes, and it's ghosted on GitHub. So if you do github.com.slashdubab. Arduino CLI, Arduino CLI, you will find the project. And there is, I put everything in the Docker file branch. So feel free to have a look at the code. So if you do Docker images on my disk, you should see that there is an image here. It's a bit bigger, an image called Zubab Arduino CLI. So if you do Docker search, Arduino CLI should find Zubab image, which is 1.2 gigabyte. So what I have prepared here is, so the actual, maybe I can talk about just the standalone. Here I've installed the Arduino CLI on my laptop, not inside Docker. So here if I have, here I'm blinking a light every 10 seconds. So this is 10,000 milliseconds, so 10 seconds. And I made a small script that basically calls the Arduino CLI, compiles everything and then do a flash over my DevTTY USB 0 here. So it throws this error, but it basically continues. So now it's flashing for people who are familiar with the Arduino. So now it should blink every 10 seconds if everything is fine. So that's, the flash has been successful. So that was basically, I listed the board, I created a new sketch. It's going to create a directory in the home Arduino blink 2 and I copy my blink 2.ino file over there. Then it does a compile where I have to specify my V1, my Wemos D1 mini board with the code I want to compile. And then it does a upload. So I did Docker file. So before I showed the Arduino CLI outside of Docker, now I want to use everything in Docker because my goal is to put everything into GitLab and GitLab has standard, let's say, container flow for deploying containers. So from the SDK which I called Arduino CLI, there's a small bug which I reported where you have to fix a Unix user called root. I copy this blink 2 to, here it's a slash root, Arduino blink 2, blink 2.ino. And then I launch the compilation. And so if everybody is familiar with the entry point, it's the entry point when I do Docker run the name of the image, then it should, by default, take this command and execute it. So when I will do Docker run my blink 2 image, then it will do the flashing. And inside this image, the binaries will be in the image. So this is something where it can be transported, like you give it to someone, you just say, hey, take this image and it will, the person can just run the image and have the same flashing results. Okay. So here I made another small shell script which is build, build and run. So the build is just doing a Docker build. And I call the image blink 2. And when the run is just doing Docker run. So in order to access the cell port, I need to be in privilege mode. So this kind of root access and image name. And I have another script which is called build and run, which is basically getting the time of the build, getting the time of the run. So if I modify my blink 2 and put it to 5 seconds, it's going to copy the INO file, do the compilation. So depending on the, sometimes it's fast, sometimes it's not. Okay. Normally there should be a time somewhere. Yeah. So 25 seconds to execute. And then it's going to try to flash it. Sometimes it's fast. I've been to situations where it takes 45 seconds to flash. But it basically does the same as the previous example, but everything in Docker. Okay. Fine. So we have, for the build it took 25. And for the run it took 25, so it was like 50 seconds. So the next step is to put that, everything in GitLab. So GitLab, since there was Microsoft acquisition of GitHub, a lot of people looked at GitLab.com. The advantage of GitLab is you have this CI, GitLab CI, which GitLab still doesn't have, where you have to use external service like Travis. And it's also the hosted version, it's the enterprise version, but you can also run the community edition on your, let's say on-premise, on your laptop. So here I used the, let's say the hosted free version. And what I did was, so you have to, next to the Docker file, you need to have, where is it? You need to have a .GitLab CI YAML file. And when you go into the web interface of GitLab CI, you create, you say a new file, and then you can choose .GitLab.YAML, and you have pre-configured template. I just took the Docker file, which is the standard one, and modified it a bit, so the first ones are the same as the template. And then I tried to use a Raspberry Pi and the ESP as a standalone. My first attempt was to send this slash-def-tty-usb-0 to a server on the internet where I could run a small Kubernetes cluster. And for that I used Ser2Net, which is a Serial2 network, Serial2 TCP program, and I could successfully send it and create a slash-def-tty-0 on my server with SoCAD that creates a virtual dev entry. But unfortunately, when I was using the Arduino CLI upload, it was throwing some weird errors. So it might be that I misconfigured somewhere some parameter in Ser2Net. So I didn't manage to get that working, so I rolled back to a design. Maybe I can show here in the diagram where I used the GitLab, which is connected to runners. So one of the issues, one thing I wanted to have was the caching because on my laptop it was cached. And the GitLab has, by default, shared runners. So you have eight runners available where it shoots the build. But they have the policy to not do any caching for security reasons that don't want to do any cache. But so I tried to install a small digital ocean machine with one gig of RAM and put the runner over there to try to have this caching mechanism of Docker, but I didn't succeed. So it means that the time of the CI will increase because it doesn't use the cache, so it's pulling one gig of the SDK for each build. But that's going to be a room for improvement for the near future. They provide GitLab compared to the community edition. They provide the Docker registry built-in. So on the right side of your GitLab, you see a registry entry. And I tried to put a small communities cluster, whether it's Minikube or KS3S, which is a stripped-down version of communities where they removed lots of features on my laptop, but it was not that stable. So at the end I said, okay, I do an SSH tunnel to my laptop which is connected to the ESP. Okay. So yeah, let's have a look at the GitLab YAML again. So here at the end in GitLab CI, in the settings of the project, you can put some environment variables. And over there I put a SSH private key. So when you build, you can get these environment variables and redirect to an SSH key file, fix the permissions, and then the GitLab runner is going to SSH to some host called zoobab.servio.net. So Zoobab.net is a free, let's say, free service with Linux binaries and everything just using simple SSH. But server-side, they have provided the binaries but not the source code. So that is used here in my tunnel.sh. So tunnel.sh is doing just a SSH remote port forwarding. So here I've said, yeah, I will try to modify the code. So if I go on files, I have my blink.ino. And I will put the delay to two seconds. And there I calculated that it takes roughly three minutes. So it triggered the CI CD pipeline. So the pipeline itself is split in two phases. There is a build of the Docker image and then there is a deploy. The deploy is basically SSH-ing to my machine and say, hey, pull this image to be the last one and then flush it. So the build is running. It's pulling the SDK. So maybe I can talk while it's building. Normally it should take three minutes. I can talk a bit about the GitLab, about the other problems or which other improvements I want to make. So I tried to, I made some simple YAML files. So with MiniCube, there is MiniCube, which spawns a VM. And I was looking for how to take this flash drive USB, TTY USB 0 on the host and put it inside the MiniCube VM, but I couldn't find out. MiniCube has also VM driver none, which is basically spawning community cluster without any virtualization. So if you have a Docker running, it's just going to spawn a list of Docker containers. But on that one, I don't think I could see the slash def TTY USB 0. So I tried another one, which is called kind, which is Kubernetes in Docker. And there it basically spawned one container and on that container, I could see the slash def TTY USB 0 from the host. And when I would spawn a container in privileged mode, I could see also the slash def TTY 0. But when I run, on here I can show maybe the YAML file for the flashing, basically saying, I spawned me a container with that image. Then my cluster blew up, so I still have to debug it. But basically the idea is to have a GitLab CI connected to a community cluster, whether it's local or in the cloud, and either send the serial port to there or having directly the community cluster running next to the machine where the hardware is. In the past, I've done some similar things with OpenWRT. So taking the building, the whole thing, put it into a big Docker image. The SDK right now seems to be fixed. So if you want to do a basic package for OpenWRT, you could use the same approach, which is to have the SDK in the upper layer and have your code, which is the package or the code you want to build for OpenWRT in the second layer. And nothing prevents to use GitLab CI as well. So where is it now? It's still running for two minutes. So the first part has succeeded, and the deploy has succeeded as well. So now I said it was how many seconds? Two seconds? So yeah, now it's two seconds. So you could see in the CI that it has been flashed correctly, that the pipeline says passed. If I can zoom in. Oh, yeah, here. And it took three minutes to complete. So this is definitely way longer than 50 seconds I had on my laptop because it has to pull the one dot gig each time. So I think I measured. It takes 50 seconds to download this. So you can remove it. But the advantage is when it does the pool in the deploy part, when it did the pool. So you can see that here it said all the... This is on my laptop. It says all the layers already exist and basically downloaded just a few layers which corresponds to the compile part on basically the last step of the process, but the rest was already cached. So it gained a lot of time. What else? Yeah, so that already showed. Yes, so there is also one issue. I tried to use GitLab CI, including for the SDK, but I couldn't figure out how to have the integration with both. So for your information, the Docker Hub is not integrated with GitLab. So you can't... In Docker Hub, if you log in, you can quickly create a build if it's hosted on GitHub. But if it's hosted on GitLab, you can't. Okay, some other ideas. I have tested another board for the BluePill, which is an STM32-1.0.50 board, much more powerful than the standard Arduino. And they have some kind of... The project is called Dubboot. And it's a web interface which is using WebUSB and you can reflash directly if your browser allows it. You give the permission and it can reflash directly your USB device. So I also found another WebID called G5GS or something like this, used by processing where you could have, let's say, a better IDE and maybe a direct connection to your USB device. This has also some security implications, but... Yeah, I have the standard Arduino IDE Git support so that if you make some changes, you say, commit and then it pushed to GitLab and then triggers the pipeline. Yeah, one option would be also to take the INO file and just send it to the container so that you would just wait and take it on the fly and build it. But it doesn't fit with the mantra that everything is container and reproducible. Yeah, I also used another project called G-Link which is taken in ESP and use it as a serial to TCP bridge and the idea would be to take a second ESP hook it there, send it to a server, a console server and then from there do the flashing. Another idea is to integrate the over-the-air update for the ESP. So the ESP has a Wi-Fi so you could flash the thing over the Wi-Fi. Yeah, so in the case of Raspberry Pi, use a QMU wrapper. So the binaries, all the containers here are AMD64 but if you want to run them on the Raspberry Pi, you might look at QMU wrapper and that's basically it. So if you have any questions? One of the concepts of CI-CD is being able to test what you are doing. In your case, I see you are preparing or flashing but how do you control the feedback loop to know what your push is for example? So for this example, it's the B-Link but if you look at the GIT history, I've added serial messages saying I blink at that speed and so if you would a third test step, you would just check the serial console if you see those messages for example. Are there any virtual images? May you have another in MIMU if that's simply running on QMU or some virtualization so that you could, instead of flashing something into real hardware, just test it on an invitation? That I don't know. Emulation of the MCU? It probably exists but I don't know by heart. I don't know. Well, thank you.