OS build #44
This file contains 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
# Home Assistant Operating System build workflow | |
name: OS build | |
on: | |
workflow_dispatch: | |
inputs: | |
boards: | |
description: 'List of boards to build (comma separated identifiers)' | |
required: false | |
type: string | |
default: 'rockpi-4a,rockpi-4a-plus,rockpi-4b,rockpi-4b-plus,rockpi-4c,rock-4c-plus,rock-4se' | |
env: | |
PYTHON_VERSION: "3.10" | |
jobs: | |
prepare: | |
name: Prepare build | |
runs-on: ubuntu-22.04 | |
permissions: | |
contents: read | |
pull-requests: read | |
packages: write | |
outputs: | |
version_dev: ${{ steps.version_dev.outputs.version_dev }} | |
version_main: ${{ steps.version.outputs.version_main }} | |
version_full: ${{ steps.version.outputs.version_full }} | |
channel: ${{ steps.channel.outputs.channel }} | |
matrix: ${{ steps.generate_matrix.outputs.result }} | |
build_container_image: ghcr.io/${{ github.repository_owner }}/haos-builder@${{ steps.build_haos_builder.outputs.digest }} | |
publish_build: ${{ steps.check_publish.outputs.publish_build }} | |
self_signed_cert: ${{ steps.generate_signing_key.outputs.self_signed_cert }} | |
steps: | |
- name: Checkout source | |
uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Check if build should be published | |
id: check_publish | |
env: | |
PUBLISH_FLAG: ${{ inputs.publish }} | |
run: | | |
if [ "${{ github.repository }}" == "home-assistant/operating-system" ]; then | |
if [ "${PUBLISH_FLAG}" != "true" ] && [ "${{ github.event_name }}" != "release" ]; then | |
echo "publish_build=false" >> "$GITHUB_OUTPUT" | |
else | |
echo "publish_build=true" >> "$GITHUB_OUTPUT" | |
fi | |
else | |
echo "publish_build=false" >> "$GITHUB_OUTPUT" | |
fi | |
- name: Generate development version | |
shell: bash | |
id: version_dev | |
if: ${{ github.event_name != 'release' }} | |
env: | |
PUBLISH_BUILD: ${{ steps.check_publish.outputs.publish_build }} | |
run: | | |
version_dev="dev$(date --utc +'%Y%m%d')" | |
#if [ "${{ env.PUBLISH_BUILD }}" != "true" ]; then | |
# version_dev="dev$(date +%s)" | |
#fi | |
echo "Development version \"${version_dev}\"" | |
echo "version_dev=${version_dev}" >> $GITHUB_OUTPUT | |
- name: Set version suffix | |
if: ${{ github.event_name != 'release' }} | |
env: | |
VERSION_DEV: ${{ steps.version_dev.outputs.version_dev }} | |
run: | | |
sed -i -E "s/(^VERSION_SUFFIX=\").*(\"$)/\1${VERSION_DEV}\2/" buildroot-external/meta | |
- name: Get version | |
id: version | |
run: | | |
. ${GITHUB_WORKSPACE}/buildroot-external/meta | |
echo "version_main=${VERSION_MAJOR}.${VERSION_MINOR}" >> $GITHUB_OUTPUT | |
if [ -z "${VERSION_SUFFIX}" ]; then | |
version_full="${VERSION_MAJOR}.${VERSION_MINOR}" | |
else | |
version_full="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_SUFFIX}" | |
fi | |
echo "version_full=${version_full}" >> $GITHUB_OUTPUT | |
echo "Full version number of this release is \"${version_full}\"." | |
- name: Validate version | |
id: version_check | |
if: ${{ github.event_name == 'release' }} | |
run: | | |
if [ "${{ steps.version.outputs.version_full }}" != "${{ github.event.release.tag_name }}" ]; then | |
echo "Version number in Buildroot metadata does not match tag (${{ steps.version.outputs.version_full }} vs ${{ github.event.release.tag_name }})." | |
exit 1 | |
fi | |
- name: Get channel | |
id: channel | |
run: | | |
if [[ "${{ github.event_name }}" == "release" ]]; then | |
if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then | |
echo "channel=beta" >> "$GITHUB_OUTPUT" | |
else | |
echo "channel=stable" >> "$GITHUB_OUTPUT" | |
fi | |
else | |
echo "channel=dev" >> "$GITHUB_OUTPUT" | |
fi | |
- name: Create build matrix | |
uses: actions/github-script@v7 | |
id: generate_matrix | |
with: | |
script: | | |
const boards = require('./.github/workflows/matrix.json') | |
if ("${{ github.event_name }}" == "release") { | |
return { "board": boards } | |
} | |
const boardFilter = "${{ github.event.inputs.boards }}" | |
if (boardFilter == "") { | |
console.log("Run full build for all boards") | |
return { "board": boards } | |
} else { | |
console.log("Run partial build") | |
const boardSet = new Set(boardFilter.split(",")) | |
const buildBoards = boards.filter(b => boardSet.has(b.id)) | |
return { "board": buildBoards } | |
} | |
- name: Set up Docker Buildx | |
uses: docker/[email protected] | |
- name: Log in to the GitHub container registry | |
uses: docker/[email protected] | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Build and Push | |
uses: docker/[email protected] | |
id: build_haos_builder | |
with: | |
context: . | |
file: Dockerfile | |
tags: ghcr.io/${{ github.repository_owner }}/haos-builder | |
cache-from: ghcr.io/${{ github.repository_owner }}/haos-builder:cache-${{ steps.version.outputs.version_main }} | |
cache-to: ghcr.io/${{ github.repository_owner }}/haos-builder:cache-${{ steps.version.outputs.version_main }} | |
push: true | |
- name: Generate self-signed certificate | |
id: generate_signing_key | |
env: | |
RAUC_CERTIFICATE: ${{ secrets.RAUC_CERTIFICATE }} | |
RAUC_PRIVATE_KEY: ${{ secrets.RAUC_PRIVATE_KEY }} | |
if: env.RAUC_CERTIFICATE == '' || env.RAUC_PRIVATE_KEY == '' | |
run: | | |
echo "::warning:: RAUC certificate or key is missing in the repository secrets. Building with a public self-signed certificate!" | |
buildroot-external/scripts/generate-signing-key.sh cert.pem key.pem | |
echo "self_signed_cert=true" >> $GITHUB_OUTPUT | |
- name: Create signing key | |
uses: actions/upload-artifact@v4 | |
if: steps.generate_signing_key.outcome == 'success' | |
with: | |
name: signing-key | |
path: | | |
cert.pem | |
key.pem | |
build: | |
name: Build for ${{ matrix.board.id }} | |
permissions: | |
contents: write # for actions/upload-release-asset to upload release asset | |
needs: prepare | |
strategy: | |
fail-fast: ${{ github.event_name == 'release' }} | |
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} | |
runs-on: ha_buildhost | |
steps: | |
- name: Checkout source | |
uses: actions/checkout@v4 | |
with: | |
submodules: true | |
persist-credentials: false | |
- name: Setup Python version ${{ env.PYTHON_VERSION }} | |
if: ${{ github.event_name != 'release' }} | |
uses: actions/setup-python@v5 | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
- name: Install AWS CLI | |
if: ${{ github.event_name != 'release' && needs.prepare.outputs.publish_build == 'true' }} | |
run: pip install awscli | |
- name: Set version suffix | |
if: ${{ github.event_name != 'release' }} | |
env: | |
VERSION_DEV: ${{ needs.prepare.outputs.version_dev }} | |
run: | | |
sed -i -E "s/(^VERSION_SUFFIX=\").*(\"$)/\1${VERSION_DEV}\2/" buildroot-external/meta | |
- name: 'Add release PKI certs' | |
if: ${{ needs.prepare.outputs.self_signed_cert != 'true' }} | |
env: | |
RAUC_CERTIFICATE: ${{ secrets.RAUC_CERTIFICATE }} | |
RAUC_PRIVATE_KEY: ${{ secrets.RAUC_PRIVATE_KEY }} | |
run: | | |
echo -e "-----BEGIN CERTIFICATE-----\n${RAUC_CERTIFICATE}\n-----END CERTIFICATE-----" > cert.pem | |
echo -e "-----BEGIN PRIVATE KEY-----\n${RAUC_PRIVATE_KEY}\n-----END PRIVATE KEY-----" > key.pem | |
- name: Get self-signed certificate from the prepare job | |
if: ${{ needs.prepare.outputs.self_signed_cert == 'true' }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: signing-key | |
- name: Build | |
run: | | |
BUILDER_UID="$(id -u)" | |
BUILDER_GID="$(id -g)" | |
docker run --rm --privileged \ | |
-e BUILDER_UID="${BUILDER_UID}" -e BUILDER_GID="${BUILDER_GID}" \ | |
-v "${GITHUB_WORKSPACE}:/build" \ | |
-v "ha-build-cache:/cache" \ | |
${{ needs.prepare.outputs.build_container_image }} \ | |
make BUILDDIR=/build ${{ matrix.board.defconfig }} | |
- name: Check Linux config | |
run: | | |
docker run --rm --privileged \ | |
-e BUILDER_UID="$(id -u)" -e BUILDER_GID="$(id -g)" \ | |
-v "${GITHUB_WORKSPACE}:/build" \ | |
-v "ha-build-cache:/cache" \ | |
${{ needs.prepare.outputs.build_container_image }} \ | |
make -C buildroot O="/build/output" BR2_EXTERNAL="/build/buildroot-external" \ | |
BR2_CHECK_DOTCONFIG_OPTS="--github-format --strip-path-prefix=/build/" linux-check-dotconfig | |
- name: Upload artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: haos-image-${{ matrix.board.id }} | |
path: | | |
output/images/haos_*.img.xz | |
output/images/haos_*.raucb | |
if-no-files-found: error | |
- name: Generate build summary | |
run: | | |
echo "# ${{ matrix.board.id }} build summary" >> $GITHUB_STEP_SUMMARY | |
echo "## Artifacts" >> $GITHUB_STEP_SUMMARY | |
echo "| File | Size (bytes) | Size (formatted) |" >> $GITHUB_STEP_SUMMARY | |
echo "|:-|:-|:-|" >> $GITHUB_STEP_SUMMARY | |
for f in output/images/haos_*; do | |
echo "| $(basename $f) | $(du -b $f | cut -f1) | $(du -bh $f | cut -f1) |" >> $GITHUB_STEP_SUMMARY | |
done | |
echo "## Partitions" >> $GITHUB_STEP_SUMMARY | |
echo "| File | Size (bytes) | Size (formatted) |" >> $GITHUB_STEP_SUMMARY | |
echo "|:-|:-|:-|" >> $GITHUB_STEP_SUMMARY | |
for f in boot.vfat kernel.img rootfs.erofs overlay.ext4 data.ext4; do | |
echo "| ${f} | $(du -b output/images/$f | cut -f1) | $(du -bh output/images/$f | cut -f1) |" >> $GITHUB_STEP_SUMMARY | |
done |