Closed oprypin closed 3 years ago
If there is no crystal property the semantic is crystal: < 1.0.0
shards install --ignore-crystal-version
can be used as a workaround until a more fine grained alternative of forcing the resolution is added.
Maybe shards should also read a SHARDS_OPTS
env variable so this can be widely configured 🤔
If there is no crystal property the semantic is crystal:
< 1.0.0
Yea I get it, but nobody asked for that to be that way??
It is a choice that make things work similar to what will happen from 1.0 to 2.0 eventually. Major releases will require some work from the ecosystem to migrate, or for the user to use some workaround.
It also mimic what would happen if the property was mandatory since the beginning + the semantics choosen for crystal: x.y.z
No I don't understand why you want to break almost all shards; again, who asked for that?
Oh yeah and the full fallout from most things breaking globally will exactly coincide with 1.0.0 release, just why do it?
This change was introduced in #395 and there's a lengthy discussion about this behaviour: what the default should be when no crystal
property is present specifically and more importantly, which effect the crystal
property has.
The core team was devided on this topic. We still went trough with it and agreed that it can be reverted if it goes south and everyone complains about this (that part was discussed off Github in a private core team meeting).
While it may be a good idea in general (not sure if that's true), I'm still expecting that introducing this hard breaking change on short notice in 1.0 is going to cause a huge mess for the ecosystem.
I don't know if it's related, but even after specifying crystal
attribute I still get a failure. Can't reproduce locally. Looks really weird.
https://github.com/oprypin/crystal-chipmunk/runs/800778520#step:16:10
Unable to satisfy the following requirements:
- `crystal (~> 0.24, >= 0.24.1)` required by `spec_assert 0.1.0+git.commit.29f719936bc600b98b665cf91be7f6583a20be1f`
- `crystal (~> 0.25, >= 0.25.1)` required by `crsfml 2.5.1`
- `crystal (~> 0.30, >= 0.30.1)` required by `chipmunk 0.1.0`
Either append --ignore-crystal-version in https://github.com/oprypin/crystal-chipmunk/commit/899e676b5d3f4b8aa17be6cb6a6dd51848d88414#diff-e9f950f17198d3d5e3122a44230a09b9R100
Or update dependencies to a crystal: 1.0.0
like https://github.com/oprypin/crsfml/blob/master/shard.yml#L15 and others.
The dependencies are the ones that are incompatible with crystal 1.0.0-dev
Excuse me? Should I take this to understand that crystal
1.0.0
is somehow not >= 0.30.1
and that's intended behavior?
The issue is that
crystal: 0.30.1
is ~> 0.30, >= 0.30.1
.~> 0.30
is >= 0.30, < 1.0
. Same as in bundler. Ref: https://thoughtbot.com/blog/rubys-pessimistic-operatorThat is where the < 1.0
is coming from.
When just a version number is used it has a different semantic compared to dependencies:
x.y.z
will be interpreted as~> x.y, >= x.y.z
(ie:>= x.y.z, < (x+1).0.0
) honoring semver. Ref: SPEC.md
OK, now do you want to explain all of these fine points to literally every user on the day of the 1.0.0 release? When there are like 5 layers of "surely this is a bug"?
Now I realize that both of the cases, which together surely cover 99% of existing shards:
crystal: 0.*
imply crystal
< 1.0.0
.
So is the idea that every single shard author is expected to add crystal: 1.0.0
exactly on the day of its release and drop support for all other versions of Crystal at the same time? How is this supposed to work at all?
Now, I also realize that it's possible for me to replace all my crystal: 0.24.1
etc with crystal: '>= 0.24.1'
to get rid of this problem, but hmmmmm
I think the idea is that there will be a pre-release. Then all shards authors will be encouraged to release a shard version compatible with 1.0.0. Then when 1.0.0 releases only maintained shards are usable.
@oprypin could you first please consider change your tone and attitude? We're human beings, with feelings, emotions and mistakes. We did what it's done for a reason and with a goal in mind. The fact that you have different viewpoints doesn't necessarily makes ours wrong or less important than yours. I could try to re-explain the rationale but it's really hard and discouraging if you just try to impose with messages full of irony or rage.
IMO a major implementation issue is the implicit meaning of crystal: x.y.z
. It's far from obvious that it's equivalent to crystal: ~> x.y, >= x.y.z
. It's against expectations. The established semantics of version: x.y.z
in dependencies refer to a single version, not a range.
Following that, as soon as you notice that crystal: x.y.z
also matches x.y.z+1
the first assumption would be that it means crystal: >= x.y.z
.
@waj
I could try to re-explain the rationale but it's really hard and discouraging if you just try to impose with messages full of irony or rage
Well no, I could also try to explain my numerous thoughts how this is not the right direction to take, but there are so many big and obvious points that I thought it was not necessary. At some point I'll need to do that, though.
I suppose the moment of realizing that this is not a bug but intentional really did trigger rage; not necessarily due to the fact itself, just that it's an instant switch in thinking. What followed directly was disbelief, rather than a rational re-evaluation.
I don't want to let a self-imposed and easily predicted catastrophe to happen and honestly the prospect of having to live through the fallout from that is just scary on some level. I literally imagined how I'd feel participating in chat on that day, trying to contain antagonistic demeanor. So yes, the feelings really are hard for me to contain at this time as well.
The discussion on why restricting the compatible language version beforehand can be followed at https://github.com/crystal-lang/shards/issues/365.
I think that the same policy should apply from 0.x to 1.x and from 1.x to 2.x.
When shards are built with crystal: 1.2
, that version will not be a candidate for crystal 2.x. The fact that the language is not going to change that much between 0.x and 1.x is exceptional. It might do between 1.x and 2.x.
This allows pruning the space search and more importantly allows the language to keep evolving. Without this restriction it will be harder to make decisions of breacking-changes on the language itself.
Nothing prevents you to use crystal: *
explicitly to say that that shard version is available for every crystal version, same as with dependencies. But it's not a practice I encourage. There are no guarantees today to support that claim.
As mentioned in https://github.com/crystal-lang/shards/issues/413#issuecomment-647768257 you can use --ignore-crystal-version when installing shards to turn off this check during transition periods. In #417 I propose that that can come from an env var since that might be more comportable in CIs and build scripts.
Can we mention --ignore-crystal-version
in the error message, alongside a little text blob explaining that it's worth a shot if you just installed Crystal 1.0, or something along the lines of that?
Yes. #418 :-)
Even shard's nightlies are broken, btw.: https://app.circleci.com/pipelines/github/crystal-lang/shards/347/workflows/5c706c91-30e7-473b-8675-6d94428e9618/jobs/1043/steps
It's a common practice to have CI builds against latest and nightly Crystal releases. Currently, lot's of nightlies are failing because shards refuses to install dependencies unless they're explicitly enabled with crystal: 1.0.0
.
This problem shows a real dilemma. How's this supposed to work when latest and nightly Crystal releases have different major versions?
A trivial solution would be to use --ignore-crystal-version
for the nightly build. But that's not good because it's a different behaviour than in normal use cases. I want nightlies to work the same way as a normal user would and it should help identify problems with installing shards.
Alternatively, all dependencies could be changed to crystal: 1.0.0
(or rather something like crystal: ~> 0.35.0, ~>1.0.0
to work with Crystal latest). But that might be a lie. Or maybe a declaration of intent. Until the next major version is released, there's no way to tell whether a shard is actually compatible with that release.
An modified approach would be using crystal: 1.0.0-dev
for dependencies (that version restriction by itself doesn't work btw., only crystal: '~> 1.0.0-dev'
). That's more clearly expression than crystal: 1.0.0
. But it's still not really accurate because we don't know whether it's actually going to be compatible with 1.0.0
. So we could make the version even stricter crystal: '~> 1.0.0-dev, < 1.0.0'
.
That might be the proper definition. But it's also rather complex. And it requires two changes to the shard dependencies: When Crystal nightly becomes a development version of a new major version and when that major version is finally released. Considering that even one such change throughout the ecosystem is going to be incredibly hard, I can't imagine such an approach to be feasible.
Hey, just wanted to chime in real quick that I'm seeing the same deal when trying to upgrade the Lucky website to our latest version https://github.com/luckyframework/website/pull/341. My build fails due to Crystal version conflicts.
Unable to satisfy the following requirements:
- `crystal (~> 0.35, >= 0.35.0)` required by `lucky 0.23.0`
- `crystal (~> 0.35, >= 0.35.0)` required by `authentic 0.6.1`
- `crystal (~> 0.35, >= 0.35.0)` required by `carbon 0.1.2`
- `crystal (~> 0.35, >= 0.35.0)` required by `habitat 0.4.4`
- `crystal (~> 0.35, >= 0.35.0)` required by `dexter 0.3.1`
- `crystal (~> 0.33, >= 0.33.0)` required by `exception_page 0.1.4`
- `crystal (~> 0.33, >= 0.33.0)` required by `cry 0.4.2`
- `crystal (~> 0.22, >= 0.22.0)` required by `shell-table 0.9.2+git.commit.078a04ea58ead5203bb435a3b5fff448ddabaeea`
- `crystal (~> 0.35, >= 0.35.0)` required by `lucky_router 0.3.0`
- `crystal (~> 0.35, >= 0.35.0)` required by `avram 0.16.0`
- `crystal (~> 0.26, >= 0.26.1)` required by `wordsmith 0.2.0`
- `crystal (~> 0.35, >= 0.35.0)` required by `lucky_cli 0.23.0`
- `crystal (~> 0.35, >= 0.35.0)` required by `lucky_flow 0.7.0`
- `crystal (~> 0.34, >= 0.34.0)` required by `cadmium_transliterator 0.1.0+git.commit.6ee68d64869ade8f39d2ec16cae3c7b80d5a4805`
- `crystal (~> 0.35, >= 0.35.0)` required by `markd 0.2.1+git.commit.620845abb6776d1765d20d86cc0220aa40f89a91`
- `crystal (< 1.0.0)` required by `dotenv 0.7.0`
- `crystal (< 1.0.0)` required by `blank 0.1.0`
- `crystal (< 1.0.0)` required by `pg 0.21.1`
- `crystal (~> 0.35, >= 0.35.0)` required by `teeplate 0.8.2`
- `crystal (~> 0.35, >= 0.35.0)` required by `selenium 0.6.0`
- `crystal (~> 0.35, >= 0.35.0)` required by `webdrivers 0.3.0`
- `crystal (~> 0.25, >= 0.25.0)` required by `db 0.9.0`
- `crystal (~> 0.34, >= 0.34.0)` required by `future 0.1.0`
- `crystal (~> 0.35, >= 0.35.1)` required by `crystar 0.1.7`
Failed to resolve dependencies
For anyone else that might land here, I updated to use that shards install --ignore-crystal-version
, and that fixed it for me.
It would be nice if the error message would tell you why crystal (~> 0.35, >= 0.35.0)
didn't match (what's the crystal version being used?).
That looks really strange. It seems this action runs in a crystallang/crystal:0.35.0
container, so all the crystal (~> 0.35, >= 0.35.0)
and crystal (<1.0.0)
requirements should actually match.
All other requirements are broken though with the current behaviour of shards. Their crystal
property is based on outdated semantics.
@jwoertink Could you add a crystal version
somewhere before the shards install runs? Just to be sure.
FYI for that particular run:
It uses Crystal 0.35.0 but one dependency has >= 0.35.1
I think there may have been a few other things going on here. I hacked around it so I could close out the issue, but in that action, I had 2 containers. The first container didn't specify a version where the second one did. Then on top of that, I was caching the shards install
I can probably try and push another "test" PR from that version to recreate it with that crystal version
if that would help @straight-shoota
At first I thought this would be helpful, but now I'm thinking it may cause some issues with launch and unnecessary burden/time crunch on shard authors.
I have a proposal for how we might get the best of both worlds. In Crystal 1.0 show a warning for this and say it will be an error by default in Crystal 1.1. This gives shard authors time to update and doesn't result in errors on day 1 for shards that may need a bit of time to be updated and released (maybe author is on vacation or doesn't know).
--fail-on-crystal-version-mismatch
to prep for Crystal 1.1--ignore-crystal-version
is still there and will not show the warning--fail-on-crystal-version-mismatch
. People can use this on 1.0 to prepare for 1.1--fail-on-crystal-version-mismatch
is used that tells the user this is now the default behavior. I think this solves the problem fairly well. It warns users that shards they are using might not work on 1.0, but allows them to give it a shot. It sets the path for 1.1 to use the more strict behavior. And it gives some time for authors to test on 1.0 and update their shard.yml
Thoughts?
@paulcsmith https://github.com/crystal-lang/shards/pull/418#discussion_r446421572, so yeah, warnings would be way easier to manage for every1. Also, I can't imagine 1.0
without being able to override shards.
The issue appears while we are on a transition period of major release. While developing 1.0.0-dev, how does the ecosystem prepare for it if it's not a closed release? We don't want packages to be forced to do releases while 1.0.0-dev is not closed. On regular dependencies we've been using branch requirements to stay up to date with upstream changes.
If we want to use the dependency as is, using --ignore-crystal-version
is enough. On the next shards release (that will be bundled at some point in 1.0.0-dev), #417 will be included at might be even easier to include them in the CI for nightlies.
As soon as there is a breaking-change in 1.0.0-dev that affect a dependency you will need to update the version restriction to branch.
Having some logic on shards to accept packages with crystal: 0.x
on 1.0.0-dev/1.0.0 will offer more confusion IMO. I think using --ignore-crystal-version
(or setting CRYSTAL_VERSION
) is good enough as a temporal solution while 1.0.0 si being developed.
Being able to override shards as in #412 will also offer a more fine grained alternative that will allow developers to pick branches for shards that are getting updates for next release.
Once 1.0.0 is released, the ecosystem should catch up, at worst pushing new mainteiners for abandoned shards.
In my opinion --ignore-crystal-version
is not very useful as a workaround. I run nightly tests to see that my shards are compatible with upcoming Crystal (and shards) releases. It needs to be as close as possible to the stable environment, just based on a more recent Crystal version. I don't expect users to install their shards with --ignore-crystal-version
, so to me it makes no sense to use it for nightly builds. I want to know if incompatible versions fail installation of dependencies before it becomes a problem.
It seems that some people currently tend to simply resort to --ignore-crystal-version
to fix their dependency resolution. That may be out of annoyance or because it's recommended.
However, I don't understand why this is encouraged. What's the point in having crystal version enforcement when everyone disables it?
It may be acceptable as a temporary solution in the approach of 1.0. But I can't see why we wouldn't have the same problem when we approach 2.0 and later major releases? I honestly don't expect we'd want such a massively annoying situation again.
And, again, it doesn't really help much because running --ignore-crystal-version
for nightlies doesn't tell you if installing without that flag would succeed.
I have come to the conclusion to treat crystal
version restriction mainly as a lower boundary of support level. I know my shard works at this version and I intend to support it (and at least its patch releases).
So currently, this is what I assign:
crystal: '>= 0.35.0'
I don't place an upper bound because:
< 2.0
would be sensible extension, but I'm not sure about it.The lower bound intended to express the intended support level. It doesn't necessarily mean it doesn't work below that, but it's just not tested and may fail.
That would be a use case for --ignore-crystal-version
if I want to get a shard working with an older crystal version (because I'm somehow stuck with that). Then you can justr install it and try. If it works, it's fine. If not, you'll notice.
The replies before have been focused on "mm maybe it's not so bad, maybe we can find a compromise, maybe we have to just stick through this"
But can someone clarify, what exactly is the advantage to preventing people from installing shards? There's only one possible advantage I can imagine, it's that possible errors will show up during the installation of a shard, rather than during first compilation.
There's no advantage from also asking library authors to do a meaningless bump for "certified working for 1.0.0", those that maintain their libraries will keep doing that anyway, and those that don't won't. So that is already just a disadvantage. Additionally, all non-root libraries and applications will also need to do a meaningless bump of deps just to get a release that includes the meaningless bump.
And libraries can very well keep working just fine without the certification, I have libraries that easily work on the entire range 0.25-0.35-1.0. Certainly agree with @straight-shoota, I had simply gone and updated all my libs to have >=
[whatever was there before]. That's the best the community can do with this kind of hand of cards.
Now, giving Shards a reputation that "you just always have to disable that check" maybe even by itself is not worth it.
Even shards' nightly test fails because of crystal version restriction: https://app.circleci.com/pipelines/github/crystal-lang/shards/564/workflows/b9287f8f-50be-4a68-93d9-a8284ca78a9e/jobs/1358
Hey guys! I know I'm late to the game here, but I wanted to chime with my own experience as a shard maintainer that may not follow the Crystal landscape as often as I should.
I recently ran into this exact issue here: https://github.com/jessedoyle/duktape.cr/pull/64.
My first thought was "there's no way that Crystal core would default compatibility of all shards implicitly to < 1.0.0
". After reading the discussion here, it turns out that assumption was incorrect.
I know there's arguments for both sides here, but I just wanted to share my experience. I do think the current behaviour is very surprising to developers.
The fallout of this is still ongoing, people are coming back to Crystal now that it's 1.0.0 and this is the first thing they're hit in the face with. I opened https://github.com/crystal-lang/shards/pull/493 to remove this check by default.
In the wild:
https://github.com/oprypin/crystal-chipmunk/runs/796810944?check_suite_focus=true#step:16:12
My shard became not installable as a dependency ever since crystal-1.0.0-dev.
I think that (despite @jhass hinting that this might be intentional), from the point of view of any user, this looks like a bug in Shards. Some things come to mind:
>= 0.25.1
and< 1.0.0
are conflicting?< 1.0.0
specified..?Repro: