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

Make Linux build in a container for compatibility with older distros #2253

Merged
merged 1 commit into from
Oct 12, 2023

Conversation

per1234
Copy link
Contributor

@per1234 per1234 commented Oct 10, 2023

Background

The Linux build of Arduino IDE is dynamically linked against the libstdc++ and glibc shared libraries. This results in it having a dependency on the version of the libraries that happen to be present in the environment it is built in.

Although newer versions of the shared libraries are compatible with executables linked against an older version, the reverse is not true. This means that building Arduino IDE on a Linux machine with a recent distro version installed causes the IDE to error on startup for users who have a distro with older versions of the dependencies (#2018). For example:

Error: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by /home/per/Downloads/arduino-ide_nightly-20231006_Linux_64bit/resources/app/lib/backend/native/nsfw.node)

or:

Error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /home/per/Downloads/arduino-ide_2.0.5-snapshot-90b1f67_Linux_64bit/resources/app/node_modules/nsfw/build/Release/nsfw.node)

We were originally able to achieve our targeted range of Linux distro compatibility by running the Linux build in the ubuntu-18.04 GitHub Actions hosted runner machine. Unfortunately GitHub stopped offering that runner machine. This meant we were forced to update to using the ubuntu-20.04 runner machine instead (#1983), which caused the loss of compatibility of the automatically generated builds with previously supported distro versions (e.g., Ubuntu 18.04). Since that time, the release builds have been produced manually, which is inefficient and prone to human error.

Update

The identified solution to restoring fully automated builds with the target range of Linux distro compatibility is to run the build in a Docker container that provides the suitable environment. This means a combination of an older distro version with the modern versions of the development tool dependencies of the build.

Such a combination was achieved by creating a bespoke image based on the ubuntu:18.04 image. The Dockerfile is hosted in the Arduino IDE repository in order to allow it to be maintained in parallel with the code and infrastructure.

Image Publishing

A "Push Container Images" GitHub Actions continuous delivery workflow is added to push updated images to the GitHub Container registry when a commit that modifies relevant files is pushed to the main branch.

The ghcr.io/arduino/arduino-ide/linux:main image should be built and pushed to the GitHub Container registry under the arduino organization upon the merge of this pull request. Arduino is already making use of the Container registry for several other projects:

https://github.com/orgs/arduino/packages

The push strategy described above means the image does not have formally versioned tags and the IDE build uses the container that results from the configuration at the tip of the main branch at the time of the build. I think that is a reasonable approach in this use case where the image is targeted to a single application rather than intended to be used by multiple projects.

Container Validation

The build workflow is configured to trigger on completion of that push workflow in order to provide validation of the IDE build using the updated container as well as the resulting tester builds of the IDE.

A "Check Containers" GitHub Actions continuous integration workflow is added to provide basic validation for changes to the Dockerfile. It will automatically build the image and run the container on any push or pull request that modifies relevant files.

Container Workflow Design

With the goal of reusability, the image data is contained in a job matrix in the workflow to allow them to accommodate any number of arbitrary images.

Build Workflow Configuration

A container property is added to the build job matrix data. If the container property is set to null, GitHub Actions will run the job directly in the runner environment instead of in a container. This allows us to produce the builds using either a container or a bare runner machine as is appropriate for each target.

Unfortunately the latest v4 version of the actions/checkout action used to checkout the repository into the job environment has a dependency on a higher version of glibc than is provided by the Linux container (actions/checkout#1442). For this reason, the workflow is configured to use actions/checkout@v3 for the Linux build job. We will likely receive pull requests from Dependabot offering to update this outdated action dependency for the v4 (UPDATE: here #2257) and at each subsequent major version release of the action (which are not terribly frequent). We must decline the bump of the action in that specific step, but accept the bumps of all other usages of the action in the workflows. Dependabot remembers when you decline a bump so this should not be too bothersome.

Information For Reviewers

Demonstration full run of the "Push Container Images" workflow in my fork:

https://github.com/per1234/arduino-ide/actions/runs/6479854195

The image published to GitHub Container registry via that run under my GitHub account:

https://github.com/per1234/arduino-ide/pkgs/container/arduino-ide%2Flinux/136273836?tag=test-ubuntu-18.04

Demonstration full run of the "Arduino IDE" build workflow using the image above for the Linux build job:

https://github.com/per1234/arduino-ide/actions/runs/6479878430

Note that the ~11 minute job duration from that run with the updated workflow is comparable to the ~12 minute job duration of the latest run in the bare ubuntu-20.04 runner machine.


The failure of the "Arduino IDE" workflow run triggered by this PR is expected due to the fact that the ghcr.io/arduino/arduino-ide/linux:main container image won't be published until the merge to the main branch.


Fixes #2018

@per1234 per1234 added topic: infrastructure Related to project infrastructure os: linux Specific to Linux operating system type: imperfection Perceived defect in any part of project labels Oct 10, 2023
@per1234 per1234 requested review from kittaakos and umbynos October 10, 2023 15:51
@per1234 per1234 self-assigned this Oct 10, 2023
Background
----------

The Linux build of Arduino IDE is dynamically linked against the libstdc++ and glibc shared libraries. This results in
it having a dependency on the version of the libraries that happens to be present in the environment it is built in.

Although newer versions of the shared libraries are compatible with executables linked against an older version, the
reverse is not true. This means that building Arduino IDE on a Linux machine with a recent distro version installed
causes the IDE to error on startup for users who have a distro with older versions of the dependencies. For example:

```
Error: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by /home/per/Downloads/arduino-ide_nightly-20231006_Linux_64bit/resources/app/lib/backend/native/nsfw.node)
```

or:

```
Error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /home/per/Downloads/arduino-ide_2.0.5-snapshot-90b1f67_Linux_64bit/resources/app/node_modules/nsfw/build/Release/nsfw.node)
```

We were originally able to achieve our targeted range of Linux distro compatibility by running the Linux build in the
ubuntu-18.04 GitHub Actions hosted runner machine. Unfortunately GitHub stopped offering that runner machine. This meant
we were forced to update to using the ubuntu-20.04 runner machine instead, which caused the loss of compatibility of
the automatically generated builds with previously supported distro versions (e.g., Ubuntu 18.04). Since that time, the
release builds have been produced manually, which is inefficient and prone to human error.

Update
------

The identified solution to restoring fully automated builds with the target range of Linux distro compatibility is to
run the build in a Docker container that provides the suitable environment. This means a combination of an older distro
version with the modern versions of the development tool dependencies of the build.

Such a combination was achieved by creating a bespoke image based on the ubuntu:18.04 image. The Dockerfile is hosted in
the Arduino IDE repository in order to allow it to be maintained in parallel with the code and infrastructure.

Image Publishing
----------------

A "Push Container Images" GitHub Actions continuous delivery workflow is added to push updated images to the GitHub
Container registry when a commit that modifies relevant files is pushed to the main branch.

This means the image does not have formally versioned tags and the IDE build uses the container that results from the
configuration at the tip of the main branch at the time of the build. I think that is a reasonable approach in this use
case where the image is targeted to a single application rather than intended to be used by multiple projects.

Container Validation
--------------------

The build workflow is configured to trigger on completion of that push workflow in order to provide validation of the IDE build using the
updated container as well as the resulting tester builds of the IDE.

A "Check Containers" GitHub Actions continuous integration workflow is added to provide basic validation for changes to
the Dockerfile. It will automatically build the image and run the container on any push or pull request that modifies
relevant files.

Container Workflow Design
-------------------------

With the goal of reusability, the image data is contained in a job matrix in the workflow to allow them to accommodate
any number of arbitrary images.

Build Workflow Configuration
----------------------------

A container property is added to the build job matrix data. If the container.image property is set to null, GitHub
Actions will run the job directly in the runner environment instead of in a container. This allows us to produce the
builds using either a container or a bare runner machine as is appropriate for each target.

Unfortunately the latest v4 version of the actions/checkout action used to checkout the repository into the job
environment has a dependency on a higher version of glibc than is provided by the Linux container. For this reason, the
workflow is configured to use actions/checkout@v3 for the Linux build job. We will likely receive pull requests from
Dependabot offering to update this outdated action dependency for the v4 and at each subsequent major version release of
the action (which are not terribly frequent). We must decline the bump of the action in that specific step, but accept
the bumps of all other usages of the action in the workflows. Dependabot remembers when you decline a bump so this
should not be too bothersome.
Copy link
Contributor

@kittaakos kittaakos left a comment

Choose a reason for hiding this comment

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

Thank you, Per. It's looking great!

Copy link

@umbynos umbynos left a comment

Choose a reason for hiding this comment

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

Awesome work Per

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
os: linux Specific to Linux operating system topic: infrastructure Related to project infrastructure type: imperfection Perceived defect in any part of project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Current test/nightly builds not compatible with Ubuntu 18.04
3 participants