Skip to content
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

Cache Toolchain Version in Built Artifacts #457

Closed
dOrgJelli opened this issue Aug 31, 2021 · 4 comments
Closed

Cache Toolchain Version in Built Artifacts #457

dOrgJelli opened this issue Aug 31, 2021 · 4 comments
Assignees

Comments

@dOrgJelli
Copy link
Contributor

This is required to make sure the client doesn't try to use packages that aren't compatible with itself.

Maybe add a field to web3api.yaml?

@dOrgJelli
Copy link
Contributor Author

Client will define a lower bound version number that they're compatible with. Call this back_compat_version, The client will know what version of the toolchain it represents. Call this "current_version".

It's expected that client's support all packages built with toolchain versions that satisfy:
back_compat_version <= versions <= current_version

@dOrgJelli
Copy link
Contributor Author

An example of a change that creates a new back_compat_version can be seen here: https://github.com/polywrap/monorepo/pull/456/files#diff-0f970eebde2e4513f1ee2ae19de194ced30fb567a7eb023146801512c5932e7aL111

We are removing functionality that older modules required.

@pwvpwvpwv
Copy link

pwvpwvpwv commented Mar 30, 2022

A quick TLDR for the stuff below: we agree with Jordan about the need for versioning things to make sure the clients don't try to run wrappers that were built for old versions. The way we think that should be done is to version the Polywrap "runtime" and the CLI separately, and to include those versions in everything the toolchain touches so that anything that consumes wrappers/artifacts knows what is expected of it. We also think wrapper devs should be given the opportunity to specify what versions their wrappers work with, so that they can test them themselves and make sure things work the way they want them to.

Ideas

Versioning Strategies

As per semver convention, changes made to a contract can be divided into "breaking", "non-breaking", and possibly "trivial" changes (the last usually being reserved for documentation updates and such). [2] and [4] consider three classes of versioning strategies for handling these categories of changes:

  • Strict: no backward or forward compatibility, every change (breaking or otherwise) creates a standalone artifact version
  • Flexible: backwards compatibility is considered, but with no guarantee for forward compatibility
  • Loose: both backward and forward compatibility are considered

[4] suggests that the "flexible" strategy is the best because it offers the most compatibility to end-users while requiring the least amount of governance commitment from a project. We would tend to agree with this for the Polywrap project, while it is still in prealpha/alpha/beta (later stages should provide enough maturity for the project to be able to set reasonable expectations surrounding feature/contract lifetimes and when they might be deprecated). The "flexible" strategy also appears to be the approach that Jordan is proposing above with his back_compat_version schema, which suggests that this is the way to go. That being said, allowing end-users to specify a range of values themselves, or a list of compatible versions, may provide a better mechanism than simply specifying the lower bounded version, as it places the onus of specification on the wrapper developer, rather than on Polywrap (more on this below).
As an aside, it is possible to implement something like the "loose" strategy now, by simply capping all upper bounds on the next major breaking version (e.g. all products are versioned for x.0.0 <= x.y.z < (x+1).0.0).

What Actually Needs To Be Versioned?

Contracts. While the artifacts themselves can be versioned (e.g. FooWrapper v1.2.3) for the sake of dependency handling and such, it is actually the contracts that the Polywrap tooling provides (the interfaces of the CLI and SDK, as of right now) whose versioning we should be concerned about, as they are the entities that produce and consume the artifacts. As such, the artifacts should carry versioning information about what contracts they expect to be able to interact with, and the services that provide those contracts should be able to read and interpret those versions so that they know what to do with the wrapper.
The convenience of this convention is that it is very conducive to the open and distributed nature of the Polywrap project: if someone else creates a tool that produces/consumes wrappers, they only need to worry that they're meeting the contract which has that requested version; also, once the CLI is changed to use wrapper implementations for its commands, developers will be able to create service broker wrappers which can act as adapters for legacy wrappers that expect older versions of the CLI contract.

Impl

Toolchain

Clients/SDKs

Clients in different languages may have different versions, independent of the actual runtime version they implement. This is something that Polywrap should probably work to prevent, and we touch on this lightly in issue 32, but the general idea being that while the Go SDK may be at version 2 and implement version 3 of the Polywrap runtime, the JavaScript SDK may already be at version 8 since it is much older, and these different numbers may prove to be confusing to newcomers.

Each client should maintain knowledge of what runtime version(s) it supports, independent of its actual version, and have this be readily surfaceable at runtime. This can be included as a hardcoded value (or range) that is manually updated on each release, or it can be handled in a more complex manner down the line.

CLI

The CLI itself should likely have a version number as well. While the CLI offers build tools for creating wrapper artifacts, the version number that it assigns to those artifacts should likely be of the appropriate runtime version for which the wrapper was built — this keeps the SDKs from needing to know all the CLI versions that can build for it, and instead keeps them focused on which runtime they support. However, since the CLI also performs other functions, such as reading/writing from ENS, scaffolding new projects, etc., it should also have its own versioning chain that can be written to the various structures/artifacts it produces, other than the built wrappers.

The CLI should be aware of both its own version and which version it is able to build for. Both of these versions should be included in the wrapper manifests of wrapper artifacts it builds, and the CLI-specific version may need to be included in other output where it is relevant.

Toolchain

Finally, the toolchain itself may have named (or numbered) versions, which package up the underlying SDK + CLI combo as a single installable, with set known-compatible versions for each. To this end we should look towards the Rust toolchain environment, which itself derives from classic Linux toolchaining: Rust terms the "toolchain" to be composed of "components", each of which have their own versions; those components are then bundled up into a single "toolchain", which gets a name in the <channel>[-<date>[-<host>]] format, and is hosted publically for download.
For now, since there are only two major components in the Polywrap toolchain, it may suffice to simply place both version numbers where appropriate in the metadata of produced artifacts, and to keep in mind the idea of overall toolchain versioning for a later time when there may be more complex component relationships at play.

Toolchain versioning is not something we think Polywrap should be overtly concerned about, as it already handles major versioning jointly at the prealpha-level. This is something that, again, may change in the future, but for now should probably be held off on given the early stage of the project.

Wrappers

Wrappers should define what runtime(s) they are versioned for by giving a list/range. It will be up to the individual wrapper developers to test against various versions of the toolchain and make their claims about compatibility (this may be something to explore in the future with automated changelogs, but for now we should embrace common practices and let the authors themselves assume the burden of correctly versioning their "runtime dependency"). This gives wrapper developers the greatest freedom, while minimizing the compatibility commitments made by Polywrap, which should simplify governance and maintenance concerns at this early stage in the project.
Runtimes will then have the option to check every wrapper they load and reject it (or warn and ignore) if the version they implement doesn't provide the contract expected by the wrapper.

Wrappers should include the required runtime version field in their manifests and expect that SDKs may choose to reject them based on this field.

References

  1. Blake, D., Mozilla Corporation, & Rustup contributors. (2022). Concepts. In The Rustup Book (ch. 2). https://rust-lang.github.io/rustup/concepts/toolchains.html
  2. Erl, T., Karmarkar, A., Walmsley, P., Haas, H., Yalçinalp, L. Ü., Liu, K., ... & Pasley, J. (2008). Web service contract design and versioning for SOA (p. 486). New York: Prentice Hall.
  3. Novakouski, M., Lewis, G., & Anderson, W. (2012). Best practices for artifact versioning in service-oriented systems. Pittsburgh, PA: Carnegie-Mellon University Software Engineering Institute.
  4. Parameshwaran, S. (2013). Versioning Artifacts. In Oracle® Retail Functional Artifacts Guide (ch. 4). Oracle. https://docs.oracle.com/cd/E82085_01/140/funtional_artifacts_guide/or-fasg-versioning.htm

@dOrgJelli
Copy link
Contributor Author

This has been completed as part of this PR: #986

The version of the WRAP standard that's required by clients that run modules is stored within the wrap.info file. Its schema can be found here: https://github.com/polywrap/monorepo/tree/origin/packages/manifests/wrap/formats/wrap.info

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants