Skip to content

Commit

Permalink
find-cycles (aws#350)
Browse files Browse the repository at this point in the history
Add a tool by @rix0rrr to help find cycles.
Add instructions in CONTRIBUTING
  • Loading branch information
Elad Ben-Israel authored Jul 17, 2018
1 parent 41b8f3b commit 3ed832d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
18 changes: 17 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,22 @@ Guidelines:
`^1.2.3`). This enables non-breaking updates to automatically be picked up.
* Make sure `package-lock.json` files are included in your commit.

### Finding Dependency Cycles

You can use `find-cycles` to print a list of internal dependency cycles:

```shell
$ tools/find-cycles/find-cycles.sh
Cycle: @aws-cdk/iam => @aws-cdk/assert => aws-cdk => @aws-cdk/s3 => @aws-cdk/kms => @aws-cdk/iam
Cycle: @aws-cdk/assert => aws-cdk => @aws-cdk/s3 => @aws-cdk/kms => @aws-cdk/assert
Cycle: @aws-cdk/iam => @aws-cdk/assert => aws-cdk => @aws-cdk/s3 => @aws-cdk/iam
Cycle: @aws-cdk/assert => aws-cdk => @aws-cdk/s3 => @aws-cdk/assert
Cycle: @aws-cdk/assert => aws-cdk => @aws-cdk/cloudformation => @aws-cdk/assert
Cycle: @aws-cdk/iam => @aws-cdk/assert => aws-cdk => @aws-cdk/util => @aws-cdk/iam
Cycle: @aws-cdk/sns => @aws-cdk/lambda => @aws-cdk/codecommit => @aws-cdk/sns
Cycle: @aws-cdk/sns => @aws-cdk/lambda => @aws-cdk/codecommit => @aws-cdk/codepipeline => @aws-cdk/sns
```

### Updating all Dependencies

We use `npm update` to
Expand All @@ -223,4 +239,4 @@ We use `npm update` to
5. Now, run `./build.sh` again to verify all tests pass.
6. Submit a Pull Request.

[CHANGELOG]: [./CHANGELOG.md]
[CHANGELOG]: [./CHANGELOG.md]
46 changes: 46 additions & 0 deletions tools/find-cycles/find-cycles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python
import json
import sys
import collections
import pprint

def find(xs, x):
for i, value in enumerate(xs):
if x == value:
return i
return None

filenames = sys.argv[1:]

graph = collections.defaultdict(set)
for filename in filenames:
with file(filename) as f:
package_json = json.load(f)

for key in ['devDependencies', 'dependencies']:
if key in package_json:
graph[package_json['name']].update(package_json[key].keys())


checked = set()

# Do a check for cycles for each package. This is slow but it works,
# and it has the advantage that it can give good diagnostics.
def check_for_cycles(package, path):
i = find(path, package)
if i is not None:
cycle = path[i:] + [package]
print 'Cycle: %s' % ' => '.join(cycle)
return

if package in checked:
return

checked.add(package)

deps = graph.get(package, [])
for dep in deps:
check_for_cycles(dep, path + [package])

for package in graph.keys():
check_for_cycles(package, [])
4 changes: 4 additions & 0 deletions tools/find-cycles/find-cycles.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -euo pipefail
scriptdir="$(cd $(dirname $0) && pwd)"
python ${scriptdir}/find-cycles.py $(find . -name package.json | grep -v node_modules)

0 comments on commit 3ed832d

Please sign in to comment.