crystal-lang / shards

Dependency manager for the Crystal language
Other
765 stars 102 forks source link

Notify users of deprecated/outdated package #579

Open dinkopehar opened 1 year ago

dinkopehar commented 1 year ago

NPM has support for Deprecating packages. Users are notified when their dependencies are outdated when using npm install.

It would be also nice to see this when using shards install. Not sure how this would be implemented, but something like:

  1. Check when did last commit happen of specified branch/tag. If it's more than X Months/ Years, notify end user.
  2. Something in shard.yml to state it's deprecated
  3. ???

For example, I see this repository https://github.com/kostya/myhtml is built on latest crystal, but the last commit was 2 years ago and it's dependencies are not maintained anymore.

Blacksmoke16 commented 1 year ago
  • Check when did last commit happen of specified branch/tag. If it's more than X Months/ Years, notify end user.

Definitely not this. No recent activity does not mean deprecated or that it won't work anymore. Nor can you can be sure that just because a shard is old it's abandoned, even without the owner explicitly saying so.

  • Something in shard.yml to state it's deprecated

Unlike NPM there is no central repository for shards so the approach of adding something into shard.yml would be the most straightforward way to do that. It would also allow shard aggregator sites to pick that up as well without needing to manually mark them as deprecated within each implementation.

The argument against this is that it would only handle the case of willingly deprecating, such as myhtml. Otherwise if someone abandons a shard, it's unlikely they're going to take the time to push up another commit/release a new version with that flag set or something.

The other argument against it is would it really bring that much value? The readme of myhtml is pretty clear thats its deprecated. And you're probably going to go look at the repo for a dependency before you install it, so having something there/archiving the repo would give you most of the benefit without touching shards itself.

dinkopehar commented 1 year ago

I wanted to state that lot of people are not aware of state of open source package. At first, they can check the package, see it's development and add it as dependency. Once the time has passed, and they start relaying on that package heavily, they will just blindly use shards install. They would not be aware of what happens to maintainer or will he ever maintain package again. This can make their application rely heavily on outdated package.


As far as I can see, these are mostly packages that still have crystal version specified 0.36 and below OR packages that have version from 1.x.x to 2.x.x .

EDIT: Maybe ability of addind @Deprecated annotation on module or when requiring it 😕

Blacksmoke16 commented 1 year ago

IMO it's the responsibility of the application owner to be aware of the dependencies of their application, including their maintenance status and latest version. Crystal isn't NPM in that installing a shard isn't going to also require thousands of other random dependencies. So I don't think it's that big of a deal to just be aware/stay up to date with the shards you're using.

By using a shard, you somewhat accept the risk that it could be abandoned or a future upgrade may have breaking changes that need to be dealt with. However, if the application/shard follow semver, as shards suggests, is pinning its dependencies, and not blindly updating, there isn't anything wrong with not upgrading past an older release of a shard, bar security patches or bug fixes you need. Outdated doesn't necessarily mean "no longer working", especially if it supports Crystal 1.0 as it means it should work on any 1.x release.

As far as I can see, these are mostly packages that still have crystal version specified 0.36 and below OR packages that have version from 1.x.x to 2.x.x .

In this case, if you try to install a shard whose crystal value doesn't accept the currently installed Crystal version, you do get a warning that it may not be compatible. E.g.

Shard "example-shard" may be incompatible with Crystal 1.7.3

But whats the problem with shards that have it set between 1.x.x and 2.x.x? That's the most real use case as there is no way to know if a shard will work against a future Crystal 2.x version until it actually is released. Of which it could always be updated to also allow 2.x if it's found that it is compatible.

EDIT: Maybe ability of addind @Deprecated annotation on module or when requiring it

https://crystal-lang.org/api/Deprecated.html already exists. But don't think it currently works for modules/classes? At least the quick test I did didn't produce any warnings.

dinkopehar commented 1 year ago

@Blacksmoke16 Maybe you and your team can take as idea and discuss Deprecated annotation to be enabled on Module/Class. I also tested it, it does not work with those.

Sija commented 1 year ago

It should work with classes 🤔 (docs are explicitly stating that too)

straight-shoota commented 1 year ago

@Blacksmoke16

IMO it's the responsibility of the application owner to be aware of the dependencies of their application, including their maintenance status and latest version.

True. But the ecosystem should help out with that. It's annoying if developers have to check all their dependencies manually whether they're still maintained. Tools like shards outdated exist to make this easier. When it's convenient to check dependency health, it's more likely that developers will do it regularly. Thus, I'm convinced that having good analytic tools should improve overall health in the ecosystem.

Unfortunately, the mechanism of shards makes it practically impossible to alter the metadata of a shard's release after it's been released. All information is included in the released commit. Changing that would require retagging, which is not recommended. A technical solution could be to yank all releases, but that's not really helpful either.

So basically the only process I could see to mark a release as deprecated would be to make a new release. That would not affect older releases, though. So it's maybe not that useful. Perhaps it could be worth considering some out-of-band mechanism to override the metadata of previous releases. For example, shards could look in HEAD (or some other location, such as a dedicated metadata branch) for override information about previous releases. They could be encoded in shard.yml or a separate file. It would be useful for marking previous releases as deprecated or yanked. Another use case for that would be altering version constraints of previous releases to express compatibility restrictions with dependencies that have only been discovered after the original release. For marking an entire shard as deprecated, on platforms such as GitHub the author can mark the repo as archived. Perhaps shards could be made aware of that and report it when installing a shard from an archived repo.

However, this entire process has some requirements, especially on the shard author's cooperation. They need to realize their shard is outdated and be willing and able to communicate that. There are more than enough cases where this will not play out, leaving shards practically abandoned but without any clear indication about it.

To cater for this, there needs to be a different mechanism that doesn't depend on the ability to edit the shard source. One method for that could be shard indices. https://shardbox.org for example allows marking a shard as archived. Then it becomes a community effort to identify and indicate abandoned shards. This information could be integrated into shards or another tool.

Metrics such as age, commit frequency, responsiveness on the issue tracker etc. can also helpful to determine the health of a dependency. But I don't think they can be useful for an automated, hard categorization. They're soft indicators. No activity doesn't necessarily mean a shard is abandoned. I think https://www.ruby-toolbox.com handles this in a nice way: Metrics are automatically calculated and associated with a red, yellow, green score. If a gem has lots of red metrics, it's definitely a sign to be careful about it. Naturally, this would be a feature that can be easily integrated into a shard index. But it could also work in a CLI tool.

dinkopehar commented 1 year ago

@Sija

@[Deprecated("Deprecation of MODULE")]
module Document
  @[Deprecated("Deprecation of CLASS")]
  class Image
    @[Deprecated("Deprecation of METHOD")]
    def url
      puts "http://dummy.io/image.png"
    end

    @[Deprecated("Deprecation of INITIALIZE")]
    def initialize
      @w = 1000
      @h = 1000
    end
  end
end

I'm only able to get Warnings on initialize and url method, not sure if those other 2 work.

straight-shoota commented 1 year ago

@[Deprecated] annotation is unrelated to shards. Let's keep that out of this discussion. It currently has no effect when used on types and constants (ref https://github.com/crystal-lang/crystal/issues/11043).