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

Fix source code packaging #19

Merged
merged 47 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
706c072
Exclude "meta/Cargo.lock" from the packaged source code.
andreibancioiu Jan 19, 2023
2836c96
In the packaged source code file, sort entries by path (ascending).
andreibancioiu Jan 19, 2023
52db5b7
Improve unit tests.
andreibancioiu Jan 19, 2023
424fa64
Split tests, order files.
andreibancioiu Jan 19, 2023
af984f7
Include whole project, if necessary.
andreibancioiu Jan 19, 2023
e212710
Adjust condition for building a specific contract.
andreibancioiu Jan 19, 2023
6959c1b
Add extra tests.
andreibancioiu Jan 19, 2023
ef6a4bc
Bump version.
andreibancioiu Jan 19, 2023
ee8ac06
Handle both "elrond.json" and "multiversx.json".
andreibancioiu Jan 20, 2023
de60e98
Save a "context" name in the artifacts (to keep e.g. the Docker image…
andreibancioiu Jan 20, 2023
b81713e
Do not create zip archives of the source code anymore.
andreibancioiu Jan 20, 2023
63e8bc0
Add some test data (for contracts with local dependencies).
andreibancioiu Jan 20, 2023
3fe8b39
Rename, refactor, add source code size warning back.
andreibancioiu Jan 20, 2023
35d7417
Include local dependencies in packaged SRC.
andreibancioiu Jan 20, 2023
bbaf069
Add unit test.
andreibancioiu Jan 20, 2023
431ff55
Use "cargo metadata" to get local dependencies.
andreibancioiu Jan 20, 2023
4b7dba4
Handle recursive dependencies (code hash does not match).
andreibancioiu Jan 20, 2023
a4d7127
Cleanup before unwrap.
andreibancioiu Jan 20, 2023
dc815d4
Properly pass CONTEXT.
andreibancioiu Jan 20, 2023
7bf87a8
Sketch workflow for build and test.
andreibancioiu Jan 20, 2023
df35be2
Reproduce previous builds (as a test). Do not force CARGO_TARGET_DIR …
andreibancioiu Jan 21, 2023
485685b
Merge workflow steps.
andreibancioiu Jan 21, 2023
9e47c8d
Fix docker build for tests.
andreibancioiu Jan 21, 2023
c42c2c9
Re-create cargo lock.
andreibancioiu Jan 21, 2023
a484e3a
Test additional past builds.
andreibancioiu Jan 21, 2023
374f322
Add extra tests (past builds to reproduce).
andreibancioiu Jan 21, 2023
7b70a88
Add extra release to check.
andreibancioiu Jan 22, 2023
dde97f5
Add extra previous builds to reproduce (tests).
andreibancioiu Jan 22, 2023
8dea537
Update readme.
andreibancioiu Jan 22, 2023
e78718d
Add support script: linking deployed contracts to github releases.
andreibancioiu Jan 22, 2023
cfaf6bf
Bit of refactoring, code movement.
andreibancioiu Jan 22, 2023
c2998d8
Fix workflow trigger.
andreibancioiu Jan 22, 2023
ddd58a0
Adjust tests.
andreibancioiu Jan 23, 2023
6f2e54a
Add new integration test.
andreibancioiu Jan 23, 2023
7574933
Fix worflows for integration tests.
andreibancioiu Jan 23, 2023
cda63cc
Enable long integration tests.
andreibancioiu Jan 23, 2023
938765c
Refactor, cleanup tests.
andreibancioiu Jan 23, 2023
1cb3a47
Fix after self-review, fix de-duplication.
andreibancioiu Jan 23, 2023
2e1cd07
Ignore mock dependencies listed in cargo metadata.
andreibancioiu Jan 23, 2023
a77f632
Ignore mock packages.
andreibancioiu Jan 23, 2023
976f48e
Debugging.
andreibancioiu Jan 23, 2023
9131cbf
WIP: Cleanup workspace before starting to build (remove tests, dev-de…
andreibancioiu Jan 23, 2023
8ca509c
Some test optimizations etc.
andreibancioiu Jan 23, 2023
19f5a5b
Fix imports.
andreibancioiu Jan 23, 2023
06c3e73
Refactor, fix after self-review.
andreibancioiu Jan 23, 2023
2c327e4
Adjust versions
andreibancioiu Jan 23, 2023
28ec1fe
Merge pull request #20 from multiversx/debug-19
andreibancioiu Jan 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
name: Build & publish
name: Build & publish image

on:
workflow_dispatch:
release:
types: [published]

jobs:
push_to_registry:
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/run_long_integration_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Long integration tests

on:
workflow_dispatch:
pull_request:

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build image
run: |
docker buildx build --output type=docker --no-cache . -t sdk-rust-contract-builder:next -f ./Dockerfile

- name: Build
run: |
export PYTHONPATH=.
python ./integration_tests/test_previous_builds_are_reproducible.py --selected-builds "a.1" "a.2" "a.3" "b.1" "b.2" "b.3" "c.1" "c.2" "c.3" "c.4" "c.5" "d.1" "e.1"
25 changes: 25 additions & 0 deletions .github/workflows/run_regular_integration_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Regular integration tests

on:
workflow_dispatch:
pull_request:

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build image
run: |
docker buildx build --output type=docker --no-cache . -t sdk-rust-contract-builder:next -f ./Dockerfile

- name: Build
run: |
export PYTHONPATH=.
python ./integration_tests/test_project_folder_and_packaged_src_are_equivalent.py
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,6 @@ dmypy.json
typings/**

# Test data
testdata/**/output
testdata/input/extracted
testdata/output
testdata/rust
9 changes: 7 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
FROM ubuntu:22.04

# Constants
ARG VERSION_RUST="nightly-2022-12-08"
ARG VERSION_RUST="nightly-2022-10-16"
ARG VERSION_BINARYEN="105-1"
ARG VERSION_WABT="1.0.27-1"
# Normally, this should be "multiversx/sdk-rust-contract-builder:{{pyproject.toml:project:version}}"
ARG CONTEXT="multiversx/sdk-rust-contract-builder:v4.1.0"

# Install dependencies (including binaryen and wabt)
RUN apt-get update && apt-get install -y \
wget \
build-essential \
python3.10 python-is-python3 \
python3.11 python-is-python3 python3-pip \
binaryen=${VERSION_BINARYEN} \
wabt=${VERSION_WABT}

RUN pip3 install tomlkit==0.11.6

# Install rust
RUN wget -O rustup.sh https://sh.rustup.rs && \
chmod +x rustup.sh && \
Expand All @@ -25,6 +29,7 @@ COPY "multiversx_sdk_rust_contract_builder" "/multiversx_sdk_rust_contract_build
ENV PATH="/rust/bin:${PATH}"
ENV CARGO_HOME="/rust"
ENV RUSTUP_HOME="/rust"
ENV CONTEXT=${CONTEXT}
ENV PYTHONPATH=/

# Additional arguments (must be provided at "docker run"):
Expand Down
52 changes: 31 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,66 @@
# mx-sdk-build-contract
# mx-sdk-rust-contract-builder

Docker image (and wrappers) for reproducible contract builds (Rust). See [docs.multiversx.com](https://docs.multiversx.com/developers/reproducible-contract-builds/).

## Build the Docker image

We use `docker buildx` to build the image:

```
docker buildx build --output type=docker --no-cache . -t sdk-rust-contract-builder:next -f ./Dockerfile
```
docker buildx build --no-cache . -t sdk-rust-contract-builder:experimental -f ./Dockerfile

Maintainers can publish the image as follows:

```
docker buildx create --name multiarch --use

docker buildx build --no-cache --push --platform=linux/amd64,linux/arm64 . -t multiversx/sdk-rust-contract-builder:next -f ./Dockerfile

docker buildx rm multiarch
```

For the above to work properly, make sure to install `tonistiigi/binfmt` beforehand. Please follow the official Docker documentation [here](https://docs.docker.com/build/building/multi-platform/).

Though, note that currently (January 2023) we recommend against using the `linux/arm64` image for performing reproducible contract builds. This is because, in some (possibly rare) circumstances, a WASM binary generated on the `linux/amd64` image _might_ differ (at the bytecode level) from one generated on the `linux/arm64` image - probably due to distinct (unfortunate) bytecode-emitting logic in the Rust compiler.

## Build contract using the wrapper

Without providing `cargo-target-dir`:
If you are using a Mac with ARM64, we _recommend_ setting the following variable beforehand (contract builds will be slower, but this eliminates the risk of not being able to reproduce the build on Linux):

```
python3 ./build_with_docker.py --image=sdk-rust-contract-builder:experimental \
--project=~/contracts/reproducible-contract-build-example \
--output=~/contracts/output-from-docker
export DOCKER_DEFAULT_PLATFORM=linux/amd64
```

With providing `cargo-target-dir`:
Building from a project folder:

```
python3 ./build_with_docker.py --image=sdk-rust-contract-builder:experimental \
--project=~/contracts/reproducible-contract-build-example \
--output=~/contracts/output-from-docker \
--cargo-target-dir=~/cargo-target-dir-docker
python3 ./build_with_docker.py --image=sdk-rust-contract-builder:next \
--project=~/contracts/example \
--output=~/contracts/output-from-docker
```

Building from a packaged source code:

```
python3 ./build_with_docker.py --image=sdk-rust-contract-builder:experimental \
python3 ./build_with_docker.py --image=sdk-rust-contract-builder:next \
--packaged-src=~/contracts/example-0.0.0.source.json \
--output=~/contracts/output-from-docker
```

## Build contract using the Docker inner script

This is useful for useful for testing, debugging and reviewing the script.
## Run unit tests (without Docker)

```
export PROJECT=${HOME}/contracts/reproducible-contract-build-example
export OUTPUT=${HOME}/contracts/output
export CARGO_TARGET_DIR=${HOME}/cargo-target-dir
export PATH=${HOME}/multiversx-sdk/vendor-rust/bin:${HOME}/multiversx-sdk/wabt/latest/bin:${PATH}
export RUSTUP_HOME=${HOME}/multiversx-sdk/vendor-rust
export CARGO_HOME=${HOME}/multiversx-sdk/vendor-rust

pytest .
```

Build a project:
## Run integration tests (with Docker)

```
python3 ./build_within_docker.py --project=${PROJECT} --output=${OUTPUT} \
--cargo-target-dir=${CARGO_TARGET_DIR}
python3 ./integration_tests/test_previous_builds_are_reproducible.py --selected-builds "a.1" [...]
python3 ./integration_tests/test_project_folder_and_packaged_src_are_equivalent.py
```
2 changes: 1 addition & 1 deletion build_with_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def run_docker(
docker_mount_args.extend(["--volume", f"{packaged_src_path}:/packaged-src.json"])

if cargo_target_dir:
docker_mount_args += ["--volume", f"{cargo_target_dir}:/cargo-target-dir"]
docker_mount_args += ["--volume", f"{cargo_target_dir}:/rust/cargo-target-dir"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since /rust/cargo-target-dir is used in the Docker image.


docker_args = ["docker", "run"]

Expand Down
1 change: 1 addition & 0 deletions integration_tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__all__ = []
9 changes: 9 additions & 0 deletions integration_tests/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from pathlib import Path

DOWNLOADS_FOLDER = Path("./testdata/downloads").resolve()
EXTRACTED_FOLDER = Path("./testdata/input/extracted").resolve()
PARENT_OUTPUT_FOLDER = Path("./testdata/output").resolve()
CARGO_TARGET_DIR = Path("./testdata/rust/cargo_target_dir").resolve()
RUST_REGISTRY = Path("./testdata/rust/registry").resolve()
RUST_GIT = Path("./testdata/rust/git").resolve()
RUST_TMP = Path("./testdata/rust/tmp").resolve()
Loading