Skip to content

Commit

Permalink
Merge pull request #1 from ElrondNetwork/move-v1-from-original-repo
Browse files Browse the repository at this point in the history
Add files for V1.
  • Loading branch information
andreibancioiu authored Oct 11, 2022
2 parents b0e78cf + 4b471f7 commit 0c0b570
Show file tree
Hide file tree
Showing 5 changed files with 491 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Build & publish

on:
workflow_dispatch:

jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v2

# https://stackoverflow.com/questions/32113330/check-if-imagetag-combination-already-exists-on-docker-hub
- name: Ensure image isn't already published
run: |
docker login --username ${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
if DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect elrondnetwork/build-contract-rust:${GITHUB_REF_NAME} >/dev/null; then
echo "Image already published. Will NOT publish."
exit 1
else
echo "Image not yet published. Will publish."
fi
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
file: ./Dockerfile
tags: elrondnetwork/build-contract-rust:${GITHUB_REF_NAME}
50 changes: 50 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
FROM ubuntu:20.04

# Constants
ARG VERSION_RUST="nightly-2022-08-23"
ARG VERSION_BINARYEN="version_105"
ARG VERSION_WABT="1.0.27"

RUN apt-get update && apt-get install wget -y
RUN apt-get update && apt-get install python3.8 python-is-python3 -y
RUN apt-get update && apt-get install build-essential -y

# Install rust
RUN wget -O rustup.sh https://sh.rustup.rs && \
chmod +x rustup.sh && \
CARGO_HOME=/rust RUSTUP_HOME=/rust ./rustup.sh --verbose --default-toolchain ${VERSION_RUST} --profile minimal --target wasm32-unknown-unknown -y && \
rm rustup.sh

# Install wasm-opt
RUN wget -O binaryen.tar.gz https://github.com/WebAssembly/binaryen/releases/download/${VERSION_BINARYEN}/binaryen-${VERSION_BINARYEN}-x86_64-linux.tar.gz && \
tar -xf binaryen.tar.gz && mv binaryen-${VERSION_BINARYEN}/bin/wasm-opt /usr/bin && \
rm binaryen.tar.gz && \
rm -rf binaryen-${VERSION_BINARYEN}

# Install wabt
RUN wget -O wabt.tar.gz https://github.com/WebAssembly/wabt/releases/download/${VERSION_WABT}/wabt-${VERSION_WABT}-ubuntu.tar.gz && \
tar -xf wabt.tar.gz && mv wabt-${VERSION_WABT}/bin/wasm2wat /usr/bin && mv wabt-${VERSION_WABT}/bin/wasm-objdump /usr/bin && \
rm wabt.tar.gz && \
rm -rf wabt-${VERSION_WABT}


COPY "./build_within_docker.py" "/build.py"

ENV PATH="/rust/bin:${PATH}"
ENV CARGO_HOME="/rust"
ENV RUSTUP_HOME="/rust"

# Additional arguments (must be provided at "docker run"):
# --output-owner-id
# --output-group-id
# --no-wasm-opt (optional)
ENTRYPOINT ["python", "./build.py", \
"--project", "/project", \
"--output", "/output", \
"--cargo-target-dir", "/cargo-target-dir"]

LABEL frozen="yes"
LABEL rust=${VERSION_RUST}
LABEL wasm-opt-binaryen=${VERSION_BINARYEN}
LABEL wabt=${VERSION_WABT}

60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,62 @@
# elrond-sdk-images-build-contract-rust

Docker image (and wrappers) for reproducible contract builds (Rust).

## Build the Docker image

```
docker image build --no-cache . -t build-contract-rust:experimental -f ./Dockerfile
```

## Build contract using the wrapper

Without providing `cargo-target-dir`:

```
python3 ./build_with_docker.py --image=build-contract-rust:experimental \
--project=~/contracts/reproducible-contract-build-example \
--output=~/contracts/output-from-docker
```

With providing `cargo-target-dir`:

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

## Build contract using the Docker inner script

This is useful for useful for testing, debugging and reviewing the script.

```
export PROJECT=${HOME}/contracts/reproducible-contract-build-example
export PROJECT_ARCHIVE=${HOME}/contracts/adder.tar
export OUTPUT=${HOME}/contracts/output
export CARGO_TARGET_DIR=${HOME}/cargo-target-dir
export OWNER_ID=$(id -u)
export GROUP_ID=$(id -g)
export PATH=${HOME}/elrondsdk/vendor-rust/bin:${HOME}/elrondsdk/wabt/latest/bin:${PATH}
export RUSTUP_HOME=${HOME}/elrondsdk/vendor-rust
export CARGO_HOME=${HOME}/elrondsdk/vendor-rust
```

Build a project directory:

```
python3 ./build_within_docker.py --project=${PROJECT} --output=${OUTPUT} \
--cargo-target-dir=${CARGO_TARGET_DIR} \
--output-owner-id=${OWNER_ID} \
--output-group-id=${GROUP_ID}
```

Build a project archive:

```
python3 ./build_within_docker.py --project=${PROJECT_ARCHIVE} --output=${OUTPUT} \
--cargo-target-dir=${CARGO_TARGET_DIR} \
--output-owner-id=${OWNER_ID} \
--output-group-id=${GROUP_ID}
```
72 changes: 72 additions & 0 deletions build_with_docker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import logging
import os
import subprocess
import sys
from argparse import ArgumentParser
from pathlib import Path
from typing import List, Union

logger = logging.getLogger("build-with-docker")


def main(cli_args: List[str]):
logging.basicConfig(level=logging.DEBUG)

parser = ArgumentParser()
parser.add_argument("--image", type=str, required=True)
parser.add_argument("--project", type=str)
parser.add_argument("--output", type=str,
default=Path(os.getcwd()) / "output")
# Providing this parameter
# (a) *might* (should, but it doesn't) speed up (subsequent) builds, but
# (b) *might* (with a *very low* probability) break build determinism.
# As of September 2022, both (a) and (b) are still open points.
parser.add_argument("--cargo-target-dir", type=str)
parser.add_argument("--no-wasm-opt", action="store_true", default=False,
help="do not optimize wasm files after the build (default: %(default)s)")

parsed_args = parser.parse_args(cli_args)
image = parsed_args.image
project_path = Path(parsed_args.project).expanduser().resolve()
output_path = Path(parsed_args.output).expanduser().resolve()
cargo_target_dir = Path(parsed_args.cargo_target_dir).expanduser(
).resolve() if parsed_args.cargo_target_dir else None
no_wasm_opt = parsed_args.no_wasm_opt

output_path.mkdir(parents=True, exist_ok=True)

return_code = run_docker(
image, project_path, output_path, cargo_target_dir, no_wasm_opt)
return return_code


def run_docker(image: str, project_path: Path, output_path: Path, cargo_target_dir: Union[Path, None], no_wasm_opt: bool):
docker_mount_args = [
"--mount", f"type=bind,source={project_path},destination=/project",
"--mount", f"type=bind,source={output_path},destination=/output"
]

if cargo_target_dir:
docker_mount_args += ["--mount",
f"type=bind,source={cargo_target_dir},destination=/cargo-target-dir"]

docker_args = ["docker", "run"] + docker_mount_args + ["--rm", image]

entrypoint_args = [
"--output-owner-id", str(os.getuid()),
"--output-group-id", str(os.getgid())
]

if no_wasm_opt:
entrypoint_args.append("--no-wasm-opt")

args = docker_args + entrypoint_args
logger.info(f"Running docker: {args}")

result = subprocess.run(args)
return result.returncode


if __name__ == "__main__":
return_code = main(sys.argv[1:])
exit(return_code)
Loading

0 comments on commit 0c0b570

Please sign in to comment.