Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions .github/workflows/PR-build-image-rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
env:
IMAGE_NAME: devcontainer-smart-contracts-rust
REGISTRY_HOSTNAME: multiversx

name: Build Docker image - rust (PR)

on:
pull_request:

jobs:
build-docker-image:
strategy:
matrix:
runner: [ubuntu-latest, ubuntu-24.04-arm]
runs-on: ${{ matrix.runner }}

steps:
- name: Check out the repo
uses: actions/checkout@v5

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

- name: Build image
uses: docker/build-push-action@v6
with:
context: ./resources/smart-contracts-rust
push: false
file: ./resources/smart-contracts-rust/Dockerfile
tags: ${{ env.REGISTRY_HOSTNAME }}/${{ env.IMAGE_NAME }}:pr-test
52 changes: 0 additions & 52 deletions .github/workflows/publish-image-rust.yml

This file was deleted.

119 changes: 119 additions & 0 deletions .github/workflows/release-publish-image-rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
env:
IMAGE_NAME: devcontainer-smart-contracts-rust
REGISTRY_HOSTNAME: multiversx

name: Publish Docker image - rust (release)

on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Simulate release version (e.g., v0.4.2)'
required: false
default: ''
type: string

jobs:
prepare:
runs-on: ubuntu-latest
outputs:
tags: ${{ steps.meta.outputs.tags }}
tags-json: ${{ steps.meta.outputs.json }}
labels: ${{ steps.meta.outputs.labels }}
steps:
- name: Check out the repo
uses: actions/checkout@v4

- name: Compute version from template (release)
id: version
if: github.event_name == 'release'
run: |
VERSION=v$(jq -r '.["version"]' ./src/smart-contracts-rust/devcontainer-template.json)
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"

- name: Extract metadata
id: meta
env:
VERSION: ${{ steps.version.outputs.VERSION }}
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_HOSTNAME }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest
${{ (github.event_name == 'release' && format('type=raw,value={0}', env.VERSION)) || (github.event.inputs.version != '' && format('type=raw,value={0}', github.event.inputs.version)) || '' }}

build:
strategy:
matrix:
arch:
- { runner: ubuntu-latest, platform: linux/amd64, platform_tag: linux_amd64 }
- { runner: ubuntu-24.04-arm, platform: linux/arm64, platform_tag: linux_arm64 }
runs-on: ${{ matrix.arch.runner }}
needs: prepare
steps:
- name: Check out the repo
uses: actions/checkout@v4

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

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: ./resources/smart-contracts-rust
file: ./resources/smart-contracts-rust/Dockerfile
platforms: ${{ matrix.arch.platform }}
labels: ${{ needs.prepare.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY_HOSTNAME }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true

- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.arch.platform_tag }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

manifest:
runs-on: ubuntu-latest
needs: [prepare, build]

steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true

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

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Create and push manifest
working-directory: /tmp/digests
env:
TAGS_JSON: ${{ needs.prepare.outputs.tags-json }}
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$TAGS_JSON") \
$(printf '${{ env.REGISTRY_HOSTNAME }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
83 changes: 39 additions & 44 deletions resources/smart-contracts-rust/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,64 +1,59 @@
FROM ubuntu:22.04
FROM ubuntu:24.04

ARG USERNAME=developer
ARG USER_UID=1000
ARG USER_GID=$USER_UID
ARG USERNAME=ubuntu
ARG VERSION_MXPY="11.3.1"
ARG VERSION_RUST="1.90.0"
ARG VERSION_SC_META="0.64.2"

ARG VERSION_MXPY="v11.1.1"
ARG VERSION_RUST="1.86.0"
ARG VERSION_SC_META="0.62.0"
ENV DEBIAN_FRONTEND=noninteractive

# Create the user
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
#
# [Optional] Add sudo support. Omit if you don't need to install software after connecting.
&& apt-get update \
&& apt-get install -y sudo \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME

# Install some dependencies as root
# Base system dependencies
RUN apt-get update && apt-get install -y \
wget \
build-essential \
python3.10 python3-pip python3.10-venv \
sudo \
curl \
git \
build-essential \
pkg-config \
libssl-dev && \
rm -rf /var/lib/apt/lists/*

# Switch to regular user
USER $USERNAME
libssl-dev \
python3 \
python3-venv \
python3-pip \
pipx \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Give sudo access to the user without password
RUN echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \
&& chmod 0440 /etc/sudoers.d/${USERNAME}

USER ${USERNAME}
WORKDIR /home/${USERNAME}

# Environment variables
ENV MULTIVERSX="/home/${USERNAME}/multiversx-sdk"
ENV PATH="/home/${USERNAME}/.local/bin:${PATH}"
ENV PATH="/home/${USERNAME}/.cargo/bin:${PATH}"

# Install pipx
RUN python3 -m pip install --no-cache-dir --user pipx

# Install mxpy
# Install mxpy via pipx
RUN pipx install multiversx-sdk-cli==${VERSION_MXPY}

# Install rust
RUN wget -O rustup.sh https://sh.rustup.rs && \
chmod +x rustup.sh && \
CARGO_HOME=/home/${USERNAME}/.cargo RUSTUP_HOME=/home/${USERNAME}/.rustup ./rustup.sh --verbose --default-toolchain ${VERSION_RUST} --profile minimal -y && \
rm rustup.sh
# Install Rust
RUN curl https://sh.rustup.rs -sSf | \
sh -s -- -y --profile minimal --default-toolchain ${VERSION_RUST}

# Install sc-meta tools
RUN CARGO_HOME=/home/${USERNAME}/.cargo RUSTUP_HOME=/home/${USERNAME}/.rustup PATH="/home/${USERNAME}/.cargo/bin:${PATH}" \
cargo install multiversx-sc-meta --version ${VERSION_SC_META} --locked

RUN CARGO_HOME=/home/${USERNAME}/.cargo RUSTUP_HOME=/home/${USERNAME}/.rustup PATH="/home/${USERNAME}/.cargo/bin:${PATH}" \
sc-meta install all
RUN cargo install multiversx-sc-meta --version ${VERSION_SC_META} --locked \
&& sc-meta install all

# Install test wallets
RUN mxpy deps install testwallets && rm ${MULTIVERSX}/*.tar.gz
RUN mxpy deps install testwallets

# Rust components + cleanup
RUN rustup component add rustfmt \
&& rm -rf /home/${USERNAME}/.cargo/registry \
&& rm -rf /home/${USERNAME}/.cargo/git

RUN rustup component add rustfmt && rm -rf /home/${USERNAME}/.cargo/registry/* && rm -rf /home/${USERNAME}/.cargo/git/*
# Devcontainer resources
COPY post_create_command.py ${MULTIVERSX}/devcontainer-resources/

# This command will be executed once the devcontainer is created
COPY "post_create_command.py" "${MULTIVERSX}/devcontainer-resources/"
CMD ["bash"]
2 changes: 1 addition & 1 deletion src/smart-contracts-rust/devcontainer-template.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "smart-contracts-rust",
"version": "0.4.0",
"version": "0.5.0",
"name": "MultiversX: Smart Contracts Development (Rust)",
"description": "Develop smart contracts for MultiversX. Includes Rust, mxpy, VSCode extensions etc.",
"documentationURL": "https://github.com/multiversx/mx-template-devcontainers/blob/main/src/smart-contracts-rust",
Expand Down