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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throw error if publishing a non-pre package that has pre-dependencies #333
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a few comments, hope this helps.
lib/mix/tasks/hex/publish.ex
Outdated
if !is_pre_version(meta) && has_pre_requirements(meta) do | ||
# Better wording would be nice... | ||
Mix.raise "Cannot publsh non-pre package that depends on a pre package" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exception message should begin with lowercase, wdyt about this: "A stable package release cannot have a pre-release dependency"
test/mix/tasks/hex/publish_test.exs
Outdated
@@ -192,4 +192,23 @@ defmodule Mix.Tasks.Hex.PublishTest do | |||
after | |||
purge [ReleaseMeta.Mixfile] | |||
end | |||
|
|||
test "create a non-pre package with pre-package deps" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about: create a stable package release with a pre-release dependency?
lib/mix/tasks/hex/publish.ex
Outdated
defp has_pre_requirements(meta) do | ||
meta.requirements | ||
|> Enum.map(fn(req) -> req[:requirement] end) | ||
|> Enum.any?(fn(req) -> req =~ "pre" end) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about other common suffixes as: -rc
, -alpha
, -beta
?. Also, you should consider the following:
A pre-release version number MAY be denoted by appending an arbitrary string immediately following the patch version and a dash. The string MUST be comprised of only alphanumerics plus dash [0-9A-Za-z-]. Pre-release versions satisfy but have a lower precedence than the associated normal version. Precedence SHOULD be determined by lexicographic ASCII sort order. For instance: 1.0.0-alpha1 < 1.0.0-beta1 < 1.0.0-beta2 < 1.0.0-rc1 < 1.0.0.
Source: http://semver.org/spec/v1.0.0.html#semantic-versioning-specification-semver
lib/mix/tasks/hex/publish.ex
Outdated
end | ||
|
||
defp is_pre_version(meta) do | ||
meta.version =~ "pre" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the same check above should be done like this:
version = Hex.Version.parse!(string)
version.pre != []
6ad1c88
to
0ed6c37
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good! We still need to correctly handle more complicated version requirements
lib/mix/tasks/hex/publish.ex
Outdated
meta.requirements | ||
|> Enum.map(fn(req) -> req[:requirement] end) | ||
|> Enum.any?(fn(req) -> is_pre_version(req) end) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lib/mix/tasks/hex/publish.ex
Outdated
@@ -190,6 +194,17 @@ defmodule Mix.Tasks.Hex.Publish do | |||
Hex.Shell.yes?("Proceed?") | |||
end | |||
|
|||
defp is_pre_version(version) do | |||
version = Hex.Version.parse!(version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version
should actually be version_requirement
for which there's a Hex.Version.parse_requirement!
. There's unfortunately no .pre
field on Version.Requirement
struct, we'd probably need to extract this information ourselves.
PS Having a function to determine if a version requirement allows prereleases could be a nice addition to Elixir. cc @ericmj
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, a quick'n'dirty way of determining this is simply doing:
String.contains?(requirement, "-")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, after @milmazz left his comment about matching other version suffixes I though exactly about this approach, but I'd prefer to use Hex's correct way over a hack :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We check the pre-release for each component of the requirement so: ~> 1.0-dev and ~> 2.0
does not match 2.1.0-dev
. But there is no way of knowing what versions we expect so I think the String.contains?
check is our best bet.
test/support/release_samples.ex
Outdated
defmodule ReleasePreDeps.Mixfile do | ||
def project do | ||
[app: :release_b, description: "bar", version: "0.0.1", | ||
deps: [{:ex_doc, "0.0.1-pre"}], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please change to ~> 0.0.1-pre
Oh, btw: IMHO we should warn (instead of throwing an error) to give more flexibility to folks but I don't have a strong opinion about it. |
I think we should error but allow an override flag. In my experience people don't read the warnings on |
3960bf6
to
4d821bf
Compare
@ericmj I added a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fteem I've spoken with @ericmj about this issue and we've decided that it would be better to display an error and not allow --force
flag in this situation. I think it would be a reasonable assumption that a stable packages can depend only on other stable ones. If someone needs to depend on a pre-release version then that should be a pre-release as well. We could revisit this decision if someone comes up with a use case.
Sorry for going back'n'forth; do you mind updating the PR accordingly?
A use case for depending on pre-releases that happened in the past with ecto, is that you accept versions of the dependency since that beta release, but later stable releases are fine too. SemVer is all about expressing minimal requirements, so it might make sense in that context. Example: https://hex.pm/packages/ecto/2.0.6 depends on sbroker Another case is preparing for a release of a new version of "parent" package by allowing prerelease, e.g To sum up: I don't agree with such a warning/error. |
@michalmuskala the question is: if your software depends on beta software, can your software be production ready then? I would likely to at least put a blocker on front on this. In regards to |
If we add an override it would need to be an override flag specific to this case, for example
If users need the pre-release they have the option to add overrides for this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move this check to build.ex where we have the other package validation: https://github.com/hexpm/hex/blob/master/lib/mix/hex/build.ex#L68
lib/mix/tasks/hex/publish.ex
Outdated
@@ -190,6 +190,24 @@ defmodule Mix.Tasks.Hex.Publish do | |||
Hex.Shell.yes?("Proceed?") | |||
end | |||
|
|||
defp stable_release?(build, opts) do | |||
if !pre_requirement?(build.meta.version) && has_pre_requirements?(build.meta) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are working with booleans we can change this to not pre_requirement?(build.meta.version) and has_pre_requirements?(build.meta)
.
lib/mix/tasks/hex/publish.ex
Outdated
false | ||
end | ||
true | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this function raises and we don't care about the return value we can remove the booleans and change the name to check_pre_releases
.
This function will raise an error if the package is stable but it has dependencies on pre-release packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. Travis errors seem unrelated.
Thanks @fteem! |
Took a quick shot at #320 and I'd like some feedback because I think it needs more polishing. Also, should it throw an error or just show a warning? Fire away! 馃槂