firmware-module #7
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
name: firmware-module | |
on: | |
schedule: | |
# 03:30 PST / Nightly | |
- cron: '30 10 * * *' | |
workflow_dispatch: | |
inputs: | |
tg_disabled: | |
type: boolean | |
description: 'Disable Telegram notifications' | |
required: false | |
default: true | |
tg_scratch: | |
type: boolean | |
description: 'Use TG scratch channel' | |
required: false | |
default: false | |
graph_enabled: | |
type: boolean | |
description: 'Enable build time graph' | |
required: false | |
default: false | |
teacup_only: | |
type: boolean | |
description: 'Only build Tea Cup profile' | |
required: false | |
default: false | |
debug_enabled: | |
type: boolean | |
description: 'Debug: Generate dummy image files' | |
required: false | |
default: false | |
env: | |
TAG_NAME: module | |
TERM: linux | |
BR2_DL_DIR: ~/dl | |
TG_TOKEN: ${{secrets.TELEGRAM_TOKEN_BOT_THINGINO}} | |
TG_CHANNEL: -1002083893006_14394 | |
TG_TOPIC: 14394 | |
TG_CHANNEL_SCRATCH: ${{secrets.TELEGRAM_CHANNEL_THINGINO_SCRATCH}} | |
FORCE_UNSAFE_CONFIGURE: 1 | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
TG_DISABLED: true | |
jobs: | |
notify-begin: | |
runs-on: ubuntu-latest | |
outputs: | |
start_time: ${{ steps.set_output.outputs.time }} | |
tg_disabled: ${{ steps.set_env.outputs.tg_disabled }} | |
steps: | |
- name: Set timezone | |
run: | | |
sudo timedatectl set-timezone "America/Los_Angeles" | |
- name: Save workflow start time to ENV | |
id: set_output | |
run: echo "time=$(date +%s)" >> $GITHUB_OUTPUT | |
- name: Configure Environment Variables | |
run: | | |
echo "TG_DISABLED=${{ github.event.inputs.tg_disabled || 'false' }}" >> $GITHUB_ENV | |
echo "tg_disabled=${{ github.event.inputs.tg_disabled || 'false' }}" >> $GITHUB_OUTPUT | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
ref: "master" | |
fetch-depth: "1" | |
- name: Send build start notifcation via Telegram | |
if: env.TG_DISABLED == 'false' | |
run: | | |
if [[ "${{ github.event.inputs.tg_scratch }}" == 'true' ]]; then | |
TG_CHANNEL=${{ env.TG_CHANNEL_SCRATCH }} | |
export TG_TOPIC="" | |
fi | |
.github/scripts/tg-notify.sh -s $TG_TOKEN $TG_CHANNEL $TG_TOPIC start $TAG_NAME ${{ github.run_id }} ${{ github.repository }} | |
generate-matrix: | |
runs-on: ubuntu-latest | |
outputs: | |
matrix: ${{ steps.set-matrix.outputs.matrix }} | |
steps: | |
- name: Set timezone | |
run: | | |
sudo timedatectl set-timezone "America/Los_Angeles" | |
- name: Configure GH workspace | |
run: git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
ref: "master" | |
fetch-depth: "1" | |
- name: Generate device matrix | |
id: set-matrix | |
run: | | |
if [[ "${{ github.event.inputs.teacup_only }}" == 'true' ]]; then | |
CONFIGS=$(find configs/modules/ -type f | sort | awk -F '/' '{print $(NF)}' | awk NF | grep 't31zx_imx327_eth') | |
else | |
CONFIGS=$(find configs/modules/ -type f | sort | awk -F '/' '{print $(NF)}' | awk NF) | |
fi | |
JSON_MATRIX="{\"thingino-version\": [" | |
for CONFIG in $CONFIGS; do | |
JSON_MATRIX+="\"${CONFIG}\"," | |
done | |
JSON_MATRIX="${JSON_MATRIX%,}]}" | |
echo "Matrix: $JSON_MATRIX" | |
echo "matrix=$JSON_MATRIX" >> $GITHUB_OUTPUT | |
buildroot: | |
name: ${{ matrix.thingino-version }} | |
needs: [generate-matrix, notify-begin] | |
runs-on: ubuntu-latest | |
outputs: | |
# Feed the hash of the commit we are building into the notify-completion release-notes step | |
GIT_HASH: ${{ steps.env.outputs.git_hash }} | |
TAG_NAME: ${{ steps.env.outputs.tag_name }} | |
defaults: | |
run: | |
shell: bash | |
container: | |
image: debian:bookworm | |
strategy: | |
fail-fast: false | |
matrix: ${{fromJson(needs.generate-matrix.outputs.matrix)}} | |
steps: | |
- name: Update package manager sources | |
run: | | |
apt-get update | |
- name: Install build dependencies | |
run: | | |
apt-get install -y --no-install-recommends --no-install-suggests build-essential bc cmake cpio curl ca-certificates file git make gawk jq procps rsync tzdata u-boot-tools unzip wget | |
- name: Set timezone | |
run: | | |
ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime | |
echo "America/Los_Angeles" > /etc/timezone | |
DEBIAN_FRONTEND=noninteractive dpkg-reconfigure -f noninteractive tzdata | |
- name: Setup gh workspace in container | |
run: git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
- name: Checkout repository source | |
uses: actions/checkout@v4 | |
with: | |
submodules: 'true' | |
ref: "master" | |
fetch-depth: "1" | |
- name: Configure Environment Variables | |
id: env | |
run: | | |
echo "WEEK_NUMBER=$(date +%U)" >> $GITHUB_ENV | |
echo "CURRENT_YEAR=$(date +%Y)" >> $GITHUB_ENV | |
echo "GIT_HASH=$(git rev-parse --short ${GITHUB_SHA})" >> $GITHUB_ENV | |
echo "GIT_BRANCH=${GITHUB_REF_NAME}" >> $GITHUB_ENV | |
echo "TG_DISABLED=${{ github.event.inputs.tg_disabled || 'false' }}" >> $GITHUB_ENV | |
TAG_NAME="$TAG_NAME-$(date +'%Y-%m-%d')" | |
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV | |
echo "GIT_HASH=$(git rev-parse --short ${GITHUB_SHA})" >> $GITHUB_OUTPUT | |
echo "TAG_NAME=${TAG_NAME}" >> $GITHUB_OUTPUT | |
- name: Setup cache directories | |
run: | | |
mkdir -p ~/.ccache | |
mkdir -p ~/dl | |
- name: Restore build cache | |
uses: actions/cache@v4 | |
if: always() | |
with: | |
path: ~/.ccache | |
key: ${{ runner.os }}-ccache-${{ matrix.thingino-version }}-${{ env.CURRENT_YEAR }}-week-${{ env.WEEK_NUMBER }}-${{ github.run_id }} | |
restore-keys: | | |
${{ runner.os }}-ccache-${{ matrix.thingino-version }}-${{ env.CURRENT_YEAR }}-week-${{ env.WEEK_NUMBER }} | |
${{ runner.os }}-ccache-${{ matrix.thingino-version }}-${{ env.CURRENT_YEAR }}-week- | |
${{ runner.os }}-ccache-${{ matrix.thingino-version }}- | |
${{ runner.os }}-ccache- | |
${{ runner.os }}-ccache-shared-v1-${{ env.CURRENT_YEAR }}-week-${{ env.WEEK_NUMBER }} | |
- name: Restore Buildroot DL cache | |
uses: actions/cache/restore@v4 | |
if: always() | |
with: | |
path: ~/dl | |
key: ${{ runner.os }}-dl-shared-v1-${{ env.CURRENT_YEAR }}-week-${{ env.WEEK_NUMBER }} | |
- name: Build firmware | |
if: ${{ github.event.inputs.debug_enabled != 'true' }} | |
run: | | |
BOARD=${{ matrix.thingino-version }} make fast | |
TIME=$(date -d @${SECONDS} +%M:%S) | |
echo "TIME=${TIME}" >> ${GITHUB_ENV} | |
- name: Generate debug dummy firmware for workflow testing | |
if: ${{ github.event.inputs.debug_enabled == 'true' }} | |
run: | | |
DYNAMIC_PART="${{ matrix.thingino-version }}" | |
mkdir -p ${HOME}/output/${DYNAMIC_PART}/images/ | |
echo "debug" > ${HOME}/output/${DYNAMIC_PART}/images/thingino-${DYNAMIC_PART}.bin | |
echo "debug uboot" > ${HOME}/output/${DYNAMIC_PART}/images/u-boot-lzo-with-spl.bin | |
echo "debug kernel" > ${HOME}/output/${DYNAMIC_PART}/images/uImage | |
echo "debug rootfs" > ${HOME}/output/${DYNAMIC_PART}/images/rootfs.squashfs | |
echo "debug rootfs" > ${HOME}/output/${DYNAMIC_PART}/images/rootfs.tar | |
echo "debug sha" > ${HOME}/output/${DYNAMIC_PART}/images/thingino-${DYNAMIC_PART}.bin.sha256sum | |
echo "debug" > ${HOME}/output/${DYNAMIC_PART}/images/thingino-${DYNAMIC_PART}-update.bin | |
echo "debug sha" > ${HOME}/output/${DYNAMIC_PART}/images/thingino-${DYNAMIC_PART}-update.bin.sha256sum | |
echo "TIME=7:77" >> ${GITHUB_ENV} | |
- name: Generate build time graphs | |
if: ${{ github.event.inputs.graph_enabled == 'true' }} | |
run: | | |
apt-get install -y --no-install-recommends --no-install-suggests python3-numpy python3-matplotlib | |
BOARD=${{ matrix.thingino-version }} make br-graph-build | |
- name: Locate Built Firmware Artifacts | |
run: | | |
DYNAMIC_PART="${{ matrix.thingino-version }}" | |
FULL_FW=$(find ${HOME}/output/${DYNAMIC_PART}*/images/ -name "thingino-${DYNAMIC_PART}.bin" ! -name "*update.bin" | head -n 1) | |
FULL_FW_UBOOT=$(find ${HOME}/output/${DYNAMIC_PART}*/images/ -name "u-boot-lzo-with-spl.bin" | head -n 1) | |
FULL_FW_KERNEL=$(find ${HOME}/output/${DYNAMIC_PART}*/images/ -name "uImage" | head -n 1) | |
FULL_FW_ROOTFS=$(find ${HOME}/output/${DYNAMIC_PART}*/images/ -name "rootfs.squashfs" | head -n 1) | |
FULL_FW_ROOTFS_TAR=$(find ${HOME}/output/${DYNAMIC_PART}*/images/ -name "rootfs.tar" | head -n 1) | |
UPDATE_FW=$(find ${HOME}/output/${DYNAMIC_PART}*/images/ -name "thingino-${DYNAMIC_PART}-update.bin" | head -n 1) | |
echo "FULL_FW: $FULL_FW" | |
if [[ -n "$FULL_FW" ]]; then | |
echo "FULL_FW=${FULL_FW}" >> ${GITHUB_ENV} | |
echo "FULL_FW_UBOOT=${FULL_FW_UBOOT}" >> ${GITHUB_ENV} | |
echo "FULL_FW_KERNEL=${FULL_FW_KERNEL}" >> ${GITHUB_ENV} | |
echo "FULL_FW_ROOTFS=${FULL_FW_ROOTFS}" >> ${GITHUB_ENV} | |
echo "FULL_FW_ROOTFS_TAR=${FULL_FW_ROOTFS_TAR}" >> ${GITHUB_ENV} | |
echo "FULL_FW_SHA=${FULL_FW}.sha256sum" >> ${GITHUB_ENV} | |
echo "UPDATE_FW=${UPDATE_FW}" >> ${GITHUB_ENV} | |
echo "UPDATE_FW_SHA=${UPDATE_FW}.sha256sum" >> ${GITHUB_ENV} | |
else | |
echo "Matching .bin files not found." | |
exit 1 | |
fi | |
- name: Upload duration graph artifact | |
if: ${{ github.event.inputs.graph_enabled == 'true' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ matrix.thingino-version }}-build.hist-duration | |
path: | | |
~/output/${{ matrix.thingino-version }}/graphs/build.hist-duration.pdf | |
- name: Upload update firmware artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: thingino-${{ matrix.thingino-version }}-update-firmware | |
path: | | |
${{ env.UPDATE_FW }} | |
${{ env.UPDATE_FW_SHA }} | |
- name: Upload full firmware artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: thingino-${{ matrix.thingino-version }}-full-firmware | |
path: | | |
${{ env.FULL_FW }} | |
${{ env.FULL_FW_UBOOT }} | |
${{ env.FULL_FW_KERNEL }} | |
${{ env.FULL_FW_ROOTFS }} | |
${{ env.FULL_FW_ROOTFS_TAR }} | |
${{ env.FULL_FW_SHA }} | |
- name: Upload full firmware to release | |
uses: softprops/action-gh-release@master | |
with: | |
tag_name: ${{ env.TAG_NAME }} | |
make_latest: false | |
files: | | |
${{ env.FULL_FW }} | |
${{ env.FULL_FW_SHA }} | |
- name: Send firmware completion notifications with binaries | |
if: ${{ env.TG_DISABLED == 'false' && (env.FULL_FW) }} | |
run: | | |
if [[ "${{ github.event.inputs.tg_scratch }}" == 'true' ]]; then | |
TG_CHANNEL=${{ env.TG_CHANNEL_SCRATCH }} | |
export TG_TOPIC="" | |
fi | |
if [ -n "${{ env.FULL_FW }}" ]; then | |
.github/scripts/tg-notify.sh -s $TG_TOKEN $TG_CHANNEL $TG_TOPIC completed $TAG_NAME ${{ github.run_id }} ${{ github.repository }} ${GIT_HASH} ${GIT_BRANCH} ${TAG_NAME} ${TIME} ${FULL_FW} | |
fi | |
- name: Send error notification | |
if: ${{ env.TG_DISABLED == 'false' && failure() }} | |
run: | | |
if [[ "${{ github.event.inputs.tg_scratch }}" == 'true' ]]; then | |
TG_CHANNEL=${{ env.TG_CHANNEL_SCRATCH }} | |
export TG_TOPIC="" | |
fi | |
.github/scripts/tg-notify.sh -s $TG_TOKEN $TG_CHANNEL $TG_TOPIC error $TAG_NAME ${{ github.run_id }} ${{ github.repository }} | |
notify-completion: | |
needs: [buildroot, notify-begin] | |
runs-on: ubuntu-latest | |
if: always() | |
steps: | |
- name: Set timezone | |
run: | | |
sudo timedatectl set-timezone "America/Los_Angeles" | |
- name: Configure Environment | |
run: | | |
echo "TG_DISABLED=${{ github.event.inputs.tg_disabled || 'false' }}" >> $GITHUB_ENV | |
echo "GIT_HASH=${{ needs.buildroot.outputs.git_hash }}" >> $GITHUB_ENV | |
echo "TAG_NAME=${{ needs.buildroot.outputs.tag_name }}" >> $GITHUB_ENV | |
- name: Send completion summary | |
if: ${{ env.TG_DISABLED == 'false' }} | |
run: | | |
if [[ "${{ github.event.inputs.tg_scratch }}" == 'true' ]]; then | |
TG_CHANNEL=${{ env.TG_CHANNEL_SCRATCH }} | |
export TG_TOPIC="" | |
fi | |
START_TIME=${{ needs.notify-begin.outputs.start_time }} | |
END_TIME=$(date -u +%s) | |
ELAPSED=$((END_TIME - START_TIME)) | |
ELAPSED_MIN=$((ELAPSED / 60)) | |
ELAPSED_SEC=$((ELAPSED % 60)) | |
.github/scripts/tg-notify.sh $TG_TOKEN $TG_CHANNEL $TG_TOPIC finish ${{ github.workflow }} "${ELAPSED_MIN}m ${ELAPSED_SEC}s" ${{ github.run_id }} ${{ github.repository }} |