Skip to content

Release Stage 2 - Create Raspbian Homebridge Image refs/heads/latest - stable:32020497585 #119

Release Stage 2 - Create Raspbian Homebridge Image refs/heads/latest - stable:32020497585

Release Stage 2 - Create Raspbian Homebridge Image refs/heads/latest - stable:32020497585 #119

name: Release Stage 2 - Create Raspbian Homebridge Image using pi-gen
run-name: Release Stage 2 - Create Raspbian Homebridge Image ${{ github.ref }} - ${{ inputs.run_name }}
on:
workflow_dispatch:
inputs:
# The github tag. e.g: v1.0.1
# Download assets from a specific tag/version
release-increment:
description: 'Increment Release Version'
type: choice
options:
- patch
- minor
- major
default: 'patch'
publish:
description: 'Publish Release to RPI Imager Registry'
type: boolean
default: false
release-stream:
description: 'Release Stream to build against'
type: choice
options:
- stable
default: 'stable'
required: false
Scheduled:
description: 'Whether this is a scheduled run'
required: false
type: choice
options:
- Scheduled
- Manual
default: Manual
run_name:
description: 'Unique name of the run'
required: false
type: string
default: ''
concurrency:
group: release-stage-2-build-raspbian-image
cancel-in-progress: false
jobs:
tag:
name: Create Release Tag
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.v-version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get next version
uses: reecetech/version-increment@2024.10.1
id: version
with:
scheme: semver
increment: ${{ inputs.release-increment }}
- name: Display version information
run: |
echo "::notice::Next version will be: ${{ steps.version.outputs.v-version }}"
echo "::notice::Current version: ${{ steps.version.outputs.current-v-version }}"
echo "::notice::Release increment: ${{ inputs.release-increment }}"
determine_package_versions:
name: Determine package versions
needs: tag
runs-on: ubuntu-latest
outputs:
HOMEBRIDGE_APT_PKG_VERSION: ${{ steps.get_versions.outputs.HOMEBRIDGE_APT_PKG_VERSION }}
FFMPEG_FOR_HOMEBRIDGE_VERSION: ${{ steps.get_versions.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Get Homebridge version
id: get_versions
run: |
HOMEBRIDGE_APT_PKG_VERSION=$(jq -r '.dependencies["@homebridge/homebridge-apt-pkg"]' ./stable/package.json | sed 's/\^//')
FFMPEG_FOR_HOMEBRIDGE_VERSION=$(jq -r '.dependencies["ffmpeg-for-homebridge"]' ./stable/package.json | sed 's/\^//')
echo "HOMEBRIDGE_APT_PKG_VERSION=${HOMEBRIDGE_APT_PKG_VERSION}" >> $GITHUB_OUTPUT
echo "FFMPEG_FOR_HOMEBRIDGE_VERSION=v${FFMPEG_FOR_HOMEBRIDGE_VERSION}" >> $GITHUB_OUTPUT
echo "::notice::Homebridge APT Package Version: ${HOMEBRIDGE_APT_PKG_VERSION}"
echo "::notice::FFmpeg for Homebridge Version: v${FFMPEG_FOR_HOMEBRIDGE_VERSION}"
- name: Show version summary
run: |
echo "## Version Information" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Component | Version |" >> $GITHUB_STEP_SUMMARY
echo "|-----------|---------|" >> $GITHUB_STEP_SUMMARY
echo "| Release | ${{ needs.tag.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
echo "| Homebridge APT Package | ${{ steps.get_versions.outputs.HOMEBRIDGE_APT_PKG_VERSION }} |" >> $GITHUB_STEP_SUMMARY
echo "| FFmpeg for Homebridge | ${{ steps.get_versions.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }} |" >> $GITHUB_STEP_SUMMARY
build_images:
name: Build RPI Homebridge (${{ matrix.name }}) Image ${{ needs.tag.outputs.version }}
needs: [tag, determine_package_versions]
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
name: [
32bit,
64bit
]
include:
- pi-gen-version: arm64
release: trixie
name: 64bit
devices: '["pi5-64bit", "pi4-64bit", "pi3-64bit"]'
recommended: "Recommended"
runs-on: ubuntu-24.04-arm
- pi-gen-version: master
release: trixie
name: 32bit
devices: '["pi5-32bit", "pi4-32bit", "pi3-32bit", "pi2-32bit", "pi1-32bit"]'
recommended: "Not Recommended, support will be ending Spring 2027"
runs-on: ubuntu-22.04
# The build
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
# https://stackoverflow.com/questions/72444103/what-does-running-the-multiarch-qemu-user-static-does-before-building-a-containe
# - name: Setup Dependencies
# run: |
# sudo apt-get update
# sudo apt-get --yes --no-install-recommends install binfmt-support qemu-user-static
# docker run --rm --privileged multiarch/qemu-user-static:register --reset
# Only needed for 32bit build on x86_64 runner
- name: Set up QEMU
if: matrix.name == '32bit'
uses: docker/setup-qemu-action@v4
# f022813 aka 1.7.0
- uses: usimd/pi-gen-action@v1
id: build
with:
# If you require the use of an apt proxy, set it here. This proxy setting will not
# be included in the image, making it safe to use an apt-cacher or similar package
# for development.
apt-proxy: ''
# Compression to apply on final image (either "none", "zip", "xz" or "gz").
compression: zip
# Compression level to be used. From 0 to 9 (refer to the tool man page for more
# information on this. Usually 0 is no compression but very fast, up to 9 with the
# best compression but very slow).
compression-level: 6
# Disable the renaming of the first user during the first boot. This make it so
# 'username' stays activated. 'username' must be set for this to work. Please be
# aware of the implied security risk of defining a default username and password
# for your devices.
disable-first-boot-user-rename: 0
# Additional options to include in PIGEN_DOCKER_OPTS
# docker-opts: ''
docker-opts: '--env BUILD_VERSION="${{ github.repository }}-${{ needs.tag.outputs.version }}-\(${{ matrix.name }}\)" --env HOMEBRIDGE_APT_PKG_VERSION="${{ needs.determine_package_versions.outputs.HOMEBRIDGE_APT_PKG_VERSION }}" --env FFMPEG_FOR_HOMEBRIDGE_VERSION="${{ needs.determine_package_versions.outputs.FFMPEG_FOR_HOMEBRIDGE_VERSION }}" --env RELEASE_STREAM=${{ inputs.release-stream }} --env IMG_SIZE=5G'
# If set to `1`, cloud-init and netplan will be installed and configured. This
# will allow you to configure your Raspberry Pi using cloud-init configuration
# files. The cloud-init configuration files should be placed in the bootfs or by
# editing the files in `stage2/04-cloud-init/files`. Cloud-init will be configured
# to read them on first boot.
enable-cloud-init: 0
# Set whether a NOOBS image should be built as well. If enabled, the output
# directory containing the NOOBS files will be saved as output variable
# 'image-noobs-path'.
enable-noobs: false
# Enable SSH access to Pi.
enable-ssh: 1
# If this feature is enabled, the action will configure pi-gen to not export any
# stage as image but the last one defined in property 'stage-list'. This is
# helpful when building a single image flavor (in contrast to building a
# lite/server and full-blown desktop image), since it speeds up the build process
# significantly.
export-last-stage-only: true
# Comma or whitespace separated list of additional packages to install on host
# before running pi-gen. Use this list to add any packages your custom stages may
# require. Note that this is not affecting the final image. In order to add
# additional packages, you need to add a respective 'XX-packages' file in your
# custom stage.
extra-host-dependencies: ''
# Comma or whitespace separated list of additional modules to load on host before
# running pi-gen. If your custom stage requires additional software or kernel
# modules to be loaded, add them here. Note that this is not meant to configure
# modules to be loaded in the target image.
extra-host-modules: ''
# Token to use for checking out pi-gen repo.
github-token: ${{ github.token }}
# Host name of the image.
hostname: homebridge
# Final image name.
image-name: 'Homebridge-${{ matrix.release }}-${{ matrix.name }}'
# Enabling this option will remove plenty of components from the GitHub Actions
# runner that are not mandatory pre-requisites for a (vanilla) pi-gen build. This
# shall increase the available disk space so that also large images can be
# compiled on a free GHA runner (benchmark is the full image including a desktop
# environment). If any packages are missing during the build consider adding them
# to the `extra-host-dependencies` list.
increase-runner-disk-size: false
# Default keyboard keymap.
keyboard-keymap: gb
# Default keyboard layout.
keyboard-layout: English (UK)
# Default locale of the system image.
locale: en_GB.UTF-8
# Password of the intial user account, locked if empty.
password: ''
# Path where selected pi-gen ref will be checked out to. If the path does not yet
# exist, it will be created (including its parents).
pi-gen-dir: pi-gen
# The release name to use in `/etc/issue.txt`. The default should only be used for
# official Raspberry Pi builds.
pi-gen-release: Raspberry Pi reference
# GitHub repository to fetch pi-gen from, must be a fork from RPi-Distro/pi-gen.
pi-gen-repository: RPi-Distro/pi-gen
# Release version of pi-gen to use. This can both be a branch or tag name known in
# the pi-gen repository.
pi-gen-version: ${{ matrix.pi-gen-version }}
# Setting to `1` will disable password authentication for SSH and enable public
# key authentication. Note that if SSH is not enabled this will take effect when
# SSH becomes enabled.
pubkey-only-ssh: 0
# Setting this to a value will make that value the contents of the
# FIRST_USER_NAME's ~/.ssh/authorized_keys. Obviously the value should therefore
# be a valid authorized_keys file. Note that this does not automatically enable
# SSH.
pubkey-ssh-first-user: ''
# The release version to build images against. Valid values are jessie, stretch,
# buster, bullseye, bookworm, trixie and testing.
release: ${{ matrix.release }}
# Setting to `1` will prevent pi-gen from dropping the "capabilities" feature.
# Generating the root filesystem with capabilities enabled and running it from a
# filesystem that does not support capabilities (like NFS) can cause issues. Only
# enable this if you understand what it is.
setfcap: ''
# List of stage name to execute in given order. Relative and absolute paths to
# custom stage directories are allowed here. Note that by default pi-gen exports
# images in stage2 (lite), stage4 and stage5. You probably want to hook in custom
# stages before one of the exported stages. Otherwise, the action will make sure
# any custom stage will include an image export directive.
stage-list: stage0_prep stage0 stage1 stage2 stage3_homebridge
# An additional temporary apt repo to be used during the build process. This could
# be useful if you require pre-release software to be included in the image. The
# variable should contain sources in one-line-style format. "RELEASE" will be
# replaced with the RELEASE variable. (see
# https://manpages.debian.org/stable/apt/sources.list.5.en.html#ONE-LINE-STYLE_FORMAT)
temp-repo: ''
# System timezone.
timezone: Europe/London
# Name of the initial user account.
username: pi
# Print all output from pi-gen.
verbose-output: true
# Wifi country code of default network to connect to.
wpa-country: ''
# SSID of a default wifi network to connect to.
wpa-essid: ''
# Password of default wifi network to connect to.
wpa-password: ''
- name: Build complete
run: |
echo "::notice::Homebridge VM image version: Homebridge-${{ matrix.release }}-${{ matrix.name }}"
echo "::notice::Run ID: ${{ github.run_id }}"
echo "::notice::Architecture: ${{ matrix.name }}"
echo "::notice::Release: ${{ needs.tag.outputs.version }}"
echo "::notice::image-path: ${{ steps.build.outputs.image-path }}"
IMGFILENAME=`basename ${{ steps.build.outputs.image-path }}`
echo "IMGFILENAME=${IMGFILENAME}" >> $GITHUB_ENV
echo "RPI_IMAGER_NAME: Homebridge ${{ matrix.release }} (${{ matrix.name }})"
echo "RPI_IMAGER_DESCRIPTION: Official Homebridge Raspberry Pi Image ${{ matrix.release }} (${{ matrix.name }}) - ${{ matrix.recommended }}"
echo "RPI_IMAGER_ICON: https://user-images.githubusercontent.com/3979615/116509191-3c35f880-a906-11eb-9a7f-7cad7c2aa641.png"
echo "RPI_IMAGER_WEBSITE: https://github.com/homebridge/homebridge-raspbian-image/wiki/Getting-Started"
echo "RPI_IMAGER_IMAGE_URL: https://github.com/${{ github.repository }}/releases/download/${{ needs.tag.outputs.version }}/${IMGFILENAME}"
echo "RPI_IMAGER_DEVICES: '${{ matrix.devices }}'"
# This is not currently used
- name: Calculate Image Checksum
id: get_sha256_checksum
run: |
export IMAGE_SHA256_CHECKSUM=$(shasum -a 256 ${{ steps.build.outputs.image-path }} | awk '{print $1}')
echo "$IMAGE_SHA256_CHECKSUM ${{ steps.build.outputs.image-path }}"
echo "::notice::IMAGE_SHA256_CHECKSUM ${IMGFILENAME} ==> ${IMAGE_SHA256_CHECKSUM}"
- name: Prepare output directory
run: |
mkdir -p output
cp ${{ steps.build.outputs.image-path }} output/
- name: Generate rpi-image-repo.json
id: generate_rpi-image-repo
run: |
export RPI_IMAGER_NAME="Homebridge ${{ matrix.release }} (${{ matrix.name }})"
export RPI_IMAGER_DESCRIPTION="Official Homebridge Raspberry Pi Image ${{ matrix.release }} (${{ matrix.name }}) - ${{ matrix.recommended }}"
export RPI_IMAGER_ICON="https://user-images.githubusercontent.com/3979615/116509191-3c35f880-a906-11eb-9a7f-7cad7c2aa641.png"
export RPI_IMAGER_WEBSITE="https://github.com/homebridge/homebridge-raspbian-image/wiki/Getting-Started"
export RPI_IMAGER_IMAGE_URL="https://github.com/${{ github.repository }}/releases/download/${{ needs.tag.outputs.version }}/${{ env.IMGFILENAME }}"
export RPI_IMAGER_DEVICES='${{ matrix.devices }}'
./make_rpi-imager-snipplet.py --rpi_imager_url ${RPI_IMAGER_IMAGE_URL}
- name: Copy rpi-image-repo to output directory
run: |
cp pi-gen/deploy/rpi-image-repo.json output/rpi-image-repo-${{ matrix.name }}.json
# Extract /opt/homebridge/*manifest from the image and upload to the release
- name: Extract /opt/homebridge/*manifest from the image
run: |
# Unzip the image first
unzip ${{ steps.build.outputs.image-path }}
IMAGE_FILE=$(ls *.img | head -n1)
echo "Found image: $IMAGE_FILE"
mkdir mnt
# Use losetup to automatically handle partition detection
LOOP_DEVICE=$(sudo losetup -fP --show "$IMAGE_FILE")
sudo mount ${LOOP_DEVICE}p2 mnt # p2 is usually the root partition
ls -l mnt/opt/homebridge/
cp mnt/opt/homebridge/homebridge_raspbian_image*manifest output/
# Add extracted manifest(s) to the GitHub step summary (Markdown)
for f in output/homebridge_raspbian_image*manifest; do
if [ -f "$f" ]; then
echo "## Extracted manifest: $(basename "$f")" >> $GITHUB_STEP_SUMMARY
echo '' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
sed -n '1,10000p' "$f" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi
done
sudo umount mnt
sudo losetup -d $LOOP_DEVICE
rm -rf mnt
- name: Build Release Body
id: release_body
run: |
./scripts/create-release-body.sh ${{ inputs.release-stream }}
cat output/*manifest output/release-body.md > output/final-release-body.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Build Artifacts
uses: actions/upload-artifact@v7
with:
retention-days: 7
name: build-${{ matrix.name }}
path: output/
trigger-stage-3:
name: Trigger Release Stage 3
needs: [tag, build_images]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Trigger Release Stage 3 Workflow
run: |
gh workflow run release-stage-3_package_release.yml \
--ref latest \
--field run_id="${{ github.run_id }}" \
--field release_tag="${{ needs.tag.outputs.version }}" \
--field publish="${{ inputs.publish && 'true' || 'false' }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Workflow triggered
run: |
echo "::notice::Release Stage 3 workflow triggered for version ${{ needs.tag.outputs.version }}"
echo "::notice::Run ID: ${{ github.run_id }}"
echo "::notice::Publish to Registry: ${{ inputs.publish }}"