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

Docker build image and devcontainer config #147

Merged
merged 35 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
40b1eb2
0.8.0 Release: Merge pull request #78 from KomodoPlatform/dev
CharlVS Oct 20, 2023
8281a1a
update rates url
smk762 Oct 30, 2023
b0eb54a
Merge pull request #91 from KomodoPlatform/dev
ca333 Dec 19, 2023
68138a3
Merge pull request #93 from KomodoPlatform/dev
ca333 Jan 16, 2024
b853544
Merge pull request #100 from KomodoPlatform/dev
ca333 Jan 24, 2024
523e7c1
Add docker image and devcontainer
takenagain Mar 10, 2024
6df3044
Merge pull request #123 from KomodoPlatform/dev
ca333 May 4, 2024
69d98b2
SSL migration (#143)
ca333 May 13, 2024
ee3d6f7
Merge branch 'master' of https://github.com/KomodoPlatform/komodo-wal…
CharlVS May 21, 2024
0bde503
Replace python script with new dart version
takenagain May 21, 2024
2e31b5a
Fix issues with new dart script as when used via CLI
takenagain May 21, 2024
4059941
Revert "Replace python script with new dart version"
takenagain May 21, 2024
a6f0fc3
Change from clone to COPY and fix permission issue
takenagain May 21, 2024
93dfbaa
Add documentation and fix build directory permission issues
takenagain May 21, 2024
1e351d0
Update devcontainer image and fix permission issues
takenagain May 21, 2024
566ba0b
Fix devcontainer ndk install error
takenagain May 21, 2024
2f258ca
Move changing ownership of android sdk folder to dockerfile
takenagain May 21, 2024
6160a98
Replace Flutter archive download with git clone of Flutter repo
takenagain May 22, 2024
505279d
Refactor to fetch Defi binaries only from GH releases (#148)
CharlVS May 22, 2024
6d2d379
Remove the hardcoded platform from the devcontainer image
takenagain May 22, 2024
d5943df
Copy over android sdk dockerfile from Cirrus CI
takenagain May 22, 2024
2622fd4
Fix bug in API fetch script
CharlVS May 22, 2024
7022813
Add script to abstract apk release build
takenagain May 22, 2024
95ce8bf
Change devcontainer to docker-compose format
takenagain May 23, 2024
08baacc
Revert "Change devcontainer to docker-compose format"
takenagain May 23, 2024
78a51a0
Add note regarding build limitations and the Python script
takenagain May 23, 2024
d86be74
Update fetch coins scripts
takenagain May 23, 2024
924bf63
Merge branch 'dev' into feature/docker-build
CharlVS May 23, 2024
77a9b69
Add komodo-defi-framework build step to apk build image
takenagain May 27, 2024
b4abb97
Fix kdf branch build argument
takenagain May 27, 2024
7cdbc98
Remove unnecessary copy
takenagain May 27, 2024
1753e65
Combine dockerfiles into `android-dev` for Github codespaces
takenagain May 31, 2024
2aa8459
Move API build to postAttach event of devcontainer
takenagain Jun 1, 2024
7212f53
Fix cargo install in devcontainer/Codespaces
takenagain Jun 3, 2024
99efab0
Set the minimum host requirements for Codespaces
takenagain Jun 4, 2024
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
12 changes: 12 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "flutter_docker",
"context": "..",
"dockerFile": "../.docker/android-dev.dockerfile",
"remoteUser": "komodo",
"postAttachCommand": "sh .docker/dev-setup.sh",
"runArgs": [
"--privileged"
],
"workspaceMount": "source=${localWorkspaceFolder},target=/home/komodo/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/home/komodo/workspace"
}
46 changes: 46 additions & 0 deletions .docker/android-apk-build.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
FROM --platform=linux/amd64 ubuntu:latest as build

RUN apt update && \
apt upgrade -y && \
apt install -y python3 python3-pip git curl nodejs python3-venv && \
mkdir -p /app

WORKDIR /app

COPY . .

# TODO: add .gitkeep files for the missing directories
RUN curl -o assets/coins.json https://raw.githubusercontent.com/KomodoPlatform/coins/master/coins && \
curl -o assets/coins_config.json https://raw.githubusercontent.com/KomodoPlatform/coins/master/utils/coins_config.json && \
mkdir -p android/app/src/main/cpp/libs/armeabi-v7a && \
mkdir -p android/app/src/main/cpp/libs/arm64-v8a && \
python3 -m venv .venv && \
.venv/bin/pip install -r .docker/requirements.txt && \
.venv/bin/python .docker/update_api.py --force

FROM --platform=linux/amd64 ghcr.io/cirruslabs/android-sdk:34 as final

ENV FLUTTER_VERSION="2.8.1"
ENV FLUTTER_HOME "/home/komodo/.flutter-sdk"
ENV USER="komodo"
ENV PATH $PATH:$FLUTTER_HOME/bin

# Download and extract Flutter SDK
RUN mkdir -p $FLUTTER_HOME \
&& git config --global --add safe.directory /home/komodo/.flutter-sdk \
&& cd $FLUTTER_HOME \
&& curl --fail --remote-time --silent --location -O https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz \
&& tar xf flutter_linux_${FLUTTER_VERSION}-stable.tar.xz --strip-components=1 \
&& rm flutter_linux_${FLUTTER_VERSION}-stable.tar.xz

RUN flutter config --no-analytics \
&& flutter precache \
&& yes "y" | flutter doctor --android-licenses \
&& flutter doctor \
&& flutter update-packages

COPY --from=build /app /app

WORKDIR /app

CMD [ "flutter", "build", "apk", "--release" ]
29 changes: 29 additions & 0 deletions .docker/android-dev.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM --platform=linux/amd64 ghcr.io/cirruslabs/android-sdk:34 as final

ENV FLUTTER_VERSION="2.8.1"
ENV FLUTTER_HOME "/home/komodo/.flutter-sdk"
ENV USER="komodo"
ENV PATH $PATH:$FLUTTER_HOME/bin

RUN apt update && apt install -y python3 python3-pip python3-venv && \
python3 -m venv /home/komodo/.venv && \
useradd -u 1001 -m $USER && \
usermod -aG sudo $USER && \
echo "$USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
chown -R $USER:$USER /home/$USER

USER $USER

# Download and extract Flutter SDK
RUN mkdir -p /home/komodo/workspace \
&& chown -R $USER:$USER /home/komodo/workspace \
&& mkdir -p $FLUTTER_HOME \
&& cd $FLUTTER_HOME \
&& curl --fail --remote-time --silent --location -O https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz \
&& tar xf flutter_linux_${FLUTTER_VERSION}-stable.tar.xz --strip-components=1 \
&& rm flutter_linux_${FLUTTER_VERSION}-stable.tar.xz \
&& flutter config --no-analytics \
&& flutter precache \
&& yes "y" | flutter doctor --android-licenses \
&& flutter doctor \
&& flutter update-packages
29 changes: 29 additions & 0 deletions .docker/build_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"api": {
"version": "b0fd99e",
"should_update": true,
"base_url": "https://sdk.devbuilds.komodo.earth",
"default_branch": "main",
"platforms": {
"ios": {
"keywords": [
"ios",
"aarch64"
],
"path": "ios"
},
"android-armv7": {
"keywords": [
"android-armv7"
],
"path": "android/app/src/main/cpp/libs/armeabi-v7a"
},
"android-aarch64": {
"keywords": [
"android-aarch64"
],
"path": "android/app/src/main/cpp/libs/arm64-v8a"
}
}
}
}
5 changes: 5 additions & 0 deletions .docker/dev-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
chmod u+rw,g+r komodo:komodo /home/komodo/workspace
mkdir -p android/app/src/main/cpp/libs/armeabi-v7a
mkdir -p android/app/src/main/cpp/libs/arm64-v8a
/home/komodo/.venv/bin/pip install -r .docker/requirements.txt
/home/komodo/.venv/bin/python .docker/update_api.py
3 changes: 3 additions & 0 deletions .docker/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
requests==2.31.0
beautifulsoup4==4.12.2

229 changes: 229 additions & 0 deletions .docker/update_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
import os
import re
import sys
import json
import shutil
import zipfile
import requests
import argparse
import subprocess
from pathlib import Path
from datetime import datetime
from bs4 import BeautifulSoup


class UpdateAPI():
'''Updates the API module version for all or a specified platform.'''
def __init__(self, version=None, platform=None, force=False):
self.version = version
self.platform = platform
self.force = force

# Get the absolute path of the project root directory
self.project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
self.config_file = os.path.join(self.project_root, ".docker/build_config.json")

# Load the build_config.json
with open(self.config_file, "r") as f:
self.config = json.load(f)

# Use version from build_config.json if version is not specified
if not self.version:
self.version = self.config["api"]["version"]

# Get the platforms config
self.platforms_config = self.config["api"]["platforms"]

# Get the base URL and branch for the API module
self.base_url = self.config["api"]["base_url"]
self.api_branch = self.config["api"]["default_branch"]


def get_platform_destination_folder(self, platform):
'''Returns the destination folder for the specified platform.'''
if platform in self.platforms_config:
return os.path.join(self.project_root, self.platforms_config[platform]["path"])
else:
raise ValueError(f"Invalid platform: {platform}. Please select a valid platform from the following list: {', '.join(self.platforms_config.keys())}")

def get_zip_file_url(self, platform, branch):
'''Returns the URL of the zip file for the requested version / branch / platform.'''
response = requests.get(f"{self.base_url}/{branch}/")
response.raise_for_status()

# Configure the HTML parser
soup = BeautifulSoup(response.text, "html.parser")
search_parameters = self.platforms_config[platform]
keywords = search_parameters["keywords"]
extensions = [".zip"] # Assuming that the extensions are the same for all platforms

# Parse the HTML and search for the zip file
for link in soup.find_all("a"):
file_name = link.get("href")
if all(keyword in file_name for keyword in keywords) \
and any(file_name.endswith(ext) for ext in extensions) \
and self.version in file_name:
return f"{self.base_url}/{branch}/{file_name}"
return None

def download_api_file(self, platform):
'''Downloads the API version zip file for a specific platform.'''
# Get the URL of the zip file in the main directory
zip_file_url = self.get_zip_file_url(platform, self.api_branch)

# If the zip file is not found in the main directory, search in all directories
if not zip_file_url:
response = requests.get(self.base_url)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")

for link in soup.find_all("a"):
branch = link.get("href")
zip_file_url = self.get_zip_file_url(platform, branch)

if zip_file_url:
print(f"'{platform}': Found zip file in '{branch}' folder.")
break

if not zip_file_url:
raise ValueError(f"Could not find zip file for version '{self.version}' on '{platform}' platform!")

# Download the zip file
print(f"Downloading '{self.version}' API module for [{platform}]...")
response = requests.get(zip_file_url, stream=True)
response.raise_for_status()

destination_folder = self.get_platform_destination_folder(platform)
zip_file_name = os.path.basename(zip_file_url)
destination_path = os.path.join(destination_folder, zip_file_name)

# Save the zip file to the specified folder
with open(destination_path, "wb") as file:
response.raw.decode_content = True
shutil.copyfileobj(response.raw, file)

print(f"Saved to '{destination_path}'")
return destination_path

def update_documentation(self):
'''Updates the API version in the documentation.'''
documentation_file = f"{self.project_root}/docs/UPDATE_API_MODULE.md"

# Read the existing documentation file
with open(documentation_file, "r") as f:
content = f.read()

# Update the version information in the documentation
updated_content = re.sub(
r"(Current api module version is) `([^`]+)`",
f"\\1 `{self.version}`",
content
)

# Write the updated content back to the documentation file
with open(documentation_file, "w") as f:
f.write(updated_content)

print(f"API version in documentation updated to {self.version}")

def update_api(self):
'''Updates the API module.'''
if self.config["api"]["should_update"]:
version = self.config["api"]["version"][:7]
platforms = self.config["api"]["platforms"]

# If a platform is specified, only update that platform
if self.platform:
platforms = {self.platform: platforms[self.platform]}

for platform, platform_info in platforms.items():
# Set the api module destination folder
destination_folder = self.get_platform_destination_folder(platform)

# Check if .api_last_updated file exists
last_api_update_file = os.path.join(destination_folder, ".api_last_updated")

is_outdated = True

if not self.force and os.path.exists(last_api_update_file):
with open(last_api_update_file, "r") as f:
last_api_update = json.load(f)
if last_api_update.get("version") == version:
print(f"{platform} API module is up to date ({version}).")
is_outdated = False

if is_outdated:
# Download the API file for the platform
zip_file_path = self.download_api_file(platform)

# Unzip the downloaded file
print(f"Extracting...")
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
zip_ref.extractall(destination_folder)

# Update wasm module
if platform == 'web':
print(f"Updating WASM module...")
npm_exec = "npm.cmd" if sys.platform == "win32" else "npm"
# If we dont do this first, we might get stuck at the `npm run build` step as there
# appears to be no "non-interactive" flag to accept installing deps with `npm run build`
result = subprocess.run([npm_exec, "install"], capture_output=True, text=True)
if result.returncode == 0:
print("npm install completed.")
else:
print("npm install failed. Please make sure you are using nodejs 18, e.g. `nvm use 18`.)")
print(result.stderr)
sys.exit(1)

result = subprocess.run([npm_exec, "run", "build"], capture_output=True, text=True)
if result.returncode == 0:
print("Done.")
else:
print("npm run build failed. Please make sure you are using nodejs 18, e.g. `nvm use 18`.)")
print(result.stderr)
sys.exit(1)

# Make mm2 file executable for Linux
if platform == 'linux':
print("Make mm2 file executable for Linux")
os.chmod(os.path.join(destination_folder, "mm2"), 0o755)

# Delete the zip file after extraction
os.remove(zip_file_path)

# Update .api_last_updated file
with open(last_api_update_file, "w") as f:
current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
json.dump({"version": version, "timestamp": current_timestamp}, f)

# Update the API version in documentation
# self.update_documentation()

def update_build_config_version(self):
'''Updates the API version in build_config.json.'''
self.config["api"]["version"] = self.version

with open(self.config_file, "w") as f:
json.dump(self.config, f, indent=4)

print(f"Version in build_config.json updated to {self.version}.")


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Download API module file for specified version and platform.")
# Optional arguments
parser.add_argument("-a", "--api", help="version of the API module to download.", default=None)
parser.add_argument("-p", "--platform", help="platform for which the API module should be downloaded.", default=None)
parser.add_argument("--force", action="store_true", help="force update, ignoring .api_last_updated.", default=False)
args = parser.parse_args()

try:
updateAPI = UpdateAPI(args.api, args.platform, args.force)
# Update the API version in build_config.json if the API version is specified
if args.api:
updateAPI.update_build_config_version()
updateAPI.update_api()

except Exception as e:
print(f"Error: {e}")
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ Windows: `choco install jq`, [Choco software](https://chocolatey.org/)

https://github.com/KomodoPlatform/AtomicDEX-mobile/wiki/Project-Setup#build-and-run

### Build with docker

To build from a container without installing Flutter on an x86_64 machine (Linux or Windows) with Docker or Podman installed, you can use the provided Dockerfile.

```bash
docker build -f .docker/android-apk-build.dockerfile . -t mobile_apk_build
docker run --rm -u 1001:1001 -v ./build:/app/build mobile_apk_build:latest
```

The build output should be in the following directory: `build/app/outputs/flutter-apk/app-release.apk`

## Run/Build with screenshot and video recording ON

Expand Down
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ android {
defaultConfig {
applicationId "com.komodoplatform.atomicdex"
minSdkVersion 28
targetSdkVersion 31
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
buildConfigField "Long", "BUILD_TIME", "" + System.currentTimeMillis() + "L"
Expand Down
Binary file removed assets/coin-icons/aibc.png
Binary file not shown.
Loading
Loading