Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unbound variables while loading a plugins exec-env #115

Closed
mchristen opened this issue Mar 16, 2022 · 10 comments
Closed

unbound variables while loading a plugins exec-env #115

mchristen opened this issue Mar 16, 2022 · 10 comments

Comments

@mchristen
Copy link

I have a .tool-versions file with ruby 2.7.2 in it and after running asdf install direnv reload fails to load ruby with the following error. This also seems to happen to other plugins that export environment variables.

direnv: loading ~/baracus/.envrc
direnv: using asdf
direnv: Creating env file /home/developer/.cache/asdf-direnv/env/190183025-499670833-176628233-2702695381
direnv: loading ~/.cache/asdf-direnv/env/190183025-499670833-176628233-2702695381  
direnv: using asdf direnv 2.30.3     
direnv: using asdf ruby 2.7.2    
direnv: loading ~/.asdf/plugins/ruby/bin/exec-env          
./exec-env:6: RUBYLIB: unbound variable             

If I inspect my cached env file from asdf-direnv 0.1.0 I can see that the last line has
export RUBYLIB=$'/home/developer/.asdf/plugins/ruby/rubygems-plugin:/home/developer/.asdf/plugins/ruby/rubygems-plugin'
whereas the env file made by asdf-direnv 0.2.0 does not contain that line.

@jfly
Copy link
Contributor

jfly commented Mar 17, 2022

That's interesting. I'm not able to reproduce the issue locally. I checked, and I also have a ~/.asdf/plugins/ruby/bin/exec-env file, and I'm guessing it looks identical to yours:

$ cat ~/.asdf/plugins/ruby/bin/exec-env
#!/usr/bin/env bash

current_script_path=${BASH_SOURCE[0]}
ruby_plugin_dir=$(dirname "$(dirname "$current_script_path")")

if [ "$RUBYLIB" = "" ]; then
  export RUBYLIB="$ruby_plugin_dir/rubygems-plugin"
else
  export RUBYLIB="$ruby_plugin_dir/rubygems-plugin:$RUBYLIB"
fi

export PATH=$install_path/bin:$PATH

Line 6 is this if [ "$RUBYLIB" = "" ]; then, which does look like an unbound variable reference. If I add a set -u to the top of this script, I see the exact same behavior as you.

Wild guess: I wonder if there's something different between your bash and my bash, or their configurations that's causing yours to have bash's nounset behavior always turned on? What do you see if you create and run this dead simple bash script?

$ cat test.sh
#!/usr/bin/env bash

BOUND=42
echo "bound: $BOUND"
echo "unbound: $UNBOUND"
$ chmod +x ./test.sh
$ ./test.sh
bound: 42
unbound:

And for the record, here's what my bash looks like:

$ bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

@mchristen
Copy link
Author

This is what I get when I run that script

developer@ip-10-10-251-87:~$ ./test.sh
bound: 42
unbound:
developer@ip-10-10-251-87:~$ cat ./test.sh
#!/usr/bin/env bash

BOUND=42
echo "bound: $BOUND"
echo "unbound: $UNBOUND"

My bash version is:

GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

The base system is Debian 11 and I am using asdf 0.9.0.

If I goto this plugin's directory and checkout the 0.1.0 branch and change nothing else about the system the problem goes away entirely which is why I figured maybe the issue was here.

@jfly
Copy link
Contributor

jfly commented Mar 22, 2022

@mchristen, sorry, without the ability to reproduce this myself, I'm pretty stumped. Could you try running env ASDF_DIRENV_DEBUG=true direnv reload in your project directory and sharing the output? There might be something useful there.

@BradenM
Copy link

BradenM commented Mar 26, 2022

@jfly @mchristen

Hi. Ran into this issue myself and figured I'd chime in with what I've found.

Same as @mchristen, running direnv allow failed with ./exec-env:6: RUBYLIB: unbound variable after I updated to the recent v2 release.

Some likely key info:

  • My project-local .tool-versions did not contain ruby nor postgres.
  • My global (~/.tool-versions) file contained both ruby and postgres.

Header of my project-local .envrc:

#!/usr/bin/env bash

use asdf

Header of ~/.config/direnv/direnvrc:

#!/usr/bin/env bash

# ASDF Integration
source "$(asdf direnv hook asdf)"

Header of my ~/.zshrc:

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
##: init direnv (see: https://github.com/romkatv/powerlevel10k/blob/master/README.md#how-do-i-initialize-direnv-when-using-instant-prompt)
. $HOME/.asdf/asdf.sh
(( ${+commands[direnv]} )) && emulate zsh -c "$(asdf exec direnv export zsh)"
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
(( ${+commands[direnv]} )) && emulate zsh -c "$(asdf exec direnv hook zsh)"

Some notes while trying to determine the problem:

  • Adding ruby system to my project local .tool-versions appeared to solve the issue (for ruby at least), but then failed due to postgres with a similiar: ./exec-env:3: PGDATA: unbound variable., but then I realized that it was causing postgres to be loaded prior to ruby, so it likely didn't do much.

  • Running with env ASDF_DIRENV_DEBUG=true gave identical output as without.

  • I tried adding some dummy exports to see what whould happen, like so:

#!/usr/bin/env bash

export PGDATA="/tmp/maybe-work"
# ->  and dummy exports for pghost,pgport,rubylib

use asdf

and while it seemed to have worked for postgres, the ruby plugin would then fail with:

direnv: loading ~/projects/work/my/project/.envrc
direnv: using asdf
direnv: Creating env file /home/bradenmars/.cache/asdf-direnv/env/2251840191-302452863-543912477-3033906221
direnv: ([/home/bradenmars/.asdf/installs/direnv/2.30.3/bin/direnv export zsh]) is taking a while to execute. Use CTRL-C to give up.
direnv: loading ~/.cache/asdf-direnv/env/2251840191-302452863-543912477-3033906221
direnv: using asdf yq v4.12.2
direnv: using asdf yarn 1.22.17
direnv: using asdf shfmt 3.4.2
direnv: using asdf shellcheck 0.8.0
direnv: using asdf rust 1.54.0
direnv: loading ~/.asdf/plugins/rust/bin/exec-env
direnv: using asdf ruby 3.1.1
direnv: loading ~/.asdf/plugins/ruby/bin/exec-env
./exec-env:12: install_path: unbound variable

Finally, I just gave in and removed postgres and ruby from my ~/.tool-versions file. While this did make it work, it's definitely not a solution 😉

@jfly
Copy link
Contributor

jfly commented Mar 26, 2022

@BradenM thanks for chimining in! That's good to know that this might have something to do with your ~/.tool-versions file. Unfortunately, I'm still not able to reproduce the issue. Can you try boiling your example down to the smallest example possible that reproduces the issue? I assume yq, yarn, etc aren't actually necessary to reproduce the issue?

For example, here's a simple thing I've tried with a system ruby and a project specific python. It seems fine:

$ cat ~/.tool-versions
direnv 2.30.3
ruby 3.1.1
$ cat .tool-versions
python 3.8.10
$ cat .envrc
use asdf
$ direnv reload
direnv: loading ~/tmp/asdf-direnv-issue-115/.envrc
direnv: using asdf
direnv: Creating env file /home/jeremy/.cache/asdf-direnv/env/3021084817-1069596949-3093830401-3260146122
direnv: loading ~/.cache/asdf-direnv/env/3021084817-1069596949-3093830401-3260146122
direnv: using asdf ruby 3.1.1
direnv: loading ~/.asdf/plugins/ruby/bin/exec-env
direnv: using asdf direnv 2.30.3
direnv: using asdf python 3.8.10
direnv: export +RUBYLIB ~PATH
$ ruby --version
ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux]
$ python --version
Python 3.8.10

Does this work for you?

@BradenM
Copy link

BradenM commented Mar 27, 2022

@jfly Sure thing!

I have reproduced the issue by taking the following steps:

  • Moving my ~/.tool-versions file to a backup
  • Creating a new, empty ~/.tool-versions file
  • Executing: asdf global direnv 20.3.3; asdf global ruby 3.1.1
  • Reloading my shell
  • Creating a temporary directory
  • Executing asdf local nodejs 16.3.2
  • Creating a .envrc with bash shebang and (only) use asdf
  • Executing direnv allow (Fails with unbound ruby issue)
  • Trying again following direnv prune (fails with unbound ruby issue)

Here is an asciinema cast I have created of me going through the above steps:

asciicast

(and a direct link if the embed isn't working for you: https://asciinema.org/a/480884)

Some additional system information:

Bash Version
$ bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

zsh Version
$ zsh --version
zsh 5.8.1 (x86_64-pc-linux-gnu)
asdf info
$ asdf info
OS:
Linux braden-desktop 5.16.14-1-MANJARO #1 SMP PREEMPT Fri Mar 11 14:12:18 UTC 2022 x86_64 GNU/Linux

SHELL:
zsh 5.8.1 (x86_64-pc-linux-gnu)

ASDF VERSION:
v0.9.0-7493f40

ASDF ENVIRONMENT VARIABLES:
ASDF_DIR=/home/bradenmars/.asdf

ASDF INSTALLED PLUGINS:
awscli                       https://github.com/MetricMike/asdf-awscli.git main ec4ccdc
aws-iam-authenticator        https://github.com/stefansedich/asdf-aws-iam-authenticator.git master ac2668a
cmctl                        https://github.com/asdf-community/asdf-cmctl.git master c013518
dart                         https://github.com/PatOConnor43/asdf-dart.git master 5afa94b
direnv                       https://github.com/asdf-community/asdf-direnv.git master 3e7578b
eksctl                       https://github.com/elementalvoid/asdf-eksctl.git master 5309e4b
flutter                      https://github.com/oae/asdf-flutter.git master 556a70d
flux2                        https://github.com/tablexi/asdf-flux2.git master 0f987b7
fluxctl                      https://github.com/stefansedich/asdf-fluxctl.git master c2ecce0
git-chglog                   https://github.com/GoodwayGroup/asdf-git-chglog.git main ef79c13
golang                       https://github.com/kennyp/asdf-golang.git master cc8bc47
hadolint                     https://github.com/looztra/asdf-hadolint.git master 69840f7
helm                         https://github.com/Antiarchitect/asdf-helm.git master 87eef5a
helmfile                     https://github.com/feniix/asdf-helmfile.git master 80c93ce
java                         https://github.com/halcyon/asdf-java.git master dc8eb0e
jq                           https://github.com/azmcode/asdf-jq.git master 844d712
kind                         https://github.com/johnlayton/asdf-kind.git master 4b6ed61
kompose                      https://github.com/technikhil314/asdf-kompose.git master 2706fa5
kops                         https://github.com/Antiarchitect/asdf-kops.git master 088bf60
krew                         https://github.com/jimmidyson/asdf-krew.git main bcbe4d9
kubectl                      https://github.com/Banno/asdf-kubectl.git master 11ac5c3
kubectx                      https://gitlab.com/wt0f/asdf-kubectx.git master 8c0b4aa
kubespy                      https://github.com/jfreeland/asdf-kubespy.git main 08a4aba
maven                        https://github.com/halcyon/asdf-maven.git master b30fff9
minikube                     https://github.com/alvarobp/asdf-minikube.git master 8ca7b8d
mongosh                      https://github.com/itspngu/asdf-mongosh.git master 23c5fe0
mysql                        https://github.com/iroddis/asdf-mysql.git master 3aaf756
nodejs                       https://github.com/asdf-vm/asdf-nodejs.git master f9957f3
okteto                       https://github.com/BradenM/asdf-okteto master 34f28d7
please                       https://github.com/asdf-community/asdf-please.git master 99bd59f
pnpm                         https://github.com/jonathanmorley/asdf-pnpm.git master 95752a9
poetry                       https://github.com/asdf-community/asdf-poetry.git master 7ea77b0
postgres                     https://github.com/smashedtoatoms/asdf-postgres.git master ff9e6a6
ruby                         https://github.com/asdf-vm/asdf-ruby.git master 811c824
rust                         https://github.com/code-lever/asdf-rust.git master 0c88f99
shellcheck                   https://github.com/luizm/asdf-shellcheck.git master 31cb328
shfmt                        https://github.com/luizm/asdf-shfmt.git master f893252
sops                         https://github.com/feniix/asdf-sops.git master 954411c
vault                        https://github.com/Banno/asdf-hashicorp.git master aeff16f
yarn                         https://github.com/twuni/asdf-yarn.git main 376c540
yq                           https://github.com/sudermanjr/asdf-yq.git master ee7c63c

direnv toml config
[global]
disable_stdin = true
strict_env = true
skip_dotenv = true

@BradenM
Copy link

BradenM commented Mar 27, 2022

@jfly Aha!

After looking at my direnv toml config while copying it over to the previous post, the strict_env flag stood out to me...

And what would ya know, disabling strict_env and running direnv reload works perfectly fine!

The above demo works without an issue with the following direnv config:

[global]
disable_stdin = true
strict_env = false
skip_dotenv = true

However, it should be noted, according to the man page for direnv.toml:

[global]
   bash_path
       This allows one to hard-code the position of bash. It maybe be useful to set this to avoid having direnv to fail when PATH is being mutated.

   disable_stdin
       If set to true, stdin is disabled (redirected to /dev/null) during the .envrc evaluation.

   skip_dotenv
       Don't look for .env files, only .envrc files.

   strict_env
       If set to true, the .envrc will be loaded with set -euo pipefail. This option will be the default in the future.

   warn_timeout
       Specify how long to wait before warning the user that the command is taking too long to execute. Defaults to "5s".

       A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".  Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

strict_env
If set to true, the .envrc will be loaded with set -euo pipefail. This option will be the default in the future.

IIRC, I had gone ahead and enabled it back when I setup direnv since its set to become the eventual default.

What are your thoughts on this?

jfly added a commit to jfly/asdf-ruby that referenced this issue Mar 27, 2022
When run under asdf-direnv with direnv's `strict_env` set to true, then
this script will run with bash's `nounset` enabled, which will cause
this script to crash in the following way:

  ./exec-env:6: RUBYLIB: unbound variable

(see asdf-community/asdf-direnv#115 for
details)

I know this doesn't affect regular asdf users, but this seems like a
reasonable change to make, I hope you'll accept it!
@jfly
Copy link
Contributor

jfly commented Mar 27, 2022

Awesome work! If I enable strict_env = true in my ~/.config/direnv/direnv.toml, I can also reproduce the issue.

IMO, this a bug in asdf-ruby itself. I've sent in this PR upstream: asdf-vm/asdf-ruby#259 to address it.

It looks like asdf-postgres has the same issue, but with 4 variables. Would you like to send in a similar PR to them, @BradenM?

@jfly
Copy link
Contributor

jfly commented Mar 27, 2022

I'm going to go ahead and close this issue, because I don't consider this to an asdf-direnv issue, and fortunately there's a straightforward workaround by turning off direnv's strict mode.

@jfly jfly closed this as completed Mar 27, 2022
@BradenM
Copy link

BradenM commented Mar 27, 2022

It looks like asdf-postgres has the same issue, but with 4 variables. Would you like to send in a similar PR to them, @BradenM?

Sure! No problem.

I'm going to go ahead and close this issue, because I don't consider this to an asdf-direnv issue, and fortunately there's a straightforward workaround by turning off direnv's strict mode.

Agreed, the root of the issue(s) lie elsewhere. 👍

Thanks!

jfly added a commit to jfly/dotfiles that referenced this issue Mar 27, 2022
Turns out some of asdf-direnv's users have this setting turned on (see
asdf-community/asdf-direnv#115), so I should
probably have it turned on myself to catch these sorts of things
earlier.
benperiton added a commit to benperiton/asdf-php that referenced this issue Aug 12, 2022
Similar to the issue over on the ruby plugin (asdf-community/asdf-direnv#115) if using direnv and have `strict_env = true` then it fails to load with `./exec-env:5: COMPOSER_HOME: unbound variable`
benperiton added a commit to benperiton/asdf-deno that referenced this issue Aug 15, 2022
When using with asdf-direnv with direnv configured as strict_env=true, it fails with `./exec-env:4: DENO_INSTALL_ROOT: unbound variable`

Original issue: asdf-community/asdf-direnv#115
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants