shapehq / tartelet

⚙️💻 A macOS app that makes it a breeze to manage multiple GitHub Actions runners in ephemeral virtual machines on a single host machine. The benefits are that runners can run in parallel, and each job runs in an isolated environment.
MIT License
510 stars 17 forks source link

[Question] Access Runner Name from within VM #73

Closed hisaac closed 5 months ago

hisaac commented 5 months ago

I'm trying to set up some monitoring for our build infrastructure (using Datadog), and I have a need to be able to determine the name of the tart runner from within the runner.

A little more context:

When Datadog reports vitals on a computer, it uses the computer's hostname to report information back to Datadog. Because the same virtual machine image is being used for all our Tart runners, the hostname is identical (runners-Virtual-Machine.local). Datadog handles this by only reporting on one virtual machine and ignoring the others.

So I'm trying to find a way of accessing the VM's name from within the VM, so that I can set the host name within a script.

Do you have any ideas on how I could accomplish this in Tartelet's current state? Or is there a change to Tartelet that could be made that might help here? I'd be happy to put in the work to make the change if so.

Here are a couple possible ideas I've thought of:

  1. Give Tartelet the ability to set the Tart VM's hostname after it has been started (maybe in the boot.sh script, or via command over SSH).
  2. Give Tartelet the ability to set or modify global environment variables on the VM after it's been booted (maybe by creating/modifying a file on the VM that can then be sourced or read from within .zshrc or .bashrc files, etc.)
  3. Give Tartelet the ability to run a post-boot script that runs before (or after) the boot.sh script, with the option of passing some variables into the script that could be useful.
simonbs commented 5 months ago

This is a very interesting use case. I prefer your third idea the most, as it enables users to do anything when a virtual machine is booted, as opposed to only setting the hostname or environment variables. I think supporting a post-boot script is the way to go.

Previously, Tartelet supported pre- and post-run scripts, but this was removed in version 0.8.0. While pre- and post-run scripts may not be the most elegant solution to your problem, maybe they could have been utilized to address it. Pre- and post-run scripts were removed because, with the transition to configuring virtual machines over SSH, we had to come up with a new way for users to pass the pre- and post-run scripts to Tartelet.

I hope that we can bring back pre- and post-run scripts some day, and I could see a user-defined boot script fit right in with this, so maybe it's time we figure out how these scripts can be configured in Tartelet 😃

I can come up with two decent ways of configuring the scripts to be run during the lifecycle of a virtual machine and a GitHub Actions run.

  1. By convention. Tartelet could look for scripts at a specific location in the virtual machine and run them when applicable. E.g., the scripts could be located at ~/.tartelet/post-boot.sh, ~/.tartelet/pre-run.sh, and ~/.tartelet/post-run.sh. Only if Tartelet finds a script at a path will it be run, and if no script exists, it will "fail" silently.
  2. Defined through settings. Scripts could be stored on the host machine and selected in a new settings panel in Tartelet's settings. Tartelet would then transfer the scripts to the virtual machine through SSH and run them when needed.

If you have other ideas then I'd love to hear them!

My original thinking was to go for option 2 as it seems easiest to set up as a user. However, that requires this to be configured on all host machines through Tartelet's settings. If we go for option 1, the scripts would only need to be transferred to a virtual machine once, and then the image can be distributed to multiple host machines without any configuration needed.

Typically, I'm not a huge fan of conventions like this in software as it can seem a bit "magic," but in this case, it might be both easiest to use as a user and easiest for us to maintain as developers of Tartelet.

I'd appreciate your input on this. And if you're up for taking a swing at it, I'll be ready to merge a PR that implements this 😃

hisaac commented 5 months ago

I agree, I think option 1 would be best in this instance.

I'd be down to take a shot at implementing it. I'm not super familiar with the codebase here, so if you've got any guidance or recommendations on where to start looking and editing, I'd appreciate it.

In addition to the runner's name, can you think of any other variables that would be useful to pass to the boot script?

simonbs commented 5 months ago

I agree, I think option 1 would be best in this instance.

Let's go with that then.

I'd be down to take a shot at implementing it.

Awesome! 🙌

I'm not super familiar with the codebase here, so if you've got any guidance or recommendations on where to start looking and editing, I'd appreciate it.

~Let's focus on the post-boot script for now, as that's where you seem to have an immediate need. Then I or someone else can tackle the pre- and post-run scripts at a later point.~ Pre- and post-run scripts were added in #78.

While skimming through the codebase to give you some pointers as to how you can proceed with this, I found that this could be done fairly straightforwardly and went ahead and implemented it.

Can I get you to try this build? It's Tartelet 0.8.3 but with support for a post-boot script. It'll look for a script located at ~/.tartelet/post-boot.sh and run it if one exists. The changes are shown in #77.

The post-boot script is run as soon as an SSH connection to the virtual machine can be established and is run before the runner is started. The script can read the RUNNER_NAME environment variable to get the name of the runner.

In addition to the runner's name, can you think of any other variables that would be useful to pass to the boot script?

I can't think of anything off the top of my head, partly because I'm unsure what kind of interesting things a post-boot script can be utilized for. I think it's fine to just add the runner name for now, and then we'll expand it in the future.

However, I think it's key that we make it as easy as possible to provide more information to the post-boot script in the future. Therefore, I'm thinking that we shouldn't pass this information as arguments to the post-boot script and rely on the script extracting those positional arguments. Instead, we can set environment variables and rely on the post-boot script reading those. That makes it easy to add new environment variables in the future without affecting existing post-boot scripts.

hisaac commented 5 months ago

Great! I'll give it a try today or tomorrow hopefully, and let you know how it goes.

hisaac commented 5 months ago

mm, I've had some other priorities come up at work, so I won't likely get to this in the short-term. If things look good to you, feel free to merge the changes in if you'd like, and I'll give a test ASAP and report back.

simonbs commented 5 months ago

mm, I've had some other priorities come up at work, so I won't likely get to this in the short-term. If things look good to you, feel free to merge the changes in if you'd like, and I'll give a test ASAP and report back.

No worries! I might merge it and get it into a release in the mean time but I'm looking forward to hear if it addresses your need 😊

simonbs commented 5 months ago

I will close this now that #77 is merged, but don't hesitate to reopen the issue if the current solution is inadequate.

hisaac commented 5 months ago

Sounds good, thanks!