Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit e6f5f87

Browse files
authored
Relax dcou dep. in order-crates-for-publishing.py (#32432)
* Relax dcou dep. in order-crates-for-publishing.py * Comment, comment and comment... * Avoid early-abort and report all collected errors
1 parent 0b5421f commit e6f5f87

File tree

1 file changed

+61
-2
lines changed

1 file changed

+61
-2
lines changed

ci/order-crates-for-publishing.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,70 @@ def load_metadata():
2121
return json.loads(subprocess.Popen(
2222
cmd, shell=True, stdout=subprocess.PIPE).communicate()[0])
2323

24+
# Consider a situation where a crate now wants to use already existing
25+
# developing-oriented library code for their integration tests and benchmarks,
26+
# like creating malformed data or omitting signature verifications. Ideally,
27+
# the code should have been guarded under the special feature
28+
# `dev-context-only-utils` to avoid accidental misuse for production code path.
29+
#
30+
# In this case, the feature needs to be defined then activated for the crate
31+
# itself. To that end, the crate actually needs to depend on itself as a
32+
# dev-dependency with `dev-context-only-utils` activated, so that the feature
33+
# is conditionally activated only for integration tests and benchmarks. In this
34+
# way, other crates won't see the feature activated even if they normal-depend
35+
# on the crate.
36+
#
37+
# This self-referencing dev-dependency can be thought of a variant of
38+
# dev-dependency cycles and it's well supported by cargo. The only exception is
39+
# when publishing. In general, cyclic dev-dependency doesn't work nicely with
40+
# publishing: https://github.com/rust-lang/cargo/issues/4242 .
41+
#
42+
# However, there's a work around supported by cargo. Namely, it will ignore and
43+
# strip these cyclic dev-dependencies when publishing, if explicit version
44+
# isn't specified: https://github.com/rust-lang/cargo/pull/7333 (Released in
45+
# rust 1.40.0: https://releases.rs/docs/1.40.0/#cargo )
46+
#
47+
# This script follows the same safe discarding logic to exclude these
48+
# special-cased dev dependencies from its `dependency_graph` and further
49+
# processing.
50+
def is_self_dev_dep_with_dev_context_only_utils(package, dependency, wrong_self_dev_dependencies):
51+
no_explicit_version = '*'
52+
53+
is_special_cased = False
54+
if (dependency['kind'] == 'dev' and
55+
dependency['name'] == package['name'] and
56+
'dev-context-only-utils' in dependency['features'] and
57+
'path' in dependency):
58+
is_special_cased = True
59+
if dependency['req'] != no_explicit_version:
60+
# it's likely `{ workspace = true, ... }` is used, which implicitly pulls the
61+
# version in...
62+
wrong_self_dev_dependencies.append(dependency)
63+
64+
return is_special_cased
65+
66+
def should_add(package, dependency, wrong_self_dev_dependencies):
67+
related_to_solana = dependency['name'].startswith('solana')
68+
self_dev_dep_with_dev_context_only_utils = is_self_dev_dep_with_dev_context_only_utils(
69+
package, dependency, wrong_self_dev_dependencies
70+
)
71+
72+
return related_to_solana and not self_dev_dep_with_dev_context_only_utils
73+
2474
def get_packages():
2575
metadata = load_metadata()
2676

2777
manifest_path = dict()
2878

2979
# Build dictionary of packages and their immediate solana-only dependencies
3080
dependency_graph = dict()
81+
wrong_self_dev_dependencies = list()
82+
3183
for pkg in metadata['packages']:
3284
manifest_path[pkg['name']] = pkg['manifest_path'];
33-
dependency_graph[pkg['name']] = [x['name'] for x in pkg['dependencies'] if x['name'].startswith('solana')];
85+
dependency_graph[pkg['name']] = [
86+
x['name'] for x in pkg['dependencies'] if should_add(pkg, x, wrong_self_dev_dependencies)
87+
];
3488

3589
# Check for direct circular dependencies
3690
circular_dependencies = set()
@@ -41,8 +95,13 @@ def get_packages():
4195

4296
for dependency in circular_dependencies:
4397
sys.stderr.write('Error: Circular dependency: {}\n'.format(dependency))
98+
for dependency in wrong_self_dev_dependencies:
99+
sys.stderr.write('Error: wrong dev-context-only-utils circular dependency. try: ' +
100+
'{} = {{ path = ".", features = {} }}\n'
101+
.format(dependency['name'], json.dumps(dependency['features']))
102+
)
44103

45-
if len(circular_dependencies) != 0:
104+
if len(circular_dependencies) != 0 or len(wrong_self_dev_dependencies) != 0:
46105
sys.exit(1)
47106

48107
# Order dependencies

0 commit comments

Comments
 (0)