Skip to content

Commit

Permalink
Add installation checks + CI Workflow (#2119)
Browse files Browse the repository at this point in the history
* add ci workflow

* add check for user home

* changes for docker tests

* added verify functions

* exit on failed update

* add check for samba setup

* add check for mpd setup

* add check for jukebox core setup

* add check for git setup

* add check for kiosk mode setup

* add check for optimize boot setup

* add check for webapp setup

* add check for autohotspot setup

* make rfid reader setup an optional step

* Add Option for No Rfid Reader

* moved setup checks to individual scripts

* fix missing iw package

* refactored get_reader_descriptions into function.
be more consistent by using same var for display and index access

* moved function to specific routine script

* make sure verify parameters are all set.
fix functionnames

* added fix for not available interface in CI runs

* check supported os type first

* moved exit_on_error function top level

* moved logging setup to function and added usage

* moved load sources to function

* change function name and var usage

* updated log output for better logfile readability

* harmonize log output

* refactored disable onboard audio.

only execute if flag is true. inlined function

* add restart nginx.service again. use HOME_PATH

* fix and check adding samba user

* fix logging mpd setup routine

* fix Disable boot logs error on existing file

* added timer to log frame

* add core package installation from file

used also for ci optimization

* Dont let remove packages fail install.
ignore for ci

* Update test scripts

use robust path determination
move noninteractive to dockerfile

* fix clear in mpd option

* fix bug in rfid configure

* fix error on uninitialized rfid_reader settings

* add checks for static ip config

* Added test for webapp download in prod.
Update test descriptions.

* renamend workflow files
to not interfere with develop branch

* Update install links
  • Loading branch information
AlvinSchiller authored Dec 2, 2023
1 parent c0d5a20 commit 234cc3c
Show file tree
Hide file tree
Showing 35 changed files with 1,439 additions and 363 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
# Application
docker
docs
installation
shared

# webapp
Expand Down
183 changes: 183 additions & 0 deletions .github/workflows/test_docker_debian_codename_sub_v3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
name: Subworkflow Test Install Scripts Debian V3

on:
workflow_call:
inputs:
debian_codename:
required: true
type: string
docker_image_name:
required: false
type: string
default: rpi-jukebox-rfid-v3
platform:
required: false
type: string
default: linux/arm/v7
cache_scope:
required: false
type: string
default: ${{ github.ref }}-test-debian-v3
local_registry_port:
required: false
type: number
default: 5000
runs_on:
required: false
type: string
default: ubuntu-latest

# let only one instance run the test so cache is not corrupted.
# cancel already running instances as only the last run will be relevant
concurrency:
group: ${{ inputs.cache_scope }}-${{ inputs.debian_codename }}
cancel-in-progress: true

jobs:

# Build container for test execution
build:
runs-on: ${{ inputs.runs_on }}

outputs:
cache_key: ${{ steps.vars.outputs.cache_key }}
image_file_name: ${{ steps.vars.outputs.image_file_name }}
image_tag_name: ${{ steps.vars.outputs.image_tag_name }}

# create local docker registry to use locally build images
services:
registry:
image: registry:2
ports:
- ${{ inputs.local_registry_port }}:5000

steps:
- uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/[email protected]

- name: Set up Docker Buildx
uses: docker/[email protected]
with:
# network=host driver-opt needed to push to local registry
driver-opts: network=host

- name: Set Output pre-vars
id: pre-vars
env:
DEBIAN_CODENAME: ${{ inputs.debian_codename }}
DOCKER_IMAGE_NAME: ${{ inputs.docker_image_name }}
CACHE_SCOPE: ${{ inputs.cache_scope }}
run: |
echo "image_tag_name=${{ env.DOCKER_IMAGE_NAME }}:${{ env.DEBIAN_CODENAME }}-test" >> $GITHUB_OUTPUT
echo "image_file_name=${{ env.DOCKER_IMAGE_NAME }}-${{ env.DEBIAN_CODENAME }}.tar" >> $GITHUB_OUTPUT
echo "cache_scope=${{ env.CACHE_SCOPE }}-${{ env.DEBIAN_CODENAME }}" >> $GITHUB_OUTPUT
- name: Set Output vars
id: vars
env:
LOCAL_REGISTRY_PORT: ${{ inputs.local_registry_port }}
run: |
echo "image_tag_name=${{ steps.pre-vars.outputs.image_tag_name }}" >> $GITHUB_OUTPUT
echo "image_tag_name_local_base=localhost:${{ env.LOCAL_REGISTRY_PORT }}/${{ steps.pre-vars.outputs.image_tag_name }}-base" >> $GITHUB_OUTPUT
echo "image_file_name=${{ steps.pre-vars.outputs.image_file_name }}" >> $GITHUB_OUTPUT
echo "image_file_path=./${{ steps.pre-vars.outputs.image_file_name }}" >> $GITHUB_OUTPUT
echo "cache_scope=${{ steps.pre-vars.outputs.cache_scope }}" >> $GITHUB_OUTPUT
echo "cache_key=${{ steps.pre-vars.outputs.cache_scope }}-${{ github.sha }}#${{ github.run_attempt }}" >> $GITHUB_OUTPUT
# Build base image for debian version name. Layers will be cached and image pushes to local registry
- name: Build Image - Base
uses: docker/build-push-action@v5
with:
context: .
load: false
push: true
file: ./ci/ci-debian.Dockerfile
target: test-code
platforms: ${{ inputs.platform }}
tags: ${{ steps.vars.outputs.image_tag_name_local_base }}
cache-from: type=gha,scope=${{ steps.vars.outputs.cache_scope }}
cache-to: type=gha,mode=max,scope=${{ steps.vars.outputs.cache_scope }}
build-args: |
DEBIAN_CODENAME=${{ inputs.debian_codename }}
GIT_BRANCH=${{ github.head_ref || github.ref_name }}
GIT_USER=${{ github.event.pull_request.head.user.login || github.repository_owner }}
# Build new image with updates packages based on base image. Layers will NOT be chached. Result is written to file.
- name: Build Image - Update
uses: docker/build-push-action@v5
with:
context: .
load: false
push: false
file: ./ci/ci-debian.Dockerfile
target: test-update
platforms: ${{ inputs.platform }}
tags: ${{ steps.vars.outputs.image_tag_name }}
cache-from: type=gha,scope=${{ steps.vars.outputs.cache_scope }}
# DON'T use 'cache-to' here as the layer is then cached and this build would be useless
outputs: type=docker,dest=${{ steps.vars.outputs.image_file_path }}
build-args: |
BASE_TEST_IMAGE=${{ steps.vars.outputs.image_tag_name_local_base }}
- name: Artifact Upload Docker Image
uses: actions/upload-artifact@v3
with:
name: ${{ steps.vars.outputs.image_file_name }}
path: ${{ steps.vars.outputs.image_file_path }}
retention-days: 1


# Run tests with build image
test:
needs: [build]
runs-on: ${{ inputs.runs_on }}

strategy:
fail-fast: false
matrix:
username: ['pi']
test_script: ['run_install_common.sh', 'run_install_faststartup.sh', 'run_install_webapp_local.sh', 'run_install_webapp_download.sh']
include:
- username: hans
test_script: run_install_user_not_pi.sh

steps:
- name: Set up QEMU
uses: docker/[email protected]

- name: Set up Docker Buildx
uses: docker/[email protected]

- name: Artifact Download Docker Image
uses: actions/download-artifact@v3
with:
name: ${{ needs.build.outputs.image_file_name }}

- name: Load Docker Image
run: |
docker load --input ${{ needs.build.outputs.image_file_name }}
# Run test
- name: Run Test ${{ inputs.debian_codename }}-${{ matrix.username }}-${{ matrix.test_script }}
uses: tj-actions/docker-run@v2
with:
image: ${{ needs.build.outputs.image_tag_name }}
options: --platform ${{ inputs.platform }} --user ${{ matrix.username }} --init
name: ${{ matrix.test_script }}
args: |
./${{ matrix.test_script }}
# cleanup after test execution
cleanup:
# run only if tests didn't fail: keep the artifact to make job reruns possible
if: ${{ !failure() }}
needs: [build, test]
runs-on: ${{ inputs.runs_on }}

steps:
- name: Artifact Delete Docker Image
uses: geekyeggo/delete-artifact@v2
with:
name: ${{ needs.build.outputs.image_file_name }}
31 changes: 31 additions & 0 deletions .github/workflows/test_docker_debian_v3.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Test Install Scripts Debian v3

on:
schedule:
# run at 17:00 every sunday
- cron: '0 17 * * 0'
push:
pull_request:
# The branches below must be a subset of the branches above
branches: [ future3/develop ]

# let only one instance run the test so cache is not corrupted.
# cancel already running instances as only the last run will be relevant
concurrency:
group: ${{ github.ref }}-test-debian-v3
cancel-in-progress: true

jobs:

# Build container and run tests. Duplication of job intended for better visualization.
run_bookworm:
name: 'bookworm'
uses: ./.github/workflows/test_docker_debian_codename_sub_v3.yml
with:
debian_codename: 'bookworm'

run_bullseye:
name: 'bullseye'
uses: ./.github/workflows/test_docker_debian_codename_sub_v3.yml
with:
debian_codename: 'bullseye'
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,4 @@ The documentation can be found [here](./documentation/README.md)

## Installation?

Run the following one-liner in a shell and follow the instructions

~~~bash
cd; bash <(wget -qO- https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID/future3/develop/installation/install-jukebox.sh)
~~~
[Install Phoniebox software](documentation/builders/installation.md#install-phoniebox-software)
100 changes: 100 additions & 0 deletions ci/ci-debian.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Base Target to build and install all needed base configuration and packages. Specifie the needed platform with the docker '--platform XXX' option
ARG DEBIAN_CODENAME=bookworm
ARG BASE_TEST_IMAGE=test-code
FROM debian:${DEBIAN_CODENAME}-slim as base
ARG DEBIAN_CODENAME

ENV TERM=xterm DEBIAN_FRONTEND=noninteractive
ENV CI_RUNNING=true

# create pi configs to test installation
RUN touch /boot/config.txt
RUN echo "logo.nologo" > /boot/cmdline.txt

RUN echo "--- install packages (1) ---" \
&& apt-get update \
&& apt-get -y install \
apt-utils \
curl \
gnupg \
&& echo "--- add sources ---" \
&& curl -fsSL http://raspbian.raspberrypi.org/raspbian.public.key | gpg --dearmor > /usr/share/keyrings/raspberrypi-raspbian-keyring.gpg \
&& curl -fsSL http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor > /usr/share/keyrings/raspberrypi-archive-debian-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/raspberrypi-raspbian-keyring.gpg] http://raspbian.raspberrypi.org/raspbian/ ${DEBIAN_CODENAME} main contrib non-free rpi" > /etc/apt/sources.list.d/raspi.list \
&& echo "deb [signed-by=/usr/share/keyrings/raspberrypi-archive-debian-keyring.gpg] http://archive.raspberrypi.org/debian/ ${DEBIAN_CODENAME} main" >> /etc/apt/sources.list.d/raspi.list \
&& echo "--- install packages (2) ---" \
&& apt-get update \
&& apt-get -y upgrade \
&& apt-get -y install \
build-essential \
iproute2 \
openssh-client \
sudo \
systemd \
wireless-tools \
wget \
wpasupplicant \
&& rm -rf /var/lib/apt/lists/*

# Set NonInteractive for sudo usage in container. 'sudo' package needed
RUN echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
# ------

# Base Target for setting up the default user. user can be selected with the docker '--user YYY' option
FROM base as user
ARG USER_NAME=pi
ARG USER_GROUP=$USER_NAME
ARG USER_ID=1000

ENV TEST_USER_GROUP=test
RUN groupadd --gid 1002 $TEST_USER_GROUP

RUN groupadd --gid 1000 $USER_GROUP \
&& useradd -u $USER_ID -g $USER_GROUP -G sudo,$TEST_USER_GROUP -d /home/$USER_NAME -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' $USER_NAME \
&& echo "$USER_NAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER_NAME

ENV XDG_RUNTIME_DIR=/run/user/$USER_ID DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$USER_ID/bus
# ------


# Target for setting up an alternativ user 'hans:wurst'. user can be selected with the docker '--user YYY' option
FROM user as test-user

RUN export USER_ALT=hans \
&& export USER_ALT_GROUP=wurst \
&& groupadd --gid 1001 $USER_ALT_GROUP \
&& useradd -u 1001 -g $USER_ALT_GROUP -G sudo,$TEST_USER_GROUP -d /home/$USER_ALT -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' $USER_ALT \
&& echo "$USER_ALT ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER_ALT
# ------


# Target for adding envs and scripts from the repo to test installation
FROM test-user as test-code
ARG GIT_BRANCH
ARG GIT_USER

ENV GIT_BRANCH=$GIT_BRANCH GIT_USER=$GIT_USER

COPY --chown=root:$TEST_USER_GROUP --chmod=770 packages-core.txt ./

RUN echo "--- install internal packages ---" \
&& apt-get update \
&& sed 's/#.*//g' packages-core.txt | xargs apt-get -y install \
&& rm -rf /var/lib/apt/lists/*

ENV INSTALL_SCRIPT_PATH=/code

WORKDIR ${INSTALL_SCRIPT_PATH}
COPY --chown=root:$TEST_USER_GROUP --chmod=770 installation/install-jukebox.sh ./

WORKDIR ${INSTALL_SCRIPT_PATH}/tests
COPY --chown=root:$TEST_USER_GROUP --chmod=770 ci/installation/*.sh ./
# ------


# Target for applying latest updates (should not be cached!)
FROM $BASE_TEST_IMAGE as test-update
RUN apt-get update \
&& apt-get -y upgrade \
&& rm -rf /var/lib/apt/lists/*
# ------
43 changes: 43 additions & 0 deletions ci/installation/run_install_common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

# Install Phoniebox and test it
# Used e.g. for tests on Docker

# Objective:
# Test for a common installation path. Including autohotspot

SOURCE="${BASH_SOURCE[0]}"
SCRIPT_DIR="$(dirname "$SOURCE")"
LOCAL_INSTALL_SCRIPT_PATH="${INSTALL_SCRIPT_PATH:-${SCRIPT_DIR}/../../installation}"
LOCAL_INSTALL_SCRIPT_PATH="${LOCAL_INSTALL_SCRIPT_PATH%/}"

export ENABLE_WEBAPP_PROD_DOWNLOAD=true
# Run installation (in interactive mode)
# y - start setup
# n - use static ip
# n - deactivate ipv6
# y - setup autohotspot
# n - use custom password
# n - deactivate bluetooth
# n - disable on-chip audio
# - - mpd overwrite config (only with existing installation)
# n - setup rfid reader
# y - setup samba
# y - setup webapp
# n - setup kiosk mode
# - - install node (forced WebApp Download)
# n - reboot

"${LOCAL_INSTALL_SCRIPT_PATH}/install-jukebox.sh" <<< 'y
n
n
y
n
n
n
n
y
y
n
n
'
Loading

0 comments on commit 234cc3c

Please sign in to comment.