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

Fixes openjdk_dep_name_if_applicable when not using CurlGitHubPackagesDownloadStrategy #16439

Merged
merged 2 commits into from Jan 31, 2024

Conversation

arianf
Copy link

@arianf arianf commented Jan 6, 2024

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew typecheck with your changes locally?
  • Have you successfully run brew tests with your changes locally?

Fixes openjdk_dep_name_if_applicable when not using CurlGitHubPackagesDownloadStrategy

When installing a formula, FormulaInstaller calls #pour, which in turn calls:

tab = Utils::Bottles.load_tab(formula)

This tab is expected to have #runtime_dependencies, and it typically will because most packages come from http://ghcr.io

if (tab_attributes = formula.bottle_tab_attributes.presence)

Any DownloadStrategy that does not match CurlGitHubPackagesDownloadStrategy will lead here:

return if @resource.download_strategy != CurlGitHubPackagesDownloadStrategy

Causing this branch to be executed for creating the tab, without #runtime_dependencies:

Tab.for_keg(keg)

This causes a slight issue because openjdk_dep_name_if_applicable calls keg.runtime_dependencies when it's still nil.

def openjdk_dep_name_if_applicable
deps = runtime_dependencies
return if deps.blank?
dep_names = deps.map { |d| d["full_name"] }
dep_names.find { |d| d.match? Version.formula_optionally_versioned_regex(:openjdk) }
end

And if it's blank, it won't do the regex replacement on @@HOMEBREW_JAVA@@, resulting in the following error when running Kafka:

$ tail -f /opt/homebrew/var/log/kafka/kafka_output.log
/opt/homebrew/Cellar/kafka/3.6.0/libexec/bin/kafka-run-class.sh: line 346: /opt/homebrew/@@HOMEBREW_JAVA@@/bin/java: No such file or directory
/opt/homebrew/Cellar/kafka/3.6.0/libexec/bin/kafka-run-class.sh: line 346: exec: /opt/homebrew/@@HOMEBREW_JAVA@@/bin/java: cannot execute: No such file or directory

As mentioned by: https://github.com/orgs/Homebrew/discussions/2530#discussioncomment-2002374

Installing Java-dependent formulae from bottle mirrors doesn't work properly at the moment. The issue is that brew needs the manifest in order to correctly replace @@HOMEBREW_JAVA@@ but brew only knows how to fetch manifests from ghcr.io.
Pull requests to fix this welcome.

This should fix this issue, by getting the runtime_dependencies directly from the formula for those cases that it can't get it from https://ghcr.io or tabfile

f_runtime_deps = formula.runtime_dependencies(read_from_tab: false)
tab.runtime_dependencies = Tab.runtime_deps_hash(formula, f_runtime_deps)

@apainintheneck
Copy link
Contributor

Thanks for taking a look at this.

It's interesting that we already update the runtime dependency field in the tab when finishing up the install and this is essentially just moving that work earlier in the process so that keg relocation works here.

# Update tab with actual runtime dependencies
tab = Tab.for_keg(keg)
Tab.clear_cache
f_runtime_deps = formula.runtime_dependencies(read_from_tab: false)
tab.runtime_dependencies = Tab.runtime_deps_hash(formula, f_runtime_deps)
tab.write

Does this have to wait until after the keg is installed or can we just do it for all of them earlier on in the install process?

Copy link
Member

@MikeMcQuaid MikeMcQuaid 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 great PR @arianf and comprehensive explanation, wonderful work. Have a few questions and interested in answers to @apainintheneck's too.


describe ".load_tab" do
context "when tab_attributes and tabfile are missing" do
it "includes runtime_dependencies", :integration_test do
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure this needs to be an :integration_test? Would like to avoid adding new ones whenever possible because they are so slow 🐌

Copy link
Author

@arianf arianf Jan 9, 2024

Choose a reason for hiding this comment

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

I added :integration_test, because I needed install_test_formula and setup_test_formula to perform the tests with the formulas. I'd be open to other ways of testing this.

Copy link
Member

Choose a reason for hiding this comment

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

Search for temporarily_install_bottle or when it can't remove a keg or eligible_kegs_for_cleanup for some examples of tests that do installation without an integration test.

Copy link
Author

Choose a reason for hiding this comment

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

@MikeMcQuaid sorry for the delay, I have fixed this and made the test a non :integration_test

Library/Homebrew/utils/bottles.rb Outdated Show resolved Hide resolved
@arianf
Copy link
Author

arianf commented Jan 9, 2024

Thank you both for reviewing this PR.

It's interesting that we already update the runtime dependency field in the tab when finishing up the install and this is essentially just moving that work earlier in the process so that keg relocation works here.

# Update tab with actual runtime dependencies
tab = Tab.for_keg(keg)
Tab.clear_cache
f_runtime_deps = formula.runtime_dependencies(read_from_tab: false)
tab.runtime_dependencies = Tab.runtime_deps_hash(formula, f_runtime_deps)
tab.write

Does this have to wait until after the keg is installed or can we just do it for all of them earlier on in the install process?

Yea, that's something I was wondering as well. To be honest, I'm not sure why the runtime dependency are always overwritten in the #finish step. My assumption was there might be some edge conditions that I'm unaware of, where this is needed.. so I was hesitant to modify it.

That block above is reason why @carlocab observed the correct value within runtime_dependencies. It's just happening much later than relocate tries to use them.

https://github.com/orgs/Homebrew/discussions/2530#discussioncomment-1696893

The problem is here:

deps = runtime_dependencies

runtime_dependencies is evaluating to nil for some reason. I don't really understand why, because the tab/install receipt indicates a runtime dependency on openjdk@11. Instantiating a Keg after installing your formula also has the correct value for runtime_dependencies. @Bo98, any ideas here?
@carlocab

@MikeMcQuaid
Copy link
Member

To be honest, I'm not sure why the runtime dependency are always overwritten in the #finish step.

We always want to calculate the actual formula linkage based on current dependencies rather than using the one in the tab.

@MikeMcQuaid MikeMcQuaid removed their request for review January 11, 2024 09:01
…agesDownloadStrategy`

When installing a formula, `FormulaInstaller` calls `#pour`, which in turn calls:

https://github.com/Homebrew/brew/blob/6f20c0300aee2ab0feae3132d13f859d91cf295b/Library/Homebrew/formula_installer.rb#L1260

This `tab` is expected to have `#runtime_dependencies`, and it typically will because most packages come from http://ghcr.io

https://github.com/Homebrew/brew/blob/6f20c0300aee2ab0feae3132d13f859d91cf295b/Library/Homebrew/utils/bottles.rb#L111

Any `DownloadStrategy` that does not match `CurlGitHubPackagesDownloadStrategy` will lead here:
https://github.com/Homebrew/brew/blob/6f20c0300aee2ab0feae3132d13f859d91cf295b/Library/Homebrew/software_spec.rb#L463

Causing this branch to be executed for creating the `tab`:
https://github.com/Homebrew/brew/blob/6f20c0300aee2ab0feae3132d13f859d91cf295b/Library/Homebrew/utils/bottles.rb#L119

This causes a slight issue because `openjdk_dep_name_if_applicable` calls `keg.runtime_dependencies` when it's still `nil`.

https://github.com/Homebrew/brew/blob/6f20c0300aee2ab0feae3132d13f859d91cf295b/Library/Homebrew/keg_relocate.rb#L134-L140

And if it's blank, it won't do the regex replacement on `@@HOMEBREW_JAVA@@`, resulting in the following error when running `Kafka`:

```console
$ tail -f /opt/homebrew/var/log/kafka/kafka_output.log
/opt/homebrew/Cellar/kafka/3.6.0/libexec/bin/kafka-run-class.sh: line 346: /opt/homebrew/@@HOMEBREW_JAVA@@/bin/java: No such file or directory
/opt/homebrew/Cellar/kafka/3.6.0/libexec/bin/kafka-run-class.sh: line 346: exec: /opt/homebrew/@@HOMEBREW_JAVA@@/bin/java: cannot execute: No such file or directory
```

As mentioned by: https://github.com/orgs/Homebrew/discussions/2530#discussioncomment-2002374

> Installing Java-dependent formulae from bottle mirrors doesn't work properly at the moment. The issue is that brew needs the manifest in order to correctly replace @@HOMEBREW_JAVA@@ but brew only knows how to fetch manifests from ghcr.io.
> Pull requests to fix this welcome.

This should fix this issue, by getting the `runtime_dependencies` directly from the formula for those cases that it can't get it from https://ghcr.io or tabfile

```ruby
f_runtime_deps = formula.runtime_dependencies(read_from_tab: false)
tab.runtime_dependencies = Tab.runtime_deps_hash(formula, f_runtime_deps)
```
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

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

Thanks so much for your first contribution! Without people like you submitting PRs we couldn't run this project. You rock, @arianf!

@MikeMcQuaid MikeMcQuaid merged commit 3707c90 into Homebrew:master Jan 31, 2024
24 checks passed
@github-actions github-actions bot added the outdated PR was locked due to age label Mar 2, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants