Skip to content

Build and publish imswitch images #22

Build and publish imswitch images

Build and publish imswitch images #22

Workflow file for this run

name: Build and publish imswitch images
permissions:
contents: write
on:
release:
types: [published]
workflow_dispatch:
jobs:
build-imswitch-image:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create swap file (4GB)
run: |
sudo fallocate -l 4G /swapfile || sudo dd if=/dev/zero of=/swapfile bs=1M count=4096
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
free -h
- name: Add imswitch Stage
run: |
# 1) Make the stage folder
mkdir -p stage-imswitch/package-imswitch
# 2) Indicate we depend on stage2
echo "2" > stage-imswitch/depends
# 3) Create prerun.sh
cat > stage-imswitch/prerun.sh << 'PRERUN'
#!/bin/bash -e
if [ ! -d "${ROOTFS_DIR}" ]; then
copy_previous
fi
PRERUN
chmod +x stage-imswitch/prerun.sh
# 4) Create the main 00-run-chroot.sh script
cat > stage-imswitch/package-imswitch/00-run-chroot.sh << 'EOF'
#!/bin/bash -e
#
# 00-run-chroot.sh
# Runs in chroot during pi-gen build to:
# - Prevent services from starting
# - Download camera driver files into /opt/camera-drivers
# - Prepare a first-boot systemd service that installs them on real hardware
# ----------------------------------------------------------------------------
# 1. Prevent services from auto-starting in chroot
# ----------------------------------------------------------------------------
cat << 'POLICYRC' > /usr/sbin/policy-rc.d
#!/bin/sh
exit 101
POLICYRC
chmod +x /usr/sbin/policy-rc.d
# ----------------------------------------------------------------------------
# 2. Fix hostname resolution warnings
# ----------------------------------------------------------------------------
echo "127.0.0.1 $(hostname)" >> /etc/hosts
# ----------------------------------------------------------------------------
# 3. Non-interactive debconf
# ----------------------------------------------------------------------------
export DEBIAN_FRONTEND=noninteractive
# ----------------------------------------------------------------------------
# 4. Install basic tools needed for downloading & unzipping
# ----------------------------------------------------------------------------
apt-get update
apt-get install -y git nano python3-pip wget unzip ntpdate
# install docker
ntpdate pool.ntp.org
# Check if Docker is installed
if ! command -v docker &> /dev/null
then
echo "Docker is not installed. Installing Docker..."
# Install Docker
curl -sSL https://get.docker.com | sh
# Add current user to the Docker group
usermod -aG docker pi || true
# Print message to logout and login again
echo "Please log out and log back in to apply the Docker group changes."
else
echo "Docker is already installed. Skipping installation."
fi
# install raspap
export TERM=xterm
apt-get update -y && apt-get install -y curl dhcpcd5 iptables procps whiptail # (for the two lines)
curl -sL https://install.raspap.com | bash -s -- --yes --wireguard 0 --adblock 0 --openvpn 0 --restapi 1 --update
# Generate your custom SSID with random digits
SSID="openUC2-$(tr -dc 0-9 < /dev/urandom | head -c 6)"
echo "Using SSID: $SSID"
# Update hostapd settings with new SSID and pass
sudo sed -i "s/^ssid=.*/ssid=$SSID/g" /etc/hostapd/hostapd.conf
sudo sed -i "s/^wpa_passphrase=.*/wpa_passphrase=youseetoo/g" /etc/hostapd/hostapd.conf
# ----------------------------------------------------------------------------
# 5. Download camera driver files into /opt/camera-drivers
# (They remain in the final image at that location.)
# ----------------------------------------------------------------------------
mkdir -p /opt/camera-drivers
cd /opt/camera-drivers
# --- Daheng ---
wget -O Galaxy_Linux_Python_2.0.2106.9041.tar_1.gz \
https://dahengimaging.com/downloads/Galaxy_Linux_Python_2.0.2106.9041.tar_1.gz
wget -O Galaxy_Linux-armhf_Gige-U3_32bits-64bits_1.5.2303.9202.zip \
https://dahengimaging.com/downloads/Galaxy_Linux-armhf_Gige-U3_32bits-64bits_1.5.2303.9202.zip
# --- Hik (MVS) driver zip ---
cd /opt/camera-drivers
wget -O MVS_STD_V3.0.1_240902.zip \
https://www.hikrobotics.com/en2/source/vision/video/2024/9/3/MVS_STD_V3.0.1_240902.zip
mkdir -p /opt/camera-drivers/MVS_STD_V3.0.1_240902
unzip MVS_STD_V3.0.1_240902.zip -d /opt/camera-drivers/MVS_STD_V3.0.1_240902
mv /opt/camera-drivers/MVS_STD_V3.0.1_240902/MVS-3.0.1_aarch64_20240902.deb /opt/camera-drivers/MVS-3.0.1_aarch64_20240902.deb
rm -r /opt/camera-drivers/MVS_STD_V3.0.1_240902
rm -r /opt/camera-drivers/MVS_STD_V3.0.1_240902.zip
# ----------------------------------------------------------------------------
# 6. Create first_boot_setup.sh & service
# ----------------------------------------------------------------------------
cat << 'FIRSTBOOT' > /usr/local/bin/first_boot_setup.sh
#!/bin/bash -e
#
# first_boot_setup.sh
# Runs exactly once on the real Pi to install camera drivers from /opt/camera-drivers.
echo "[FIRST BOOT] Installing camera drivers from /opt/camera-drivers..."
# Directory where we stored them in chroot
DRIVER_DIR="/opt/camera-drivers"
# A) Install HIK/MVS driver
cd "$DRIVER_DIR"
# Check if .deb is inside the unzipped folder:
if [ -f MVS-3.0.1_aarch64_20240902.deb ]; then
dpkg -i MVS-3.0.1_aarch64_20240902.deb || true
# Optionally remove the .deb after install if you like
# rm -f MVS-3.0.1_aarch64_20240902.deb
else
echo "[WARN] MVS .deb not found after unzipping. Check folder contents."
fi
# If the MVS install has a GrabImage.py
if [ -d /opt/MVS/Samples/aarch64/Python/ ]; then
cd /opt/MVS/Samples/aarch64/Python/
cp GrabImage/GrabImage.py MvImport/GrabImage.py || true
fi
# Append environment variables to /etc/profile
echo 'export MVCAM_COMMON_RUNENV=/opt/MVS/lib' >> /etc/profile
echo 'export LD_LIBRARY_PATH=/opt/MVS/lib/64:/opt/MVS/lib/32:$LD_LIBRARY_PATH' >> /etc/profile
# B) Install Daheng driver
echo "[FIRST BOOT] Installing Daheng driver..."
cd "$DRIVER_DIR"
unzip Galaxy_Linux-armhf_Gige-U3_32bits-64bits_1.5.2303.9202.zip || true
tar -zxvf Galaxy_Linux_Python_2.0.2106.9041.tar_1.gz || true
cd $DRIVER_DIR/Galaxy_Linux-armhf_Gige-U3_32bits-64bits_1.5.2303.9202
chmod +x Galaxy_camera.run
# Build & install the Python API
cd $DRIVER_DIR/Galaxy_Linux_Python_2.0.2106.9041/api
python3 setup.py build
python3 setup.py install
# Auto-enter the Daheng run script
echo "Y En Y" | $DRIVER_DIR/Galaxy_Linux-armhf_Gige-U3_32bits-64bits_1.5.2303.9202/Galaxy_camera.run || true
# Set library path
echo 'export LD_LIBRARY_PATH=/usr/lib:'$DRIVER_DIR'/Galaxy_Linux-armhf_Gige-U3_32bits-64bits_1.5.2303.9202:$LD_LIBRARY_PATH' >> /etc/profile
# Install extra Python packages
pip3 install --break-system-packages pillow numpy
# ---------------------------------------
# Create Desktop for user 'pi'
# ---------------------------------------
USER_HOME="/home/pi"
DESKTOP_PATH="$USER_HOME/Desktop"
DOWNLOADS_PATH="$USER_HOME/Downloads"
mkdir -p "$DESKTOP_PATH" "$DOWNLOADS_PATH"
chown -R pi:pi "$DESKTOP_PATH" "$DOWNLOADS_PATH"
# Create Docker scripts
cat << 'SCRIPT1' > "$DESKTOP_PATH/update_docker_container.sh"
#!/bin/bash
sudo docker pull ghcr.io/openuc2/imswitch-noqt-arm64:latest
SCRIPT1
cat << 'SCRIPT2' > "$DESKTOP_PATH/launch_docker_container.sh"
#!/bin/bash
docker run -it --rm \
-p 8001:8001 -p 8002:8002 -p 8003:8003 -p 8888:8888 -p 2222:22 \
-e CONFIG_PATH=/config \
-e DATA_PATH=/dataset \
-v ~/Documents/imswitch_docker/imswitch_git:/tmp/ImSwitch-changes \
-v ~/Documents/imswitch_docker/imswitch_pip:/persistent_pip_packages \
-v ~/Downloads:/dataset \
-v ~/:/config \
-e HEADLESS=1 \
-e HTTP_PORT=8001 \
-e UPDATE_INSTALL_GIT=0 \
-e UPDATE_CONFIG=0 \
--privileged ghcr.io/openuc2/imswitch-noqt-arm64:latest
SCRIPT2
chmod +x "$DESKTOP_PATH/"*.sh
chown pi:pi "$DESKTOP_PATH/"*.sh
# ---------------------------------------
# Self-remove so it only runs once
# ---------------------------------------
systemctl disable first_boot_setup.service
rm -f /etc/systemd/system/first_boot_setup.service
rm -f /usr/local/bin/first_boot_setup.sh
echo "[FIRST BOOT] Done installing camera drivers!"
exit 0
FIRSTBOOT
chmod +x /usr/local/bin/first_boot_setup.sh
cat << 'SERVEOF' > /etc/systemd/system/first_boot_setup.service
[Unit]
Description=Install camera drivers & set up IMSwitch on first boot
After=multi-user.target
Requires=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/first_boot_setup.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
SERVEOF
systemctl enable first_boot_setup.service
# ----------------------------------------------------------------------------
# 7. Remove policy-rc.d so final system can start services
# ----------------------------------------------------------------------------
rm /usr/sbin/policy-rc.d
echo "Done. Exiting chroot script."
exit 0
EOF
chmod +x stage-imswitch/package-imswitch/00-run-chroot.sh
- name: Build imswitch Image
id: build
uses: usimd/pi-gen-action@v1
with:
enable-ssh: 1
stage-list: stage0 stage1 stage2 ./stage-imswitch
verbose-output: true
image-name: imswitch-raspi-lite
# Basic config
disable-first-boot-user-rename: 1
enable-noobs: false
hostname: uc2
password: youseetoo
keyboard-layout: de
timezone: Europe/Berlin
locale: en_US.UTF-8
# If your scripts need e.g. parted or other build-host packages, add them here
extra-host-dependencies: git nano
wpa-country: DE
wpa-essid: "Blynk"
wpa-password: "12345678"
# If you see memory errors:
increase-runner-disk-size: true
- name: Upload Artifact
uses: svenstaro/upload-release-action@v2
with:
asset_name: "imswitch-bookworm.img.zip"
file: ${{ steps.build.outputs.image-path }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: imswitch-${{ github.event.inputs.tag || github.ref }}
overwrite: true