2021-09-25 06:46:10 -07:00
|
|
|
---
|
|
|
|
title: "Flutter Integration Test Server in Debian 11 Nspawn Container"
|
|
|
|
date: 2021-09-24
|
|
|
|
draft: false
|
|
|
|
tags: ["debian", "nspawn", "android", "flutter"]
|
|
|
|
authors: ["trent"]
|
|
|
|
post: 22
|
|
|
|
---
|
|
|
|
date: 2021-09-24
|
|
|
|
|
|
|
|
## Introduction
|
|
|
|
### Performance
|
|
|
|
Your Debian Server is way more powerful than your laptop or desktop
|
|
|
|
and flutter integration_tests suck.
|
|
|
|
### Ergonomics
|
|
|
|
You have an Android Emulator (or a real device) connected to the machine
|
|
|
|
that you are sitting in front of for reference, and now you can run
|
|
|
|
integration_tests on a different device without having to juggle adb
|
|
|
|
connections on the same machine.
|
|
|
|
### Nspawn Tho?
|
|
|
|
Because containers unlike virtual machines access the full power of the
|
|
|
|
host, but nspawn containers are peristent like virtual machines, sparing
|
|
|
|
you the cognitive overhead of dealing with the ephemerality of docker
|
|
|
|
containers and/or of herding cats.
|
|
|
|
|
|
|
|
And you already have nspawn, it's build into systemd. Even including the
|
|
|
|
(virtual) network interfaces.
|
|
|
|
### Documentation
|
|
|
|
Let's face it: setting up an Android Development Environment is a nightmare.
|
|
|
|
|
|
|
|
So don't just follow this guide; follow this guide a repetition of three
|
2021-09-25 06:56:15 -07:00
|
|
|
times, building your own step-by-step guide for yourself as you go. Your brain
|
2021-09-25 06:46:10 -07:00
|
|
|
will thank you.
|
|
|
|
|
|
|
|
## Host Preparation (Debian 11)
|
|
|
|
1. install `systemd-container` and `debootstrap`
|
|
|
|
2. enable unprivileged user namespaces
|
|
|
|
* `echo 'kernel.unprivileged_userns_clone=1' >/etc/sysctl.d/nspawn.conf`
|
|
|
|
* `systemctl restart systemd-sysctl.service`
|
|
|
|
3. you might as well allow debootstrap to user your apt-cacher-ng proxy
|
|
|
|
* `export http_proxy=http://<ip address>:3142`
|
|
|
|
### br0 bridge
|
|
|
|
describe br0 bridge in `/etc/systemd/nspawn/ftest.nspawn` (optional).
|
|
|
|
```cfg
|
|
|
|
# /etc/systemd/nspawn/ftest.nspawn
|
|
|
|
[Network]
|
|
|
|
VirtualEthernet=yes
|
|
|
|
Bridge=br0
|
|
|
|
```
|
|
|
|
|
|
|
|
## ZFS mountpoint
|
|
|
|
This is optional, obviously; you might not even use zfs.
|
|
|
|
|
|
|
|
* `zfs create vm_pool/nspawn/ftest`
|
|
|
|
* `zfs set mountpoint=/var/lib/machines/ftest vm_pool/nspawn/ftest`
|
|
|
|
* sanity check `zfs list -r vm_pool/nspawn`
|
|
|
|
|
|
|
|
## bootstrap container
|
|
|
|
```shell
|
|
|
|
# for apt-cacher-ng proxy
|
|
|
|
export http_proxy=http://<ip address>:3142
|
|
|
|
|
|
|
|
debootstrap --include=systemd-container stable /var/list/machines/ftest
|
|
|
|
```
|
|
|
|
|
|
|
|
## preboot config
|
|
|
|
1. delete container's package cache
|
|
|
|
2. copy `/etc/apt/apt.conf` to container
|
|
|
|
2. copy `/root/.bashrc` to container
|
|
|
|
2. copy `/root/.inputrc` to container
|
|
|
|
2. edit `/etc/hostname` in container
|
|
|
|
2. [write nspawn file on host](#br0-bridge)
|
|
|
|
2. copy `/etc/locale.gen` to `/etc/locale.gen.bak` on container
|
|
|
|
|
|
|
|
## first interactive boot
|
|
|
|
1. `systemd-nspawn -D /var/lib/machines/ftest -U --machine ftest`
|
|
|
|
2. set passwd: `passwd`
|
|
|
|
2. stop container: `logout`
|
|
|
|
|
|
|
|
## run as service
|
|
|
|
1. `systemctl start systemd-nspawn@ftest`
|
|
|
|
2. login: `machinectl login ftest`
|
|
|
|
2. start/enable network `systemctl enable --now systemd-networkd`
|
|
|
|
2. add regular user `useradd <username>`
|
|
|
|
|
|
|
|
## install applications
|
|
|
|
### locale
|
|
|
|
* install locales
|
|
|
|
* edit `/etc/locale.gen` to taste and then run the command `locale-gen`
|
|
|
|
### essential apps
|
|
|
|
```shell
|
|
|
|
apt-get install openssh-server git unzip wget sudo curl file rsync
|
|
|
|
```
|
|
|
|
### add regular user to sudo group
|
|
|
|
`usermod -a -G sudo <user>`
|
|
|
|
### other apps
|
|
|
|
```shell
|
|
|
|
apt-get install mosh htop haveged byobu needrestart tree bash-completion
|
|
|
|
```
|
|
|
|
### install openjdk-8 from stretch repo
|
|
|
|
1. add following to `/etc/apt/sources.list`
|
|
|
|
```cfg
|
|
|
|
deb http://security.debian.org/debian-security stretch/updates main
|
|
|
|
```
|
|
|
|
2. `apt-get update && apt-get install openjdk-8-jdk-headless`
|
|
|
|
|
|
|
|
## user environment
|
|
|
|
You can now ssh into your container.
|
|
|
|
|
|
|
|
scp your favorite environment files over to the container
|
|
|
|
|
|
|
|
* ~/.byobu/
|
|
|
|
* ~/.bashrc
|
|
|
|
* ~/.bash_aliases
|
|
|
|
* ~/.inputrc
|
|
|
|
|
|
|
|
## install flutter
|
|
|
|
Pick a location to taste; I prefer `~/.local/`
|
|
|
|
```shell
|
|
|
|
cd ; cd .local
|
|
|
|
git clone https://github.com/flutter/flutter.git
|
|
|
|
```
|
|
|
|
### downgrade flutter
|
|
|
|
if needed:
|
|
|
|
```shell
|
|
|
|
cd ~/.local/flutter
|
|
|
|
git checkout 2.2.3
|
|
|
|
```
|
|
|
|
## install command-line-tools
|
|
|
|
The schuck and jive here is absurd, but here goes.
|
|
|
|
|
|
|
|
Now is the time to decide where ANDROID_HOME and ANDROID_SDK_ROOT
|
|
|
|
are going to be; I prefer `~/.local/share/Android/Sdk/`
|
|
|
|
```shell
|
|
|
|
mkdir -p ~/.local/share/Android/Sdk
|
|
|
|
```
|
|
|
|
### temporary installation of cmdline-tools
|
|
|
|
[Command line tools only Scroll half way down](https://developer.android.com/studio){target="_blank"}
|
|
|
|
```shell
|
|
|
|
cd ~/.local/share/Android/Sdk
|
|
|
|
wget https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip
|
|
|
|
unzip commandlinetools-linux-7583922_latest.zip
|
|
|
|
mkdir 5.0
|
|
|
|
mv cmdline-tools/* 5.0/
|
|
|
|
mv 5.0 cmdline-tools/
|
|
|
|
```
|
|
|
|
|
|
|
|
## flutter and sdk environment
|
|
|
|
add the following to `~/.bashrc`
|
|
|
|
```cfg
|
|
|
|
function addToPATH {
|
|
|
|
case ":$PATH:" in
|
|
|
|
*":$1:"*) :;; # already there
|
|
|
|
*) PATH="$PATH:$1";; # or PATH="$PATH:$1"
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
addToPATH ~/.local/flutter/bin
|
|
|
|
addToPATH ~/.local/share/Android/Sdk/cmdline-tools/latest/bin
|
|
|
|
addToPATH ~/.local/share/Android/Sdk/platform-tools
|
|
|
|
|
|
|
|
# temporary path to temporary version of cmdline-tools
|
|
|
|
addToPATH ~/.local/share/Android/Sdk/cmdline-tools/5.0/bin
|
|
|
|
```
|
|
|
|
|
|
|
|
add the following to `~/.bash_aliases`
|
|
|
|
```cfg
|
|
|
|
alias sdkmanager='sdkmanager --sdk_root=~/.local/share/Android/Sdk'
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Confirm by logging out and then back in and:
|
|
|
|
```shell
|
|
|
|
which flutter ; which sdkmanager ; alias
|
|
|
|
```
|
|
|
|
|
|
|
|
### now install cmdline-tools for real
|
|
|
|
`sdkmanager --install "cmdline-tools;latest"`
|
|
|
|
|
|
|
|
and then logout and log back in
|
|
|
|
#### cleanup
|
|
|
|
At this point I think you can remove or comment the temporary PATH
|
|
|
|
statement from `~/.bashrc` for the temporary location of cmdline-tools
|
|
|
|
|
|
|
|
## install Android SDK
|
|
|
|
review your options
|
|
|
|
```shell
|
|
|
|
sdkmanager --list
|
|
|
|
```
|
|
|
|
and then install them
|
|
|
|
(platform-tools: adb and fastboot will be pulled in automatically)
|
|
|
|
```shell
|
|
|
|
sdkmanager --install "platforms;android-30" \
|
|
|
|
"build-tools;31.0.0" "build-tools;30.0.3"
|
|
|
|
```
|
|
|
|
|
|
|
|
## confirm flutter installation
|
|
|
|
`flutter doctor`
|
|
|
|
|
|
|
|
## run tests
|
|
|
|
At this point you shoud be able to rsync a flutter app over to the container, connect to a device using network adb,
|
|
|
|
and run something like:
|
|
|
|
```shell
|
|
|
|
flutter drive --driver integration_test/driver.dart \
|
|
|
|
--target integration_test/app_test.dart --profile
|
|
|
|
```
|