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

Run Bundler v1 native helpers with explicit version #3196

Merged
merged 3 commits into from
Mar 2, 2021

Conversation

feelepxyz
Copy link
Contributor

@feelepxyz feelepxyz commented Feb 25, 2021

This runs existing bundler 1 native helpers by explicitly setting a BUNDLER_VERSION env var as well as pointing the BUNDLE_GEMFILE to bundler/helpers/v1/Gemfile which has been installed with BUNDLER_VERSION=1 bundle install setting BUNDLED WITH to the latest installed v1 version.

I've verified this setup works with bundler 2 installed in the core container and installing core's gems with v2 and running helpers with v1, I've got the native helper tests working with a setup that extends on this PR: https://github.com/dependabot/dependabot-core/pull/3211/files

A follow on ship from this would be running native helper specs with bundler 1 followed by actually installing bundler 2 and installing core's gems with it.

This also moves the native helpers to v1 folder making room for a v2 folder.

Release plan

  • Deploy to staging and verify a couple of different updates, including private registry/repo

@feelepxyz feelepxyz requested a review from a team as a code owner February 25, 2021 16:41
Dockerfile Outdated Show resolved Hide resolved
bundler/helpers/Gemfile Outdated Show resolved Hide resolved
@feelepxyz feelepxyz changed the title WIP: Bundler 2 Run updates with bundler 1 with bundler 2 installed Feb 26, 2021
@feelepxyz feelepxyz changed the title Run updates with bundler 1 with bundler 2 installed Run bundler v1 native helpers with unset ENV Feb 26, 2021
@feelepxyz feelepxyz changed the title Run bundler v1 native helpers with unset ENV Run Bundler v1 native helpers with unset ENV Feb 26, 2021
end

def self.helper_path(bundler_version: "v1")
"ruby #{File.join(native_helpers_root, bundler_version, 'run.rb')}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jurre running without bundle exec worked and removed the need for an empty Gemfile 🎉

@feelepxyz feelepxyz requested a review from brrygrdn February 26, 2021 17:29
@@ -8,6 +8,10 @@ if [ -z "$install_dir" ]; then
exit 1
fi

if [ ! -d "$install_dir" ]; then
mkdir -p "$install_dir"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creates the nested v1 in /opt/bundler

def self.helper_path
"bundle exec ruby #{File.join(native_helpers_root, 'run.rb')}"
def self.run_bundler_subprocess(function:, args:, bundler_version:)
bundler_env_version = bundler_version.tr("v", "")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit funky, might be easier to do the version detection here instead

@feelepxyz
Copy link
Contributor Author

@jurre @brrygrdn got specs passing with just running the native helpers with a re-set ENV and setting BUNDLER_VERSION, this worked with bundler 2 installed but the native helper specs broke so thinking it makes more sense to ship this incrementally and then follow up with a PR to install bundler 2 but not use and fix the native helper specs.

Copy link
Contributor

@brrygrdn brrygrdn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for breaking this change out, it's very easy to follow the restructuring 👍🏻

I only have a couple of questions

V2 = "2"

# TODO: Add support for bundler v2
# return "v2" if lockfile.content.match?(/BUNDLED WITH\s+2/m)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌🏻


def self.helper_path(bundler_version:)
native_helper_version = "v#{bundler_version}"
"ruby #{File.join(native_helpers_root, native_helper_version, 'run.rb')}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm, we've removed bundle exec intentionally in addition to clearing the env?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 intentionally removing as bundle exec needs to be run in a folder with a Gemfile source (or point to one with a env var) that has resolved dependencies, we currently don't rely on any dependencies in the native helpers so this just got in the way of running the native helpers with a custom bundler version. Bundler refuses to run BUNDLER_VERSION=1 cmd if the Gemfile.lock that we're pointing to has been resolved with BUNDLED WITH 2.x and vice versa.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, when we executed bundle exec cmd it inherited all existing ENV values so ended up pointing to ./bundler/Gemfile as we ran the specs with bundle exec rspec spec and inherited the same BUNDLER_VERSION ENV var which I couldn't re-set without setting unsetenv_others: true.

Similarly, when run from the updater it would inherit the BUNDLED WITH from the updaters Gemfile.lock: https://github.com/dependabot/dependabot-updater/blob/main/bin/run#L21

common/lib/dependabot/shared_helpers.rb Outdated Show resolved Hide resolved
start = Time.now
stdin_data = JSON.dump(function: function, args: args)
cmd = allow_unsafe_shell_command ? command : escape_command(command)
env_cmd = [env, cmd].compact
if ENV["DEBUG_FUNCTION"] == function
escaped_stdin_data = stdin_data.gsub("\"", "\\\"")
puts "$ cd #{Dir.pwd} && echo \"#{escaped_stdin_data}\" | #{env_cmd.join(' ')}"
env_keys = env ? env.map { |k, v| "#{k}=#{v}" } : ""
puts "$ cd #{Dir.pwd} && echo \"#{escaped_stdin_data}\" | #{env_keys} #{cmd}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully follow the switch from #{env_cmd.join(' ')} to #{env_keys} #{cmd} here, as it looks like we still pass env_cmd on line 89.

My read is that this purely to improve presentation in the logs, but I just wanted to check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path should only be used when you pass DEBUG_FUNCTION=somefunc as env var when running specs/dry-run and puts out the command that's being executed by ruby so you can cd into the temp dir and run the same thing in bash. The previous way of concatenating env and cmd didn't work when actually passing in a env hash.

The env_cmd arg still works for Open3 but now the bash version flattens the env hash to ENV_KEY=value ./func.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempted to clarify this a bit with the above comment and moving env_cmd down to where it's used

@feelepxyz feelepxyz force-pushed the feelepxyz/bundler2-spike branch from ec8f2ed to e339e4c Compare March 1, 2021 14:13
@feelepxyz feelepxyz force-pushed the feelepxyz/bundler2-spike branch from fc98076 to 5e3da4c Compare March 2, 2021 10:34
@feelepxyz feelepxyz changed the title Run Bundler v1 native helpers with unset ENV Run Bundler v1 native helpers with explicit version Mar 2, 2021
@feelepxyz feelepxyz force-pushed the feelepxyz/bundler2-spike branch from 5e3da4c to 1612bcd Compare March 2, 2021 10:45
if ENV["DEBUG_FUNCTION"] == function
escaped_stdin_data = stdin_data.gsub("\"", "\\\"")
puts "$ cd #{Dir.pwd} && echo \"#{escaped_stdin_data}\" | #{env_cmd.join(' ')}"
puts helper_subprocess_bash_command(stdin_data: stdin_data, command: cmd, env: env)
Copy link
Contributor Author

@feelepxyz feelepxyz Mar 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brrygrdn moved this into it's own method

Example output, if you run DEBUG_FUNCTION=parsed_gemspec bundle exec rspec spec/dependabot/bundler/file_parser_spec.rb:685 you'll see this in console:

$ cd /Users/feelepxyz/code/dependabot-core/bundler/tmp/dependabot_20210302-86366-1xt144c && \
echo "{\"function\":\"parsed_gemspec\",\"args\":{\"gemspec_name\":\"example.gemspec\",\"lockfile_name\":null,\"dir\":\"/Users/feelepxyz/code/dependabot-core/bundler/tmp/dependabot_20210302-86366-1xt144c\"}}" \
| BUNDLER_VERSION=1 \
BUNDLE_GEMFILE=/Users/feelepxyz/code/dependabot-core/bundler/lib/dependabot/bundler/../../../helpers/v1/Gemfile \
bundle exec ruby /Users/feelepxyz/code/dependabot-core/bundler/lib/dependabot/bundler/../../../helpers/v1/run.rb

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for clarifying this 🙇🏻

This runs existing bundler 1 native helpers by explicitly setting a
`BUNDLER_VERSION` env var as well as pointing the `BUNDLE_GEMFILE` to
the `Gemfile` in `helpers/v1` which has been bundled with:
`BUNDLER_VERSION=1 bundle install` setting `BUNDLED WITH` to the
matching installed v1 version.
@feelepxyz feelepxyz force-pushed the feelepxyz/bundler2-spike branch from 1612bcd to b088744 Compare March 2, 2021 10:53
@feelepxyz feelepxyz requested a review from brrygrdn March 2, 2021 10:58
Comment on lines +22 to +25
"RUBYLIB" => nil,
"RUBYOPT" => nil,
"GEM_PATH" => nil,
"GEM_HOME" => nil
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kinda funky but seems to work, verified that these env vars are not set in the container so get set by bundler/ruby when running core with bundle exec rspec/updater run

Copy link
Contributor

@brrygrdn brrygrdn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of copy edits, otherwise this looks 💯

I don't feel bad unsetting specific ruby/bundler envvars given the circumstances. It's well called out and doesn't feel brittle in the sense those are pretty fixed points in the ecosystem.

# gemspec so we've added it here for backwards compatability during bundler 2
# rollout.
#
# NOTE: If we don't require it and a customers `.gemspec` uses File without
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# NOTE: If we don't require it and a customers `.gemspec` uses File without
# NOTE: If we don't require it and a customers `.gemspec` uses Find without

@@ -0,0 +1,16 @@
# frozen_string_literal: true

# TODO: Look into removing this. "file" used to get required from common's
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# TODO: Look into removing this. "file" used to get required from common's
# TODO: Look into removing this. "find" used to get required from common's

"RUBYLIB" => nil,
"RUBYOPT" => nil,
"GEM_PATH" => nil,
"GEM_HOME" => nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a fair workaround, it feels like the cost of doing business since we're running bundler to run core to run bundler ♻️ 😅

if ENV["DEBUG_FUNCTION"] == function
escaped_stdin_data = stdin_data.gsub("\"", "\\\"")
puts "$ cd #{Dir.pwd} && echo \"#{escaped_stdin_data}\" | #{env_cmd.join(' ')}"
puts helper_subprocess_bash_command(stdin_data: stdin_data, command: cmd, env: env)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for clarifying this 🙇🏻

Copy link
Contributor

@brrygrdn brrygrdn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@feelepxyz feelepxyz merged commit a0dd603 into main Mar 2, 2021
@feelepxyz feelepxyz deleted the feelepxyz/bundler2-spike branch March 2, 2021 11:18
feelepxyz added a commit that referenced this pull request Mar 3, 2021
…pike"

This reverts commit a0dd603, reversing
changes made to c93e297.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants