asdf-community / asdf-direnv

direnv plugin for the asdf version manager
https://github.com/asdf-vm/asdf
Apache License 2.0
559 stars 38 forks source link

feature: Extend direnv stdlib with asdf specific helpers #155

Closed iilyak closed 1 year ago

iilyak commented 2 years ago

Quite often I find myself copy/pasting following snippet into .envrc

asdf_has() {
    asdf current $1 >>/dev/null 2>&1
}

use asdf
while read asdf_tool; do
    if ! asdf_has ${asdf_tool}; then asdf direnv local ${asdf_tool}; fi
done < <(cat .tool-versions | grep -v '\#')

watch_file ".asdf"

It would be really nice to have some commands to avoid this boilerplate.

robsonpeixoto commented 1 year ago

Have you try use only the command asdf direnv local?

iilyak commented 1 year ago

Have you try use only the command asdf direnv local?

I did test it as follows. I added aria2 1.36.0 into my .tool-versions file. I didn't use aria2 before, so I didn't have the plugin installed.

❯ cat .tool-versions
# build tools
java openjdk-11.0.2
scala 2.13.3

# optional auxiliary tools
aria2 1.36.0
❯ ls ~/.asdf/plugins/
alias/                cue/                  erlang/               gradle/               nancy/                scala/
bat/                  direnv/               github-cli/           hadolint/             python/               shfmt/
comby/                editorconfig-checker/ golang/               java/                 rust/                 yq/
coursier/             elixir/               golangci-lint/        maven/                sbt/

My .envrc has following content

❯ cat .envrc
use asdf
eval "$(/usr/local/bin/brew shellenv)"

path_add LD_LIBRARY_PATH "~/.local/share/brew/x86_64/lib/"
path_add C_INCLUDE_PATH "~/.local/share/brew/x86_64/include/"
path_add CPLUS_INCLUDE_PATH "~/.local/share/brew/x86_64/include/"

Then I run asdf direnv local as you suggest.

❯ asdf direnv local
✔️  .envrc looks fine
▶ direnv allow # ...  ✔️
direnv: loading ~/Code/zio-actors/.envrc
direnv: using asdf
direnv: Creating env file /Users/iilyak/.cache/asdf-direnv/env/1496628465-601454584-1362971206-856298759
direnv: golang 2.16.1 not installed. Run 'asdf install' and then 'direnv reload'.
direnv: asdf plugin not installed: aria2
direnv: loading ~/.cache/asdf-direnv/env/1496628465-601454584-1362971206-856298759
direnv: using asdf python miniconda3-4.7.12
direnv: using asdf golang 2.16.1
direnv: using asdf aria2 1.36.0
direnv: export +CPLUS_INCLUDE_PATH +C_INCLUDE_PATH +LD_LIBRARY_PATH ~HOMEBREW_CELLAR ~HOMEBREW_PREFIX ~HOMEBREW_REPOSITORY ~INFOPATH ~MANPATH ~PATH
robsonpeixoto commented 1 year ago

@iilyak, read it: https://github.com/asdf-community/asdf-direnv/issues/162

iilyak commented 1 year ago

@iilyak, read it: #162

I think #162 is a different issue. In #155 I propose to automate installation of plugins, while #162 discuses to make direnv not fail by default in case of missing plugins. Without #162 the UX is.

  1. cd into projects directory
  2. wait few minutes (we compile a tool if it is missing)
  3. observe that direnv failed and scroll to the error about missing plugin
  4. recall (or google) how to install the plugin (all developers on the team have different level of familiarity with the tool)
  5. install missing plugin
  6. issue direnv reload
  7. wait another few minutes
  8. possibly repeat steps 3-7 (the step 4 can be skiped because you probably still remember how to do it).

With #162 the UX probably would be

  1. cd into projects directory
  2. wait few minutes
  3. direnv succeed
  4. try work on a project but the tool is missing
  5. debug why environment is broken and eventually find a warning that plugin was missing
  6. recall (or google) how to install the plugin (all developers on the team have different level of familiarity with the tool)
  7. install missing plugins
  8. issue direnv reload
  9. wait another few minutes (we compile a tool if it is missing)

The good thing about #162 is that all missing plugins would be in the log. So you don't have to go trough iterative process. The ugly thing about it is that you do not discover the problem right away. Which means the direnv output might be not in front of your eyes anymore.

The #162 also talks about adding ability to make some tools required while others are optional. This doesn't affect my team since we commit .envrc into the repository (and use .envrc.local file for developer customizations). In addition to above mentioned boilerplate we have following line:

dotenv_if_exists .envrc.local

Ideal experience (at least for my diverse team) is

  1. cd into project
  2. all missing tools and plugins get installed automatically
  3. work on a project

Thank you for letting me know about #162. I'll keep an eye on its development, since it might be useful in other projects I am working on.

jfly commented 1 year ago

@iilyak are you familiar with the asdf install (no arguments) command? Does that do what you want?

iilyak commented 1 year ago

@iilyak are you familiar with the asdf install (no arguments) command? Does that do what you want?

@jfly Unfortunately, it doesn't do what I need. It doesn't install missing plugins. See my quick test.

❯ asdf plugin list
alias
bat
comby
coursier
cue
direnv
editorconfig-checker
elixir
erlang
github-cli
golang
golangci-lint
gradle
hadolint
java
maven
nancy
python
rust
sbt
scala
shfmt
yq

❯ asdf plugin remove bat

❯ asdf install
bat plugin is not installed
jfly commented 1 year ago

Ahh, gotcha. Unfortunately, I don't think that's a solvable problem in general: not all asdf plug-ins are in the global asdf plugin registry. In other words, no tool (neither asdf nor asdf-direnv) can know which plugins you want just by looking at the .tool-versions file.

IMO, this is a fundamental asdf issue, and not something we should try to solve in asdf-direnv. See https://github.com/asdf-vm/asdf/pull/313 for once such discussion upstream.

jfly commented 1 year ago

My teams "solution" for this problem is to maintain a "dev environment setup" script that installs all the asdf plugins you need.

iilyak commented 1 year ago

My teams "solution" for this problem is to maintain a "dev environment setup" script that installs all the asdf plugins you need.

My teams "solution" is what I mentioned above

asdf_has() {
    asdf current $1 >>/dev/null 2>&1
}

use asdf
while read asdf_tool; do
    if ! asdf_has ${asdf_tool}; then asdf direnv local ${asdf_tool}; fi
done < <(cat .tool-versions | grep -v '\#')

However it would be great if asdf install had --install-missing-plugins flag. Of cause this flag would only work with plugins in the global asdf plugin registry. This creates incentive for the team to create PRs for tools they use in the asdf plugin registry repository.

iilyak commented 1 year ago

However it would be great if asdf install had --install-missing-plugins flag. Of cause this flag would only work with plugins in the global asdf plugin registry. This creates incentive for the team to create PRs for tools they use in the asdf plugin registry repository.

Or asdf-direnv could provide a helper install_missing_asdf_plugins (or it could be named asdf::install_missing_plugins, since shell supports :: in function names) function.

jfly commented 1 year ago

@iilyak I don't fully understand that snippet you've posted: it doesn't seem to invoke asdf install anywhere.

I still think this is not something asdf-direnv should try to solve. It feels like something that should be solved in core asdf. I'd be curious what @vic thinks, though.

iilyak commented 1 year ago

@iilyak I don't fully understand that snippet you've posted: it doesn't seem to invoke asdf install anywhere.

The snippet reads .tool-versions file and calls asdf direnv local $line for each line (e.g. asdf direnv local bat 0.22.1). The asdf direnv local <tool> <version> command installs the plugin if it is missing.

I still think this is not something asdf-direnv should try to solve.

👍

jfly commented 1 year ago

I'm going to close this issue. While re-reading through https://github.com/asdf-vm/asdf/pull/313, I discovered https://github.com/ngyewch/asdf-helper, which looks like a possible solution to the "which plugins do I need and how do I get them?" problem.