You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: policy/haskell/packaging/versioning.md
+46-52Lines changed: 46 additions & 52 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,42 +4,31 @@ TODO: need to decide on a versioning policy
4
4
5
5
## Version bounds
6
6
7
-
**Scope**
7
+
### Scope
8
8
9
9
Library components of packages which are intended to be [distributed via a package repository](./distribution.md) MUST follow this policy.
10
10
Non-library components of such packages MUST also do so if it is anticipated that they will be used downstream.
11
11
12
12
(Inversely: components of packages which are not intended to be distributed, or non-library components of packages which are not intended to be used downstream do NOT need to follow this policy).
13
13
14
-
**Known-bad bounds**
14
+
#### Examples
15
15
16
-
Version bounds (both upper and lower) MUST be included when they exclude versions of dependencies that the package is known not to work with.
17
-
In addition, if it is discovered that a version of a dependency does not work with a version of the package that has been released to a package repository, then the package maintainer SHOULD revise the released version to include the new bound.
18
-
19
-
**Speculative upper bounds**
20
-
21
-
A package MAY include an upper bound that excludes the next major version of a dependency, even if it is not known whether the next major version will break the package (e.g. because it has not been released yet).
22
-
23
-
**Cardano dependencies**
24
-
25
-
A package MUST pin the major version of any Cardano package that it depends on.
26
-
27
-
**Intra-repository dependencies**
16
+
Package `pkg-a` contains a test suite and also an executable that is used to inspect binary blobs that can be produced by using `pkg-a`.
17
+
The test suite is not intended to be used downstream, but the executable is, since it can be helpful for users to diagnose the products of `pkg-a`.
18
+
Hence the test suite does not need bounds, but the executable does.
28
19
29
-
A set of packages defined in the same source repository MUST include version bounds which are as tight as necessary to ensure that they function correctly when distributed via a package repository.
30
-
Typically this will mean pinning the major version.
20
+
#### Rationale
31
21
32
-
**Implied bounds**
22
+
Non-library components are much less critical, because they cannot be depended upon, and it is rarer that someone will want to e.g. run the tests or benchmarks for an upstream package.
23
+
However, it can still be the case that this happens, especially for executables, which are sometimes explicitly intended to be used by downstream users.
24
+
For this reason we tie the choice over whether to include bounds to the decision of the maintainer over whether the component is intended to be used downstream.
33
25
34
-
A component MAY omit bounds that it is otherwise required to have if those bounds are strictly implied by other dependencies that the package has within the same source repository.
26
+
### Known-bad bounds
35
27
36
-
### Examples
28
+
Version bounds (both upper and lower) MUST be included when they exclude versions of dependencies that the package is known not to work with.
29
+
In addition, if it is discovered that a version of a dependency does not work with a version of the package that has been released to a package repository, then the package maintainer SHOULD [publish](./distribution.md) a revision of the released version to include the new bound.
37
30
38
-
**Using version bounds**
39
-
40
-
Package `pkg-a` contains a test suite and also an executable that is used to inspect binary blobs that can be produced by using `pkg-a`.
41
-
The test suite is not intended to be used downstream, but the executable is, since it can be helpful for users to diagnose the products of `pkg-a`.
42
-
Hence the test suite does not need bounds, but the executable does.
31
+
#### Examples
43
32
44
33
**Discovering an incompatible version**
45
34
@@ -53,54 +42,59 @@ This fails, so the developer either:
53
42
The developer of package `pkg-c`, which depends on `pkg-a-M`, tries to build with `pkg-b-N`.
54
43
This fails when building `pkg-a`, so the developer of `pkg-c` notifies the developer of `pkg-a`.
55
44
The developer of `pkg-a` then:
56
-
1.Revises`pkg-a-M` to have a bound of `pkg-b < N`; and
45
+
1.Publishes a revision`pkg-a-M` to have a bound of `pkg-b < N`; and
57
46
2. Adds a bound of `pkg-b < N` to the development branch of `pkg-a` if it still applies.
58
47
59
-
**Setting version bounds within a repository**
60
-
61
-
Packages `pkg-a` and `pkg-b` are defined in the same source repository, and `pkg-a` depends on `pkg-b`.
62
-
`pkg-a` is at version 1.1.2, `pkg-` is at version 2.4.3, and they both follow the PVP.
63
-
Then `pkg-a` should bound its dependency on `pkg-b` to `pkg-b == 2.4.*`
64
-
65
-
**Omitting implied bounds**
66
-
67
-
Package `pkg-a` has both a library component and an executable component, both of which are used downstream.
68
-
Both components depend on `pkg-b-N`, and do not work with `pkg-b-(N+1)`, and the executable depends on the library.
69
-
In this case it is acceptable to only put a `pkg-b < N+1` bound on the library, because the executable component strictly depends on the library component of the same version, and the library component has the bound.
70
-
71
-
### Rationale
72
-
73
-
**Scope**
74
-
75
-
Non-library components are much less critical, because they cannot be depended upon, and it is rarer that someone will want to e.g. run the tests or benchmarks for an upstream package.
76
-
However, it can still be the case that this happens, especially for executables, which are sometimes explicitly intended to be used by downstream users.
77
-
For this reason we tie the choice over whether to include bounds to the decision of the maintainer over whether the component is intended to be used downstream.
78
-
79
-
**Known-bad bounds**
48
+
#### Rationale
80
49
81
50
Excluding dependency versions which are *known* not to work is a cheap way to convey information to downstream users.
82
51
It means that if they try to use the non-working version then they will get a solver error from cabal, instead of a compilation error.
83
52
It is common to discover this kind of version incompatibility information during development, and so this policy primarily insists that such information be recorded mechanically so that other people benefit from it.
84
53
85
-
**Speculative upper bounds**
54
+
### Speculative upper bounds
55
+
56
+
A package MAY include an upper bound that excludes the next major version of a dependency, even if it is not known whether the next major version will break the package (e.g. because it has not been released yet).
57
+
58
+
However, for any Cardano dependencies, a package MUST include an upper bound that excludes the next major version of the dependency pin, and SHOULD pin it to a single major version.
59
+
60
+
#### Rationale
86
61
87
62
Speculative upper bounds are controversial.
88
63
They have advantages (ensure that users get a working (if old) build plan; robustness against future changes), and disadvantages (often overly cautious; require large amounts of bound-relaxing to allow even "safe" new major versions).
89
64
There is no consensus amongst the Cardano engineering community about which is preferable, so we simply note that either approach is acceptable.
90
65
91
-
**Cardano dependencies**
92
-
93
-
Cardano packages themselves typically both a) make frequent breaking changes and b) have important behavioural differences between major versions.
66
+
However, Cardano packages themselves typically both a) make frequent breaking changes and b) have important behavioural differences between major versions.
94
67
For this reason we recommend that projects explicitly pin the major version of any Cardano packages that they depend on.
95
68
96
-
**Intra-repository dependencies**
69
+
### Intra-repository dependencies
70
+
71
+
A set of packages defined in the same source repository MUST include version bounds which are as tight as necessary to ensure that they function correctly when [distributed](./distribution.md) via a package repository.
72
+
It is not possible to give a fully-general rule for what bounds to use, but assuming that the packages are following something like PVP, typically pinning the major version is the right thing to do.
73
+
74
+
#### Examples
75
+
76
+
Packages `pkg-a` and `pkg-b` are defined in the same source repository, and `pkg-a` depends on `pkg-b`.
77
+
`pkg-a` is at version 1.1.2, `pkg-b` is at version 2.4.3, and they both follow the PVP.
78
+
Then `pkg-a` should bound its dependency on `pkg-b` to `pkg-b == 2.4.*`
79
+
80
+
#### Rationale
97
81
98
82
Within a single source repository, packages are usually built with all the packages taken from a single commit of the source repository.
99
83
When the packages are built from a package repository, then cabal may try to build them with _different_ versions, so long as the bounds are satisfied.
100
84
For this reason it is important to have tight enough bounds on packages which are defined in the same source repository.
101
85
Typically it should be enough to pin the major version.
102
86
103
-
**Implied bounds**
87
+
### Implied bounds
88
+
89
+
A component MAY omit bounds that it is otherwise required to have if those bounds are strictly implied by other dependencies that the package has within the _same_ source repository.
90
+
91
+
### Examples
92
+
93
+
Package `pkg-a` has both a library component and an executable component, both of which are used downstream.
94
+
Both components depend on `pkg-b-N`, and do not work with `pkg-b-(N+1)`, and the executable depends on the library.
95
+
In this case it is acceptable to only put a `pkg-b < N+1` bound on the library, because the executable component strictly depends on the library component of the same version, and the library component has the bound.
96
+
97
+
#### Rationale
104
98
105
99
It is common to have a repository which has many components/packages depending on some other package P.
106
100
It is tedious to require _every_ use of P to be well-bounded, especially since the components/packages in a repository should have tight bounds on each other, such that in practice bounding a single use of P should be enough to fix it for every package in the repository.
0 commit comments