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

chore: Add docker images for building the different platforms #11397

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9c7e2c8
change(common): preliminary update of min node version
ermshiperete May 8, 2024
2dffec3
docs(common): improve formatting of `builder.md`
ermshiperete May 6, 2024
d554415
change(common): add readme and `build.sh`
ermshiperete May 6, 2024
5c337be
feat(common): add base CI image
ermshiperete May 3, 2024
72bc6c7
feat(linux): add CI image for building Keyman for Linux
ermshiperete Apr 25, 2024
2767765
feat(web): add CI image for building Keyman Web
ermshiperete Apr 25, 2024
23d8a01
feat(android): add CI image for building Keyman for Android
ermshiperete May 3, 2024
8a4cdce
feat(core): add CI image for building Keyman Core
ermshiperete May 6, 2024
1ad55b1
Merge branch 'master' into chore/linux/cicontainer
mcdurdin Aug 27, 2024
ad4bbdf
feat(common): add script to run build and tests in Docker container
ermshiperete Aug 28, 2024
cc5fef0
Merge branch 'master' into chore/linux/cicontainer
ermshiperete Aug 30, 2024
d6c5320
chore(linux): address code review comments
ermshiperete Aug 29, 2024
1772fdf
chore(linux): pre-install EMSCRIPTEN
ermshiperete Aug 31, 2024
6b34c5c
Merge branch 'master' into chore/linux/cicontainer
ermshiperete Sep 1, 2024
0d6f655
chore(linux): fix build order
ermshiperete Sep 3, 2024
475fd73
docs(android): document gradle version in `minimum-versions`
ermshiperete Sep 11, 2024
caba09a
chore(linux): attempt to fix Android build in Docker
ermshiperete Sep 11, 2024
e23e112
chore(linux): remove temporary code for Core image
ermshiperete Sep 11, 2024
e54f822
chore(linux): cleanup
ermshiperete Sep 11, 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
90 changes: 16 additions & 74 deletions docs/build/linux-ubuntu.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,83 +225,25 @@ Android projects. `JAVA_HOME_11` is mostly used by CI.
## Docker Builder

The Docker builder allows you to perform a build from anywhere Docker is supported.

To build the docker image:

```shell
cd linux
docker pull ubuntu:latest # (to make sure you have an up-to-date image)
docker build . -t keymanapp/keyman-linux-builder:latest
```

Once the image is built, it may be used to build parts of Keyman.

**Note** that it's not yet possible to run tests in the Docker container.

- core

```shell
# build 'Keyman Core' in docker
# keep linux build artifacts separate
mkdir -p $(git rev-parse --show-toplevel)/core/build/linux
docker run -it --rm -v $(git rev-parse --show-toplevel):/home/build/build \
-v $(git rev-parse --show-toplevel)/core/build/linux:/home/build/build/core/build \
keymanapp/keyman-linux-builder:latest \
core/build.sh --debug
```

- linux

```shell
# build 'Keyman for Linux' installation in docker
docker run -it --rm -v $(git rev-parse --show-toplevel):/home/build/build \
--entrypoint /bin/bash keymanapp/keyman-linux-builder:latest \
-c 'DESTDIR=/home/build /usr/bin/bashwrapper linux/build.sh --debug build install'
```

- Keyman Web

```shell
# build 'Keyman Web' in docker
docker run --privileged -it --rm \
-v $(git rev-parse --show-toplevel):/home/build/build \
keymanapp/keyman-linux-builder:latest \
web/build.sh --debug
```

- Keyman for Android

```shell
# build 'Keyman for Android' in docker
docker run -it --rm -v $(git rev-parse --show-toplevel):/home/build/build \
keymanapp/keyman-linux-builder:latest \
android/build.sh --debug
```

### Customizing the builder

You can use Docker [build args](https://docs.docker.com/build/guide/build-args/) to customize the image build. As an example, the following will build an image explicitly with Ubuntu 23.04 and Node.js 20. Check the [Dockerfile](../../linux/Dockerfile) for `ARG` entries.

```shell
cd linux
docker pull ubuntu:23.04 # (to make sure you have an up-to-date image)
docker build . -t keymanapp/keyman-linux-builder:u23.04-node20 --build-arg OS_VERSION=23.04 --build-arg NODE_MAJOR=20
````
See [this README.md](../../resources/docker-images/README.md) for details.

### Using the builder with VSCode [Dev Containers](https://code.visualstudio.com/docs/devcontainers/tutorial)

1. Save the following as `.devcontainer/devcontainer.json`, updating the `image` to match the Docker image built above.
1. Save the following as `.devcontainer/devcontainer.json`, updating the `image`
to match the Docker image built above.

```json
// file: .devcontainer/devcontainer.json
{
"name": "Keyman Ubuntu 23.04",
"image": "keymanapp/keyman-linux-builder:u23.04-node18"
}
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
```
```json
// file: .devcontainer/devcontainer.json
{
"name": "Keyman Ubuntu 23.04",
"image": "keymanapp/keyman-linux-builder:u23.04-node18"
}
// For format details, see https://aka.ms/devcontainer.json. For config options,
// see the README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
```

2. in VSCode, use the "Dev Containers: Open Folder In Container…" option and choose the Keyman directory.
2. in VSCode, use the "Dev Containers: Open Folder In Container…" option and
choose the Keyman directory.

3. You will be given a window which is running VSCode inside this builder image, regardless of your host OS.
3. You will be given a window which is running VSCode inside this builder
image, regardless of your host OS.
1 change: 1 addition & 0 deletions docs/minimum-versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ https://help.keyman.com/developer/engine/android/latest-version/
| KEYMAN_MIN_VERSION_NPM | 10.5.1 |
| KEYMAN_MIN_VERSION_VISUAL_STUDIO | 2019 |
| KEYMAN_VERSION_CLDR | 45 |
| KEYMAN_VERSION_GRADLE | 7.6.4 |
| KEYMAN_VERSION_ICU | 73.1 |
| KEYMAN_VERSION_ISO639_3 | 2024-05-22 |
| KEYMAN_VERSION_JAVA | 11 |
Expand Down
90 changes: 0 additions & 90 deletions linux/Dockerfile

This file was deleted.

5 changes: 2 additions & 3 deletions resources/build/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,12 @@ This somewhat unwieldy incantation handles all our build environments.
The intent is to get a good solid consistent path for the script so that we can
safely include the build script, no matter what `pwd` is when the script is run.


The only modification permissible in this block is the
`<relative-path-to-repo-root>` text which will be a series of `../` paths taking
us to the repository root from the location of the script itself.

It is essential to make the include relative to the repo root, even for scripts
under the resources/ folder. Doing this gives us significant performance
under the `resources/` folder. Doing this gives us significant performance
benefits.

Inclusion of other scripts should be kept outside this standard build script
Expand Down Expand Up @@ -1095,4 +1094,4 @@ Note: it is recommended that you use `$(builder_term text)` instead of
[`builder_echo`]: #builderecho-function
[`builder_die`]: #builderdie-function
[`builder_echo_debug`]: #builderechodebug-function
[`builder_is_debug_build`]: #builderisdebugbuild-function
[`builder_is_debug_build`]: #builderisdebugbuild-function
3 changes: 2 additions & 1 deletion resources/build/minimum-versions.inc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.58 # Use KEYMAN_USE_EMSDK to automati
KEYMAN_MIN_VERSION_VISUAL_STUDIO=2019
KEYMAN_MIN_VERSION_MESON=1.0.0

KEYMAN_VERSION_ICU=73.1 # See /core/subprojects/icu-minimal.wrap
KEYMAN_VERSION_GRADLE=7.6.4 # See /android/KMEA/gradle/wrapper/gradle-wrapper.properties
KEYMAN_VERSION_ICU=73.1 # See /core/subprojects/icu-minimal.wrap

# Language and runtime versions
KEYMAN_VERSION_JAVA=11 # We're using Java/OpenJDK 11
Expand Down
65 changes: 65 additions & 0 deletions resources/docker-images/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Container

Docker containers that can be used to build Keyman on the respective
platforms. They contain everything that a CI build agent needs to
build for the platform.

## Prerequisites

You'll need Docker Buildx installed to successfully be able to build the
container images. This is most easily achieved by installing the [official
Docker version](https://docs.docker.com/engine/install/ubuntu/).

Currently it is not possible to use Podman instead of Docker due to a number
of bugs and incompatibilities in the Podman implementation.

## Building the images

To build the docker images:

```shell
resources/docker-images/build.sh
```

By default this will create 64-bit images for building
Keyman Core, Keyman for Android, Keyman for Linux and
Keyman for Web. These images are based on the Ubuntu 24.04
with Node 20 and Emscripten 3.1.58 (for the exact versions,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the Dockerfiles below use Node 18?

ARG REQUIRED_NODE_VERSION=18

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's just the default value that doesn't get used. The node version get's passed in. I had to put something here, so I choose a somewhat sensible value that is different from what we currently have so that it's easier noticable if passing the value doesn't work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be node 20 -- I think the req shifted since this PR started

see [`minimum-versions.inc.sh`](../build/minimum-versions.inc.sh))
and are named e.g. `keyman-core-ci:default`.

The versions can be changed, e.g.

```shell
resources/docker-images/build.sh --ubuntu-version jammy --node 20
```

This will create an image named e.g. `keyman-core-ci:jammy-node20`.

Once the image is built, it may be used to build parts of Keyman.

## Building locally

It is possible to build locally with these images:

```shell
# build 'Keyman Core' in docker
resources/docker-images/run.sh core -- core/build.sh --debug build
```

Note: For Core and Linux we put the generated binaries in a
container specific directory because they are platform dependent.

If you build both with Docker and directly with the build scripts, it is
advisable to run a `git clean -dxf` before switching between the two. The
reason is that the Docker images use a different user, so that paths
will be different.

## Running tests locally

To run the tests locally, use the `run.sh` script:

```shell
# Run common/web tests
resources/docker-images/run.sh web -- common/web/build.sh --debug test
```
65 changes: 65 additions & 0 deletions resources/docker-images/android/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright (c) 2024 SIL International. All rights reserved.

ARG BASE_VERSION=default
FROM keymanapp/keyman-base-ci:${BASE_VERSION}
LABEL org.opencontainers.image.authors="SIL International."
LABEL org.opencontainers.image.url="https://github.com/keymanapp/keyman.git"
LABEL org.opencontainers.image.title="Keyman Android Build Image"

# Keyman for Android
SHELL ["/bin/bash", "-c"]

# Starting with Ubuntu 24.04 sdkmanager is no longer available, instead
# a version dependent package allows to install the cmdline tools
ARG JAVA_VERSION=11
RUN <<EOF
OS_VER=$(lsb_release -r -s 2>/dev/null)
echo "OS_VER=${OS_VER}"
if (( ${OS_VER%%.*} > 22 )); then
PKG_SDKMANAGER=google-android-cmdline-tools-13.0-installer
DIR_SDK=/usr/lib/android-sdk
else
PKG_SDKMANAGER=sdkmanager
DIR_SDK=/opt/android-sdk
fi
apt-get -q -y install gradle maven pandoc $PKG_SDKMANAGER jq openjdk-${JAVA_VERSION}-jdk
sdkmanager platform-tools
yes | sdkmanager --licenses
chown -R build:build $DIR_SDK
echo "export ANDROID_HOME=$DIR_SDK" >> /usr/bin/bashwrapper
echo "export JAVA_HOME_${JAVA_VERSION}=/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64" >> /usr/bin/bashwrapper
EOF

# Finish bashwrapper script and adjust permissions
RUN <<EOF cat >> /usr/bin/bashwrapper

if [[ "\$@" =~ test ]] && [ -f /usr/bin/run-tests.sh ]; then
/usr/bin/run-tests.sh "\${@:-bash}"
else
"\${@:-bash}"
fi
EOF

# now, switch to build user
USER build

VOLUME /home/build/build
WORKDIR /home/build/build

# Pre-install gradle. This will put files in ~/.gradle which will speed up builds.
RUN mkdir -p $HOME/tmp/gradle/wrapper && \
# KMEA uses gradle-7.6.4-bin
curl --location --output $HOME/tmp/gradle/wrapper/gradle-wrapper.jar https://raw.githubusercontent.com/keymanapp/keyman/master/android/KMEA/gradle/wrapper/gradle-wrapper.jar && \
curl --location --output $HOME/tmp/gradle/wrapper/gradle-wrapper.properties https://raw.githubusercontent.com/keymanapp/keyman/master/android/KMEA/gradle/wrapper/gradle-wrapper.properties && \
curl --location --output $HOME/tmp/gradlew https://raw.githubusercontent.com/keymanapp/keyman/master/android/KMEA/gradlew && \
chmod +x $HOME/tmp/gradlew && \
$HOME/tmp/gradlew --quiet && \
# Some projects use gradle-7.6.4-all, so we pre-install that as well
curl --location --output $HOME/tmp/gradle/wrapper/gradle-wrapper.jar https://raw.githubusercontent.com/keymanapp/keyman/master/android/Samples/KMSample1/gradle/wrapper/gradle-wrapper.jar && \
curl --location --output $HOME/tmp/gradle/wrapper/gradle-wrapper.properties https://raw.githubusercontent.com/keymanapp/keyman/master/android/Samples/KMSample1/gradle/wrapper/gradle-wrapper.properties && \
curl --location --output $HOME/tmp/gradlew https://raw.githubusercontent.com/keymanapp/keyman/master/android/Samples/KMSample1/gradlew && \
chmod +x $HOME/tmp/gradlew && \
$HOME/tmp/gradlew --quiet && \
rm -rf $HOME/tmp

ENTRYPOINT [ "/usr/bin/bashwrapper" ]
Loading
Loading