Skip to content

Commit 495ef19

Browse files
committed
docker: Add workflows for building and releasing CircuitPython
This commit introduces new GitHub Actions workflows for building Docker containers and creating manifests for CircuitPython. It includes: - A workflow for building containers based on specified platforms. - A workflow for building container manifests for multiple architectures. - A workflow for building releases triggered by pushes to the main branch. These changes enhance the CI/CD process for CircuitPython development. Signed-off-by: Chiho Sin <[email protected]>
1 parent 9e8fa33 commit 495ef19

File tree

6 files changed

+323
-50
lines changed

6 files changed

+323
-50
lines changed

.github/workflows/docker_build.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Build container
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
platform:
7+
description: Docker platform to target
8+
required: true
9+
type: string
10+
runs-on:
11+
description: Runner to use
12+
required: true
13+
type: string
14+
push:
15+
description: Push images to registry
16+
required: false
17+
type: boolean
18+
default: false
19+
cpy_platform:
20+
description: CircuitPython platform to target
21+
required: true
22+
type: string
23+
outputs:
24+
digest:
25+
description: Digest of built image
26+
value: ${{ jobs.docker-build.outputs.digest }}
27+
28+
env:
29+
REGISTRY: ghcr.io
30+
IMAGE_NAME: ${{ github.repository }}
31+
32+
permissions:
33+
contents: read
34+
packages: write
35+
id-token: write
36+
attestations: write
37+
38+
jobs:
39+
docker-build:
40+
name: build-${{ inputs.platform }}
41+
outputs:
42+
digest: ${{ steps.docker_platform.outputs.digest }}
43+
runs-on: ${{ inputs.runs-on }}
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- uses: docker/setup-qemu-action@v3
48+
49+
- uses: docker/setup-buildx-action@v3
50+
51+
- name: Docker login
52+
if: ${{ inputs.push }}
53+
uses: docker/login-action@v3
54+
with:
55+
registry: ${{ env.REGISTRY }}
56+
username: ${{ github.actor }}
57+
password: ${{ secrets.GITHUB_TOKEN }}
58+
59+
- name: Sanitize platform string
60+
id: sanitize_platform
61+
# Replace slashes with underscores
62+
run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT
63+
64+
- name: Docker tag
65+
id: meta
66+
uses: docker/metadata-action@v5
67+
with:
68+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
69+
tags: |
70+
GHA-main-${{ inputs.cpy_platform }}-${{ steps.sanitize_platform.outputs.cleaned_platform }}
71+
flavor: latest=false
72+
73+
- name: Docker build and push
74+
uses: docker/build-push-action@v6
75+
id: docker_platform
76+
with:
77+
context: .
78+
push: ${{ inputs.push }}
79+
tags: ${{ steps.meta.outputs.tags }}
80+
labels: ${{ steps.meta.outputs.labels }}
81+
platforms: ${{ inputs.platform }}
82+
build-args: |
83+
cpy_platform=${{ inputs.cpy_platform }}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Build container manifest
2+
on:
3+
workflow_call:
4+
inputs:
5+
cpy_platform:
6+
description: CircuitPython platform to target
7+
required: true
8+
type: string
9+
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME: ${{ github.repository }}
13+
14+
permissions:
15+
contents: read
16+
packages: write
17+
id-token: write
18+
attestations: write
19+
20+
jobs:
21+
docker-amd64:
22+
uses: ./.github/workflows/docker_build.yml
23+
with:
24+
cpy_platform: ${{ inputs.cpy_platform }}
25+
platform: linux/amd64
26+
runs-on: ubuntu-24.04
27+
push: true
28+
secrets: inherit
29+
30+
docker-arm64:
31+
uses: ./.github/workflows/docker_build.yml
32+
with:
33+
cpy_platform: ${{ inputs.cpy_platform }}
34+
platform: linux/arm64
35+
runs-on: ubuntu-24.04-arm
36+
push: true
37+
secrets: inherit
38+
39+
docker-manifest:
40+
needs:
41+
- docker-amd64
42+
- docker-arm64
43+
runs-on: ubuntu-24.04
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- name: Docker Login GHCR
48+
uses: docker/login-action@v3
49+
with:
50+
registry: ${{ env.REGISTRY }}
51+
username: ${{ github.actor }}
52+
password: ${{ secrets.GITHUB_TOKEN }}
53+
54+
- name: Docker meta
55+
id: meta_docker
56+
uses: docker/metadata-action@v5
57+
with:
58+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
59+
tags: |
60+
main-${{ inputs.cpy_platform }}
61+
flavor: latest=false
62+
63+
- name: Create Docker manifest
64+
id: manifest_docker
65+
uses: int128/docker-manifest-create-action@v2
66+
with:
67+
tags: |
68+
${{ steps.meta_docker.outputs.tags }}
69+
push: true
70+
sources: |
71+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.docker-amd64.outputs.digest }}
72+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.docker-arm64.outputs.digest }}

.github/workflows/on_pr.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Build PR
2+
on:
3+
pull_request:
4+
5+
permissions:
6+
contents: read
7+
packages: write
8+
id-token: write
9+
attestations: write
10+
11+
jobs:
12+
docker-amd64:
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
cpy_platform:
17+
- nordic
18+
- espressif
19+
uses: ./.github/workflows/docker_build.yml
20+
with:
21+
cpy_platform: ${{ matrix.cpy_platform }}
22+
platform: linux/amd64
23+
runs-on: ubuntu-24.04
24+
push: false
25+
secrets: inherit

.github/workflows/on_push.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Build Release
2+
on:
3+
push:
4+
# build and push anytime commits are pushed/merged
5+
branches:
6+
- main
7+
schedule:
8+
# build and push weekly
9+
- cron: '0 5 * * 5'
10+
workflow_dispatch: # allow manual triggering
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
id-token: write
16+
attestations: write
17+
18+
jobs:
19+
docker-platforms:
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
cpy_platform:
24+
- nordic
25+
- espressif
26+
uses: ./.github/workflows/docker_manifest.yml
27+
with:
28+
cpy_platform: ${{ matrix.cpy_platform }}
29+
secrets: inherit

Containerfile

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,51 @@
11
FROM python:3.13-bookworm AS base
22

33
ENV PIP_ROOT_USER_ACTION=ignore
4-
ENV ARM_TOOLCHAIN_EABI_VERSION=14.2.rel1
5-
ENV ARM_TOOLCHAIN_ELF_VERSION=13.3.rel1
64

75
# Apt dependencies
86
RUN apt-get update && apt-get install -y \
97
jq jdupes build-essential \
108
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libusb-1.0-0-dev libi2c-dev libuv1-dev \
119
libx11-dev libinput-dev libxkbcommon-x11-dev \
1210
openssl libssl-dev libulfius-dev liborcania-dev \
13-
git git-lfs gettext cmake mtools floppyd dosfstools \
11+
git git-lfs gettext cmake mtools floppyd dosfstools ninja-build \
1412
&& rm -rf /var/lib/apt/lists/*
1513

16-
# Install ARM toolchain (EABI) based on architecture
17-
RUN ARCH=$(dpkg --print-architecture) && \
14+
FROM base AS repo
15+
ARG BUILD_REPO="https://github.com/adafruit/circuitpython.git"
16+
ARG BUILD_REF="main"
17+
ARG BUILD_FORK_REPO="https://github.com/fobe-projects/circuitpython.git"
18+
ARG BUILD_FORK_REF="main"
19+
20+
WORKDIR /workspace
21+
22+
RUN git config --global --add safe.directory /workspace \
23+
&& git clone --depth 1 --filter=tree:0 "${BUILD_REPO}" /workspace \
24+
&& cd /workspace && git checkout "${BUILD_REF}" \
25+
&& git submodule update --init --filter=blob:none data extmod lib tools frozen \
26+
&& git fetch --no-recurse-submodules --shallow-since="2021-07-01" --tags "${BUILD_REPO}" HEAD \
27+
&& git fetch --no-recurse-submodules --shallow-since="2021-07-01" origin \
28+
&& git repack -d \
29+
&& git remote add fork "${BUILD_FORK_REPO}" \
30+
&& git fetch fork --filter=tree:0 \
31+
&& git fetch --no-recurse-submodules --filter=tree:0 fork "${BUILD_FORK_REF}" \
32+
&& git checkout -b fork-branch "fork/${BUILD_FORK_REF}" \
33+
&& git repack -d
34+
35+
RUN pip3 install --upgrade -r requirements-doc.txt \
36+
&& pip3 install --upgrade -r requirements-dev.txt \
37+
&& pip3 install --upgrade huffman
38+
39+
FROM repo AS port
40+
41+
ARG ARM_TOOLCHAIN_EABI_VERSION="14.2.rel1"
42+
ARG ARM_TOOLCHAIN_ELF_VERSION="13.3.rel1"
43+
ARG BUILD_PLATFORM
44+
45+
RUN make -C ports/"${BUILD_PLATFORM}" fetch-port-submodules
46+
47+
RUN if [ "${BUILD_PLATFORM}" != "espressif" ] && [ "${BUILD_PLATFORM}" != "zephyr-cp" ] && [ "${BUILD_PLATFORM}" != "litex" ] && [ "${BUILD_PLATFORM}" != "none" ]; then \
48+
ARCH=$(dpkg --print-architecture) && \
1849
if [ "$ARCH" = "arm64" ]; then \
1950
TOOLCHAIN_URL="https://developer.arm.com/-/media/Files/downloads/gnu/$ARM_TOOLCHAIN_EABI_VERSION/binrel/arm-gnu-toolchain-$ARM_TOOLCHAIN_EABI_VERSION-aarch64-arm-none-eabi.tar.xz"; \
2051
elif [ "$ARCH" = "amd64" ]; then \
@@ -27,10 +58,12 @@ RUN ARCH=$(dpkg --print-architecture) && \
2758
curl -fsSL "$TOOLCHAIN_URL" | tar -xJ -C /usr/local/arm-none-eabi --strip-components=1 && \
2859
for f in /usr/local/arm-none-eabi/bin/arm-none-eabi-*; do \
2960
ln -sf "$f" /usr/local/bin/$(basename "$f"); \
30-
done
61+
done \
62+
fi
3163

32-
# Install ARM toolchain (ELF) based on architecture
33-
RUN ARCH=$(dpkg --print-architecture) && \
64+
# Broadcom
65+
RUN if [ "${BUILD_PLATFORM}" = "broadcom" ]; then \
66+
ARCH=$(dpkg --print-architecture) && \
3467
if [ "$ARCH" = "arm64" ]; then \
3568
TOOLCHAIN_URL="https://developer.arm.com/-/media/Files/downloads/gnu/$ARM_TOOLCHAIN_ELF_VERSION/binrel/arm-gnu-toolchain-$ARM_TOOLCHAIN_ELF_VERSION-aarch64-aarch64-none-elf.tar.xz"; \
3669
elif [ "$ARCH" = "amd64" ]; then \
@@ -43,35 +76,49 @@ RUN ARCH=$(dpkg --print-architecture) && \
4376
curl -fsSL "$TOOLCHAIN_URL" | tar -xJ -C /usr/local/arm-none-elf --strip-components=1 && \
4477
for f in /usr/local/arm-none-elf/bin/arm-none-elf-*; do \
4578
ln -sf "$f" /usr/local/bin/$(basename "$f"); \
46-
done
47-
48-
FROM base AS repo
49-
ARG BUILD_REPO="https://github.com/adafruit/circuitpython.git"
50-
ARG BUILD_REF="main"
51-
ARG BUILD_FORK_REPO="https://github.com/fobe-projects/circuitpython.git"
52-
ARG BUILD_FORK_REF="main"
53-
ARG BUILD_PLATFORM
79+
done \
80+
fi
5481

55-
WORKDIR /workspace
56-
57-
RUN git config --global --add safe.directory /workspace
58-
RUN git clone --depth 1 --filter=tree:0 "${BUILD_REPO}" /workspace
59-
RUN git checkout "${BUILD_REF}"
60-
RUN git fetch --no-recurse-submodules --shallow-since="2021-07-01" --tags "${BUILD_REPO}" HEAD
61-
RUN git fetch --no-recurse-submodules --shallow-since="2021-07-01" origin
62-
RUN git repack -d
63-
RUN git remote add fork "${BUILD_FORK_REPO}" && git fetch fork --filter=tree:0
64-
RUN git checkout -b fork-branch "fork/${BUILD_FORK_REF}"
65-
66-
RUN pip3 install --upgrade -r requirements-dev.txt && pip3 install --upgrade -r requirements-doc.txt
67-
RUN pip3 install --upgrade huffman
68-
69-
RUN python tools/ci_fetch_deps.py ${BUILD_PLATFORM}
82+
# Nordic
83+
RUN if [ "${BUILD_PLATFORM}" = "nordic" ]; then \
84+
ARCH=$(dpkg --print-architecture) && \
85+
if [ "$ARCH" = "arm64" ]; then \
86+
TOOLCHAIN_URL="https://files.nordicsemi.com/artifactory/swtools/external/nrfutil/executables/aarch64-unknown-linux-gnu/nrfutil"; \
87+
elif [ "$ARCH" = "amd64" ]; then \
88+
TOOLCHAIN_URL="https://files.nordicsemi.com/artifactory/swtools/external/nrfutil/executables/x86_64-unknown-linux-gnu/nrfutil"; \
89+
else \
90+
echo "Unsupported architecture: $ARCH"; \
91+
exit 1; \
92+
fi && curl -fsSL "$TOOLCHAIN_URL" -o nrfutil;\
93+
chmod +x nrfutil; \
94+
./nrfutil install nrf5sdk-tools; \
95+
mv nrfutil /usr/local/bin; \
96+
nrfutil -V; \
97+
fi
7098

99+
# Espressif IDF
71100
ENV IDF_PATH=/workspace/ports/espressif/esp-idf
72101
ENV IDF_TOOLS_PATH=/workspace/.idf_tools
73102
ENV ESP_ROM_ELF_DIR=/workspace/.idf_tools
74-
RUN git submodule update --init --depth=1 --recursive $IDF_PATH
103+
RUN if [ "${BUILD_PLATFORM}" = "espressif" ]; then \
104+
git submodule update --init --depth=1 --recursive ${IDF_PATH}; \
105+
$IDF_PATH/install.sh; \
106+
bash -c "source ${IDF_PATH}/export.sh && pip3 install --upgrade minify-html jsmin sh requests-cache"; \
107+
rm -rf $IDF_TOOLS_PATH/dist; \
108+
fi
109+
110+
# Litex
111+
RUN if [ "${BUILD_PLATFORM}" = "litex" ]; then \
112+
ARCH=$(dpkg --print-architecture) && \
113+
if [ "$ARCH" = "amd64" ]; then \
114+
TOOLCHAIN_URL="https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz"; \
115+
else \
116+
echo "Unsupported architecture: $ARCH"; \
117+
exit 1; \
118+
fi && curl -fsSL "$TOOLCHAIN_URL" -o riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz;\
119+
tar -C /usr --strip-components=1 -xaf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz; \
120+
rm -rf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz; \
121+
fi
75122

76-
COPY entrypoint.sh /entrypoint.sh
123+
COPY --chmod=0755 entrypoint.sh /entrypoint.sh
77124
ENTRYPOINT [ "/entrypoint.sh" ]

0 commit comments

Comments
 (0)