From 362dc95e27d792f23ad5b09789f50c1e1e5f0df2 Mon Sep 17 00:00:00 2001
From: Jure Bajic <jure.bajic@memgraph.com>
Date: Wed, 1 Mar 2023 18:44:56 +0100
Subject: [PATCH] Add support for Ubuntu 22.04 ARM (#810)

---
 .github/workflows/package_all.yaml          | 27 ++++--
 environment/os/ubuntu-22.04-arm.sh          | 96 +++++++++++++++++++++
 environment/toolchain/v4.sh                 | 20 +++--
 environment/util.sh                         |  5 +-
 release/package/arm-builders.yml            | 11 +++
 release/package/run.sh                      |  4 +-
 release/package/ubuntu-22.04-arm/Dockerfile | 17 ++++
 7 files changed, 166 insertions(+), 14 deletions(-)
 create mode 100755 environment/os/ubuntu-22.04-arm.sh
 create mode 100644 release/package/arm-builders.yml
 create mode 100644 release/package/ubuntu-22.04-arm/Dockerfile

diff --git a/.github/workflows/package_all.yaml b/.github/workflows/package_all.yaml
index 6e1196e32..b0ef18fde 100644
--- a/.github/workflows/package_all.yaml
+++ b/.github/workflows/package_all.yaml
@@ -160,6 +160,23 @@ jobs:
           name: debian-11-platform
           path: build/output/debian-11/memgraph*.deb
 
+  fedora-36:
+    runs-on: [self-hosted, DockerMgBuild, X64]
+    timeout-minutes: 60
+    steps:
+      - name: "Set up repository"
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0 # Required because of release/get_version.py
+      - name: "Build package"
+        run: |
+          ./release/package/run.sh package fedora-36
+      - name: "Upload package"
+        uses: actions/upload-artifact@v3
+        with:
+          name: fedora-36
+          path: build/output/fedora-36/memgraph*.rpm
+
   debian-11-arm:
     runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
     timeout-minutes: 60
@@ -177,8 +194,8 @@ jobs:
           name: debian-11-arm
           path: build/output/debian-11-arm/memgraph*.deb
 
-  fedora-36:
-    runs-on: [self-hosted, DockerMgBuild, X64]
+  ubuntu-2204-arm:
+    runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
     timeout-minutes: 60
     steps:
       - name: "Set up repository"
@@ -187,9 +204,9 @@ jobs:
           fetch-depth: 0 # Required because of release/get_version.py
       - name: "Build package"
         run: |
-          ./release/package/run.sh package fedora-36
+          ./release/package/run.sh package ubuntu-22.04-arm
       - name: "Upload package"
         uses: actions/upload-artifact@v3
         with:
-          name: fedora-36
-          path: build/output/fedora-36/memgraph*.rpm
+          name: ubuntu-22.04-arm
+          path: build/output/ubuntu-22.04-arm/memgraph*.deb
diff --git a/environment/os/ubuntu-22.04-arm.sh b/environment/os/ubuntu-22.04-arm.sh
new file mode 100755
index 000000000..d3bf8f040
--- /dev/null
+++ b/environment/os/ubuntu-22.04-arm.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+set -Eeuo pipefail
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+source "$DIR/../util.sh"
+
+check_operating_system "ubuntu-22.04"
+check_architecture "arm64" "aarch64"
+
+TOOLCHAIN_BUILD_DEPS=(
+    coreutils gcc g++ build-essential make # generic build tools
+    wget # used for archive download
+    gnupg # used for archive signature verification
+    tar gzip bzip2 xz-utils unzip # used for archive unpacking
+    zlib1g-dev # zlib library used for all builds
+    libexpat1-dev libbabeltrace-dev liblzma-dev python3-dev texinfo # for gdb
+    libcurl4-openssl-dev # for cmake
+    libreadline-dev # for cmake and llvm
+    libffi-dev libxml2-dev # for llvm
+    curl # snappy
+    file
+    git # for thrift
+    libgmp-dev # for gdb
+    gperf # for proxygen
+    libssl-dev
+    libedit-dev libpcre3-dev automake bison # for swig
+)
+
+TOOLCHAIN_RUN_DEPS=(
+    make # generic build tools
+    tar gzip bzip2 xz-utils # used for archive unpacking
+    zlib1g # zlib library used for all builds
+    libexpat1 libbabeltrace1 liblzma5 python3 # for gdb
+    libcurl4 # for cmake
+    libreadline8 # for cmake and llvm
+    libffi7 libxml2 # for llvm
+    libssl-dev # for libevent
+)
+
+MEMGRAPH_BUILD_DEPS=(
+    git # source code control
+    make pkg-config # build system
+    curl wget # for downloading libs
+    uuid-dev default-jre-headless # required by antlr
+    libreadline-dev # for memgraph console
+    libpython3-dev python3-dev # for query modules
+    libssl-dev
+    libseccomp-dev
+    netcat # tests are using nc to wait for memgraph
+    python3 python3-virtualenv python3-pip # for qa, macro_benchmark and stress tests
+    python3-yaml # for the configuration generator
+    libcurl4-openssl-dev # mg-requests
+    sbcl # for custom Lisp C++ preprocessing
+    doxygen graphviz # source documentation generators
+    mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
+    dotnet-sdk-6.0 golang nodejs npm
+    autoconf # for jemalloc code generation
+    libtool  # for protobuf code generation
+)
+
+list() {
+    echo "$1"
+}
+
+check() {
+    check_all_dpkg "$1"
+}
+
+install() {
+    cd "$DIR"
+    apt update
+    # If GitHub Actions runner is installed, append LANG to the environment.
+    # Python related tests doesn't work the LANG export.
+    if [ -d "/home/gh/actions-runner" ]; then
+        echo "LANG=en_US.utf8" >> /home/gh/actions-runner/.env
+    else
+        echo "NOTE: export LANG=en_US.utf8"
+    fi
+    apt install -y wget
+    for pkg in $1; do
+        if [ "$pkg" == dotnet-sdk-6.0 ]; then
+            if ! dpkg -s dotnet-sdk-6.0 2>/dev/null >/dev/null; then
+                wget -nv https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
+                dpkg -i packages-microsoft-prod.deb
+                apt-get update
+                apt-get install -y apt-transport-https dotnet-sdk-6.0
+            fi
+            continue
+        fi
+        apt install -y "$pkg"
+    done
+}
+
+deps=$2"[*]"
+"$1" "${!deps}"
diff --git a/environment/toolchain/v4.sh b/environment/toolchain/v4.sh
index 9dd997ad4..e3fddaa1f 100755
--- a/environment/toolchain/v4.sh
+++ b/environment/toolchain/v4.sh
@@ -51,11 +51,19 @@ CPPCHECK_VERSION=2.6
 LLVM_VERSION=13.0.0
 SWIG_VERSION=4.0.2 # used only for LLVM compilation
 
-# Check for the dependencies.
-echo "ALL BUILD PACKAGES: $($DIR/../os/$DISTRO.sh list TOOLCHAIN_BUILD_DEPS)"
-$DIR/../os/$DISTRO.sh check TOOLCHAIN_BUILD_DEPS
-echo "ALL RUN PACKAGES: $($DIR/../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)"
-$DIR/../os/$DISTRO.sh check TOOLCHAIN_RUN_DEPS
+# Set the right env script
+ENV_SCRIPT="$DIR/../os/$DISTRO.sh"
+if [[ "$for_arm" = true ]]; then
+    ENV_SCRIPT="$DIR/../os/$DISTRO-arm.sh"
+fi
+
+# Check for the toolchain build dependencies.
+echo "ALL BUILD PACKAGES: $(${ENV_SCRIPT} list TOOLCHAIN_BUILD_DEPS)"
+${ENV_SCRIPT} check TOOLCHAIN_BUILD_DEPS
+
+# Check for the toolchain run dependencies.
+echo "ALL RUN PACKAGES: $(${ENV_SCRIPT} list TOOLCHAIN_RUN_DEPS)"
+${ENV_SCRIPT} check TOOLCHAIN_RUN_DEPS
 
 # check installation directory
 NAME=toolchain-v$TOOLCHAIN_VERSION
@@ -622,7 +630,7 @@ In order to be able to run all of these tools you should install the following
 packages:
 
 \`\`\`
-$($DIR/../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)
+$($DIR/../os/$ENV_SCRIPT.sh list TOOLCHAIN_RUN_DEPS)
 \`\`\`
 
 ## Usage
diff --git a/environment/util.sh b/environment/util.sh
index f1f215939..e2ecf67cf 100644
--- a/environment/util.sh
+++ b/environment/util.sh
@@ -19,13 +19,16 @@ function architecture() {
 }
 
 check_architecture() {
+    local ARCH=$(architecture)
     for arch in "$@"; do
-        if [ "$(architecture)" = "$arch" ]; then
+        if [ "${ARCH}" = "$arch" ]; then
             echo "The right architecture!"
             return 0
         fi
     done
     echo "Not the right architecture!"
+    echo "Expected: $@"
+    echo "Actual: ${ARCH}"
     exit 1
 }
 
diff --git a/release/package/arm-builders.yml b/release/package/arm-builders.yml
new file mode 100644
index 000000000..d52f3bb26
--- /dev/null
+++ b/release/package/arm-builders.yml
@@ -0,0 +1,11 @@
+version: "3"
+
+services:
+  debian-11-arm:
+    build:
+      context: debian-11-arm
+    container_name: "mgbuild_debian-11-arm"
+  ubuntu-2204-arm:
+    build:
+      context: ubuntu-22.04-arm
+    container_name: "mgbuild_ubuntu-22.04-arm"
diff --git a/release/package/run.sh b/release/package/run.sh
index 680e7a4db..7d068eaa9 100755
--- a/release/package/run.sh
+++ b/release/package/run.sh
@@ -3,7 +3,7 @@
 set -Eeuo pipefail
 
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-SUPPORTED_OS=(centos-7 centos-9 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04 ubuntu-22.04 debian-11-arm fedora-36)
+SUPPORTED_OS=(centos-7 centos-9 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04 ubuntu-22.04 debian-11-arm fedora-36 ubuntu-22.04-arm)
 PROJECT_ROOT="$SCRIPT_DIR/../.."
 TOOLCHAIN_VERSION="toolchain-v4"
 ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate"
@@ -76,7 +76,7 @@ make_package () {
     docker exec "$build_container" bash -c "cd /memgraph && git config --global --add safe.directory '*'"
     docker exec "$build_container" bash -c "cd /memgraph && $ACTIVATE_TOOLCHAIN && ./init"
     docker exec "$build_container" bash -c "cd $container_build_dir && rm -rf ./*"
-    if [[ "$os" == "debian-11-arm" ]]; then
+    if [[ "$os" =~ "-arm" ]]; then
         docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release -DMG_ARCH="ARM64" $telemetry_id_override_flag .."
     else
         docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
diff --git a/release/package/ubuntu-22.04-arm/Dockerfile b/release/package/ubuntu-22.04-arm/Dockerfile
new file mode 100644
index 000000000..5ddb94883
--- /dev/null
+++ b/release/package/ubuntu-22.04-arm/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:22.04
+
+ARG TOOLCHAIN_VERSION
+
+# Stops tzdata interactive configuration.
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt update && apt install -y \
+    ca-certificates wget git
+# Do NOT be smart here and clean the cache because the container is used in the
+# stateful context.
+
+RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz \
+    -O ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz \
+    && tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz -C /opt
+
+ENTRYPOINT ["sleep", "infinity"]