Build and publish imswitch images #22
This file contains hidden or 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
| 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 |