jdx / mise

dev tools, env vars, task runner
https://mise.jdx.dev
MIT License
9.98k stars 286 forks source link

Unresolved `mise` when doing rubygems update in Dockerfile #1663

Open DmitryPogrebnoy opened 9 months ago

DmitryPogrebnoy commented 9 months ago

Describe the bug The problem is with mise and rubygems update when building Docker image.

To Reproduce Steps to reproduce the behavior. 1) Create Dockerfile like this:

FROM ubuntu:22.04

## basic image configuration for ruby

# software update & install
RUN apt update && apt upgrade -y && apt install curl sudo gnupg2 -y

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

run curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -

RUN apt update && apt -y upgrade

run sudo bash -c 'export DEBIAN_FRONTEND=noninteractive && \
    ln -fs /usr/share/zoneinfo/Europe/Moscow /etc/localtime && \
    apt-get install -y tzdata && \
    dpkg-reconfigure --frontend noninteractive tzdata'

RUN apt install -y software-properties-common gcc cmake mc openssh-server zlib1g-dev build-essential \
    libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev \
    libffi-dev ruby ruby-dev nodejs libmysqlclient-dev git rsync rsyslog gawk autoconf automake bison \
    libgdbm-dev libncurses5-dev libtool pkg-config openjdk-8-jdk-headless libice-dev libice6 libpthread-stubs0-dev \
    libsm-dev libsm6 libx11-dev libx11-doc libxau-dev libxcb1-dev libxdmcp-dev libxt-dev libxt6 x11proto-core-dev \
    x11proto-input-dev x11proto-kb-dev xorg-sgml-doctools xtrans-dev language-pack-en yarn apt-utils lsof gdb && \
    apt autoremove -y && apt clean all
# Missing packages: jruby

# ruby 3.0 bundled bundler executable is not available via PATH and located in some strange place for some reason.
RUN ln -s /usr/lib/ruby/gems/3.0.0/gems/bundler-2.2.22/libexec/bundler /usr/bin/bundler
RUN ln -s /usr/lib/ruby/gems/3.0.0/gems/bundler-2.2.22/libexec/bundle /usr/bin/bundle

# creating user:user
RUN echo 'root:root' | chpasswd
RUN adduser --uid 1001 user --disabled-password --gecos "User"
RUN usermod -aG sudo user
RUN echo 'user:user' | chpasswd
RUN echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER user

# english locale
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:

## mise configuration

USER user
WORKDIR /home/user

RUN curl https://mise.run | sh
RUN echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc

ENV _RUBY_VERSION=2.6.10
RUN bash -c '~/.local/bin/mise install ruby@$_RUBY_VERSION && \
            ~/.local/bin/mise exec ruby@$_RUBY_VERSION -- gem update --no-document --system 3.4.22 && \
            ~/.local/bin/mise exec ruby@$_RUBY_VERSION -- gem uninstall rubygems-update'

The first part of the Dockerfile - after ## basic image configuration for ruby comment. It is just a template without something specific for that issue.

The second part -- after ## mise configuration comment. It is relevant stuff for this issue. There we install mise, then we try to install ruby@2.6.10 and update rubygems to the latest compatible version.

2) Try to build docker image from that Dockerfile. 3) Build process will fail with an error message like this:

120.7 Updating rubygems-update
120.7 ERROR:  While executing gem ... (Errno::ENOENT)
120.7     No such file or directory - mise

The problem appears with the command ~/.local/bin/mise exec ruby@$_RUBY_VERSION -- gem update --no-document --system 3.4.22. Basically it can't resolve mise somewhere in scripts. I debugged and found that the problem is in src/plugins/core/assets/rubygems_plugin.rb script at the line 14 - mise reshim. https://github.com/jdx/mise/blob/c6d4a4a7541cb6d226ebfad6f7eb6b377c64519d/src/plugins/core/assets/rubygems_plugin.rb#L14C1-L14C18 So I guess that there it assumes that mise can be resolved, but it doesn't. It is because mise is not activated because we are in non-interactive mode in Dockerfile. So the possible fix is to use full path to mise.

If I misunderstood something please let me know and explain the right way.

Expected behavior A clear and concise description of what you expected to happen.

Command ~/.local/bin/mise exec ruby@$_RUBY_VERSION -- gem update --no-document --system 3.4.22 should work fine. Dockerfile should be built without any errors from mise.

mise doctor output

Output of mise doctor after installing mise in Dockerfile

0.107 mise version:
0.107   2024.2.14 linux-arm64 (65006ad 2024-02-11)
0.107 
0.107 build:
0.107   Target: aarch64-unknown-linux-musl
0.107   Features: DEFAULT, NATIVE_TLS, OPENSSL
0.107   Built: Sun, 11 Feb 2024 19:45:44 +0000
0.107   Rust Version: rustc 1.76.0 (07dca489a 2024-02-04)
0.107   Profile: release
0.107 
0.108 shell:
0.108   (unknown)
0.108 
0.108 mise dirs:
0.108   data: /home/user/.local/share/mise
0.108   config: /home/user/.config/mise
0.108   cache: /home/user/.cache/mise
0.108   state: /home/user/.local/state/mise
0.108   shims: /home/user/.local/share/mise/shims
0.108 
0.108 mise environment variables:
0.108   (none)
0.108 
0.108 settings:
0.108   activate_aggressive = false
0.108   all_compile = false
0.108   always_keep_download = false
0.108   always_keep_install = false
0.108   asdf_compat = false
0.108   cargo_binstall = true
0.108   color = true
0.108   disable_default_shorthands = false
0.108   disable_tools = []
0.108   experimental = false
0.108   go_default_packages_file = "~/.default-go-packages"
0.108   go_download_mirror = "https://dl.google.com/go"
0.108   go_repo = "https://github.com/golang/go"
0.108   go_set_gopath = false
0.108   go_set_goroot = true
0.108   go_skip_checksum = false
0.108   jobs = 4
0.108   legacy_version_file = true
0.108   legacy_version_file_disable_tools = []
0.108   node_compile = false
0.108   not_found_auto_install = true
0.108   paranoid = false
0.108   plugin_autoupdate_last_check_duration = "7d"
0.108   python_compile = false
0.108   python_default_packages_file = "/home/user/.default-python-packages"
0.108   python_pyenv_repo = "https://github.com/pyenv/pyenv.git"
0.108   python_venv_auto_create = false
0.108   raw = false
0.108   trusted_config_paths = []
0.108   quiet = false
0.108   verbose = false
0.108   yes = false
0.108   ci = false
0.108   debug = false
0.108   trace = false
0.108   log_level = "info"
0.108 
0.108   [status]
0.108   missing_tools = "if_other_versions_installed"
0.108   show_env = false
0.108   show_tools = false
0.108 
0.108 
0.109 activated: no
0.109 shims_on_path: no
0.109 config files:
0.109 
0.109 plugins:
0.109   bun      (core)
0.109   deno     (core)
0.109   go       (core)
0.109   java     (core)
0.109   node     (core)
0.109   python   (core)
0.109   ruby     (core)
0.109 
0.112 toolset:
0.112 
0.112 
0.557 1 problem found:
0.557 mise is not activated, run mise help activate or
0.557 read documentation at https://mise.jdx.dev for activation instructions.
0.557 Alternatively, add the shims directory /home/user/.local/share/mise/shims to PATH.
0.557 Using the shims directory is preferred for non-interactive setups.

Additional context Add any other context about the problem here.

DmitryPogrebnoy commented 9 months ago

I spent some time and found a workaround for that. So you need to refresh bash in order to apply .bashrc and activate mise: SHELL ["/bin/bash", "--login" ,"-c"]

DmitryPogrebnoy commented 8 months ago

@jdx This issue also reproduces when mise is not activated and you try to install/uninstall some gems using ~/.local/bin/mise exec --quiet ruby@3.3.0 -- gem uninstall <gem_name>. Is there any way to fix this?

DmitryPogrebnoy commented 8 months ago

Here is full stacktrace of the error:

11:53:27,522 FINE   plugins.ruby.gem.gem.GemRunner - stderr: ERROR:  While executing gem ... (Errno::ENOENT)
11:53:27,522 FINE   plugins.ruby.gem.gem.GemRunner - stderr:     No such file or directory - mise
11:53:27,522 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/rubygems_plugin/rubygems_plugin.rb:14:in ``'
11:53:27,522 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/rubygems_plugin/rubygems_plugin.rb:14:in `reshim'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/rubygems_plugin/rubygems_plugin.rb:38:in `block in <top (required)>'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:170:in `block in uninstall_gem'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:169:in `each'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:169:in `uninstall_gem'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:234:in `block in remove_all'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:234:in `each'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:234:in `remove_all'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/uninstaller.rb:125:in `uninstall'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/commands/uninstall_command.rb:197:in `uninstall'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/commands/uninstall_command.rb:183:in `uninstall_gem'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/commands/uninstall_command.rb:178:in `block in uninstall_specific'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/commands/uninstall_command.rb:170:in `each'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/commands/uninstall_command.rb:170:in `uninstall_specific'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/commands/uninstall_command.rb:132:in `execute'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/command.rb:326:in `invoke_with_build_args'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/command_manager.rb:254:in `invoke_command'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/command_manager.rb:193:in `process_args'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/command_manager.rb:151:in `run'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/lib/ruby/site_ruby/3.3.0/rubygems/gem_runner.rb:56:in `run'
11:53:27,523 FINE   plugins.ruby.gem.gem.GemRunner - stderr:    /home/user/.local/share/mise/installs/ruby/3.3.0/bin/gem:12:in `<main>'
jdx commented 8 months ago

you need to add it to PATH. Also, activation is only for interactive sessions.

DmitryPogrebnoy commented 8 months ago

@jdx Well, a command ENV PATH="~/.local/bin/mise:${PATH}" after mise installation and before any other mise commands doesn't do the trick. But ENV PATH="~/.local/bin:${PATH}" does. Thank you! It would be nice if you add a notion about adding mise to PATH in that section - https://mise.jdx.dev/dev-tools/shims.html#neither-shims-nor-path.

DmitryPogrebnoy commented 8 months ago

@jdx Nevertheless, adding mise to PATH doesn't help for jruby-9.4.5.0. Stacktrace more or less the same:

ERROR:  While executing gem ... (Errno::ENOENT)
21:48:41           No such file or directory - mise
21:48:41         org/jruby/RubyKernel.java:1745:in ``'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/rubygems_plugin/rubygems_plugin.rb:1:in `reshim'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/rubygems_plugin/rubygems_plugin.rb:38:in `block in <main>'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/uninstaller.rb:170:in `block in uninstall_gem'
21:48:41         org/jruby/RubyArray.java:1989:in `each'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/uninstaller.rb:169:in `uninstall_gem'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/uninstaller.rb:234:in `block in remove_all'
21:48:41         org/jruby/RubyArray.java:1989:in `each'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/uninstaller.rb:234:in `remove_all'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/uninstaller.rb:125:in `uninstall'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/commands/uninstall_command.rb:197:in `uninstall'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/commands/uninstall_command.rb:183:in `uninstall_gem'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/commands/uninstall_command.rb:178:in `block in uninstall_specific'
21:48:41         org/jruby/RubyArray.java:1989:in `each'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/commands/uninstall_command.rb:170:in `uninstall_specific'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/commands/uninstall_command.rb:132:in `execute'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/command.rb:326:in `invoke_with_build_args'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/command_manager.rb:254:in `invoke_command'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/command_manager.rb:193:in `process_args'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/command_manager.rb:151:in `run'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/lib/ruby/stdlib/rubygems/gem_runner.rb:56:in `run'
21:48:41         /home/user/.local/share/mise/installs/ruby/jruby-9.4.5.0/bin/jgem:21:in `<main>'

Any ways to fix this?

jdx commented 8 months ago

looks like it still isn't on PATH

DmitryPogrebnoy commented 8 months ago

Well, for some reason, ENV PATH="~/.local/bin:${PATH}" doesn't work for jruby, but full path ENV PATH="home/user/.local/bin:${PATH}" works. Probably it would also be good to mention it in documentation.

andrewthauer commented 8 months ago

I don't think ~ has any guarantees to work or expand consistently in usage. If I recall correctly it doesn't work in alpine linux for example. In most scenarios, bash, etc is doing the expansion first (via an os call) before being passed to a binary.

I suspect your use case it's passed through to jruby directly and it does not expand for you. For that matter I'd be curious if cruby behaves differently.

You are using single quotes which do not expand variables. Try double quoting. For good measure you could also use $HOME as well.

DmitryPogrebnoy commented 8 months ago

@jdx Another case when I get an error with unresolved mise command. I use noninteractive shell without login, so <path to mise>/mise activate is not invoked. And I use command like bash -c '<path to mise>/mise exec ruby@3.3.0 -- <path to ruby>/ruby <path to bundle>/bundle install'. And I get an error like above:

ERROR:  While executing gem ... (Errno::ENOENT)
           No such file or directory - mise

Adding mise path to PATH in bashrc file or any other shell configuration file doesn't help in the case of noninteractive shell without login.

So if you use non-absolute paths in scripts, please add path to mise inside exec command. For now I have to use a workaround like this every time when I need to exec something: bash -c 'export PATH=$PATH:<path to mise> && <path to mise>/mise exec ruby@3.3.0 -- <path to ruby>/ruby <path to bundle>/bundle install'.