Skip to content

ci: cargo-semver-checks#2946

Merged
apoelstra merged 2 commits intorust-bitcoin:masterfrom
storopoli:ci/cargo-semver-checks
Jul 5, 2024
Merged

ci: cargo-semver-checks#2946
apoelstra merged 2 commits intorust-bitcoin:masterfrom
storopoli:ci/cargo-semver-checks

Conversation

@storopoli
Copy link
Copy Markdown
Contributor

@storopoli storopoli commented Jul 1, 2024

  • Removes check-api (cargo-public-api)
  • Adds cargo-semver-checks

Note to Reviewers

There is a new script contrib/check-semver.sh that checks for semver breaks against master.
If it detects a breaking change it will create the .semver-break file.
If this file exists then we will add an API break label and a big comment to the PR saying:

🚨 API BREAKING CHANGE DETECTED

It reproduces the current behavior of cargo-public-api:

  • bitcoin:
    • all-features
    • no-default-features
  • base58ck:
    • all-features
    • no-default-features
  • bitcoin_hashes:
    • no-default-features
    • features alloc
  • bitcoin-units:
    • no-default-features
    • features alloc
  • bitcoin-io:
    • no-default-features
    • features alloc

Closes #1875.
Supersedes #2912.

Context

Our current test to check API breaks using cargo public-api is not "automated" per se.
It needs contributors to keep tabs on text files with function signatures and other things and forces reviewers to be the de facto API break detector tool.

The idea is to use the well-acclaimed and maintained cargo semver-checks that will do this automatically in CI.

@coveralls

This comment was marked as outdated.

@storopoli
Copy link
Copy Markdown
Contributor Author

@obi1kenobi, I think that for the two items in the TODO list above we cannot do it with the obi1kenobi/cargo-semver-checks-action action right?

I'd probably need to run cargo semver-checks with some customizations and extract the information,
then pipe it to actions/labeler right?

@obi1kenobi
Copy link
Copy Markdown
Contributor

To not fail the workflow, you could use GitHub Actions' continue-on-error argument: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepscontinue-on-error

The labeling workflow is not possible with the current action, since it always uses the version on crates.io as baseline, not the repo's main branch. That means that after you merge the first breaking change, all subsequent workflow runs until the next release will re-discover that breaking change since they will be comparing "PR to crates.io" not "PR to target branch." I want this to get solved in the action, but that's blocked on finding more funding right now. If you come up with a workflow you like, I'd love to see it and possibly even accept a PR to the action.

One more caveat: support for nightly Rust versions in cargo-semver-checks is best-effort and not guaranteed. The current beta and a range of stable versions are supported, as indicated in the release notes. This is not to say you can't use it with nightly, you just have to be careful when you bump nightly versions. I don't offer any SLA for nightly support without a formal support contract: nightly Rust can ship a new rustdoc JSON format at any time without warning and it's infeasible for me to offer any kind of SLA or guarantees for free.

@apoelstra
Copy link
Copy Markdown
Member

Sounds good. We'll dig into what's needed to use a different baseline. Presumably we won't be able to use the action, and instead will need to hack up some shell scripts to do it for us. This shouldn't be too bad. We have some experience with our current label-bot doing things like this.

@obi1kenobi
Copy link
Copy Markdown
Contributor

obi1kenobi commented Jul 1, 2024

Thank you, I really appreciate it!

cargo-semver-checks supports specifying a different baseline, so I imagine the work would be mostly around plumbing that through the action and figuring out how to connect the CLI to the labeling bot.

I've also wanted to make the action annotate the code: post notes or comments on specific lines where breakage happened. I'll describe the stumbling blocks I ran into, in case that's helpful:

  • GitHub's existing annotation support in actions only allows annotating the "new" code. This is fine for regular linters, but not great here: cargo-semver-checks may need to point to a function/struct/enum etc. that used to exist but has been deleted, which we cannot do within that GitHub capability.
  • Posting comments and setting labels seems to require elevated privileges compared to what PRs usually have. We don't want to run the action on the pull_request_target trigger, because a malicious PR coming from a fork could run an arbitrary build.rs script as part of cargo-semver-checks and steal credentials etc.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 2, 2024

  • Posting comments and setting labels seems to require elevated privileges compared to what PRs usually have.

What you need to do is somehow export the information to other actions and have a flag to not fail. Then other labeling action can take that and use it. Though to be strictly secure it'd need to be another job I think. (Not a big problem I guess.)

@storopoli
Copy link
Copy Markdown
Contributor Author

storopoli commented Jul 2, 2024

Apparently cargo semver-checks hardcodes stuff to the RUSTDOCFLAGS (check https://github.com/obi1kenobi/cargo-semver-checks/blob/5108eeeffaf424e8d1a0019534414e7f11276a66/src/rustdoc_cmd.rs#L111-L113).

And we need different stuff (see https://github.com/rust-bitcoin/rust-bitcoin-maintainer-tools/blob/3494ceec521cbc2cbe7e4b0d3fb9219a2164f57d/ci/run_task.sh#L277)

So, I will try to generate the JSON files manually and call cargo semver-checks to match only on these JSONs.

EDIT: In the shell script I can generate the JSON doc files with cargo doc then, I can go to master call cargo doc to generate JSON. Finally I call cargo semver-checks --baseline-rustdoc $JSON_MASTER --current-rustdoc $PR_HEAD_JSON. That should do it.

@apoelstra
Copy link
Copy Markdown
Member

@storopoli we only need those RUSTDOCFLAGS for a specific test (the one that looks for broken doc links). Fine to use different rustdoc flags for anything/everything else.

@obi1kenobi
Copy link
Copy Markdown
Contributor

obi1kenobi commented Jul 2, 2024

This is probably obvious and you were probably already planning to do what I recommend here, but it's important so mentioning it just in case:

I would recommend against reusing the rustdoc built in the existing build_docs_with_nightly_toolchain or build_docs_with_stable_toolchain steps you linked to.

I would strongly recommend reusing the exact RUSTDOCFLAGS that cargo-semver-checks is using if at all possible, or else you might get unexpected behavior out of the tool.

For example:

  • You don't want to semver-check with --cfg docsrs set, because that isn't the API that users of the crate actually use.
  • You don't want to remove --cap-lints=allow because then a rustdoc lint in an upstream crate can break your build.
  • You don't want to remove --document-private-items --document-hidden-items, since (extremely unintuitively!) semver-checking a public API in Rust requires knowing all items that exist in each module — including private or hidden ones — because sometimes adding a private type or even a private use import item can cause a major breaking change

@coveralls

This comment was marked as outdated.

@coveralls

This comment was marked as outdated.

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 2, 2024

Pull Request Test Coverage Report for Build 9766164784

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.004%

Totals Coverage Status
Change from base Build 9763162782: 0.0%
Covered Lines: 19510
Relevant Lines: 23505

💛 - Coveralls

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 2, 2024

  • You don't want to semver-check with --cfg docsrs set, because that isn't the API that users of the crate actually use.

It really shouldn't. We only use it to enable the unstable feature that says which items are activated by which features.

  • adding a private type or even a private use import item can cause a major breaking change

OMG 🤦‍♂️ 🤦‍♂️ 🤦‍♂️

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 2, 2024

Pull Request Test Coverage Report for Build 9766958169

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 2, 2024

Pull Request Test Coverage Report for Build 9767018028

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 3, 2024

Pull Request Test Coverage Report for Build 9774220698

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@storopoli

This comment was marked as resolved.

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 3, 2024

Pull Request Test Coverage Report for Build 9774697799

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You should generate these programmatically.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't follow. Programmatically means "in a way that follows a plan or uses a particular method".
That can be anything. Can you be more specific?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I believe he means "extract the names of the crates from the top-level Cargo.toml file".

@apoelstra
Copy link
Copy Markdown
Member

warning: /home/runner/work/rust-bitcoin/rust-bitcoin/bitcoin/Cargo.toml: version requirement 0.106.0+26 for dependency bitcoinconsensus includes semver metadata which will be ignored, removing the metadata is recommended to avoid confusion
error: cannot specify features for packages outside of workspace

I wouldn't worry about this warning. I wish we could silence it. It's true that the +26 provides no additional information to Cargo.toml but it does signal to the user that this is the version of bitcoinconsensus that has Bitcoin 26. I guess we could truncate the version and then move the full version to a comment, explaining why Cargo makes us do that, but come on.

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 3, 2024

Pull Request Test Coverage Report for Build 9779513941

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 3, 2024

Pull Request Test Coverage Report for Build 9779635068

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 3, 2024

Pull Request Test Coverage Report for Build 9779726987

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 3, 2024

I guess we could truncate the version and then move the full version to a comment, explaining why Cargo makes us do that, but come on.

I think the warning is correct. The metadata in the requirement field is noop, so putting it there is equivalent to writing a comment which doesn't look like a comment, so it's confusing. We can achieve the same by writing a comment and then whoever reads it know it's just a comment and they can learn the true version by running cargo tree.

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 3, 2024

Pull Request Test Coverage Report for Build 9779939590

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9766743966: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

Comment on lines 321 to 322
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Depending on the threat model, we can speed this up with:

Suggested change
- name: "Install cargo-semver-checks"
run: cargo install cargo-semver-checks --locked
- name: "Install cargo-binstall"
uses: cargo-bins/cargo-binstall@main
- name: "Binstall cargo-semver-checks"
run: cargo binstall cargo-semver-checks --no-confirm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it's fine. We're not checking the signatures/hashes of the source either.

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9784547300

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

2 similar comments
@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9784547300

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9784547300

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9784568584

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

2 similar comments
@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9784568584

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9784568584

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

tcharding
tcharding previously approved these changes Jul 3, 2024
Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

Awesome work man, I can see you put in a whole lot of effort! I have a few minor nits but I think we should merge as is and improve in follow ups if we want to, bash always has a few nits :)

To be explicit, and for other reviewers these are the issues I see that I think are ok to merge:

  • code duplication
  • code comments
  • I think bitcoin_hashes might end up being bitcoin-hashes in some file names

Thanks again @storopoli, props on this one.

@tcharding
Copy link
Copy Markdown
Member

This PR should probably also remove the api/ directory.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jul 4, 2024

Yeah, let's merge this ASAP. I'll review it later since removing api dir is a good idea and I'm exhausted now.

Jose Storopoli added 2 commits July 4, 2024 10:08
Removes check-api workflow, helper scripts, documentation, and files.
@storopoli
Copy link
Copy Markdown
Contributor Author

This PR should probably also remove the api/ directory.

Yes, good catch. Did this in the proper commit d9567b0.
This, by now, should be ready to review and merge.

@storopoli storopoli requested a review from tcharding July 4, 2024 10:09
@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9792465705

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

2 similar comments
@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9792465705

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 9792465705

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 83.014%

Totals Coverage Status
Change from base Build 9784338166: 0.0%
Covered Lines: 19524
Relevant Lines: 23519

💛 - Coveralls

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK bc2b980b10c94e2872ca1480eb11c7e0cb16b22e Looks great -- definitely want to circle back to improve the comment it posts, try to clean up some repeated code, and possibly add a larger feature matrix

Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

ACK eeae225

This is a great improvement, my review can be addressed later.

# and then using those files to check for breaking changes with
# cargo semver-checks.

set -euo pipefail
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I always read this as "euro" :D

# Run cargo doc with the cargo semver-checks rustdoc flags.
# We don't care about dependencies.
run_cargo_doc() {
RUSTDOCFLAGS="$RUSTDOCFLAGS" cargo +"$NIGHTLY" doc --no-deps "$@"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh, wait, does it catch public deps anyway or not?

# Hack to not fail on errors.
# This is necessary since cargo semver-checks will fail if the
# semver check fails.
# We check that manually later.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There's a less brittle hack for that: append || true at the end of the command.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah that was my initial implementation.

if ! [ -f semver-break ]; then
echo "No breaking changes found"
fi
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Now I really don't understand why it's done here and not after the check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is if all cargo semver-checks got a FAIL.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh, doing it in a loop would create the comment multiple times, right?

Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

ACK eeae225

@tcharding tcharding mentioned this pull request Jul 4, 2024
@apoelstra apoelstra merged commit 57f608f into rust-bitcoin:master Jul 5, 2024
@storopoli storopoli deleted the ci/cargo-semver-checks branch July 5, 2024 14:24
@tcharding
Copy link
Copy Markdown
Member

tcharding commented Jul 9, 2024

It reproduces the current behavior of cargo-public-api:

Damn, I missed this during review. This claim is not correct. Its missing "all features" for hashes, units, and io.

# Uses `CARGO` to generate API files in the specified crate.
#
# Files:
#
# - no-features.txt
# - alloc-only.txt
# - all-features.txt
generate_api_files() {
    local crate=$1
    pushd "$REPO_DIR/$crate" > /dev/null

    run_cargo --no-default-features | $SORT | uniq > "$API_DIR/$crate/no-features.txt"
    run_cargo --no-default-features --features=alloc | $SORT | uniq > "$API_DIR/$crate/alloc-only.txt"
    run_cargo_all_features | $SORT | uniq > "$API_DIR/$crate/all-features.txt"

    popd > /dev/null
}

Was there a reason for this @storopoli?

@storopoli
Copy link
Copy Markdown
Contributor Author

@tcharding no, my intention was to mimic what we did with cargo-public-api.
From my reading of the script we only checked:

  • bitcoin:
    • all-features
    • no-default-features
  • base58ck:
    • all-features
    • no-default-features
  • bitcoin_hashes:
    • no-default-features
    • features alloc
  • bitcoin-units:
    • no-default-features
    • features alloc
  • bitcoin-io:
    • no-default-features
    • features alloc

But yeah, I need to add the all-features to bitcoin_hashes bitcoin-units and bitcoin-io.
Thanks for pointing that out.

@tcharding
Copy link
Copy Markdown
Member

My list is not correct, the generate_api_files function I posted above was called for hashes, units, and io.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check for API breaking changes in CI

6 participants