pistondevelopers / eco Goto Github PK
View Code? Open in Web Editor NEWA tool for reasoning about breaking changes in Rust ecosystems
License: Other
A tool for reasoning about breaking changes in Rust ecosystems
License: Other
Dev-dependencies are currently not supported.
Add basic support where the order is not changed, and dev-dependencies are only updated if the library needs update.
dependencies::Package::dev_dependencies
dependencies
dependencies
update::Package::dev_dependencies
update
Eco needs a model of how it knows when a library causes a breaking change, because all automated processes must be correct or have known error cases, which might be hard to figure out from the source. This issue is for tracking the model and proofs based on the planned design.
The definition of "breaking change" used here:
In summary, when a library is listed in the extract info, it is known whether the library will cause a breaking change or not:
might_cause_breaking_change(library) -> knowledge
([is_listed_in_extract_info] [:] true) -> [:] known
If a library is not listed in the extract info, it is not known whether it will cause a breaking change. It might be possible to detect whether it causes a dependency conflict, which is why the definition of "breaking change" does not include dependency conflicts. By design this desirable because:
The extract info tells which part of the ecosystem that we are interested in knowing about breaking changes. For each library, it is either listed in the extract info or not.
is_listed_in_extract_info(library) -> bool
For each library listed in the extract info, the newest version of the library is known because it is listed in the Cargo.toml given by the url:
know_newest_version(library) -> knowledge
([is_listed_in_extract_info] [:] true) -> [:] known
If we know the newest version, we can detect whether a breaking change occurs:
might_cause_breaking_change(library) -> knowledge
([know_newest_version] [:] X) -> [:] X
Since we know the newest version of libraries listed in the extract info, we know whether they might cause breaking changes:
might_cause_breaking_change([is_listed_in_extract_info] [:] true) -> [:] known
Needed by #19.
Should convert from meta data to Vec<Package>
.
I believe the same conversion code can be used for Package
when extracting from Cargo.toml.
"publish": false
tells that the version number of the package should not be updated.
This is a step toward doing automatic PR using update information.
The idea is that Eco could be part of another tool that did some automated tasks to keep an ecosystem healthy. By changing it into a library it can be reused in other projects.
main
to an example "piston"See #1
This should be limited to the part of the ecosystem we are interested in. The document does not necessarily contain all the dependencies the libraries have.
Example:
{
"pistoncore-input": {
"version": "0.4.0",
"dependencies": {}
},
"pistoncore-window": {
"version": "0.6.0",
"dependencies": {
"pistoncore-input": {
"version": "0.4.0"
}
}
},
"pistoncore-event_loop": {
"version": "0.7.0",
"dependencies": {
"pistoncore-input": {
"version": "0.4.0"
},
"pistoncore-window": {
"version": "0.6.0"
}
}
},
"piston": {
"version": "0.7.0",
"dependencies": {
"pistoncore-input": {
"version": "0.4.0"
},
"pistoncore-window": {
"version": "0.6.0"
},
"pistoncore-event_loop": {
"version": "0.7.0"
}
}
}
}
When a dependency version starts with "^" or ends with ".*", it means the same as removing this information before parsing the version number.
See #5
Add meta syntax for extracting information from Cargo.toml.
[dependencies.foo]
and [dependencies]
list)Sometimes updating is not possible, or you need to wait for merging. It would be nice to have a way to ignore the updates resulting from a specific dependency of a library, such that one can focus on the other updates.
Add "ignore-version": "0.2.0"` to extract information only if the current version number does not match the ignored version.
This way, if one sends a PR to update a library, one can add ignore-version
which will filter out updates until the PR gets merged.
Extract::override_version
with ignore_version
.package_data
if equal.Currently it prints out in generate_update_info_from
.
Currently the design of Eco solves the update problem for dependencies, but lacks a proper solution for dev-dependencies. In order to handle dev-dependencies we need a model of how they behave.
The ideal thing would be to recommend update actions that keeps a library from breaking the examples/tests/benchmarks (dev stuff).
A = has dev dependencies
B = has any dev dependendency depending on library
C = is impossible to avoid breaking dev stuff
D = all dev-dependencies have less or equal depth than the library
E = a dev-dependency is a hole
F = split update of dependencies and dev-dependencies
!A, !(B, C), D, !E, !F.
(B, C), A, !D, ?!E, F.
D, ?A, !(B, C), ?!E, !F.
E, A, ?!(B, C), !D, ?!F.
This uses a new version of the piston-meta language that is more readable.
When a breaking change occurs in the libraries listed in the extraction info, all dependency version conflicts can be solved by upgrading to the newest version, see #16.
When a library is not listed in the extraction info, a dependency version conflict might occur. I believe the right way to solve this is to use the newest version used by any dependency, because:
Also, a localized part of the ecosystem might use an older version of a library to speed up development for a time period. In this case it is desirable to have the easiest upgrade possible.
The only solution that satisfy these constraints is by upgrading to the newest version used by any dependency.
Eco has some dependencies that updates from time to time.
For example, the Github version contains breaking changes that are not yet released. Because of a breaking change in one of the dependencies, the library is published to crates.io with a patch update.
This library has recently been bumped to 0.1.0, so we need the analysis.
The extract list contains the packages in the ecosystem. It would be nice if you could print out a todo-list.
Sometimes multiple packages belong to the same repo, and in such cases it is desirable to group the updates together.
Some Cargo.toml files contains single line comments start with "#".
Can use a similar trick by replacing whitespace rules with a custom rule supporting comments, see https://github.com/bvssvni/math_notation/blob/master/assets/syntax.txt.
See #19
This algorithm is a bit tricky and requires some planning:
HashMap
storing new versions per library, then walk through ordered by dependency depth and detect whether any dependency needs update.Suggestion:
HashMap
named new_versions
.new_versions
.new_versions
(should be newer or equal).new_versions
if it does.These are the constraints satisfied by the suggested algorithm. The notation used is PistonDevelopers/piston#736.
Some variables are treated as functions of time X(t)
, where the final result is t
when all constraints are satisfied. This makes it easier to describe properties that hold for some but not all variables. When t
is not specified it means it is equal on both sides.
any_dependency_needs_update(library) -> bool
if any_dependency_needs_update([:] X(t)) {
any_dependency_needs_update([:] X(t + 1))
}
old_version(library) -> version
new_version(library) -> version
// Start with new version set to old version.
([:] X(0)) -> old_version([:] X(0))
new_version([:] X(t + 1)) = max(
if new_version([:] X(t)) = old_version([:] X(t))
& any_dependency_needs_update([:] X(t)) {
increment(new_version([:] X(t)))
} else {
new_version([:] X(t))
},
max_version_as_dependency([:] X(t))
)
increment(version) -> version
increment([:] X) > [:] X
max_version_as_dependency(library) -> version
max_version_as_dependency([:] X) <= old_version([:] X)
needs_update(library) -> bool
([:] X) -> old_version([:] X) < new_version([:] X)
([any_dependency_needs_update] [:] true) -> [:] true
The algorithm that generates the update info might overflow when dependencies are circular. This will happen in the depth_of
function. Currently this is invalid input.
The elmesque library uses piston_window
as dev-dependency, which is listed for update.
There are more libraries to add.
See #1
fn extract_dependency_info_from(extract_info: &str) -> Result<String, String>;
Move from the extract
module to dependencies::write
.
The dependencies information is generated from the extract
module, but will be needed in the update
module. Instead of using two different structures it seems to make sense to use one structure shared between the two modules. This could be added to its own dependencies
module.
dependencies
moduleextract::Package
to dependencies::Package
extract::Dependency
to dependencies::Dependency
See #1
This should follow JSON syntax like the other custom formats.
Example:
{
"piston2d-gfx_graphics": {
"order": 0,
"bump": {
"old": "0.4.0",
"new": "0.5.0"
},
"dependencies": {
"piston2d-graphics": {
"bump": {
"old": "0.4.0",
"new": "0.5.0"
}
}
}
}
}
See #1
Bump
structDependency
structPackage
structVec<Package>
Depth is given by if dependencies.len() == 0 { 0 } else { max_depth(dependencies) + 1 }
Currently it is not possible to simulate breaking changes because override-version
property in the extract format is ignored.
An external library that depends on a listed library will be assigned order 0. This leads to wrong update order. It is easy to fix, by adding the library to the extract list. Opened this issue to figure out whether something should be done to prevent this.
In the "freetype" example in the piston-examples repo, the new version was older than the old version:
"find_folder": {
"bump": {
"old": "0.2.0",
"new": "0.1.1"
}
}
Not sure right place to ask this and here seems as good as any.
Looking at a selection of Cargo.toml
files from across piston, they all appear to have declared specific versions of their dependencies. This is weird to me - I want to push out a new version of sdl2_window
that adds the new joystick events (so depends on pistoncore-input 0.7), but seems like I'll have to update virtually every project that depends on input since they're tied to 0.6. It seems that using more flexible dependencies (~> 0.7.0
) would make updates much easier.
eco
's output to sequence a release of the new sdl2_window
. Do I have to do them all in order? There are a lot...These are used by the asset_store library.
See #1
Could use JSON syntax for compability with other tools.
A simple way to start is to point directly to the Cargo.toml
:
pistoncore-input {
"url": "https://raw.githubusercontent.com/PistonDevelopers/piston/master/src/input/Cargo.toml"
}
pistoncore-window {
"url": "https://raw.githubusercontent.com/PistonDevelopers/piston/master/src/window/Cargo.toml"
}
pistoncore-event_loop {
"url": "https://raw.githubusercontent.com/PistonDevelopers/piston/master/src/event_loop/Cargo.toml"
}
piston {
"url": "https://raw.githubusercontent.com/PistonDevelopers/piston/master/Cargo.toml"
}
According to https://docs.npmjs.com/misc/semver when a dependency starts with >=
, breaking changes are allowed. For example, >=1.2.7
matches 2.5.3
. It means almost the same thing as *
except that a minimum version is required.
These dependencies can cause conflicts when the minimum version is newer than the other dependency versions. However, the update info should not be generated for such dependencies.
>=
when parsing version, such that the version information can be used.>=
.The syntax of all custom formats documents should be a subset of JSON. Adding a JSON meta syntax will make it easy to check this in the unit tests.
Currently it fetches them one by one, which is slow.
Dependencies with a "*" requirement accepts any version. It is not possible to derive any version information from it.
The interpretation of "*" is "breaking changes are allowed for this version". If a library has a such dependency there must be at least one other dependency that needs update in order to increment the version for the library.
When computing new versions for libraries, dependencies with "*" could be ignored, and no update information will be generated for such dependencies.
Currently it uses stderr_unwrap
which will print to standard error without returning the error message. The problem is that the message does not contain any information about the url or package name.
Announcement: https://users.rust-lang.org/t/the-libc-crate-is-now-at-v0-2-0/3509
This is for tracking issues with upgrading libc to 0.2.
Second phase:
The major usage of this tool will be to check if libraries are updated and what versions they should have when some of the dependencies have a breaking change.
An idea is to use piston_meta to decouple some steps, such that the data can be generated and tested in various ways:
There are 3 different custom formats:
extract_info
which tells where to get dependency_info
dependency_info
contains all information required to reason about the ecosystemupdate_info
contains actions that needs to be doneextract_info_from(extract_info) -> dependency_info
update_info_from(dependency_info) -> update_info
Some points:
Get rid of the unwraps.
Because of #17, it is necessary to know the dependencies not listed in the extract info to resolve dependency version conflicts.
When a library gets deprecated and replaced with another, it is currently not possible to discover which libraries that needs a replace.
Depends on PistonDevelopers/gfx_window_shared#7.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.