Skip to content

Commit

Permalink
Added .gitignore to ignore brew test-bot output files. Added Notes on…
Browse files Browse the repository at this point in the history
… Docker and added brew auditing commands to debugging. Wrote helper function for checking for both docker compose and prompting for valid OpenAI API key. Isolated post-install into two functions but commented them out because brew cannot run them.
  • Loading branch information
GatlenCulp committed Oct 1, 2024
1 parent f5a2d7c commit a919d33
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 74 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore brew test-bot output files
bottle_output.txt
linkage_output.txt
skipped_or_failed_formulae-arm64_sequoia.txt
steps_output.txt
8 changes: 1 addition & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@
"explorerExclude.backup": {},
"workbench.colorCustomizations": {
"editor.lineHighlightBackground": "#1073cf2d",
"editor.lineHighlightBorder": "#9fced11f",
"statusBar.background": "#28632b",
"statusBar.foreground": "#ffffff",
"statusBarItem.hoverBackground": "#327e36",
"activityBar.background": "#51173B",
"titleBar.activeBackground": "#712052",
"titleBar.activeForeground": "#FEFCFD"
"editor.lineHighlightBorder": "#9fced11f"
},
}
216 changes: 170 additions & 46 deletions Formula/vivaria.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ class Vivaria < Formula
regex(/^v?(\d+(?:\.\d+)+)$/i)
end

# docker compose is required for running task environments, but not included in deps.
# Check the README for this reasoning.
depends_on "[email protected]" => :build
depends_on "rust" => :build # Needed for pydantic
depends_on "docker"
depends_on "docker-compose"

# TODO: Add bottle block for pre-built binaries
# bottle do
Expand Down Expand Up @@ -102,7 +102,75 @@ class Vivaria < Formula
end
# TODO: Add cookiecutter package if accepted.

def check_for_docker_compose
docker_compose_installed = false
docker_compose_version = nil

# Try to get the user's actual PATH
user_path = `
source ~/.zshrc 2>/dev/null || \
source ~/.bash_profile 2>/dev/null || \
source ~/.profile 2>/dev/null && \
echo $PATH
`.strip

ohai "Current Homebrew PATH: #{ENV["PATH"]}"
ohai "User's shell PATH: #{user_path}"

# List of possible Docker binary locations
docker_paths = [
"/usr/local/bin/docker-compose",
"/opt/homebrew/bin/docker-compose",
"#{Dir.home}/bin/docker-compose",
"/Applications/Docker.app/Contents/Resources/bin/docker-compose",
]

# Add paths from user's PATH
docker_paths += user_path.split(":")

docker_path = docker_paths.uniq.find { |path| File.executable?(path) }

if docker_path
ohai "Docker Compose binary found at: #{docker_path}"
docker_compose_version = `#{docker_path} version 2>&1`.strip
docker_compose_installed = $CHILD_STATUS.success?

if docker_compose_installed
ohai "Detected Version:: #{docker_compose_version}"
else
opoo "Docker Compose command failed. Output: #{docker_compose_version}"
end
else
opoo "Docker binary not found in expected locations or user PATH"
end

unless docker_compose_installed
odie <<~EOS
Vivaria installation failed.
Docker Compose is not detected on your system.
Docker Compose is required to run task environments for Vivaria.
You can install Docker Desktop for Mac, which includes Docker Compose, from:
https://docs.docker.com/desktop/install/mac-install/
Once installed, you may have to restart your computer and check if
docker compose is available by running:
docker compose version
Note that Vivaria requires version > 2.0 of docker compose
indicated by the syntax "docker compose" instead of "docker-compose".
read more at https://docs.docker.com/compose/releases/migrate/
EOS
end
end

def install
# Check for Docker Compose
check_for_docker_compose

# Install manpage
man1.install buildpath/"cli/viv_cli/viv.1"
# Install documentation
Expand Down Expand Up @@ -131,60 +199,111 @@ def install
(etc/"vivaria").mkpath
end

def post_install
# Prompt user for OpenAI API key and run viv setup
api_key = nil

while api_key.nil?
def prompt_for_api_key
loop do
ohai "Please enter your OpenAI API key:"
api_key = $stdin.gets.chomp

next if api_key.start_with?("sk-") && api_key.length == 51

opoo "The provided OpenAI API key doesn't appear to be valid."
puts "Expected to start with 'sk-' and have length 51"
puts "Please try again."
api_key = nil
if api_key.start_with?("sk-") && api_key.length > 20
return api_key
else
opoo "The provided OpenAI API key doesn't appear to be valid."
puts "Expected to start with 'sk-' and have length greater than 20"
puts "Please try again."
end
end
end

ohai "Running viv setup command..."
Utils.safe_popen_read("viv", "setup", "--openai-api-key", api_key, err: :out)
def style_command(text)
"\e[31m\e[40m#{text}\e[0m"
end

def style_shortcut(text)
"\e[94m#{text}\e[0m"
end

# puts output
def viv_setup
# NOTE: Brew does not have permissions to edit or remove files outside of the Homebrew prefix
# This function does not work, but could be fixed if config.json is moved to the Homebrew prefix
config_file_path = File.expand_path("~/.config/viv-cli/config.json")
brew_prefix = HOMEBREW_PREFIX.to_s

loop do
config_exists = File.exist?(config_file_path)

if config_exists
ohai "A viv-cli configuration file already exists at #{config_file_path}."
ohai "Brew does not have permissions to edit or remove files outside of #{brew_prefix}."
ohai "Please delete or rename this file manually. You can use one of the following commands:"
puts " To delete: #{style_command("rm #{config_file_path}")}"
puts " To rename: #{style_command("mv #{config_file_path} #{config_file_path}.backup")}"
ohai "Once you have done so, press Enter to continue or Ctrl+C to abort the post-install process."

$stdin.gets # Wait for user input

if File.exist?(config_file_path)
opoo "The configuration file still exists. Please remove or rename it before continuing."
else
ohai "No existing viv-cli configuration found. Continuing with installation"
break # Exit the loop if the file no longer exists
end
else
ohai "No existing viv-cli configuration found."
ohai "Would you like to run 'viv setup' to create a new configuration? [y/N]"
response = $stdin.gets.chomp.downcase
break if response == "y"

unless $CHILD_STATUS.success?
opoo "viv setup command failed. Please check the output above for any errors."
puts "viv is installed, but it may not work properly. Please try running 'viv setup' directly."
exit 1
ohai "Exiting viv setup. You can run it manually later with 'viv setup'."
return
end
end

ohai "viv setup command completed successfully."
config_dir = File.dirname(config_file_path)
mkdir_p(config_dir) unless File.directory?(config_dir)
system "sudo", "chown", "-R", ENV["USER"], config_dir
system "sudo", "chmod", "755", config_dir

api_key = prompt_for_api_key

setup_command = "viv setup --openai-api-key #{api_key}"
ohai "Running: #{setup_command}"

output = `#{setup_command} 2>&1`
status = $CHILD_STATUS.success?

if status
ohai "viv setup completed successfully."
else
opoo "viv setup encountered an error. Output:"
puts output
end
end

def build_docker_images
# Prompt user to build Docker images
ohai "Would you like to build the required Vivaria Docker images now? (This may take 3-8 minutes) [y/N]"
response = $stdin.gets.chomp.downcase

if response == "y"
# ohai "Opening Docker..."
# case RUBY_PLATFORM
# when /darwin/
# system "open", "-a", "Docker"
# when /linux/
# system "systemctl", "--user", "start", "docker-desktop"
# when /mingw|mswin/
# system "start", "Docker Desktop"
# else
# opoo "Unsupported platform for automatic Docker startup. Please ensure Docker is running manually."
# end

# # Wait for Docker to start
# ohai "Waiting for Docker to start..."
# 30.times do
# if system("docker info > /dev/null 2>&1")
# break
# end
# sleep 1
# end
ohai "Opening Docker..."
case RUBY_PLATFORM
when /darwin/
system "open", "-a", "Docker"
when /linux/
system "systemctl", "--user", "start", "docker-desktop"
when /mingw|mswin/
system "start", "Docker Desktop"
else
opoo "Unsupported platform for automatic Docker startup. Please ensure Docker is running manually."
end

# Wait for Docker to start
ohai "Waiting for Docker to start..."
30.times do
break if system("docker info > /dev/null 2>&1")

sleep 1
end

ohai "Building Docker images..."
system "viv", "docker", "compose", "build"
Expand All @@ -200,16 +319,21 @@ def post_install
end
end

def post_install
# Run 'viv setup' (Note: This does not work due to permissions)
# viv_setup
# Build Docker images (Note: This requires viv setup to have run successfully)
# build_docker_images
end

def caveats
<<~EOS
Post-installation instructions:
(Optional) If you want to start task environments containing aux VMs,
you'll need to configure AWS credentials. Run:
viv setup aws
Vivaria has been installed.
For more information, visit:
https://vivaria.metr.org/
https://vivaria.metr.org/
EOS
end

Expand Down
78 changes: 57 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ For testing purposes and creating installation helper scripts, Gatlen has create
- [05.02 The Python Dependencies](#0502-the-python-dependencies)
- [05.03 Copying Everything Over](#0503-copying-everything-over)
- [05.04 Debugging](#0504-debugging)
- [05.05 Random Useful Notes](#0505-random-useful-notes)
- [05.06 Roadmap](#0506-roadmap)
- [05.05 Notes on Docker](#0505-notes-on-docker)
- [05.06 Random Useful Notes](#0506-random-useful-notes)
- [05.07 Roadmap](#0507-roadmap)
- [06 Contact the Maintainer](#06-contact-the-maintainer)

---
Expand Down Expand Up @@ -374,21 +375,14 @@ I was attempting to set up a Ruby debugger w/ intellisense in VSCode but it wasn
`gem install ruby-lsp`
`gem install debug`

### 05.05 Random Useful Notes
There are also a variety of tools to conform to both the Homebrew official style, Ruby's styling, and more. Here are a few of these commands:

`echo $(brew --prefix vivaria)` can be used to get the [opt-prefix](https://docs.brew.sh/Manpage) for Vivaria. This returns a static path to a symlinked folder pointing to the most recent version of vivaria.

The [Homebrew Ruby API documentation](https://rubydoc.brew.sh/Formula#homepage%3D-class_method) is very helpful as well as the the [higher-level Homebrew documentation](https://docs.brew.sh/).

A good man-page has yet to be written and may not ever be written but I decided to draft a simple incomplete one with a warning. This may possibly lead to more confusion, but I've decided to do it anyways for the experience and to see if it may be helpful to continue developing.

If you need to make any edits to the viv cli without editing the repo and reinstalling entirely, I recommend cloning the Vivaria repo, setting up a venv with required packages `mkdir ~/.venvs && python3 -m venv ~/.venvs/viv && source ~/.venvs/viv/bin/activate` then running `pip install -e cli` in the Vivaria project root. If you run `which viv` you should see you are not using the one in homebrew and are instead using the `viv` from your repo. Any updates to the cli will be live as you make them and commands should work normally.

Caveats are info displayed after installation.

To check whether your formula fits brew's formula style you can run `brew audit --eval-all --formula --strict --online vivaria`
01
```bash
brew style --fix gatlenculp/vivaria
```

Ex:
02
```bash
brew audit --eval-all --formula --strict --online vivaria

Expand Down Expand Up @@ -418,14 +412,57 @@ gatlenculp/vivaria/vivaria
Error: 22 problems in 1 formula detected.
```

The style fixer is also helpful:
03
```bash
brew style --fix gatlenculp/vivaria
brew test-bot --only-cleanup-before
```

04
```bash
brew test-bot --only-setup
```

05
```bash
brew test-bot --only-tap-syntax
```

As well as all other tests included in the `.github/workflows/` files.
06
```bash
brew test-bot --only-formulae
```

### 05.05 Notes on Docker

There are many variations of Docker for MacOS out there and they are a bit confusing. Here is a bit of a rundown:
1. [**docker Homebrew Formula**](https://formulae.brew.sh/formula/docker) - This includes the `docker` CLI only without docker compose or the GUI.
2. [**docker-compose Homebrew Formula**](https://formulae.brew.sh/formula/docker-compose) - This is `docker-compose` CLI, an extension for `docker`. It is important to note that despite being [referenced with the old Docker Compose v1 syntax `docker-compose` as opposed to v2 syntax](https://docs.docker.com/compose/releases/migrate/) `docker compose`, it should be the most recent version >v2.0. If this is installed but `docker compose` is not working, that is because the user did not take the extra step of actually plugging he extension into Docker. In the caveats for `docker-compose` it notes the following:
```bash
Compose is a Docker plugin. For Docker to find the plugin, add "cliPluginsExtraDirs" to ~/.docker/config.json:
"cliPluginsExtraDirs": [
"$HOMEBREW_PREFIX/lib/docker/cli-plugins"
]
```
3. [**docker Homebrew Cask**](https://formulae.brew.sh/cask/docker) - This is Desktop Docker which comes packaged with both `docker` and `docker compose`. It will dynamically install either the Intel or Apple Silicon versions based on your Mac and should be up to date with the official release. Very annoyingly, this cask conflicts with both the [**docker Homebrew Formula**](https://formulae.brew.sh/formula/docker) AND [**docker-compose Homebrew Formula**](https://formulae.brew.sh/formula/docker-compose).
4. [**docker desktop official**](https://docs.docker.com/desktop/install/mac-install/) - This is the official download from Docker to install Docker Desktop offering both intel and Apple silicon installations. Also conflicts with [**docker Homebrew Formula**](https://formulae.brew.sh/formula/docker) AND [**docker-compose Homebrew Formula**](https://formulae.brew.sh/formula/docker-compose) :).

> ℹ️ *Broadly, Homebrew Formula seem to be for open-source apps while it seems like Homebrew Casks are for closed-source apps with GUI. Homebrew casks were initially a separately maintained project from Homebrew.*
Since there are so many conflicts and we did not want to mess up the user's system, we decided only to make `docker-compose` a requirement, independently of how the user installed it and assume that the `docker compose` syntax is available. It's also important to note that for both Homebrew Formula and Casks, brew only supports installing formula as dependencies. Since Docker Desktop comes with the needed CLI as well as a simple GUI, we opted for asking the user to install the [**docker Homebrew Cask**](https://formulae.brew.sh/cask/docker) if no `docker-compose` was found

### 05.06 Random Useful Notes

`echo $(brew --prefix vivaria)` can be used to get the [opt-prefix](https://docs.brew.sh/Manpage) for Vivaria. This returns a static path to a symlinked folder pointing to the most recent version of vivaria.

The [Homebrew Ruby API documentation](https://rubydoc.brew.sh/Formula#homepage%3D-class_method) is very helpful as well as the the [higher-level Homebrew documentation](https://docs.brew.sh/).

A good man-page has yet to be written and may not ever be written but I decided to draft a simple incomplete one with a warning. This may possibly lead to more confusion, but I've decided to do it anyways for the experience and to see if it may be helpful to continue developing.

If you need to make any edits to the viv cli without editing the repo and reinstalling entirely, I recommend cloning the Vivaria repo, setting up a venv with required packages `mkdir ~/.venvs && python3 -m venv ~/.venvs/viv && source ~/.venvs/viv/bin/activate` then running `pip install -e cli` in the Vivaria project root. If you run `which viv` you should see you are not using the one in homebrew and are instead using the `viv` from your repo. Any updates to the cli will be live as you make them and commands should work normally.

Caveats are info displayed after installation.

### 05.06 Roadmap
### 05.07 Roadmap

- [ ] Automatically configure an SSH key for the user to use with viv.
```ruby
Expand All @@ -441,8 +478,7 @@ File.open(prefix/".env", "a") { |f| f.puts "SSH_PUBLIC_KEY_PATH=#{ssh_key_path}.
system "viv", "register-ssh-public-key", "#{ssh_key_path}.pub"
```
- [ ] Fix having to do `brew link docker` for each install. (Possibly only on my computer)
- [ ] Run viv setup automatically
- [ ] Make viv setup
- [ ] Allow config.json to be set up within the homebrew prefix because it appears that it cannot be automatically configured from pot-install
- [ ] Look into docker buildx as a way of building the docker images

## 06 Contact the Maintainer
Expand Down

0 comments on commit a919d33

Please sign in to comment.