Skip to content

Commit

Permalink
Docker build
Browse files Browse the repository at this point in the history
  • Loading branch information
gavv committed Oct 16, 2024
1 parent 37c11f6 commit 61cb761
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 19 deletions.
67 changes: 57 additions & 10 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@ on:
schedule:
- cron: '0 0 * * 1'

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
# native build on desktop
desktop:
strategy:
matrix:
os: [ubuntu-latest]
include:
- host: linux
image: ubuntu-latest

runs-on: ${{ matrix.os }}
name: desktop/${{ matrix.os }}
runs-on: ${{ matrix.image }}
name: desktop/${{ matrix.host }}

steps:
- name: Checkout
Expand All @@ -35,10 +42,14 @@ jobs:
channel: stable
cache: true

- name: Install doit
uses: awalsh128/cache-apt-pkgs-action@v1.4.2
- name: Install python
uses: actions/setup-python@v5
with:
packages: python3-doit
python-version: 3.11

- name: Install doit
run: |
pip install doit
- name: Run dart analyzer
run: |
Expand All @@ -48,13 +59,22 @@ jobs:
run: |
doit test
# build for android on different hosts
android:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- host: linux
image: ubuntu-latest

runs-on: ${{ matrix.os }}
name: android/${{ matrix.os }}
- host: macos
image: macos-latest

- host: windows
image: windows-latest

runs-on: ${{ matrix.image }}
name: android/${{ matrix.host }}

steps:
- name: Checkout
Expand Down Expand Up @@ -97,9 +117,36 @@ jobs:
run: |
doit build:apk variant=release
# build for different targets on different hosts using docker
docker:
strategy:
matrix:
include:
- host: linux
target: android
image: ubuntu-latest

runs-on: ${{ matrix.image }}
name: docker/${{ matrix.target }}-${{ matrix.host }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build
if: runner.os != 'Windows'
run: |
./script/docker_build.py
- name: Build (Windows)
if: runner.os == 'Windows'
run: |
.\script\docker_build.bat
# build and publish github release
release:
if: startsWith(github.ref, 'refs/tags/v')
needs: [desktop, android]
needs: [desktop, android, docker]

runs-on: ubuntu-latest
steps:
Expand Down
9 changes: 5 additions & 4 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ android {
abortOnError false
}

signingConfigs {
release {
if (System.getenv("SIGNING_STORE_FILE") != null) {

if (System.getenv("SIGNING_STORE_FILE") != null) {
signingConfigs {
release {
storeFile file(System.getenv("SIGNING_STORE_FILE"))
storePassword System.getenv("SIGNING_STORE_PASSWORD")
keyAlias System.getenv("SIGNING_KEY_ALIAS")
Expand All @@ -110,7 +111,7 @@ android {
if (System.getenv("SIGNING_STORE_FILE") != null) {
signingConfig signingConfigs.release
} else {
signingConfig = signingConfigs.debug
signingConfig signingConfigs.debug
}
}
}
Expand Down
28 changes: 24 additions & 4 deletions docs/building/build_project.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
# Build project

First follow instructions to set up environment:
## Build with docker

The easiest way to build project is to use our pre-built [docker images](https://github.com/roc-streaming/dockerfiles) with Flutter SDK. In this case you don't need to set up build environment by yourself.

First install Docker CE ([Linux](https://docs.docker.com/engine/install/)) or Docker Desktop ([macOS](https://docs.docker.com/desktop/install/mac-install/), [Windows](https://docs.docker.com/desktop/install/windows-install/)). In case of Docker Desktop, don't forget to open GUI and start engine.

Then open terminal in project root and run:

* On macOS and Linux:

./script/docker_build.py

* On Windows:

.\script\docker_build.bat

After building, you can find APK here:

dist/android/release/roc-droid-<version>.apk

## Build without docker

First follow instructions to set up build environment:

* [Windows setup](./windows_setup.md)
* [macOS and Linux setup](./macos_linux_setup.md)
* [Windows setup](./windows_setup.md)

Then open terminal in project root and run:

Expand All @@ -12,5 +34,3 @@ Then open terminal in project root and run:
After building, you can find APK here:

dist/android/release/roc-droid-<version>.apk

You can upload it to device and tap to install.
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ nav:
- Agent: architecture/agent.md
- Building:
- Build project: building/build_project.md
- Windows setup: building/windows_setup.md
- macOS and Linux setup: building/macos_linux_setup.md
- Windows setup: building/windows_setup.md
- Development:
- Automation: development/automation.md
- Testing: development/testing.md
Expand Down
106 changes: 106 additions & 0 deletions script/docker_build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
@rem -*- coding: utf-8; mode: powershell -*-
@powershell -ExecutionPolicy Unrestricted -Command ^
"$Self = '%~f0'; $Target = '%~1'; iex ((gc $Self | out-string) -replace '(?s).*:start\r?\n', '')"
@exit /b
:start

# On fresh Windows installation, there may be problems with running .ps1 file as is:
# .\script\docker_build.ps1 <target>
#
# We may instead need:
# powershell -ExecutionPolicy Unrestricted -File .\script\docker_build.ps1 <target>
#
# It would work, but is cumbersome.
#
# For convenience, we name file as .bat file (so that it can be invoked as is), but in the
# preable above we evaluate contents of the file after :start marker as a powershell script
# (so that we don't have to deal with batch programming madness).

$ErrorActionPreference = "Stop"

function Project-Version {
$content = Get-Content -Path "pubspec.yaml" -Raw
$match = [regex]::Match($content, "^version:\s*(\S+)\s*$", "Multiline")
return $match.Groups[1].Value
}

function Print-Msg ($msg) {
Write-Host "$msg" -ForegroundColor Blue
}

function Print-Err ($msg) {
Write-Host "$msg" -ForegroundColor Red
}

function Run-Cmd ($cmd) {
Write-Host ($cmd -join " ")

$proc = Start-Process -FilePath $cmd[0] -ArgumentList $cmd[1..$cmd.Length] `
-PassThru -Wait -NoNewWindow

if ($proc.ExitCode -ne 0) {
Print-Err "Command failed with code $($proc.ExitCode)"
exit 1
}
}

if ($Target -eq "") {
$Target = "android"
}
if (-not (@("android") -contains $Target)) {
Print-Err "usage: .\script\docker_build.bat [android]"
exit 1
}

Set-Location -Path (
Split-Path -Parent (Split-Path -Parent (Resolve-Path $Self)))

$cwd = Get-Location

if ($Target -eq "android") {
$workDir = "/root/build" # container
$cacheDirs = @{
# host: container
"${cwd}\build\dockercache\pub" = "/root/.pub-cache"
"${cwd}\build\dockercache\gradle" = "/root/.gradle"
"${cwd}\build\dockercache\android" = "/root/.android/cache"
}
}

$dockerCmd = @(
"docker", "run",
"--rm", "-t",
"-w", $workDir,
"-v", "${cwd}:${workDir}"
)

foreach ($pair in $cacheDirs.GetEnumerator()) {
$hostDir = $pair.Key
$containerDir = $pair.Value
New-Item -Path $hostDir -ItemType Directory -Force | Out-Null
$dockerCmd += @(
"-v", "${hostDir}:${containerDir}"
)
}

$dockerCmd += @(
"rocstreaming/env-flutter:${Target}"
)

if ($Target -eq "android") {
$dockerCmd += @(
"flutter", "build", "apk", "--release"
)
}

Print-Msg "Running ${Target} build in docker"
Run-Cmd $dockerCmd

if ($Target -eq "android") {
$appType = "apk"
$appFile = "roc-droid-$(Project-Version).apk"
}

Print-Msg
Print-Msg "Copied ${Target} ${appType} to dist\${Target}\release\${appFile}"
Get-ChildItem "dist\${Target}\release"
99 changes: 99 additions & 0 deletions script/docker_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#! /usr/bin/env python3

import argparse
import os
import platform
import re
import subprocess
import sys

os.chdir(os.path.join(
os.path.dirname(os.path.abspath(__file__)), '..'))

# We have docker_build.bat that is a windows-specific version of docker_build.py.
# It exists so that docker build doesn't require python on windows.
#
# But if the user still runs docker_build.py on windows, we redirect call to
# docker_build.bat, as we don't want duplicating windows-specific logic in two scripts.
#
# The rest of the script assumes that we're on a Unix-like system.
if platform.system() == 'Windows':
try:
subprocess.check_call(
['script/docker_build.bat'] + sys.argv[1:], shell=False)
exit(0)
except:
exit(1)

def project_version():
with open('pubspec.yaml') as fp:
m = re.search(r'^version:\s*(\S+)\s*$', fp.read(), re.MULTILINE)
return m.group(1)

def print_msg(msg=''):
print(f'\033[1;34m{msg}\033[0m', file=sys.stderr)

def run_cmd(cmd):
print(' '.join(cmd), file=sys.stderr)
try:
subprocess.check_call(cmd)
except:
exit(1)

parser = argparse.ArgumentParser()
parser.add_argument('target',
nargs='?',
choices=['android'], default='android')

args = parser.parse_args()

cwd = os.path.abspath(os.getcwd())
uid = os.getuid()
gid = os.getgid()

work_dir = None
cache_dirs = {}

if args.target == 'android':
work_dir = '/root/build' # container
cache_dirs = {
# host: container
f'{cwd}/build/dockercache/pub': '/root/.pub-cache',
f'{cwd}/build/dockercache/gradle': '/root/.gradle',
f'{cwd}/build/dockercache/android': '/root/.android/cache',
}

docker_cmd = [
'docker', 'run',
'--rm', '-t',
'-u', f'{uid}:{gid}',
'-w', work_dir,
'-v', f'{cwd}:{work_dir}',
]

for host_dir, container_dir in cache_dirs.items():
os.makedirs(host_dir, exist_ok=True)
docker_cmd += [
'-v', f'{host_dir}:{container_dir}',
]

docker_cmd += [
f'rocstreaming/env-flutter:{args.target}',
]

if args.target == 'android':
docker_cmd += [
'flutter', 'build', 'apk', '--release',
]

print_msg(f'Running {args.target} build in docker')
run_cmd(docker_cmd)

if args.target == 'android':
app_type = 'apk'
app_file = f'roc-droid-{project_version()}.apk'

print_msg()

print_msg(f'Copied {args.target} {app_type} to dist/{args.target}/release/{app_file}')
run_cmd(['ls', '-lh', f'dist/{args.target}/release'])

0 comments on commit 61cb761

Please sign in to comment.