Formula, Cask: add livecheck_defined hash value#21717
Conversation
The `Tap.autobump` logic was recently updated to not skip deprecated packages but this has lead to autobump checking packages that livecheck will automatically skip as deprecated. We want autobump to only check deprecated packages that are checkable and that effectively means only checking those with a `livecheck` block. To be able to do this, we need to include the `livecheck_defined?` value in the JSON API data for formulae and casks. This adds a `livecheck_defined` value to `Cask#to_h` and `Formula#to_hash` as a preliminary step. We need to add this value and for it to be present in the latest JSON API data before we can use it in `Tap.autobump`.
There was a problem hiding this comment.
Pull request overview
Adds a livecheck_defined boolean to formula/cask hash outputs intended for inclusion in Homebrew’s JSON API so Tap.autobump can distinguish deprecated packages that are still livecheck-checkable.
Changes:
- Add
"livecheck_defined"toFormula#to_hash. - Add
"livecheck_defined"toCask#to_h. - Update the
everything.jsoncask fixture to include the new key.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| Library/Homebrew/formula.rb | Exposes livecheck_defined? in formula hash output. |
| Library/Homebrew/cask/cask.rb | Exposes livecheck_defined? in cask hash output. |
| Library/Homebrew/test/support/fixtures/cask/everything.json | Updates expected cask JSON fixture to include livecheck_defined. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| "autobump" => autobump?, | ||
| "no_autobump_message" => no_autobump_message, | ||
| "livecheck_defined" => livecheck_defined?, | ||
| "skip_livecheck" => livecheck.skip?, |
There was a problem hiding this comment.
Adding "livecheck_defined" => livecheck_defined? to Cask#to_h won’t make this value available via the JSON API: Homebrew::API::Cask::CaskStructGenerator ends by calling CaskStruct.from_hash, which slices to CaskStruct props and will drop the new key unless Homebrew::API::CaskStruct is updated. If the goal is to have this in API JSON for Tap.autobump, add a livecheck_defined prop to CaskStruct and plumb it through struct generation/serialization (and then set it on the API-loaded cask’s DSL so cask.livecheck_defined? matches API data).
There was a problem hiding this comment.
I'm not sure that's correct. With this branch checked out, I ran brew generate-formula-api and brew generate-cask-api in the formulae.brew.sh repository and confirmed that the generated JSON contained the expected "livecheck_defined" value.
| "livecheck_defined" => livecheck_defined?, | ||
| "skip_livecheck" => livecheck.skip?, |
There was a problem hiding this comment.
Adding "livecheck_defined" => livecheck_defined? here won’t actually make the field appear in the generated JSON API data: API generation runs FormulaStructGenerator.generate_formula_struct_hash and then FormulaStruct.from_hash, which slices to FormulaStruct props (dropping unknown keys). To expose this in the API output, you’ll need to add a corresponding prop to Homebrew::API::FormulaStruct and plumb it through generate_formula_struct_hash/serialization.
| "livecheck_defined" => livecheck_defined?, | |
| "skip_livecheck" => livecheck.skip?, |
|
Just to confirm without looking too deeply, if a deprecated formula doesn't have a defined block, does it still check the default livechekc (for example, using the git strategy)? My understanding with the previous change was we only wanted to skip bumping formula with a defined livecheck skip block? But I could be wrong. |
@samford Can you elaborate on this? Why do we rely on fields in our public API for livecheck functionality? |
|
Pardon the novella but this requires a fair amount of context/detail.
Deprecated packages without a This PR maintains that behavior but skips deprecated packages that aren't checkable as a way of avoiding wasted effort at an earlier stage. If the intention is really to check all deprecated packages, that takes a lot more work than changing a guard and it's something we should discuss before doing (I wasn't part of the homebrew-core discussion and wasn't able to review the previous brew PR before it was merged). My read of the homebrew-core discussion was that they needed a way to add a deprecated package to autobump but there wasn't one. This PR provides a more refined solution, where we only check deprecated packages that have opted in via a For context on the current skip approach, my perspective was that most upstream situations leading to a package deprecation tend to also imply that there won't be further versions unless something changes. For example, If we need to check a package despite deprecation, adding/keeping a Based on my previous experience with deprecated packages and the statistics for deprecation reasons (see below), I don't think there's enough value to justify checking deprecated packages several times per day using autobump if it's unlikely there will be a new version. This is partly why I presumed that the original goal wasn't to check all deprecated packages (even if they weren't skipped, you can't flip a switch and expect hundreds of default checks to work properly). However, my issue is primarily with the frequency. We may be able to create a separate workflow to check deprecated packages once a week/month/etc. instead and that could make sense but these packages would need to work with livecheck. If we go down that route, we would have to go through all of the deprecated packages to check livecheck's behavior and add In my view, flipping the current approach to check deprecated packages by default only makes sense if most deprecated packages should be checked. I can be convinced if there's solid reasoning and data to support this but, as mentioned, I don't think autobump is the right place to check deprecated packages (i.e., it would be a waste of effort for almost all of these to check them several times per day). This also isn't something we should pursue if we will have to manually add hundreds of If we were to check deprecated packages by default, this is also a scenario where we should first go through all deprecated packages, ensure that livecheck works properly (adding To summarize, I think our options are:
If we want to check deprecated packages more broadly, I would suggest maintaining the existing skip behavior and creating a separate workflow that checks deprecated packages less frequently than autobump (option B). Otherwise I naturally support option A. Statistics on deprecations and reasons are as follows:
It's worth noting that the
Tangent aside, I was wondering why the API is used in |
@botantony can you elaborate a bit here? |
That's pretty much it. I also wasn't certain how else this could work faster. Using something like However, I understand if you prefer to prioritize reducing API file size for 99% of regular users |
From some rough math, adding a One alternative I considered is that it's technically possible to modify bump/bump-*-pr and
Full core/cask tap runs in livecheck run into this as well and the time to parse thousands of packages is substantial enough that I've considered printing temporary output to make it clear that it's doing something and not just hanging (~10s on M4 Pro for homebrew/core, ~6s for homebrew/cask). Almost no one does full tap runs, so that's remained a very niche concern. However, if we checked formula/cask objects in Another notable issue is that The related |
Now it's in the API it's hard for us to remove it now so no big priority. We could also just read the raw files or even shell back to
Yeh, I think it'd be worth migrating both to avoid using the API.
I think it's reasonable to write a cache onto disk (and into actions/cache) that we can key on the
I would rather avoid it if we can. |
|
Thinking about this some more, the issue that spurred me to create this PR was to prevent |
brew lgtm(style, typechecking and tests) with your changes locally?The
Tap.autobumplogic was recently updated to not skip deprecated packages but this has lead to autobump checking packages that livecheck will automatically skip as deprecated. We want autobump to only check deprecated packages that are checkable and that effectively means only checking those with alivecheckblock. To be able to do this, we need to include thelivecheck_defined?value in the JSON API data.This adds a
livecheck_definedvalue toCask#to_handFormula#to_hashas a preliminary step. We need to add this value and for it to be present in the latest JSON API data before we can use it inTap.autobump.An alternative approach is to modify
skip_livecheckto also factor in automatic skips fromLivecheck::SkipConditions(or add a different boolean field for that). I didn't go that route because it's much more involved due to needing to identify and check formulae/casks that are referenced in alivecheckblock, so it ends up being a fair amount of code. That may be a more robust approach in the long-term (as there are skip conditions other than deprecation) but thislivecheck_definedapproach should be a simple improvement in the interim time.This is a follow-up to #21651, as I didn't manage to review it before it was merged. I didn't think anything of it until I was reviewing autobump output and saw a dramatically higher number of "unable to get versions" output, due to deprecated packages without a
livecheckblock being checked but automatically skipped.