Skip to content

Commit 8e46694

Browse files
committed
Add tests for non-native architectures
This change introduces a new job to the CI to test the SDK on non-native architectures. Github CI ATM provides amd64 runners by default, so the new job targets testing on arch64 for now. The tests are run in containers running on the target platform(s). The container definitions are supposed to exist in the directory .github/containers/nox-cross-arch. A definition for an arm64-ubuntu20.04-python3.11 container can be found there. Since the tests take quite a while to run, given that they run on emulations, this step runs only on the `merge_group` event. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 0b9a154 commit 8e46694

File tree

21 files changed

+1091
-7
lines changed

21 files changed

+1091
-7
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# License: MIT
2+
# Copyright © 2023 Frequenz Energy-as-a-Service GmbH
3+
4+
# This Dockerfile is used to test the installation of the python package in
5+
# multiple platforms in the CI. It is not used to build the package itself.
6+
7+
FROM docker.io/library/ubuntu:20.04
8+
9+
ENV DEBIAN_FRONTEND=noninteractive
10+
11+
# Install Python 3.11 and curl to install pip later
12+
RUN apt-get update -y && \
13+
apt-get install --no-install-recommends -y \
14+
software-properties-common && \
15+
add-apt-repository ppa:deadsnakes/ppa && \
16+
apt-get install --no-install-recommends -y \
17+
ca-certificates \
18+
curl \
19+
git \
20+
python3.11 \
21+
python3.11-distutils && \
22+
apt-get clean && \
23+
rm -rf /var/lib/apt/lists/*
24+
25+
# Install pip
26+
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.11
27+
28+
RUN update-alternatives --install \
29+
/usr/local/bin/python python /usr/bin/python3.11 1 && \
30+
python -m pip install --upgrade --no-cache-dir pip
31+
32+
COPY entrypoint.bash /usr/bin/entrypoint.bash
33+
34+
ENTRYPOINT ["/usr/bin/entrypoint.bash"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
# License: MIT
3+
# Copyright © 2023 Frequenz Energy-as-a-Service GmbH
4+
set -e
5+
6+
echo "System details:" $(uname -a)
7+
echo "Machine:" $(uname -m)
8+
9+
exec "$@"

.github/workflows/ci.yaml

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,118 @@ jobs:
9292
- name: Return true
9393
run: "true"
9494

95+
nox-cross-arch:
96+
name: Cross-arch tests with nox
97+
if: github.event_name != 'pull_request'
98+
strategy:
99+
fail-fast: false
100+
# Before adding new items to this matrix, make sure that a dockerfile
101+
# exists for the combination of items in the matrix.
102+
# Refer to .github/containers/nox-cross-arch/README.md to learn how to
103+
# add and name new dockerfiles.
104+
matrix:
105+
arch:
106+
- arm64
107+
os:
108+
- ubuntu-20.04
109+
python:
110+
- "3.11"
111+
nox-session:
112+
- "pytest_min"
113+
- "pytest_max"
114+
runs-on: ${{ matrix.os }}
115+
116+
steps:
117+
- name: Fetch sources
118+
uses: actions/checkout@v4
119+
120+
- name: Set up QEMU
121+
uses: docker/setup-qemu-action@v3
122+
with:
123+
platforms: linux/${{ matrix.arch }}
124+
125+
- name: Set up Docker Buildx
126+
uses: docker/setup-buildx-action@v3
127+
128+
# This is a workaround to prevent the cache from growing indefinitely.
129+
# https://docs.docker.com/build/ci/github-actions/cache/#local-cache
130+
# https://github.com/docker/build-push-action/issues/252
131+
# https://github.com/moby/buildkit/issues/1896
132+
- name: Cache container layers
133+
uses: actions/cache@v3
134+
with:
135+
path: /tmp/.buildx-cache
136+
key: ${{ runner.os }}-buildx-nox-${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.python }}
137+
138+
- name: Build image
139+
uses: docker/build-push-action@v5
140+
with:
141+
context: .github/containers/nox-cross-arch
142+
file: .github/containers/nox-cross-arch/${{ matrix.arch }}-${{ matrix.os }}-python-${{ matrix.python }}.Dockerfile
143+
platforms: linux/${{ matrix.arch }}
144+
tags: localhost/nox-cross-arch:latest
145+
push: false
146+
load: true
147+
cache-from: type=local,src=/tmp/.buildx-cache
148+
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
149+
150+
# Refer to the workaround mentioned above
151+
- name: Move cache
152+
run: |
153+
rm -rf /tmp/.buildx-cache
154+
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
155+
156+
# Cache pip downloads
157+
- name: Cache pip downloads
158+
uses: actions/cache@v3
159+
with:
160+
path: /tmp/pip-cache
161+
key: nox-${{ matrix.nox-session }}-${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.python }}-${{ hashFiles('**/pyproject.toml') }}
162+
163+
# This ensures that the docker container has access to the pip cache.
164+
# Changing the user in the docker-run step causes it to fail due to
165+
# incorrect permissions. Setting the ownership of the pip cache to root
166+
# before running is a workaround to this issue.
167+
- name: Set pip cache owners to root for docker
168+
run: if [[ -e /tmp/pip-cache ]]; then sudo chown -R root:root /tmp/pip-cache; fi
169+
170+
- name: Run nox
171+
run: |
172+
docker run \
173+
--rm \
174+
-v $(pwd):/${{ github.workspace }} \
175+
-v /tmp/pip-cache:/root/.cache/pip \
176+
-w ${{ github.workspace }} \
177+
--net=host \
178+
--platform linux/${{ matrix.arch }} \
179+
localhost/nox-cross-arch:latest \
180+
bash -c "pip install -e .[dev-noxfile]; nox --install-only -e ${{ matrix.nox-session }}; pip freeze; nox -e ${{ matrix.nox-session }}"
181+
timeout-minutes: 30
182+
183+
# This ensures that the runner has access to the pip cache.
184+
- name: Reset pip cache ownership
185+
if: always()
186+
run: sudo chown -R $USER:$USER /tmp/pip-cache
187+
188+
# This job runs if all the `nox-cross-arch` matrix jobs ran and succeeded.
189+
# As the `nox-all` job, its main purpose is to provide a single point of
190+
# reference in branch protection rules, similar to how `nox-all` operates.
191+
# However, there's a crucial difference: the `nox-cross-arch` job is omitted
192+
# in PRs. Without the `nox-cross-arch-all` job, the inner matrix wouldn't be
193+
# expanded in such scenarios. This would lead to the CI indefinitely waiting
194+
# for these jobs to complete due to the branch protection rules, essentially
195+
# causing it to hang. This behavior is tied to a recognized GitHub matrices
196+
# issue when certain jobs are skipped. For a deeper understanding, refer to:
197+
# https://github.com/orgs/community/discussions/9141
198+
nox-cross-arch-all:
199+
# The job name should match the name of the `nox-cross-arch` job.
200+
name: Cross-arch tests with nox
201+
needs: ["nox-cross-arch"]
202+
runs-on: ubuntu-20.04
203+
steps:
204+
- name: Return true
205+
run: "true"
206+
95207
build:
96208
name: Build distribution packages
97209
runs-on: ubuntu-20.04
@@ -189,7 +301,7 @@ jobs:
189301

190302
publish-docs:
191303
name: Publish documentation website to GitHub pages
192-
needs: ["nox-all", "test-installation"]
304+
needs: ["nox-all", "nox-cross-arch-all", "test-installation"]
193305
if: github.event_name == 'push'
194306
runs-on: ubuntu-20.04
195307
permissions:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# License: {{cookiecutter.license}}
2+
# Copyright © {% now 'utc', '%Y' %} {{cookiecutter.author_name}}
3+
{% raw -%}
4+
5+
# This Dockerfile is used to run the tests in architectures not supported by
6+
# GitHub Actions.
7+
8+
FROM docker.io/library/ubuntu:20.04
9+
10+
ENV DEBIAN_FRONTEND=noninteractive
11+
12+
# Install Python 3.11 and curl to install pip later
13+
RUN apt-get update -y && \
14+
apt-get install --no-install-recommends -y \
15+
software-properties-common && \
16+
add-apt-repository ppa:deadsnakes/ppa && \
17+
apt-get install --no-install-recommends -y \
18+
ca-certificates \
19+
curl \
20+
git \
21+
python3.11 \
22+
python3.11-distutils && \
23+
apt-get clean && \
24+
rm -rf /var/lib/apt/lists/*
25+
26+
# Install pip
27+
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.11
28+
29+
RUN update-alternatives --install \
30+
/usr/local/bin/python python /usr/bin/python3.11 1 && \
31+
python -m pip install --upgrade --no-cache-dir pip
32+
33+
COPY entrypoint.bash /usr/bin/entrypoint.bash
34+
35+
ENTRYPOINT ["/usr/bin/entrypoint.bash"]
36+
{%- endraw %}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
# License: {{cookiecutter.license}}
3+
# Copyright © {% now 'utc', '%Y' %} {{cookiecutter.author_name}}
4+
{% raw -%}
5+
set -e
6+
7+
echo "System details:" $(uname -a)
8+
echo "Machine:" $(uname -m)
9+
10+
exec "$@"
11+
{%- endraw %}

cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci.yaml

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,118 @@ jobs:
118118
- name: Return true
119119
run: "true"
120120

121+
nox-cross-arch:
122+
name: Cross-arch tests with nox
123+
if: github.event_name != 'pull_request'
124+
strategy:
125+
fail-fast: false
126+
# Before adding new items to this matrix, make sure that a dockerfile
127+
# exists for the combination of items in the matrix.
128+
# Refer to .github/containers/nox-cross-arch/README.md to learn how to
129+
# add and name new dockerfiles.
130+
matrix:
131+
arch:
132+
- arm64
133+
os:
134+
- ubuntu-20.04
135+
python:
136+
- "3.11"
137+
nox-session:
138+
- "pytest_min"
139+
- "pytest_max"
140+
runs-on: ${{ matrix.os }}
141+
142+
steps:
143+
- name: Fetch sources
144+
uses: actions/checkout@v4
145+
146+
- name: Set up QEMU
147+
uses: docker/setup-qemu-action@v3
148+
with:
149+
platforms: linux/${{ matrix.arch }}
150+
151+
- name: Set up Docker Buildx
152+
uses: docker/setup-buildx-action@v3
153+
154+
# This is a workaround to prevent the cache from growing indefinitely.
155+
# https://docs.docker.com/build/ci/github-actions/cache/#local-cache
156+
# https://github.com/docker/build-push-action/issues/252
157+
# https://github.com/moby/buildkit/issues/1896
158+
- name: Cache container layers
159+
uses: actions/cache@v3
160+
with:
161+
path: /tmp/.buildx-cache
162+
key: ${{ runner.os }}-buildx-nox-${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.python }}
163+
164+
- name: Build image
165+
uses: docker/build-push-action@v5
166+
with:
167+
context: .github/containers/nox-cross-arch
168+
file: .github/containers/nox-cross-arch/${{ matrix.arch }}-${{ matrix.os }}-python-${{ matrix.python }}.Dockerfile
169+
platforms: linux/${{ matrix.arch }}
170+
tags: localhost/nox-cross-arch:latest
171+
push: false
172+
load: true
173+
cache-from: type=local,src=/tmp/.buildx-cache
174+
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
175+
176+
# Refer to the workaround mentioned above
177+
- name: Move cache
178+
run: |
179+
rm -rf /tmp/.buildx-cache
180+
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
181+
182+
# Cache pip downloads
183+
- name: Cache pip downloads
184+
uses: actions/cache@v3
185+
with:
186+
path: /tmp/pip-cache
187+
key: nox-${{ matrix.nox-session }}-${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.python }}-${{ hashFiles('**/pyproject.toml') }}
188+
189+
# This ensures that the docker container has access to the pip cache.
190+
# Changing the user in the docker-run step causes it to fail due to
191+
# incorrect permissions. Setting the ownership of the pip cache to root
192+
# before running is a workaround to this issue.
193+
- name: Set pip cache owners to root for docker
194+
run: if [[ -e /tmp/pip-cache ]]; then sudo chown -R root:root /tmp/pip-cache; fi
195+
196+
- name: Run nox
197+
run: |
198+
docker run \
199+
--rm \
200+
-v $(pwd):/${{ github.workspace }} \
201+
-v /tmp/pip-cache:/root/.cache/pip \
202+
-w ${{ github.workspace }} \
203+
--net=host \
204+
--platform linux/${{ matrix.arch }} \
205+
localhost/nox-cross-arch:latest \
206+
bash -c "pip install -e .[dev-noxfile]; nox --install-only -e ${{ matrix.nox-session }}; pip freeze; nox -e ${{ matrix.nox-session }}"
207+
timeout-minutes: 30
208+
209+
# This ensures that the runner has access to the pip cache.
210+
- name: Reset pip cache ownership
211+
if: always()
212+
run: sudo chown -R $USER:$USER /tmp/pip-cache
213+
214+
# This job runs if all the `nox-cross-arch` matrix jobs ran and succeeded.
215+
# As the `nox-all` job, its main purpose is to provide a single point of
216+
# reference in branch protection rules, similar to how `nox-all` operates.
217+
# However, there's a crucial difference: the `nox-cross-arch` job is omitted
218+
# in PRs. Without the `nox-cross-arch-all` job, the inner matrix wouldn't be
219+
# expanded in such scenarios. This would lead to the CI indefinitely waiting
220+
# for these jobs to complete due to the branch protection rules, essentially
221+
# causing it to hang. This behavior is tied to a recognized GitHub matrices
222+
# issue when certain jobs are skipped. For a deeper understanding, refer to:
223+
# https://github.com/orgs/community/discussions/9141
224+
nox-cross-arch-all:
225+
# The job name should match the name of the `nox-cross-arch` job.
226+
name: Cross-arch tests with nox
227+
needs: ["nox-cross-arch"]
228+
runs-on: ubuntu-20.04
229+
steps:
230+
- name: Return true
231+
run: "true"
232+
121233
build:
122234
name: Build distribution packages
123235
runs-on: ubuntu-20.04
@@ -216,7 +328,7 @@ jobs:
216328
publish-docs:
217329
name: Publish documentation website to GitHub pages
218330
{% endraw -%}
219-
needs: ["nox-all", "test-installation"{{', "protolint"' if cookiecutter.type == "api"}}]
331+
needs: ["nox-all", "nox-cross-arch-all", "test-installation"{{', "protolint"' if cookiecutter.type == "api"}}]
220332
{% raw -%}
221333
if: github.event_name == 'push'
222334
runs-on: ubuntu-20.04
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# License: MIT
2+
# Copyright © 2023 Frequenz Energy-as-a-Service GmbH
3+
# This Dockerfile is used to run the tests in architectures not supported by
4+
# GitHub Actions.
5+
6+
FROM docker.io/library/ubuntu:20.04
7+
8+
ENV DEBIAN_FRONTEND=noninteractive
9+
10+
# Install Python 3.11 and curl to install pip later
11+
RUN apt-get update -y && \
12+
apt-get install --no-install-recommends -y \
13+
software-properties-common && \
14+
add-apt-repository ppa:deadsnakes/ppa && \
15+
apt-get install --no-install-recommends -y \
16+
ca-certificates \
17+
curl \
18+
git \
19+
python3.11 \
20+
python3.11-distutils && \
21+
apt-get clean && \
22+
rm -rf /var/lib/apt/lists/*
23+
24+
# Install pip
25+
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.11
26+
27+
RUN update-alternatives --install \
28+
/usr/local/bin/python python /usr/bin/python3.11 1 && \
29+
python -m pip install --upgrade --no-cache-dir pip
30+
31+
COPY entrypoint.bash /usr/bin/entrypoint.bash
32+
33+
ENTRYPOINT ["/usr/bin/entrypoint.bash"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
# License: MIT
3+
# Copyright © 2023 Frequenz Energy-as-a-Service GmbH
4+
set -e
5+
6+
echo "System details:" $(uname -a)
7+
echo "Machine:" $(uname -m)
8+
9+
exec "$@"

0 commit comments

Comments
 (0)