ci: build the Espressif examples weekly

A weekly scheduled job builds both ESP-IDF example projects, so a break
in the Espressif port surfaces on its own instead of waiting for a user
to report it.

- compileAllExamples.sh builds every project under examples/, pointing
  the local components at WOLFSSH_ROOT and WOLFSSL_ROOT
- the workflow covers ESP-IDF release-v5.5 and release-v5.1, built
  against wolfSSL v5.9.1-stable
- a scheduled failure opens or comments on an issue labelled
  espressif-build-failure
pull/1255/head
John Safranek 2026-09-16 11:32:35 -07:00
parent f4daee5ac3
commit 3c2eb6cd55
2 changed files with 186 additions and 0 deletions

97
.github/workflows/espressif.yml vendored 100644
View File

@ -0,0 +1,97 @@
name: wolfSSH Espressif Build Test
on:
schedule:
# Weekly: Mondays at 07:00 UTC
- cron: '0 7 * * 1'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
WOLFSSL_REF: v5.9.1-stable
jobs:
build_examples:
name: ESP-IDF ${{ matrix.idf-ref }}
strategy:
fail-fast: false
matrix:
# release-v5.5 is the current stable line; release-v5.1 is the version
# the example READMEs and VisualGDB projects document.
idf-ref: [ release-v5.5, release-v5.1 ]
runs-on: ubuntu-latest
container:
image: espressif/idf:${{ matrix.idf-ref }}
timeout-minutes: 30
steps:
- name: Checkout wolfSSH
uses: actions/checkout@v6
with:
path: wolfssh
- name: Checkout wolfSSL
uses: actions/checkout@v6
with:
repository: wolfssl/wolfssl
ref: ${{ env.WOLFSSL_REF }}
path: wolfssl
- name: Build the Espressif examples
env:
WOLFSSH_ROOT: ${{ github.workspace }}/wolfssh
WOLFSSL_ROOT: ${{ github.workspace }}/wolfssl
run: |
# The image sets IDF_PATH, but the ESP-IDF tool paths come from
# export.sh, which a job step does not get from the entrypoint.
. "${IDF_PATH}/export.sh"
"${WOLFSSH_ROOT}/ide/Espressif/ESP-IDF/compileAllExamples.sh"
notify_failure:
name: Open issue on scheduled failure
needs: [build_examples]
if: failure() && github.event_name == 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
issues: write
steps:
- uses: actions/github-script@v7
with:
script: |
const label = 'espressif-build-failure';
const runUrl = `${context.serverUrl}/${context.repo.owner}/` +
`${context.repo.repo}/actions/runs/${context.runId}`;
const body = [
'The weekly Espressif example build failed.',
'',
`Run: ${runUrl}`,
`Commit: ${context.sha}`,
].join('\n');
const existing = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: label,
});
if (existing.data.length > 0) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existing.data[0].number,
body: body,
});
} else {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'Weekly Espressif example build failed',
body: body,
labels: [label],
});
}

View File

@ -0,0 +1,89 @@
#!/usr/bin/env bash
# Build every wolfSSH ESP-IDF example project under ./examples/
#
# The examples carry local wolfssh and wolfssl components that compile the
# library sources in place, so both source trees have to be on disk. Their
# CMakeLists find them through the WOLFSSH_ROOT and WOLFSSL_ROOT environment
# variables, which this script fills in when they are not already set.
#
# Run from an ESP-IDF environment:
#
# . /opt/esp/idf/export.sh
# WOLFSSL_ROOT=/path/to/wolfssl ide/Espressif/ESP-IDF/compileAllExamples.sh
#
# WOLFSSH_ROOT defaults to the tree holding this script, WOLFSSL_ROOT to a
# wolfssl checkout beside it. IDF_TARGET selects the chip; default esp32.
if [ -z "${IDF_PATH}" ]; then
echo "ERROR: IDF_PATH is not set. Source the ESP-IDF export.sh first."
exit 1
fi
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
if [ -z "${WOLFSSH_ROOT}" ]; then
WOLFSSH_ROOT=$(cd "${SCRIPT_DIR}/../../.." && pwd)
fi
if [ -z "${WOLFSSL_ROOT}" ]; then
WOLFSSL_ROOT="$(dirname "${WOLFSSH_ROOT}")/wolfssl"
fi
export WOLFSSH_ROOT
export WOLFSSL_ROOT
export IDF_TARGET="${IDF_TARGET:-esp32}"
if [ ! -f "${WOLFSSH_ROOT}/wolfssh/ssh.h" ]; then
echo "ERROR: no wolfSSH source in WOLFSSH_ROOT=${WOLFSSH_ROOT}"
exit 1
fi
if [ ! -f "${WOLFSSL_ROOT}/wolfssl/ssl.h" ]; then
echo "ERROR: no wolfSSL source in WOLFSSL_ROOT=${WOLFSSL_ROOT}"
echo "Clone wolfssl beside wolfssh or set WOLFSSL_ROOT."
exit 1
fi
echo "IDF_PATH = ${IDF_PATH}"
echo "IDF_TARGET = ${IDF_TARGET}"
echo "WOLFSSH_ROOT = ${WOLFSSH_ROOT}"
echo "WOLFSSL_ROOT = ${WOLFSSL_ROOT}"
BUILT=""
FAILED=""
for PROJECT in "${SCRIPT_DIR}"/examples/*/; do
# A project directory is one with a top level CMakeLists.txt.
if [ ! -f "${PROJECT}/CMakeLists.txt" ]; then
continue
fi
NAME=$(basename "${PROJECT}")
echo
echo "--------------------------------------------------------------"
echo "Building ${NAME} for ${IDF_TARGET}"
echo "--------------------------------------------------------------"
if (cd "${PROJECT}" && idf.py fullclean && idf.py build); then
BUILT="${BUILT} ${NAME}"
else
FAILED="${FAILED} ${NAME}"
fi
done
if [ -z "${BUILT}" ] && [ -z "${FAILED}" ]; then
echo "ERROR: no example projects found in ${SCRIPT_DIR}/examples/"
exit 1
fi
echo
echo "Built: ${BUILT:- none}"
if [ -n "${FAILED}" ]; then
echo "Failed:${FAILED}"
exit 1
fi
echo "All wolfSSH Espressif examples built."