LXC container platform support #3333
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# RaspberryMatic Continious Integration Check Workflow | |
# yamllint disable rule:truthy | |
--- | |
name: CI Build | |
on: | |
push: | |
branches-ignore: | |
- 'gh-pages' | |
tags-ignore: | |
- '3.*' | |
paths-ignore: | |
- '**.md' | |
- 'helm/**' | |
- 'release/LATEST-VERSION.js' | |
- 'release/rpi-imager.json' | |
- 'home-assistant-addon-dev/config.yaml' | |
pull_request: | |
branches-ignore: | |
- 'gh-pages' | |
tags-ignore: | |
- '3.*' | |
paths-ignore: | |
- '**.md' | |
- 'helm/**' | |
- 'release/LATEST-VERSION.js' | |
- 'release/rpi-imager.json' | |
- 'home-assistant-addon-dev/config.yaml' | |
workflow_dispatch: | |
inputs: | |
skip_build: | |
description: 'Skip build (for testing workflow)?' | |
required: true | |
default: "true" | |
# default read-only permission | |
permissions: | |
contents: read | |
env: | |
# NOTE: secrets cannot be access directly in conditions | |
# https://github.com/actions/runner/issues/520 | |
SECRETS_ARE_AVAILABLE: ${{ secrets.CR_PAT != '' }} | |
jobs: | |
skip_check: | |
name: Duplicate Check | |
runs-on: ubuntu-latest | |
outputs: | |
should_skip: ${{ steps.check.outputs.should_skip }} | |
steps: | |
- id: check | |
uses: fkirc/skip-duplicate-actions@v5.3.1 | |
with: | |
skip_after_successful_duplicate: 'true' | |
concurrent_skipping: 'same_content_newer' | |
linter: | |
name: Linter Checks | |
needs: skip_check | |
if: ${{ needs.skip_check.outputs.should_skip != 'true' }} | |
runs-on: ubuntu-22.04 | |
steps: | |
- name: Checkout Code | |
uses: actions/checkout@v4 | |
- name: Check Dockerfile | |
uses: brpaz/hadolint-action@v1.5.0 | |
with: | |
dockerfile: ./buildroot-external/board/oci/Dockerfile | |
- name: Check shell scripts | |
uses: ludeeus/action-shellcheck@2.0.0 | |
with: | |
ignore_paths: >- | |
buildroot-external/package/neoserver/pkg/mediola/neo_server | |
buildroot-patches/0001-setlocalversion/buildroot/support/scripts | |
buildroot-patches/0010-lib32-integration/buildroot/support/scripts | |
env: | |
SHELLCHECK_OPTS: -e SC3010 -e SC3014 -e SC3057 -e SC3036 -e SC3028 -e SC3020 | |
- name: Check Home Assistant Add-on Lint | |
uses: frenck/action-addon-linter@main | |
with: | |
path: "./home-assistant-addon" | |
- name: Check Home Assistant Add-on Lint (dev) | |
uses: frenck/action-addon-linter@main | |
with: | |
path: "./home-assistant-addon-dev" | |
- name: Check yaml files | |
uses: frenck/action-yamllint@v1.4 | |
- name: Check markdown files | |
uses: avto-dev/markdown-lint@v1 | |
with: | |
ignore: '**/node_modules/** **/codemirror/README.md' | |
- name: Check Package consistency | |
run: | | |
pip install flake8 | |
make check | |
build: | |
permissions: | |
contents: write # actions/upload-artifact | |
name: CI build [${{ matrix.platform }}] | |
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'jens-maus') && github.actor != 'dependabot[bot]' && github.repository == 'jens-maus/RaspberryMatic' }} | |
needs: linter | |
runs-on: self-hosted | |
timeout-minutes: 480 | |
outputs: | |
build_datetime: ${{ steps.env.outputs.build_datetime }} | |
build_version: ${{ steps.env.outputs.build_version }} | |
strategy: | |
fail-fast: false | |
matrix: | |
platform: [rpi0, rpi2, rpi3, rpi4, rpi5, tinkerboard, odroid-c2, odroid-c4, odroid-n2, intelnuc, ova, oci_amd64, oci_arm64, oci_arm, generic-aarch64, lxc_amd64, lxc_arm64, lxc_arm] | |
steps: | |
- name: Checkout Code | |
uses: actions/checkout@v4 | |
- name: Install Dependencies | |
run: | | |
if ! dpkg-query -l wget bc cpio rsync zip python3 file >/dev/null 2>&1; then | |
apt update | |
apt install -y --no-install-recommends wget bc cpio rsync zip python3 file | |
fi | |
if ! getent group | grep -q ^builder:; then groupadd -g 48 builder; fi | |
if ! getent passwd | grep -q ^builder:; then useradd -m -u 1003 -g 48 -G sudo builder; fi | |
if ! grep -q ^builder; then echo "builder ALL=(ALL:ALL) NOPASSWD: ALL" >>/etc/sudoers; fi | |
chown -R builder:builder /home/builder | |
- name: Setup Environment | |
id: env | |
run: | | |
echo "DATE=$(date +%Y%m%d)" >> $GITHUB_ENV | |
echo "OCCU_VERSION=$(grep 'OCCU_VERSION =' buildroot-external/package/occu/occu.mk | cut -d' ' -f3 | cut -d'-' -f1)" >> $GITHUB_ENV | |
echo "VERSION=$(grep 'OCCU_VERSION =' buildroot-external/package/occu/occu.mk | cut -d' ' -f3 | cut -d'-' -f1).$(date +%Y%m%d)" >> $GITHUB_ENV | |
echo "GITHUB_SHA7=$(echo ${GITHUB_SHA::7})" >> $GITHUB_ENV | |
if [[ -z "${{ github.event.inputs.skip_build }}" ]]; then | |
echo "FAKE_BUILD=true" >> $GITHUB_ENV | |
else | |
echo "FAKE_BUILD=${{ github.event.inputs.skip_build }}" >> $GITHUB_ENV | |
fi | |
JLEVEL=0 | |
if [[ -f /sys/fs/cgroup/cpu.max ]]; then # cgroups v2 | |
CPU_QUOTA=$(cut -d ' ' -f1 /sys/fs/cgroup/cpu.max) | |
if [[ "${CPU_QUOTA}" != "max" ]]; then | |
CPU_PERIOD=$(cut -d ' ' -f2 /sys/fs/cgroup/cpu.max) | |
JLEVEL=$((CPU_QUOTA / CPU_PERIOD + 1)) | |
fi | |
elif [[ -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us ]]; then # cgroups v1 | |
CPU_QUOTA=$(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us) | |
if [[ "${CPU_QUOTA}" != "-1" ]]; then | |
CPU_PERIOD=$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us) | |
JLEVEL=$((CPU_QUOTA / CPU_PERIOD + 1)) | |
fi | |
fi | |
echo "JLEVEL=${JLEVEL}" >> $GITHUB_ENV | |
echo "build_datetime=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_OUTPUT | |
echo "build_version=$(grep 'OCCU_VERSION =' buildroot-external/package/occu/occu.mk | cut -d' ' -f3 | cut -d'-' -f1).$(date +%Y%m%d)" >> $GITHUB_OUTPUT | |
- name: Switch to experimental EULA files | |
run: | | |
mv -f release/updatepkg/raspmatic_${{ matrix.platform }}/EULA.de_nightly release/updatepkg/raspmatic_${{ matrix.platform }}/EULA.de | |
mv -f release/updatepkg/raspmatic_${{ matrix.platform }}/EULA.en_nightly release/updatepkg/raspmatic_${{ matrix.platform }}/EULA.en | |
# - name: remote debug tmate session | |
# uses: mxschmitt/action-tmate@v1 | |
# if: matrix.platform == 'ova' | |
# major build step | |
- name: Build | |
timeout-minutes: 480 | |
run: | | |
sudo -H -E -u builder nice -n 19 make DATE=${{ env.DATE }} BR2_DL_DIR=/mnt/download BR2_CCACHE_DIR=/mnt/ccache/${{ matrix.platform }} BR2_JLEVEL=${{ env.JLEVEL }} clean raspmatic_${{ matrix.platform }}-release | |
# cleanup | |
- name: Cleanup | |
run: | | |
rm -f release/*.img* | |
make clean | |
######################### | |
# upload build artifacts | |
- name: Upload build artifact [rpi*, tinkerboard, intelnuc, ova, generic-*] | |
if: | | |
!startsWith(matrix.platform, 'oci_') && | |
!startsWith(matrix.platform, 'lxc_') | |
uses: actions/upload-artifact@v4 | |
with: | |
path: release/RaspberryMatic-${{ env.VERSION }}-${{ matrix.platform }}.zip* | |
name: RaspberryMatic-${{ env.VERSION }}-${{ env.GITHUB_SHA7 }}-${{ matrix.platform }}.zip | |
continue-on-error: true | |
- name: Upload build artifact [ccu3] | |
if: | | |
matrix.platform == 'rpi3' | |
uses: actions/upload-artifact@v4 | |
with: | |
path: release/RaspberryMatic-${{ env.VERSION }}-ccu3.tgz* | |
name: RaspberryMatic-${{ env.VERSION }}-${{ env.GITHUB_SHA7 }}-ccu3.tgz | |
continue-on-error: true | |
- name: Upload build artifact [ova] | |
if: | | |
matrix.platform == 'ova' | |
uses: actions/upload-artifact@v4 | |
with: | |
path: release/RaspberryMatic-${{ env.VERSION }}.ova* | |
name: RaspberryMatic-${{ env.VERSION }}-${{ env.GITHUB_SHA7 }}.ova | |
continue-on-error: true | |
- name: Upload build artifact [oci] | |
if: | | |
startsWith(matrix.platform, 'oci_') | |
uses: actions/upload-artifact@v4 | |
with: | |
path: release/RaspberryMatic-${{ env.VERSION }}-${{ matrix.platform }}.tgz* | |
name: RaspberryMatic-${{ env.VERSION }}-${{ env.GITHUB_SHA7 }}-${{ matrix.platform }}.tgz | |
continue-on-error: true | |
- name: Upload build artifact [lxc] | |
if: | | |
startsWith(matrix.platform, 'lxc_') | |
uses: actions/upload-artifact@v4 | |
with: | |
path: release/RaspberryMatic-${{ env.VERSION }}-${{ matrix.platform }}.tar.gz* | |
name: RaspberryMatic-${{ env.VERSION }}-${{ env.GITHUB_SHA7 }}-${{ matrix.platform }}.tar.gz | |
continue-on-error: true | |
########################################## | |
# OCI/Docker build and registry push step | |
oci-multiarch-build-push: | |
permissions: | |
contents: write # actions/upload-artifact | |
packages: write # docker/build-push-action | |
name: OCI/Docker Build+Push | |
runs-on: ubuntu-22.04 | |
needs: build | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup Environment | |
run: | | |
echo "BUILD_DATETIME=${{ needs.build.outputs.build_datetime }}" >> $GITHUB_ENV | |
echo "BUILD_VERSION=${{ needs.build.outputs.build_version }}" >> $GITHUB_ENV | |
echo "GIT_REF=$(git symbolic-ref -q --short HEAD || git describe --tags --exact-match)" >> $GITHUB_ENV | |
echo "GITHUB_SHA7=$(echo ${GITHUB_SHA::7})" >> $GITHUB_ENV | |
echo "CCU_OCI_REPO=ghcr.io/${{ github.repository_owner }}/raspberrymatic" >> $GITHUB_ENV | |
echo "CCU_OCI_TAG=${{ needs.build.outputs.build_version }}-$(echo ${GITHUB_SHA::7})" >> $GITHUB_ENV | |
# download OCI platform artifacts | |
- name: Download oci_amd64 artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: RaspberryMatic-${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }}-oci_amd64.tgz | |
- name: Download oci_arm64 artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: RaspberryMatic-${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }}-oci_arm64.tgz | |
- name: Download oci_arm artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: RaspberryMatic-${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }}-oci_arm.tgz | |
- name: Extract OCI artifacts | |
run: | | |
mkdir -p oci_build | |
cd oci_build | |
for f in ../*-oci_*.tgz; do | |
tar --wildcards --strip-components 1 -xf $f "*/layer.tar" | |
mv -f layer.tar $(basename $f .tgz).tar | |
rm -f $f | |
done | |
- name: Set up Docker Buildx | |
id: buildx | |
uses: docker/setup-buildx-action@v3.0.0 | |
with: | |
install: true | |
- name: Login to GitHub Container Registry | |
if: env.SECRETS_ARE_AVAILABLE == 'true' | |
uses: docker/login-action@v3.0.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.CR_PAT }} | |
- name: Build and push container image | |
if: github.event.inputs.skip_build == 'false' | |
uses: docker/build-push-action@v5.1.0 | |
id: docker_build | |
with: | |
context: oci_build | |
file: buildroot-external/board/oci/Dockerfile | |
platforms: linux/amd64,linux/arm64,linux/arm/v7 | |
# load not supported -> https://github.com/docker/buildx/issues/290 | |
# load: true #load in docker - needed for testing later on | |
push: ${{ env.SECRETS_ARE_AVAILABLE }} | |
build-args: | | |
tar_prefix=RaspberryMatic-${{ env.BUILD_VERSION }}-oci_ | |
labels: | | |
org.opencontainers.image.title=RaspberryMatic | |
org.opencontainers.image.description=Alternative OS for your HomeMatic CCU | |
org.opencontainers.image.vendor=RasperryMatic OpenSource Project | |
org.opencontainers.image.authors=RaspberryMatic OpenSource Team | |
org.opencontainers.image.licenses=Apache-2.0 | |
org.opencontainers.image.url=https://raspberrymatic.de | |
org.opencontainers.image.source=https://github.com/${{ github.repository }} | |
org.opencontainers.image.documentation=https://github.com/${{ github.repository }}/wiki | |
org.opencontainers.image.created=${{ env.BUILD_DATETIME }} | |
org.opencontainers.image.ref.name=${{ env.GIT_REF }} | |
org.opencontainers.image.revision=${{ github.sha }} | |
org.opencontainers.image.version=${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }} | |
io.hass.name=RaspberryMatic CCU | |
io.hass.description=HomeMatic/homematicIP CCU central based on RaspberryMatic | |
io.hass.url=https://github.com/${{ github.repository }}/tree/master/home-assistant-addon | |
io.hass.version=${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }} | |
io.hass.type=addon | |
io.hass.arch=armv7|aarch64|amd64 | |
tags: | | |
${{ env.CCU_OCI_REPO }}:${{ env.CCU_OCI_TAG }} | |
- name: Image digest | |
run: echo ${{ steps.docker_build.outputs.digest }} | |
# Testing | |
- name: Build and load container image for test | |
uses: docker/build-push-action@v5.1.0 | |
id: docker_build_test | |
with: | |
context: oci_build | |
file: buildroot-external/board/oci/Dockerfile | |
platforms: linux/amd64 # load does not support muti-arch https://github.com/docker/buildx/issues/290 | |
load: true # load in docker - needed for testing later on | |
push: false | |
build-args: | | |
tar_prefix=RaspberryMatic-${{ env.BUILD_VERSION }}-oci_ | |
labels: | | |
org.opencontainers.image.title=RaspberryMatic | |
org.opencontainers.image.description=Alternative OS for your HomeMatic CCU | |
org.opencontainers.image.vendor=RasperryMatic OpenSource Project | |
org.opencontainers.image.authors=RaspberryMatic OpenSource Team | |
org.opencontainers.image.licenses=Apache-2.0 | |
org.opencontainers.image.url=https://raspberrymatic.de | |
org.opencontainers.image.source=https://github.com/${{ github.repository }} | |
org.opencontainers.image.documentation=https://github.com/${{ github.repository }}/wiki | |
org.opencontainers.image.created=${{ env.BUILD_DATETIME }} | |
org.opencontainers.image.ref.name=${{ env.GIT_REF }} | |
org.opencontainers.image.revision=${{ github.sha }} | |
org.opencontainers.image.version=${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }} | |
io.hass.name=RaspberryMatic CCU | |
io.hass.description=HomeMatic/homematicIP CCU central based on RaspberryMatic | |
io.hass.url=https://github.com/${{ github.repository }}/tree/master/home-assistant-addon | |
io.hass.version=${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }} | |
io.hass.type=addon | |
io.hass.arch=armv7|aarch64|amd64 | |
tags: | | |
${{ env.CCU_OCI_REPO }}:${{ env.CCU_OCI_TAG }} | |
- name: Enable experimental features for the Docker daemon and CLI | |
run: | | |
echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json | |
mkdir -p ~/.docker | |
echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json | |
sudo service docker restart | |
#docker version -f '{{.Client.Experimental}}' | |
#docker version -f '{{.Server.Experimental}}' | |
docker version | |
- name: Test container deploy (install-docker.sh) | |
run: | | |
export CCU_DOCKER_PULL_REFRESH="false" | |
export CCU_CONTAINER_IP="192.168.178.4" | |
export CCU_CONTAINER_IP_AUX="192.168.178.2" | |
export CCU_NETWORK_NAME="none" | |
export CCU_NETWORK_INTERFACE="none" | |
export CCU_NETWORK_SUBNET="none" | |
sudo mknod /dev/eq3loop c 239 0 # fake /dev/eq3loop | |
sudo -E ./scripts/install-docker.sh | |
- name: Test container startup+stop | |
if: github.event.inputs.skip_build == 'false' | |
run: | | |
docker start ccu | |
error=0 | |
n=1 | |
while ! docker exec ccu test -e /var/status/startupFinished ; do | |
if [ "$n" -ge 120 ]; then | |
echo "ERROR: container not started after 120s. aborting." | |
error=1 | |
break | |
fi | |
sleep 1 | |
n=$((n+1)) | |
done | |
docker exec ccu tar --owner=root --group=root --one-file-system --ignore-failed-read -czf - /tmp /usr/local > debug_output.tgz | |
docker stop ccu | |
docker logs ccu | |
exit $error | |
- name: Upload debug information | |
if: github.event.inputs.skip_build == 'false' | |
uses: actions/upload-artifact@v4 | |
with: | |
path: debug_output.tgz | |
name: RaspberryMatic-debug_output-${{ env.BUILD_VERSION }}-${{ env.GITHUB_SHA7 }}.tgz | |
- name: Remove/Cleanup container environment | |
run: | | |
sudo -E ./scripts/install-docker.sh uninstall | |
docker volume rm ccu_data | |
docker image ls -a | |
docker image rm ${{ env.CCU_OCI_REPO }}:${{ env.CCU_OCI_TAG }} |