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

feat!: v0.4.0 rewrite #202

Merged
merged 33 commits into from
Oct 7, 2024
Merged

feat!: v0.4.0 rewrite #202

merged 33 commits into from
Oct 7, 2024

Conversation

beeb
Copy link
Collaborator

@beeb beeb commented Sep 29, 2024

Version 0.4.0 marks a big step in the evolution of the soldeer codebase and implements many new features and improvements compared to previous releases. Below are the main points.

New code structure

The codebase has been split into 3 crates to enable integration of the soldeer core logic and CLI commands with other applications.

  • soldeer-core: the core functionality of soldeer. Things like reading and writing config files, lock files, interacting with the registry API and more. At the moment, logging is gated behind a cli feature flag.
  • soldeer-commands: high-level clap commands which can be used to implement a CLI tool. This is meant to be used by forge and the soldeer CLI.
  • soldeer: this is the standalone soldeer CLI application

In the future, I would like to further reduce the coupling between the soldeer-core crate and cliclack UI library, so that logging can be made agnostic of the (T)UI, but still be integrated nicely with it.

Version requirement specifiers

Dependencies were previously specified with at least a name and a version. Starting with this release, the version can be a version requirement specifier. The format follows the semver::VersionReq comparator specification, with the notable exception that the absence of an operator is considered to mean "exact" (similar to what solidity does).

Remappings format

In remappings, the default behavior is to include the version requirement string as a suffix to the left-hand side path. As an example, this enables the following:

[profile.default]
remappings = [
    "forge-std-1/=dependencies/forge-std-1.9.2/",
    "@openzeppelin-contracts-5/=dependencies/@openzeppelin-contracts-5.0.2/",
    "@openzeppelin-contracts-legacy/=dependencies/@openzeppelin-contracts-4.9.6/"
]

[dependencies]
forge-std = "1"
"@openzeppelin-contracts" = "5"
"@openzeppelin-contracts-legacy" = "4.9.6"

Remappings customization is now also handled properly, meaning that the left-hand side part can be customized to anything, which won't get overwritten when commands are ran without the --regenerate-remappings option. The right part can likewise be customized to include additional path segments after the dependency's directory. Examples:

[profile.default]
remappings = [
    "forge-std/=dependencies/forge-std-1.9.2/src/",
    "@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.0.2/contracts/",
    "@openzeppelin/contracts-legacy/=dependencies/@openzeppelin-contracts-upgradeable-4.9.6/contracts/"
]

New progress and prompts UI

The UI now uses cliclack to display progress and prompt the user for information. This is a significantly nicer experience than previously.

Improved install command

The install command now avoids to perform useless work by checking already installed dependencies and skipping associated downloads. For git dependencies, most operations leverage available git commands to avoid unnecessary clones.

Each dependency is installed in parallel, with more pipelining and thus a shorter total install time even if all dependencies must be installed.

Improved update command

Previously the update command was not performing according to user expectations. Now, the command updates dependencies which satisfy these requirements:

  • HTTP dependencies without a custom URL (from soldeer.xyz)
    • If the version requirement allows for multiple versions (e.g. 5 or ^5.0.0 or >=5.0.0) and
    • If all registry versions for the dependency are semver-compatible
  • Git dependencies with a branch identifier or no identifier (default branch)

The lockfile stores the exact installed version so that installs are reproducible. When the update command is ran, the lockfile is updated with the new versions.

Improved init command

The init command is now smarter and does slightly more:

  • Prompt the user to chose a config location for the dependencies
  • Create the dependencies dir
  • Add and install the forge-std dependency
  • Remove the git submodules and lib folder
  • Create the lockfile
  • Create the remappings
  • Add the dependencies folder to the .gitignore.

New lockfile format

The new lockfile format has differentiated entries for Git vs HTTP dependencies, allowing for a more concise and explicit representation. For HTTP dependencies, the zip archive checksum is stored and checked upon downloading. If the hash is different, installation is aborted. Likewise, the unzipped dependency is hashed upon installation and checked to avoid re-installing an existing dependency.

New test suite

All tests have been rewritten to enable running them in parallel. All IO side effects are contained to special temporary folders thanks to testdir. API mocking is performed with mockito and environment variables are mocked with temp-env.

The new suite runs significantly faster than the old one and can be efficiently parallelized with cargo-nextest, which is the recommended way to run them.

All tests are now ran in CI on Linux, macOS and Windows.

Various fixes and performance improvements

Various bugfixes have been implemented during the refactor, either as a result of the change in architecture or because they showed up in unit/integration tests. Some functions have been refactored to improve performance and parallelism.

Closes #188
Closes #182
Closes #181
Closes #156
Closes #155
Closes #153
Closes #152
Closes #144
Closes #138
Closes #134
Closes #120
Closes #108
Closes #46

beeb and others added 29 commits September 6, 2024 02:19
0.4.0 rewrite, more modular more awesome thanks to @beeb
* docs(core): document `auth` and `config` modules

* ci: add doctests
* docs(core): document `auth` and `config` modules

* ci: add doctests

* refactor(core): move integrity checksum type to utils

* docs(core): download module

* docs(core): download module

* docs(core): add documentation

* docs(core): add docs

* docs(core): typo

* docs(core): rephrase

* docs(core): install

* docs(core): typo
* docs(core): document `auth` and `config` modules

* ci: add doctests

* refactor(core): move integrity checksum type to utils

* docs(core): download module

* docs(core): download module

* docs(core): add documentation

* docs(core): add docs

* docs(core): typo

* docs(core): rephrase

* docs(core): install

* docs(core): typo

* docs(core): install mod

* docs(core): lock module

* docs(core): various

* refactor(commands): move push zip file path logging to commands crate

* docs(core): push mod

* fix(core): missing import

* docs(core): registry

* docs(core): add missing item

* docs(core): remappings

* docs(core): update

* docs(core): utils
* test(commands): init integration tests
* refactor(commands)!: rename `Subcommands` to `Command`

* test(commands): add integration tests for install command

* refactor(core)!: zip download path clarification

The zip is now downloaded inside the folder indicated by the argument to `download_file` and the filename can be chosen by the caller.
* test(commands): add integration tests for uninstall

* test(commands): add integration test for config in foundry file

* test(commands): add test for remappings in foundry file

* test(commands): add uninstall test with foundry config
* feat(core): improve remappings matching

Existing remappings can now be kept even during an update which changes the version string of the dependency folder.

* fix(core): remappings rewriting on windows
* feat(core): improve remappings matching

Existing remappings can now be kept even during an update which changes the version string of the dependency folder.

* fix(core): updating git dependencies

Updating git dependencies which should follow a branch did not work because we check out a given commit. This has been fixed.
Signed-off-by: Valentin B. <[email protected]>
perf: lock-free synchronization, add rayon
* (Ehancement) Add Banner
- Display banner with useful information

* Update crates/cli/src/main.rs

Signing off , since there is no action i need to perform

Co-authored-by: Valentin B. <[email protected]>
Signed-off-by: xyizko <[email protected]>

---------

Signed-off-by: xyizko <[email protected]>
Co-authored-by: Valentin B. <[email protected]>
* test(commands): integration tests for push

* chore: remove file

* test(commands): add integration tests

* test(commands): add integration test

* test(commands): add assert
@beeb beeb marked this pull request as ready for review September 29, 2024 18:09
@beeb beeb changed the title feat: v0.4.0 rewrite feat!: v0.4.0 rewrite Sep 30, 2024
@mario-eth mario-eth self-requested a review October 3, 2024 06:33
beeb added 3 commits October 3, 2024 01:41
This function should only attempt to match a version to a version requirement if both can be parsed
Also added extra tests
The tests for the `push` command were changing the current directory
which lead to race conditions when run with `cargo test`.
`cargo-nextest` does not seem to suffer from this.
@mario-eth mario-eth merged commit 6dd0d97 into main Oct 7, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment