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

[move][cli] Support safe module republishing with breaking changes ch… #6753

Merged
merged 1 commit into from
Dec 18, 2020

Conversation

sblackshear
Copy link
Contributor

…ecks

  • If the CLI is trying to compile M.move, the logic for finding compilation deps now removes M.move from the deps list.
    More generally, any files directly or transitively reachable from the compilation targets are removed from the deps list. This
    fixes the annoying "duplicate definition" warning that you used to get when trying to re-publish a module
  • Before a move publish, the CLI runs the bytecode linking and data layout compatibility checks and reports an error if the
    code to be published could cause a breaking change to either linking or data layout
  • Added tests for republishing, running move check M.move after publishing M.move, and the breaking changes checks

@bors-libra bors-libra added this to In Review in bors Nov 25, 2020
@sblackshear
Copy link
Contributor Author

Can't add @mengxu-fb as a reviewer for some reason, but definitely want your opinion!

let deps = self.get_compilation_deps()?;
let to_compile_filenames = move_lang::find_move_filenames(to_compile, true)?;
// convert /path/to/File.move to File.move
let file_names: Vec<&str> = to_compile_filenames.iter().map(|s| get_stem(s)).flatten().collect();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe using a Set here instead of a Vec?

// exclude any filenames in `deps` that do not match File.move
// Note: this is best-effort in at least two ways:
// (1) It will wrongly filter modules in the same name under different addresses (e.g., 0x1/M.move and 0x2/M.move)
// (2) It will fail to filter modules with the same filename, but different module names (e.g., 0x1/M in both M1.move and M2.move)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(3) It may cause modules to be lost? (e.g., 0x1/M and 0x1/N in the deps' M.move but only 0x1/M in the updated M.move (although I guess this should not be an issue for stdlib modules).

@meng-xu-cs
Copy link
Contributor

Thanks Sam for pinning me here. The changes LGTM, and I'll leave it to others to stamp it :)

I think given what the CLI has, the file exclusion can only be best-effort and never perfect. I wish we had compiler-side change to support module updates directly, say, in, move_compile(targets: &[String], deps: &[String], ...) modules in targets supersedes modules found in deps.

Copy link
Contributor

@tzakian tzakian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just a couple small things

@@ -91,6 +93,11 @@ enum Command {
/// If set, modules will not override existing ones in storage
#[structopt(long = "no-republish")]
no_republish: bool,
/// By default, code that might cause breaking changes for bytecode
/// linking or data layout compatibility checks will not be published.
/// Set this flag to ignore breakng changes checks and publish anyway
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
/// Set this flag to ignore breakng changes checks and publish anyway
/// Set this flag to ignore breaking changes checks and publish anyway

let new_api = Module::new(m);
let compat = Compatibility::check(&old_api, &new_api);
if !compat.is_fully_compatible() {
println!("Breaking change detected--publishing aborted. Re-run with --ignore-breaking-changes to publish anyway.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly a larger question for the CLI as well, but I'm thinking this should probably be an eprintln! instead since this is a warning/error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good call. I'll do that for now, and in the future I'd like to get rid of all print's and turn them into writes to a buffer. I think we need to do this in order to run CLI tests concurrently in the same process.

@sblackshear
Copy link
Contributor Author

/land

@bors-libra bors-libra moved this from In Review to Queued in bors Dec 17, 2020
@bors-libra bors-libra moved this from Queued to Testing in bors Dec 17, 2020
bors-libra pushed a commit that referenced this pull request Dec 17, 2020
…ecks

- If the CLI is trying to compile `M.move`, the logic for finding compilation deps now removes `M.move` from the deps list.
More generally, any files directly or transitively reachable from the compilation targets are removed from the deps list. This
fixes the annoying "duplicate definition" warning that you used to get when trying to re-publish a module
- Before a `move publish`, the CLI runs the bytecode linking and data layout compatibility checks and reports an error if the
code to be published could cause a breaking change to either linking or data layout
- Added tests for republishing, running `move check M.move` after publishing `M.move`, and the breaking changes checks

Closes: #6753
@github-actions
Copy link

Cluster Test Result

Cluster test runner terminated
Logs: http://kibana.ct-2-k8s-testnet.aws.hlw3truzy4ls.com/app/kibana#/discover?_g=(time:(from:'2020-12-17T19:37:31Z',to:'2020-12-17T19:41:06Z'))
Dashboard: http://grafana.ct-2-k8s-testnet.aws.hlw3truzy4ls.com/d/2XqUIhnWz/performance?from=1608233851000&to=1608234066000
Validator 1 logs: http://kibana.ct-2-k8s-testnet.aws.hlw3truzy4ls.com/app/kibana#/discover?_g=(time:(from:'2020-12-17T19:37:31Z',to:'2020-12-17T19:41:06Z'))&_a=(columns:!(log),query:(language:kuery,query:'kubernetes.pod_name:"val-1"'),sort:!(!('@timestamp',desc)))

❗ Cluster Test failed - non-zero exit code for cti

Repro cmd:

./scripts/cti --tag land_815df951 --cluster-test-tag land_ef8273e6 -E RUST_LOG=debug -E BATCH_SIZE=15 -E UPDATE_TO_TAG=land_ef8273e6 --report report.json --suite land_blocking_compat

@bors-libra
Copy link
Contributor

💔 Test Failed - Build images and run cluster test

@bors-libra bors-libra moved this from Testing to In Review in bors Dec 17, 2020
@sblackshear
Copy link
Contributor Author

/land

@bors-libra bors-libra moved this from In Review to Queued in bors Dec 17, 2020
@sblackshear
Copy link
Contributor Author

/land

@bors-libra
Copy link
Contributor

@sblackshear 💡 This PR is already queued for landing

sblackshear added a commit to sblackshear/libra that referenced this pull request Dec 17, 2020
This command does a bunch of sanity checks to ensure that the storage directory is well-formed. For now:
- All modules verify
- All modules link
- All resources deserialize w.r.t the current version of their declaring module

It does this in the obvious way: iterating through the global storage, collecting each module/resource, and doing the check.
This is useful for detecting breaking changes (both code and data layout) after-the-fact, as well as bugs in the CLI.

I was motivated to create this check when I noticed a bug where `move publish` sometimes publishes a module `M` without publishing library modules.
If you run `move doctor` on such a state, it would catch the issue. I am planning to add `move doctor` to a bunch of the publish tests once I fix this bug.
It will also be useful for testing the `--ignore-breaking-changes` flag in diem#6753.
sblackshear added a commit to sblackshear/libra that referenced this pull request Dec 18, 2020
This command does a bunch of sanity checks to ensure that the storage directory is well-formed. For now:
- All modules verify
- All modules link
- All resources deserialize w.r.t the current version of their declaring module

It does this in the obvious way: iterating through the global storage, collecting each module/resource, and doing the check.
This is useful for detecting breaking changes (both code and data layout) after-the-fact, as well as bugs in the CLI.

I was motivated to create this check when I noticed a bug where `move publish` sometimes publishes a module `M` without publishing library modules.
If you run `move doctor` on such a state, it would catch the issue. I am planning to add `move doctor` to a bunch of the publish tests once I fix this bug.
It will also be useful for testing the `--ignore-breaking-changes` flag in diem#6753.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants