diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index c2d3a9c..cf65cd7 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -14,14 +14,29 @@ jobs: include: - arch: linux/386 arch_friendly: i386 + hass_arch: i386 + s6_arch: x86 + rust_arch: i686-unknown-linux-gnu - arch: linux/amd64 arch_friendly: amd64 + hass_arch: amd64 + s6_arch: amd64 + rust_arch: x86_64-unknown-linux-gnu - arch: linux/arm/v6 arch_friendly: armv6 + hass_arch: armv6 + s6_arch: arm + rust_arch: arm-unknown-linux-gnueabi - arch: linux/arm/v7 arch_friendly: armv7 + hass_arch: armv7 + s6_arch: armhf + rust_arch: armv7-unknown-linux-gnueabihf - arch: linux/arm64 arch_friendly: arm64 + hass_arch: aarch64 + s6_arch: aarch64 + rust_arch: aarch64-unknown-linux-gnu steps: - name: Checkout @@ -35,17 +50,31 @@ jobs: with: install: true + - name: Cache Docker layers + uses: actions/cache@v2 + continue-on-error: true + with: + path: /tmp/.buildx-cache + key: ${{ matrix.arch }}-${{ github.sha }} + restore-keys: | + ${{ matrix.arch }}- + # label version as branch-run_number - name: Build Branch if: ${{ startsWith(github.ref, 'refs/heads/') }} run: | set -x docker build \ + --build-arg HASS_ARCH=${{ matrix.hass_arch }} \ + --build-arg S6_ARCH=${{ matrix.s6_arch }} \ + --build-arg RUST_ARCH=${{ matrix.rust_arch }} \ --build-arg BUILD_VERSION=${GITHUB_REF##*/}-${{ github.run_number }} \ --tag ci:${{ github.run_number }} \ --platform ${{ matrix.arch }} \ --progress plain \ - --file ./Dockerfile \ + --file ./docker/Dockerfile \ + --cache-from type=local,src=/tmp/.buildx-cache \ + --cache-to type=local,dest=/tmp/.buildx-cache-new \ --load \ . @@ -55,18 +84,32 @@ jobs: run: | set -x docker build \ + --build-arg HASS_ARCH=${{ matrix.hass_arch }} \ + --build-arg S6_ARCH=${{ matrix.s6_arch }} \ + --build-arg RUST_ARCH=${{ matrix.rust_arch }} \ --build-arg BUILD_VERSION=${GITHUB_REF##*/} \ --tag ci:${{ github.run_number }} \ --platform ${{ matrix.arch }} \ --progress plain \ - --file ./Dockerfile \ + --file ./docker/Dockerfile \ + --cache-from type=local,src=/tmp/.buildx-cache \ + --cache-to type=local,dest=/tmp/.buildx-cache-new \ --load \ . + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + - name: Inspect run: | set -x docker image inspect ci:${{ github.run_number }} + docker history --no-trunc ci:${{ github.run_number }} - name: Save tarball run: | diff --git a/.github/workflows/update-base.yml b/.github/workflows/update-base.yml deleted file mode 100644 index ae8e79b..0000000 --- a/.github/workflows/update-base.yml +++ /dev/null @@ -1,21 +0,0 @@ -# This workflow will dispatch a build event to the base-image repository if the requirements are changed - -name: Trigger Base Image Build - -on: - push: - branches: [master] - paths: - - 'requirements.txt' -jobs: - dispatch: - runs-on: ubuntu-latest - steps: - - name: Install dependencies - run: | - curl -XPOST \ - -u "${{ secrets.GCHR_USERNAME}}:${{secrets.GHCR_PAT}}" \ - -H "Accept: application/vnd.github.everest-preview+json" \ - -H "Content-Type: application/json" https://api.github.com/repos/hass-emulated-hue/base-image/dispatches \ - --data '{"event_type": "build_image"}' - echo "Dispatch Successful" diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e203731..0000000 --- a/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -ARG BUILD_VERSION - -##################################################################### -# # -# Download and extract rootfs # -# # -##################################################################### -FROM alpine:latest as s6-base-downloader -WORKDIR /base - -RUN wget -O /tmp/base.tar.gz "https://github.com/hass-emulated-hue/s6-overlay-base/archive/master.tar.gz" \ - && mkdir -p /tmp/base \ - && tar zxvf /tmp/base.tar.gz --strip 1 -C /tmp/base \ - && mv /tmp/base/* . - -##################################################################### -# # -# Final Image # -# # -##################################################################### -FROM ghcr.io/hass-emulated-hue/base-image -# Required to persist build arg -ARG BUILD_VERSION - -# Copy root filesystem -COPY --from=s6-base-downloader /base/rootfs/ / -# Copy app -COPY emulated_hue emulated_hue - -LABEL io.hass.version=${BUILD_VERSION} diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..ffa30d7 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,127 @@ +# syntax=docker/dockerfile:experimental +ARG HASS_ARCH=amd64 +ARG S6_ARCH=amd64 +ARG RUST_ARCH=x86_64-unknown-linux-gnu +ARG BUILD_VERSION=latest + +##################################################################### +# # +# Build Wheels # +# # +##################################################################### +FROM python:3.9-slim as wheels-builder +ARG RUST_ARCH + +ENV PIP_EXTRA_INDEX_URL=https://www.piwheels.org/simple +ENV PATH="${PATH}:/root/.cargo/bin" + +# Install buildtime packages +RUN set -x \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + curl \ + gcc \ + git \ + libffi-dev \ + libssl-dev + +RUN set -x \ + && curl -o rustup-init https://static.rust-lang.org/rustup/dist/${RUST_ARCH}/rustup-init \ + && chmod +x rustup-init \ + && ./rustup-init -y --no-modify-path --profile minimal --default-host ${RUST_ARCH} + +WORKDIR /wheels +COPY requirements.txt . + +# build python wheels +RUN set -x \ + && pip wheel -r requirements.txt + +##################################################################### +# # +# Download and extract s6 overlay # +# # +##################################################################### +FROM alpine:latest as s6downloader +# Required to persist build arg +ARG S6_ARCH +WORKDIR /s6downloader + +RUN set -x \ + && OVERLAY_VERSION=$(wget --no-check-certificate -qO - https://api.github.com/repos/just-containers/s6-overlay/releases/latest | awk '/tag_name/{print $4;exit}' FS='[""]') \ + && wget -O /tmp/s6-overlay.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/${OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.gz" \ + && mkdir -p /tmp/s6 \ + && tar zxvf /tmp/s6-overlay.tar.gz -C /tmp/s6 \ + && mv /tmp/s6/* . + +##################################################################### +# # +# Download and extract bashio # +# # +##################################################################### +FROM alpine:latest as bashiodownloader +WORKDIR /bashio + +RUN set -x \ + && wget -O /tmp/bashio.tar.gz "https://github.com/hassio-addons/bashio/archive/v0.13.1.tar.gz" \ + && mkdir -p /tmp/bashio \ + && tar zxvf /tmp/bashio.tar.gz --strip 1 -C /tmp/bashio \ + && mv /tmp/bashio/lib/* . + +##################################################################### +# # +# Final Image # +# # +##################################################################### +FROM python:3.9-slim AS final-build +WORKDIR /app + +ENV DEBIAN_FRONTEND="noninteractive" + +RUN set -x \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + git \ + jq \ + openssl \ + tzdata \ + # cleanup + && rm -rf /tmp/* \ + && rm -rf /var/lib/apt/lists/* + +# Install bashio +COPY --from=bashiodownloader /bashio /usr/lib/bashio +RUN ln -s /usr/lib/bashio/bashio /usr/bin/bashio + +# Install s6 overlay +COPY --from=s6downloader /s6downloader / + +# https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md#build-mounts-run---mount +# Install pip dependencies with built wheels +RUN --mount=type=bind,target=/tmp/wheels,source=/wheels,from=wheels-builder,rw \ + set -x \ + && pip install --no-cache-dir -f /tmp/wheels -r /tmp/wheels/requirements.txt + +# Copy root filesystem +COPY docker/rootfs / + +# Copy app +COPY emulated_hue emulated_hue + +ENV S6_BEHAVIOUR_IF_STAGE2_FAILS=2 + +# Required to persist build arg +ARG BUILD_VERSION +ARG HASS_ARCH +LABEL \ + io.hass.version=${BUILD_VERSION} \ + io.hass.name="Hass Emulated Hue" \ + io.hass.description="Hue Emulation for Home Assistant" \ + io.hass.arch="${HASS_ARCH}" \ + io.hass.type="addon" + +CMD ["/init"] diff --git a/docker/rootfs-dev/etc/cont-init.d/20-install.sh b/docker/rootfs-dev/etc/cont-init.d/20-install.sh new file mode 100644 index 0000000..22c4445 --- /dev/null +++ b/docker/rootfs-dev/etc/cont-init.d/20-install.sh @@ -0,0 +1,37 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Community Hass.io Add-ons: Emulated Hue +# This file installs the Emulated Hue version if specified +# ============================================================================== + +declare release_version + +if bashio::config.has_value 'tag_commit_or_branch'; then + release_version=$(bashio::config 'tag_commit_or_branch') +else + release_version=${TAG_COMMIT_OR_BRANCH:-master} +fi + +colon_count=$(tr -dc ':' <<<"$release_version" | awk '{ print length; }') +repo_name="core" + +if [[ "$colon_count" == 1 ]]; then + IFS=':' read -r -a array <<< "$release_version" + username=${array[0]} + ref=${array[1]} +elif [ "$colon_count" == 2 ]; then + IFS=':' read -r -a array <<< "$release_version" + username=${array[0]} + repo_name=${array[1]} + ref=${array[2]} +else + username="hass-emulated-hue" + ref=$release_version +fi +full_url="https://github.com/${username}/${repo_name}/archive/${ref}.tar.gz" +bashio::log.info "Installing Emulated Hue version '${release_version}' (${full_url})..." +curl -Lo /tmp/emulator.tar.gz "${full_url}" +mkdir -p /tmp/emulator +tar zxvf /tmp/emulator.tar.gz --strip 1 -C /tmp/emulator +mv /tmp/emulator/emulated_hue . +bashio::log.info "Installed successfully!" diff --git a/docker/rootfs/etc/cont-init.d/00-set-vars.sh b/docker/rootfs/etc/cont-init.d/00-set-vars.sh new file mode 100644 index 0000000..839e9bc --- /dev/null +++ b/docker/rootfs/etc/cont-init.d/00-set-vars.sh @@ -0,0 +1,39 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Community Hass.io Add-ons: Emulated Hue +# This file defines environment variables based on user specified config options +# This overrides native environment variables with options.json +# ============================================================================== + + +if bashio::fs.file_exists '/data/options.json'; then + + if bashio::config.has_value 'data'; then + echo $(bashio::config 'data') > /var/run/s6/container_environment/DATA_DIR + fi + + if bashio::config.has_value 'http_port'; then + echo $(bashio::config 'http_port') > /var/run/s6/container_environment/HTTP_PORT + fi + + if bashio::config.has_value 'https_port'; then + echo $(bashio::config 'https_port') > /var/run/s6/container_environment/HTTPS_PORT + fi + + if bashio::config.has_value 'token'; then + echo $(bashio::config 'token') > /var/run/s6/container_environment/HASS_TOKEN + fi + + if bashio::config.has_value 'url'; then + echo $(bashio::config 'url') > /var/run/s6/container_environment/HASS_URL + fi + + if bashio::config.has_value 'use_default_ports_for_discovery'; then + echo $(bashio::config 'use_default_ports_for_discovery') > /var/run/s6/container_environment/USE_DEFAULT_PORTS + fi + + if bashio::config.has_value 'verbose'; then + echo $(bashio::config 'verbose') > /var/run/s6/container_environment/VERBOSE + fi + +fi \ No newline at end of file diff --git a/docker/rootfs/etc/services.d/emulated-hue/finish b/docker/rootfs/etc/services.d/emulated-hue/finish new file mode 100644 index 0000000..f9836d2 --- /dev/null +++ b/docker/rootfs/etc/services.d/emulated-hue/finish @@ -0,0 +1,7 @@ +#!/usr/bin/execlineb -S0 +# ============================================================================== +# Community Hass.io Add-ons: Emulated Hue +# Take down the S6 supervision tree when Emulated Hue fails to start/crashes +# ============================================================================== + +s6-svscanctl -t /var/run/s6/services diff --git a/docker/rootfs/etc/services.d/emulated-hue/run b/docker/rootfs/etc/services.d/emulated-hue/run new file mode 100644 index 0000000..61f122d --- /dev/null +++ b/docker/rootfs/etc/services.d/emulated-hue/run @@ -0,0 +1,9 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Community Hass.io Add-ons: Emulated Hue +# Runs Emulated Hue +# ============================================================================== + +bashio::log.info "Starting Emulated Hue..." +cd /app +exec python3 -m emulated_hue