Skip to content

ci: run Zephyr builds in parallel #807

ci: run Zephyr builds in parallel

ci: run Zephyr builds in parallel #807

Workflow file for this run

name: Package, test and upload core
on:
- push
- pull_request
jobs:
build-env:
name: Prepare build environment
runs-on: ubuntu-latest
outputs:
CORE_TAG: ${{ env.CORE_TAG }}
CORE_HASH: ${{ env.CORE_HASH }}
ALL_BOARD_DATA: ${{ env.ALL_BOARD_DATA }}
ARTIFACTS: ${{ env.ARTIFACTS }}
SUB_ARCHES: ${{ env.SUB_ARCHES }}
steps:
- name: Install OS dependencies
working-directory: /opt
run: |
sudo apt-get remove --purge man-db -y # skips the mandb triggers
sudo apt-get update
sudo apt-get install -y --no-install-recommends git cmake wget python3-pip ninja-build ccache
- uses: actions/checkout@v4
with:
submodules: 'recursive'
fetch-depth: 0
persist-credentials: false
fetch-tags: true
- name: Initialize Zephyr environment
run: |
yes | ./extra/bootstrap.sh -o=--filter=tree:0
echo "CORE_HASH=$(git describe --always)" >> "$GITHUB_ENV"
echo "ALL_BOARD_DATA=$(extra/get_board_details.sh | jq -c 'sort_by(.variant)')" >> "$GITHUB_ENV"
echo "## Building \`$(extra/get_core_version.sh)\`" >> "$GITHUB_STEP_SUMMARY"
- name: Map output packages
# needs the above env vars to be usable
run: |
echo "CORE_TAG=$(git describe --tags --exact-match 2>/dev/null || echo $CORE_HASH)" >> "$GITHUB_ENV"
echo "ARTIFACTS=$(jq -c '["zephyr"] + (map(.artifact) | unique)' <<< ${ALL_BOARD_DATA})" >> "$GITHUB_ENV"
echo "SUB_ARCHES=$(jq -c 'map(.subarch) | unique' <<< ${ALL_BOARD_DATA})" >> "$GITHUB_ENV"
(cd && tar cphf - .cmake work zephyr-sdk-* | zstd > build-env.tar.zstd)
tar cphf - cores/arduino/api | zstd > arduino-api.tar.zstd
- name: Archive build environment
uses: actions/upload-artifact@v4
with:
name: build-env
path: ~/build-env.tar.zstd
- name: Archive API snapshot
uses: actions/upload-artifact@v4
with:
name: arduino-api
path: arduino-api.tar.zstd
build-board:
name: Build loader for ${{ matrix.board }}
runs-on: ubuntu-latest
needs:
- build-env
env:
CCACHE_IGNOREOPTIONS: -specs=*
OUTPUT_ARTIFACT: binaries-${{ matrix.board }}-${{ needs.build-env.outputs.CORE_HASH }}
strategy:
matrix:
include:
${{ fromJSON( needs.build-env.outputs.ALL_BOARD_DATA ) }}
fail-fast: false
steps:
- uses: actions/download-artifact@v4
with:
path: /home/runner
name: build-env
- name: Restore build environment
run: |
(cd ~ && tar --use-compress-program=unzstd -xpf build-env.tar.zstd && rm build-env.tar.zstd)
- name: ccache
uses: hendrikmuhs/[email protected]
with:
verbose: 1
- name: Build loader
shell: bash
run: |
if ! ./extra/build.sh ${{ matrix.board }} 2> >(tee error.log) ; then
echo "### :x: ${{ matrix.board }} (\`${{ matrix.variant }}\`) build errors" > $GITHUB_STEP_SUMMARY
echo >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat error.log >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Package board binaries
if: ${{ !cancelled() }}
run: |
tar chf - \
firmwares/*${{ matrix.variant }}* \
variants/${{ matrix.variant }}/ \
${{ (job.status == 'failure') && format('build/{0}/', matrix.variant) }} \
| zstd > ${OUTPUT_ARTIFACT}.tar.zstd
- name: Archive board binaries
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: ${{ format('{0}{1}', (job.status == 'failure') && 'failed-' || '', env.OUTPUT_ARTIFACT) }}
path: ${{ env.OUTPUT_ARTIFACT }}.tar.zstd
package-core:
name: Package ${{ matrix.artifact }}
runs-on: ubuntu-latest
needs:
- build-env
- build-board
env:
CORE_ARTIFACT: ArduinoCore-${{ matrix.artifact }}-${{ needs.build-env.outputs.CORE_HASH }}
CORE_TAG: ${{ needs.build-env.outputs.CORE_TAG }}
strategy:
matrix:
artifact: ${{ fromJSON( needs.build-env.outputs.ARTIFACTS ) }}
fail-fast: false
if: ${{ !cancelled() && needs.build-env.result == 'success' }}
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
fetch-depth: 0
persist-credentials: false
fetch-tags: true
- uses: actions/download-artifact@v4
with:
path: .
name: arduino-api
- uses: actions/download-artifact@v4
with:
path: .
pattern: binaries-*
merge-multiple: true
- name: Package core
run: |
rm -f cores/arduino/api # remove broken symlink
tar --use-compress-program=unzstd -xpf arduino-api.tar.zstd
for f in binaries-*.tar.zstd ; do
tar --use-compress-program=unzstd -xpf $f
done
./extra/package_core.sh ${{ matrix.artifact }} ${CORE_TAG} distrib/${CORE_ARTIFACT}.tar.bz2
- uses: actions/upload-artifact@v4
if: ${{ success() || failure() }}
with:
name: ${{ env.CORE_ARTIFACT }}
path: distrib/${{ env.CORE_ARTIFACT }}.tar.bz2
cleanup-build:
name: Clean up intermediates
runs-on: ubuntu-latest
needs:
- package-core
if: always()
steps:
- uses: geekyeggo/[email protected]
with:
name: |
arduino-api
binaries-*
build-env
failOnError: false
test-core:
name: Test ${{ matrix.subarch }}:${{ matrix.board }}
runs-on: ubuntu-latest
needs:
- build-env
- package-core
strategy:
matrix:
include:
${{ fromJSON( needs.build-env.outputs.ALL_BOARD_DATA ) }}
fail-fast: false
env:
PLAT: arduino:${{ matrix.subarch }}
FQBN: arduino:${{ matrix.subarch }}:${{ matrix.board }}
CORE_ARTIFACT: ArduinoCore-${{ matrix.artifact }}-${{ needs.build-env.outputs.CORE_HASH }}
if: ${{ !cancelled() && needs.build-env.result == 'success' }}
steps:
- uses: actions/download-artifact@v4
with:
name: ${{ env.CORE_ARTIFACT }}
- name: Set up core
run: |
tar xf ${CORE_ARTIFACT}.tar.bz2 # will create ArduinoCore-zephyr/
echo "REPORT_FILE=$(echo ${FQBN} | tr ':' '-').json" >> $GITHUB_ENV
- name: Create Blink sketch
run: |
mkdir Blink/
wget -nv https://raw.githubusercontent.com/arduino/arduino-examples/refs/heads/main/examples/01.Basics/Blink/Blink.ino -P Blink/
- name: Compile Blink for ${{ matrix.board }}
uses: pillo79/compile-sketches@main
with:
fqbn: ${{ env.FQBN }}
platforms: |
# Use Board Manager to install the latest release of Arduino Zephyr Boards to get the toolchain
- name: "arduino:zephyr"
source-url: "https://downloads.arduino.cc/packages/package_zephyr_index.json"
- name: ${{ env.PLAT }}
source-path: "ArduinoCore-zephyr"
sketch-paths: Blink
cli-compile-flags: |
- '--build-property'
- 'compiler.c.extra_flags=-Wno-type-limits -Wno-missing-field-initializers'
- '--build-property'
- 'compiler.cpp.extra_flags=-Wno-type-limits -Wno-missing-field-initializers'
verbose: 'false'
enable-deltas-report: 'false'
enable-warnings-report: 'true'
enable-warnings-log: 'true'
- name: Get job ID
id: job_id
if: ${{ success() || failure() }}
uses: actions/github-script@main
with:
script: |
const { data: workflow_run } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
});
const job_name = `Test ${{ matrix.subarch }}:${{ matrix.board }}`
return workflow_run.jobs.find((job) => job.name === job_name).id;
- name: Prepare log
if: ${{ success() || failure() }}
run: |
sed -i -e 's!/home/runner/.arduino15/packages/arduino/hardware/zephyr/[^/]*/!!g' sketches-reports/${REPORT_FILE}
cat sketches-reports/${REPORT_FILE} | jq -cr ".boards[0].sketches[0] += { job_id: ${{ steps.job_id.outputs.result }} }" > ${REPORT_FILE} && mv ${REPORT_FILE} sketches-reports/
- uses: actions/upload-artifact@v4
if: ${{ success() || failure() }}
with:
name: test-report-${{ needs.build-env.outputs.CORE_TAG }}-${{ matrix.board }}
path: sketches-reports/*
collect-logs:
name: Collect logs
runs-on: ubuntu-latest
needs:
- build-env
- package-core
- test-core
if: ${{ !cancelled() && needs.build-env.result == 'success' }}
env:
ALL_BOARD_DATA: ${{ needs.build-env.outputs.ALL_BOARD_DATA }}
steps:
- uses: actions/download-artifact@v4
with:
path: .
pattern: test-report-*
merge-multiple: true
- run: |
ARTIFACTS=$(jq -cr 'map(.artifact) | unique | .[]' <<< ${ALL_BOARD_DATA}) # this avoids the 'zephyr' artifact
for artifact in $ARTIFACTS ; do
echo "### \`$artifact\` test results:" >> "$GITHUB_STEP_SUMMARY"
jq -c "map(select(.artifact == \"$artifact\")) | .[]" <<< ${ALL_BOARD_DATA} | while read -r BOARD_DATA; do
BOARD=$(echo $BOARD_DATA | jq -cr '.board')
VARIANT=$(echo $BOARD_DATA | jq -cr '.variant')
SUBARCH=$(echo $BOARD_DATA | jq -cr '.subarch')
FQBN="arduino:$SUBARCH:$BOARD"
REPORT_FILE="$(echo $FQBN | tr ':' '-').json"
if [ ! -f $REPORT_FILE ]; then
echo "* :x: $BOARD (\`$VARIANT\`) - No report found?" >> "$GITHUB_STEP_SUMMARY"
else
REPORT=$(jq -cr '.boards[0].sketches[0]' $REPORT_FILE)
JOB_ID=$(echo $REPORT | jq -cr '.job_id')
JOB_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${JOB_ID}#step:5:2"
if ! $(echo $REPORT | jq -cr '.compilation_success') ; then
echo "* :x: [$BOARD]($JOB_URL) (\`$VARIANT\`) - Build failed" >> "$GITHUB_STEP_SUMMARY"
else
WARNINGS=$(echo $REPORT | jq -cr '.warnings.current.absolute // 0')
if [ $WARNINGS -eq 0 ]; then
echo "* :white_check_mark: $BOARD (\`$VARIANT\`) - Build successful" >> "$GITHUB_STEP_SUMMARY"
else
echo >> "$GITHUB_STEP_SUMMARY"
echo "<details><summary>&nbsp;&nbsp; :warning: <a href=\"$JOB_URL\">$BOARD</a> (<tt>$VARIANT</tt>) - $WARNINGS warnings:</summary>" >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY"
echo $REPORT | jq -cr '.warnings_log[]' >> "$GITHUB_STEP_SUMMARY"
echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
echo "</details>" >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
fi
fi
fi
done
done
- name: Clean up intermediate artifacts
uses: geekyeggo/[email protected]
with:
name: test-report-*
failOnError: false
verify-core:
runs-on: ubuntu-latest
if: cancelled() || contains(needs.*.result, 'failure')
needs:
- build-env
- package-core
- test-core
steps:
- name: Notify failure
run: exit 1
publish-core:
name: Publish core
runs-on: ubuntu-latest
if: ${{ github.event_name == 'push' && github.repository == 'arduino/ArduinoCore-zephyr' }}
needs:
- build-env
- package-core
- test-core
environment: production
permissions:
id-token: write
contents: read
steps:
- uses: actions/download-artifact@v4
with:
path: .
pattern: ArduinoCore-*
merge-multiple: true
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.IAM_ROLE }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Upload artifact
run: |
for f in ArduinoCore-*.tar.bz2 ; do
aws s3 cp $f s3://${{ secrets.S3_BUCKET }}/
done
prepare-json:
name: Prepare jsons
runs-on: ubuntu-latest
needs:
- build-env
- package-core
- test-core
env:
CORE_TAG: ${{ needs.build-env.outputs.CORE_TAG }}
CORE_HASH: ${{ needs.build-env.outputs.CORE_HASH }}
ARTIFACTS: ${{ needs.build-env.outputs.ARTIFACTS }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
fetch-tags: true
- uses: actions/download-artifact@v4
with:
path: .
pattern: ArduinoCore-*
merge-multiple: true
- name: Prepare package index snippets
run: |
jq -cr '.[]' <<< ${ARTIFACTS} | while read -r artifact; do
ARTIFACT_FILE=ArduinoCore-${artifact}-${CORE_HASH}.tar.bz2
PACKAGE_JSON=ArduinoCore-${artifact}-${CORE_TAG}.json
./extra/gen_package_index_json.sh ${artifact} ${ARTIFACT_FILE} ${PACKAGE_JSON}
done
- name: Archive package index snippets
uses: actions/upload-artifact@v4
with:
name: ArduinoCore-zephyr-${{ env.CORE_TAG }}-jsons
path: ArduinoCore-*-${{ env.CORE_TAG }}.json