Skip to content

Commit

Permalink
Merge pull request #64 from multiversx/ensure-no-lock-changed
Browse files Browse the repository at this point in the history
Ensure no Cargo.lock changed during build
  • Loading branch information
andreibancioiu authored May 28, 2024
2 parents b84edab + c2d2e15 commit 3181fe0
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 6 deletions.
29 changes: 26 additions & 3 deletions integration_tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ def test_has_correct_packaged_source():
assert entry.is_test_file == ("test" in str(entry.path)), f"Unexpected is_test_file marker for: {entry.path}"


def test_fail_if_any_cargo_lock_is_missing():
workspace_parent = download_project_repository("https://github.com/multiversx/mx-contracts-rs/archive/refs/tags/v0.45.4.zip", "test_fail_if_any_cargo_lock_is_missing")
def test_fail_if_contract_cargo_lock_is_missing():
workspace_parent = download_project_repository("https://github.com/multiversx/mx-contracts-rs/archive/refs/tags/v0.45.4.zip", "test_fail_if_contract_cargo_lock_is_missing")
workspace = workspace_parent / "mx-contracts-rs-0.45.4"

output_folder = PARENT_OUTPUT_FOLDER / "test_fail_if_any_cargo_lock_is_missing"
output_folder = PARENT_OUTPUT_FOLDER / "test_fail_if_contract_cargo_lock_is_missing"
shutil.rmtree(output_folder, ignore_errors=True)
output_folder.mkdir(parents=True, exist_ok=True)

Expand All @@ -82,3 +82,26 @@ def test_fail_if_any_cargo_lock_is_missing():

assert code != 0
assert "Cargo.lock needs to be updated but --locked was passed to prevent this" in stderr


def test_fail_if_workspace_cargo_lock_is_missing():
workspace_parent = download_project_repository("https://github.com/multiversx/mx-contracts-rs/archive/refs/tags/v0.45.4.zip", "test_fail_if_workspace_cargo_lock_is_missing")
workspace = workspace_parent / "mx-contracts-rs-0.45.4"

output_folder = PARENT_OUTPUT_FOLDER / "test_fail_if_workspace_cargo_lock_is_missing"
shutil.rmtree(output_folder, ignore_errors=True)
output_folder.mkdir(parents=True, exist_ok=True)

# Remove a (required) Cargo.lock file
(workspace / "Cargo.lock").unlink()

(code, stdout, _) = run_docker(
project_path=workspace,
packaged_src_path=None,
contract_name="adder",
image="sdk-rust-contract-builder:next",
output_folder=output_folder
)

assert code != 0
assert "Cargo.lock file(s) have been created during build: ['/tmp/project/Cargo.lock']" in stdout
14 changes: 12 additions & 2 deletions multiversx_sdk_rust_contract_builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
from multiversx_sdk_rust_contract_builder.build_metadata import BuildMetadata
from multiversx_sdk_rust_contract_builder.build_options import BuildOptions
from multiversx_sdk_rust_contract_builder.build_outcome import BuildOutcome
from multiversx_sdk_rust_contract_builder.cargo_toml import \
get_contract_name_and_version
from multiversx_sdk_rust_contract_builder.cargo_toml import (
ensure_no_change_within_cargo_lock_files, gather_cargo_lock_files,
get_contract_name_and_version)
from multiversx_sdk_rust_contract_builder.codehash import \
generate_code_hash_artifact
from multiversx_sdk_rust_contract_builder.constants import (
Expand Down Expand Up @@ -44,6 +45,8 @@ def build_project(
# We copy the whole project folder to the build path, to ensure that all local dependencies are available.
project_within_build_folder = copy_project_folder_to_build_folder(project_folder, build_root_folder)

cargo_lock_files_before_build = gather_cargo_lock_files(project_within_build_folder)

for contract_folder in sorted(contracts_folders):
contract_name, contract_version = get_contract_name_and_version(contract_folder)
logging.info(f"Contract = {contract_name}, version = {contract_version}")
Expand Down Expand Up @@ -77,6 +80,13 @@ def build_project(

outcome.gather_artifacts(contract_build_subfolder, output_subfolder)

cargo_lock_files_after_build = gather_cargo_lock_files(project_within_build_folder)

ensure_no_change_within_cargo_lock_files(
files_before_build=cargo_lock_files_before_build,
files_after_build=cargo_lock_files_after_build
)

return outcome


Expand Down
53 changes: 52 additions & 1 deletion multiversx_sdk_rust_contract_builder/cargo_toml.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
from pathlib import Path
from typing import Tuple
from typing import List, Tuple

import toml

from multiversx_sdk_rust_contract_builder.errors import ErrKnown


class CargoLockFile:
def __init__(self, path: Path, content: str):
self.path = path
self.content = content


def get_contract_name_and_version(contract_folder: Path) -> Tuple[str, str]:
file = contract_folder / "Cargo.toml"
Expand All @@ -11,3 +19,46 @@ def get_contract_name_and_version(contract_folder: Path) -> Tuple[str, str]:
name = data["package"]["name"]
version = data["package"]["version"]
return name, version


def gather_cargo_lock_files(folder: Path) -> List[CargoLockFile]:
paths = sorted(list(folder.glob("**/Cargo.lock")))
files: List[CargoLockFile] = []

for path in paths:
content = path.read_text()
files.append(CargoLockFile(path, content))

return files


def ensure_no_change_within_cargo_lock_files(files_before_build: List[CargoLockFile], files_after_build: List[CargoLockFile]):
"""
Ensure there are no changes within Cargo.lock files during build.
Even if "--locked" is passed to "cargo build", it's still possible that Cargo.lock files are created (think of the Cargo.lock at the workspace level).
"""

paths_before_build = [file.path for file in files_before_build]
paths_after_build = [file.path for file in files_after_build]
new_paths = list(set(paths_after_build) - set(paths_before_build))
new_paths_strings = [str(path) for path in new_paths]
removed_paths = list(set(paths_before_build) - set(paths_after_build))
removed_paths_strings = [str(path) for path in removed_paths]

if new_paths:
raise ErrKnown(f"Cargo.lock file(s) have been created during build: {new_paths_strings}")

if removed_paths:
raise ErrKnown(f"Cargo.lock file(s) have been removed during build: {removed_paths_strings}")

changed_paths: List[Path] = []

for before, after in zip(files_before_build, files_after_build):
if before.content != after.content:
changed_paths.append(before.path)

changed_paths_strings = [str(path) for path in changed_paths]

if changed_paths:
raise ErrKnown(f"Cargo.lock file(s) have changed during build: {changed_paths_strings}")

0 comments on commit 3181fe0

Please sign in to comment.