-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
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
Simplify bottling for taps #3346
Comments
I've successfully used CircleCI to create macOS and Linux bottles for a tap: |
This would need to not just upload bottles but also push a commit with the bottle checksums.
This seems sensible 👍
I think environment variables for these would be ideal for when they can't be inferred automatically. I agree automatic inferring would be ideal, though.
I think the FooTestBot pattern makes sense in terms of overhead for orgs but not taps with a single user as maintainer. As a general comment: thanks for documenting and experimenting with this @davidchall. I'd definitely like a generic process we can support for people to be able to use Travis CI and other CI providers to build bottles. I doubt this will be something that ever scales to official taps given the 60m build timeout but it should work otherwise and I'm open to reviewing and making changes to get us there. |
I'm not sure encouraging bottling in third-party taps is going to have a salutary impact on the third-party Homebrew ecosystem overall. If there is a breaking upgrade to a library dependency of a bottle, then the bottle breaks. That means the software is broken for anyone who has already installed the bottle, and for anyone who is freshly installing the bottle. The bottle will remain broken until the tap owner gets around to building and publishing a new bottle. In the meantime anyone doing a fresh install will get a broken bottle and have to uninstall it and start over with a source install, assuming they can figure out what is going on. By contrast, in a tap without bottles, preexisting installations will break when there is a breaking upgrade to a library dependency. But any fresh installations, since they will be source installs, will be fine, and there's no waiting on the tap owner to find out about and fix the problem. So encouraging bottling in third-party taps will mean spreading the problems that have been endemic to the science tap more broadly, and triggering a constant cycle of break-notify-rebuild-republish-break-notify-rebuild-republish increasing the burden on tap owners and making the user experience more inconsistent. |
@ilovezfs I maintain the Maybe I could complement my bottle-testing job with a job that searches github for homebrew-core pull requests that modify dependencies of our formulae so we aren't surprised when they get merged. |
I guess that proves the point. |
subscribing to homebrew/core and using a mail filter is probably the simplest approach |
I'm doing that as we speak. It works for individuals but doesn't scale as well for teams wanting these notifications. |
It's true, and I agree that it's a hassle, but it's worth the hassle for me since our software takes a long time to compile. I guess I'm just saying you don't have to encourage bottling for third-party taps, but I hope you don't disable it, since we find it useful. |
Yeah, we wouldn't disable it :) |
A solution that addresses some (but not all) of this breakage is… |
That's pretty much papering over the problem with an inconsistent UX. |
I have a confession to make: I was running Yosemite on my development laptop until just a few weeks ago. I backdated my homebrew-core to a point that still had yosemite bottles for the packages I needed and set If 3rd-party taps could temporarily backdate homebrew-core, this would allow them to keep working until their bottles are rebuilt. I don't know how this would be implemented; I think it's possible, though it may not be desired functionality. If this functionality was built, I could imagine |
Or bottles can include some metadata on what versions of dependent formulas (&their deps) they were built with, and |
The metadata is there in |
@alyssais placing metadata in separate file would allow checking it without downloading whole bottle. It might be placed as separate tag, so it doesn't break older brew. Are dependent formulas rebotlled manually now? Also, if it's just a version bump, only metadata on dependent formulas can be updated. Not ideal, but still better than rebuilding. |
Or another option -- add some revision number to formula, which is bumped every time a breaking change requiring rebuild of dependent bottles occurs, and use that as a reference instead if version. Not sure on how to do that without surprising older brew versions though. |
Not by default, but they often are when the maintainers expect them to be broken.
This would require a lot of manual testing if I’m understanding it right.
This is how we currently do this. |
@stek Discourse is a better forum for questions and ideas if you've not personally written any code to improve this. Note we're not going to change the bottle file format. |
@MikeMcQuaid I've not personally written any code to improve this, but I was planning to. After looking through other issues, I got an impression that you've meant "don't leave comments unless you contributed to Homebrew and/or planning to work on this issue" -- if I'm right, then let me say that I did make some minor contributions to homebrew-core, and recently made a PR for brew :) What I was suggesting is this:
Problem: Dependencies of Dependencies. Let's say there's:
Now, B and C can be some libraries, and so if C's binary_revision is changed, both A and B should be rebuilt. There's an option -- when formula's binary_revision is changed, maintainers trigger rebuild on all dependent formulas, and optionally change their binary_revision's if "they [maintainers] expect them [dependencies of rebottled formula] to be broken". |
@stek29 Consider you just made two excellent PRs today: consider my comments revoked and apologised for ❤️
Bottles have a
I'm not sure what this would be for? Can you elaborate? Checking all versions within a bottle and building from source if they don't match? There's no real way of detecting this automatically, unfortunately, and doing so manually would be a lot of work. |
@MikeMcQuaid to avoid downloading whole bottle to only find out that it links to incompatible versions of formulas.
I'm suggesting adding a property "binary_revision" to formula which is manually bumped only in case of breaking changes which would require rebottling formulas depending on it. However, as I noticed previously, "deps of deps" aren't that simple to handle. I just discovered
|
FYI we don't actually revision bump or want to revision bump and rebottle every recursive reverse dependency, only the ones that actually break without the revision bump. |
@ilovezfs That's why it should "suggest" to bump it. Also, could there be a case when A and B depend on C, but only A needs to be rebuilt when C is updated with some breaking changes? |
Yup, that happens all the time. |
Ok, then what about providing both option to fully rebuild formula and to only rebuild metadata? Again, A and B depend on C.
That means that after update all dependents are tested and either marked "just working" with new version, are rebuilt (but not marked changed so their dependents don't need to be rebuilt), or rebuilt and rebuild is marked as breaking, so their dependents need to be checked too. |
That means either a) the INSTALL_RECEIPT, which is stored inside the prebuilt bottle, not apart from it, so cannot be updated without rebuilding the bottle None of these sound like they can be handled automatically. |
@ilovezfs c -- the new property/tag which is added to the bottle. Also, they reference binary_version and not version/revision -- if there's some minor change which doesn't break anything, then binary_revision isn't bumped. If it breaks at least one formula in core, it may also likely break third-party taps, so binary_revision is bumped and all dependent formulas are reviewed (with assistance of automatic tool?..), and either rebuilt & binary_revision bumped, just rebuilt without bumping binary_revision (it's dependents aren't broken), or only metadata file is rebuilt to mark it compliant with current binary_revision without rebuilding. It's certainly is not easier or prettier for maintainers, and it introduces an overhead of metadata file & rebuilding that metadata file from time to time, but I think that it would make bottle system more robust and make third-party bottles easier to use for end users and to make for third party tap maintainers. If you don't think it's worth it -- I guess some other solution is needed :) |
@stek29 I think it's not worth optimising for this case just to avoid downloading a single bottle, for what it's worth. |
Thanks @ilovezfs that makes sense. I was interpreting "vendoring" as requiring the use of the Falling back to a build from source if the bottle breaks would be less effort / less performant, but I think that's where I'm currently leaning. |
That's also how I was interpreting your use of the word vendoring. This proposal is better than that. |
There's multiple possible technical solutions to this problem. One such solution is using old bottles. My current preferred solution is building from source until the tap has updated the bottle. |
Ah. Yeah, that's why I said "in the tap" not "in the formula" but I guess that was not clear. |
That of course doesn't do anything for people who already have something installed when the breaking |
Yes, good point. |
Some new brew magic that triggers a |
👍
If there was an easy way to rename a working core bottle, say |
That'd be nice, but it doesn't solve the proverbial framework integration issue, which is like "gazebo depends on osrf-boost which is at x.y and opencv depends on just boost which is at x.y+n and so gazebo and opencv can potentially not be linked together now". So then you end up basically needing to fork all of homebrew if you want to let your users combine your software arbitrarily with any other software in homebrew. Note, that's not a real example, just something I made up as an illustration, but something like this is realistic (imo) and has happened many times before to me. |
Yeah that would expressly need to not be a goal of the tap. |
For this discussion, I agree. I didn't mean to get this issue off topic. It's probably a somewhat unique requirement given that ROS integrates with some many other libraries at the user level while also using them internally, but it's also a big reason why we don't maintain a tap for ROS. That unfortunately means our users are more likely to avoid using macOS and Homebrew, and therefore also unlikely to contribute to Homebrew, though some do anyways. |
It should be possible if you shadow the name instead of renaming. So
|
(Note I wouldn't recommend trying that unless you're planning on expecting people to use |
Wouldn't that break formulae in Homebrew/core that depend on |
@sjackman yup. |
@scpeters You should be able to pull the core PR into your own PR before we actually merge it to master. |
So I'll try adding a core PR to our jenkins job parameters to see if this works. |
You'd need to |
Right when the pull request is made, there wouldn't be any published bottles, but they are uploaded once the jenkins CI jobs go green, right? If I was lucky with the timing to start the build after bottles had been uploaded, I think it might work? This is like an unofficial version of the "grace period" I discussed above. I'm not actually sure if that's how it works though. |
You could
and then manually download the bottles from Jenkins if they're already built and put them in your cache or upload them somewhere and set the root_url in the bottle block. They won't be on Bintray yet. |
This was a little confusing to me, but I think I understand that they would be uploaded to bintray at this point but not published. So bintray credentials would be needed to download them.
Downloading the bottles from jenkins would take a little more work, crawling through the list of recent jenkins builds or getting the CI status from the GitHub API, but there's a limited number of recent builds, so they would potentially be deleted. Is there room for a role in between contributor and maintainer (of homebrew-core) for 3rd-party tap maintainers who could have read-only access to unpublished bottles on bintray? I would consider this to be a privilege and that it wouldn't include an expectation of support from maintainers. |
I use CircleCI to build bottles for both Linux and macOS. You can download the bottle artifacts from CircleCI using their REST API. See https://github.com/Linuxbrew/homebrew-developer/blob/master/cmd/brew-pull-circle.rb#L50 You can then download the bottles form CircleCI and upload them to Bintray. I automated that step using a web hook and AWS Lambda. See https://github.com/Linuxbrew/linuxbrew-lambda |
I use Jenkins with machines in our office to build our bottles. In talking about unpublished homebrew-core bottles, I was referring to the unofficial "grace period" idea and trying to build bottles for a downstream tap before the homebrew-core pull request has been merged and bottles published to bintray. |
Ah, right. Thanks for the reminder, Steven. |
I'm hoping to get HHVM's stuff in to a shape soon where I can send a PR so it's not third-party; for others, an alternative to full vendoring is to use static linking for dependencies. You can do this for everything, but what we've found best is to statically link dependencies that are particularly problematic (for example, ICU4C bumps the major version really often) and keep the stable stuff dynamically linked. Things still break occasionally but it's manageable. |
I'm open to (and have been) accepting more specific PRs for this but closing this out as a bit too much of a meta-ask with no real completion requirements. |
Without a BrewTestBot (or similar), it's labor intensive for tap maintainers to build bottles, publish them on Bintray, and update the formula with the bottle DSL. This could potentially be achieved on Travis CI using the
brew test-bot
andbrew pull --bottle
commands.I've hacked together a partial solution by making changes only to
Homebrew/brew-test-bot
, but I'm looking for feedback from the experts to find a better solution (e.g. @MikeMcQuaid @sjackman).I think there are two main points to discuss:
Homebrew/brew
Once we arrive at a solution, it can be added to
brew tap-new
and documented.Suggested workflow
testing-#{build_id}
tags and branches)brew pull --bottle
Code refactoring
Here are some variables that need to be edited to upload bottles and push formula changes:
brew test-bot
andbrew pull --bottle
)brew test-bot
)brew test-bot
)brew test-bot
)brew test-bot
)brew pull --bottle
)BottleSpecification::DEFAULT_DOMAIN
(to get correct root_url)These are currently passed as cmdline arguments or env vars, which could instead be properties of the tap object (perhaps read from a
.brew-tap.yml
file in the tap repo). Of course, the HOMEBREW_BINTRAY_KEY will need to remain an encrypted env var.These lines also hardcode where to find bottle patches. If we're going to support Travis CI push builds, then we'd need something similar.
The text was updated successfully, but these errors were encountered: