Skip to content

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

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

Merged
merged 1 commit into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
112 changes: 112 additions & 0 deletions .github/workflows/assets/linux.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# The Arduino IDE Linux build workflow job runs in this container.
# syntax=docker/dockerfile:1

FROM ubuntu:18.04

# See: https://unofficial-builds.nodejs.org/download/release/
ARG node_version="18.17.1"

RUN \
apt-get \
--yes \
update

# This is required to get add-apt-repository
RUN \
apt-get \
--yes \
install \
"software-properties-common=0.96.24.32.22"

# Install Git
# The PPA is required to get a modern version of Git. The version in the Ubuntu 18.04 package repository is 2.17.1,
# while action/checkout@v3 requires 2.18 or higher.
RUN \
add-apt-repository \
--yes \
"ppa:git-core/ppa" && \
apt-get \
--yes \
update && \
\
apt-get \
--yes \
install \
"git=1:2.42.0-0ppa1~ubuntu18.04.1" && \
\
apt-get \
--yes \
purge \
"software-properties-common"

# The repository path must be added to safe.directory, otherwise any Git operations on it would fail with a
# "dubious ownership" error. actions/checkout configures this, but it is not applied to containers.
RUN \
git config \
--add \
--global \
"safe.directory" "/__w/arduino-ide/arduino-ide"
ENV \
GIT_CONFIG_GLOBAL="/root/.gitconfig"

# Install Python
# The Python installed by actions/setup-python has dependency on a higher version of glibc than available in the
# ubuntu:18.04 container.
RUN \
apt-get \
--yes \
install \
"python3.8-minimal=3.8.0-3ubuntu1~18.04.2" && \
\
ln \
--symbolic \
--force \
"$(which python3.8)" \
"/usr/bin/python3"

# Install Theia's package dependencies
# These are pre-installed in the GitHub Actions hosted runner machines.
RUN \
apt-get \
--yes \
install \
"libsecret-1-dev=0.18.6-1" \
"libx11-dev=2:1.6.4-3ubuntu0.4" \
"libxkbfile-dev=1:1.0.9-2"

# Install Node.js
# It is necessary to use the "unofficial" linux-x64-glibc-217 build because the official Node.js 18.x is dynamically
# linked against glibc 2.28, while Ubuntu 18.04 has glibc 2.27.
ARG node_installation_path="/tmp/node-installation"
ARG artifact_name="node-v${node_version}-linux-x64-glibc-217"
RUN \
mkdir "$node_installation_path" && \
cd "$node_installation_path" && \
\
apt-get \
--yes \
install \
"wget=1.19.4-1ubuntu2.2" && \
\
archive_name="${artifact_name}.tar.xz" && \
wget \
"https://unofficial-builds.nodejs.org/download/release/v${node_version}/${archive_name}" && \
\
apt-get \
--yes \
purge \
"wget" && \
\
tar \
--file="$archive_name" \
--extract && \
rm "$archive_name"
ENV PATH="${PATH}:${node_installation_path}/${artifact_name}/bin"

# Install Yarn
# Yarn is pre-installed in the GitHub Actions hosted runner machines.
RUN \
npm \
install \
--global \
"[email protected]"
36 changes: 34 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ on:
- '*.md'
schedule:
- cron: '0 3 * * *' # run every day at 3AM (https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule)
workflow_run:
workflows:
- Push Container Images
branches:
- main
types:
- completed

env:
# See vars.GO_VERSION field of https://github.com/arduino/arduino-cli/blob/master/DistTasks.yml
Expand All @@ -49,6 +56,10 @@ env:
# Human identifier for the job.
name: Windows
runs-on: windows-2019
# The value is a string representing a JSON document.
# Setting this to null causes the job to run directly in the runner machine instead of in a container.
container: |
null
# Name of the secret that contains the certificate.
certificate-secret: WINDOWS_SIGNING_CERTIFICATE_PFX
# Name of the secret that contains the certificate password.
Expand All @@ -68,7 +79,11 @@ env:
name: Windows_X86-64_zip
- config:
name: Linux
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
container: |
{
\"image\": \"ghcr.io/arduino/arduino-ide/linux:main\"
}
mergeable-channel-file: 'false'
artifacts:
- path: '*Linux_64bit.zip'
Expand All @@ -78,6 +93,8 @@ env:
- config:
name: macOS x86
runs-on: macos-latest
container: |
null
# APPLE_SIGNING_CERTIFICATE_P12 secret was produced by following the procedure from:
# https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate
certificate-secret: APPLE_SIGNING_CERTIFICATE_P12
Expand All @@ -93,6 +110,8 @@ env:
- config:
name: macOS ARM
runs-on: macos-latest-xlarge
container: |
null
certificate-secret: APPLE_SIGNING_CERTIFICATE_P12
certificate-password-secret: KEYCHAIN_PASSWORD
certificate-extension: p12
Expand Down Expand Up @@ -255,20 +274,34 @@ jobs:
matrix:
config: ${{ fromJson(needs.select-targets.outputs.build-matrix) }}
runs-on: ${{ matrix.config.runs-on }}
container: ${{ fromJSON(matrix.config.container) }}
defaults:
run:
# Avoid problems caused by different default shell for container jobs (sh) vs non-container jobs (bash).
shell: bash

timeout-minutes: 90

steps:
- name: Checkout
if: fromJSON(matrix.config.container).image == null
uses: actions/checkout@v4

- name: Checkout
# actions/checkout@v4 has dependency on a higher version of glibc than available in the Linux container.
if: fromJSON(matrix.config.container).image != null
uses: actions/checkout@v3

- name: Install Node.js
if: fromJSON(matrix.config.container).image == null
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
cache: 'yarn'

- name: Install Python 3.x
if: fromJSON(matrix.config.container).image == null
uses: actions/setup-python@v4
with:
python-version: '3.x'
Expand All @@ -285,7 +318,6 @@ jobs:
version: 3.x

- name: Package
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AC_USERNAME: ${{ secrets.AC_USERNAME }}
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/check-containers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Check Containers

on:
pull_request:
paths:
- ".github/workflows/check-containers.ya?ml"
- "**.Dockerfile"
- "**/Dockerfile"
push:
paths:
- ".github/workflows/check-containers.ya?ml"
- "**.Dockerfile"
- "**/Dockerfile"
repository_dispatch:
schedule:
# Run periodically to catch breakage caused by external changes.
- cron: "0 7 * * MON"
workflow_dispatch:

jobs:
run:
name: Run (${{ matrix.image.path }})
runs-on: ubuntu-latest
permissions: {}
services:
registry:
image: registry:2
ports:
- 5000:5000

env:
IMAGE_NAME: name/app:latest
REGISTRY: localhost:5000

strategy:
fail-fast: false
matrix:
image:
- path: .github/workflows/assets/linux.Dockerfile

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

- name: Build and push to local registry
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.image.path }}
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Run container
run: |
docker \
run \
--rm \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
70 changes: 70 additions & 0 deletions .github/workflows/push-container-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Push Container Images

on:
pull_request:
paths:
- ".github/workflows/push-container-images.ya?ml"
push:
paths:
- ".github/workflows/push-container-images.ya?ml"
- "**.Dockerfile"
- "**/Dockerfile"
repository_dispatch:
schedule:
# Run periodically to catch breakage caused by external changes.
- cron: "0 8 * * MON"
workflow_dispatch:

jobs:
push:
name: Push (${{ matrix.image.name }})
# Only run the job when GITHUB_TOKEN has the privileges required for Container registry login.
if: >
(
github.event_name != 'pull_request' &&
github.repository == 'arduino/arduino-ide'
) ||
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == 'arduino/arduino-ide'
)
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

strategy:
fail-fast: false
matrix:
image:
- path: .github/workflows/assets/linux.Dockerfile
name: ${{ github.repository }}/linux
registry: ghcr.io

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

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ${{ matrix.image.registry }}
username: ${{ github.repository_owner }}

- name: Extract metadata for image
id: metadata
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image.registry }}/${{ matrix.image.name }}

- name: Build and push image
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.image.path }}
labels: ${{ steps.metadata.outputs.labels }}
# Workflow is triggered on relevant events for the sake of a "dry run" validation but image is only pushed to
# registry on commit to the main branch.
push: ${{ github.ref == 'refs/heads/main' }}
tags: ${{ steps.metadata.outputs.tags }}