Skip to content

Build esptool

Build esptool #85

Workflow file for this run

name: Build esptool
on:
push:
release:
types: [published]
workflow_dispatch:
inputs:
sign-macos:
description: "Sign macOS executables"
required: false
type: boolean
default: false
sign-windows:
description: "Sign Windows executables"
required: false
type: boolean
default: false
jobs:
build-esptool-binaries:
name: Build esptool binaries for ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
strategy:
matrix:
platform: [macos-universal, windows-amd64, linux-amd64]
include:
- platform: macos-universal
separator: ":"
runner: macos-latest
- platform: windows-amd64
separator: ";"
runner: windows-latest
- platform: linux-amd64
separator: ":"
runner: ubuntu-22.04
env:
DISTPATH: esptool-${{ matrix.platform }}
# Will be changed.
ARCHIVE_NAME:
STUBS_DIR: ./esptool/targets/stub_flasher/
EFUSE_DIR: ./espefuse/efuse_defs/
# Might be changed to allow signing on macOS.
PYINSTALLER_FLAGS:
steps:
- name: Setup
shell: bash
run: |
if [[ "${{ runner.os }}" == "Windows" ]]; then
echo ARCHIVE_NAME=esptool-${{ matrix.platform }}.zip >> $GITHUB_ENV
else
echo ARCHIVE_NAME=esptool-${{ matrix.platform }}.tar.gz >> $GITHUB_ENV
fi
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python 3.13
uses: actions/setup-python@v5
if: (matrix.platform != 'linux-armv7') || contains(github.ref_name, 'dev')
with:
python-version: "3.13"
# Python is used only to apply dev-release patch on Linux runners and no packages are installed as the build happens in the container
cache: ${{ matrix.platform != 'linux-armv7' && matrix.platform != 'linux-aarch64' && matrix.platform != 'linux-amd64' && 'pip' || '' }}
- name: Patch version for dev releases
if: contains(github.ref_name, 'dev')
run: |
echo "Patching version for dev release: ${{ github.ref_name }}"
python ci/patch_dev_release.py --version ${{ github.ref_name }} esptool/__init__.py
git diff
- name: Install dependencies
# Using 6.11.1 as it apparently leads to fewer antivirus false positives.
# See: https://github.com/espressif/python-binary-action/blob/8f20755b770c5f9d03e9ce3002af330828fe473f/action.yml#L35
shell: bash
run: |
python -m pip install --upgrade pip
pip install pyinstaller==6.11.1
if [[ "${{ runner.os }}" == "macOS" ]]; then
# Pip on ARM runners prefers arm64-only wheels over universal2,
# which PyInstaller rejects for universal2 builds. Rebuild
# native extensions from source as fat binaries.
rustup target add x86_64-apple-darwin
export ARCHFLAGS="-arch x86_64 -arch arm64"
pip install --user -e .
pip install --user --force-reinstall --no-binary bitarray,cffi,pyyaml,tibs bitarray cffi pyyaml tibs
else
pip install --user -e .
fi
- name: Import signing keychain (macOS)
if: (runner.os == 'macOS' && (github.event_name == 'release' || github.event.inputs.sign-macos == 'true'))
uses: apple-actions/import-codesign-certs@v3
with:
keychain: pyinstaller_signing_temp
p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }}
p12-password: ${{ secrets.MACOS_CERTIFICATE_PWD }}
- name: Setup signing identity flag (macOS)
if: (runner.os == 'macOS' && (github.event_name == 'release' || github.event.inputs.sign-macos == 'true'))
run: |
security default-keychain -s pyinstaller_signing_temp.keychain
echo "PYINSTALLER_FLAGS=--codesign-identity ${{ vars.MACOS_TEAM_ID }}" >> $GITHUB_ENV
- name: Build with PyInstaller
shell: bash
run: |
EXTRA_FLAGS=""
if [[ "${{ runner.os }}" == "macOS" ]]; then
EXTRA_FLAGS="--target-architecture universal2"
fi
# bitstring uses dynamic imports that PyInstaller can't detect; collect all submodules explicitly.
pyinstaller ${{ env.PYINSTALLER_FLAGS }} $EXTRA_FLAGS --console --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --collect-submodules bitstring --add-data="${{ env.STUBS_DIR }}1/*.json${{ matrix.separator }}${{ env.STUBS_DIR }}1/" --add-data="${{ env.STUBS_DIR }}2/*.json${{ matrix.separator }}${{ env.STUBS_DIR }}2/" --runtime-hook fix_encoding.py esptool.py
pyinstaller ${{ env.PYINSTALLER_FLAGS }} $EXTRA_FLAGS --console --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --collect-submodules bitstring --add-data="${{ env.EFUSE_DIR }}*.yaml${{ matrix.separator }}${{ env.EFUSE_DIR }}" --runtime-hook fix_encoding.py espefuse.py
pyinstaller ${{ env.PYINSTALLER_FLAGS }} $EXTRA_FLAGS --console --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --runtime-hook fix_encoding.py espsecure.py
pyinstaller ${{ env.PYINSTALLER_FLAGS }} $EXTRA_FLAGS --console --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --runtime-hook fix_encoding.py esp_rfc2217_server.py
- name: Sign Windows binary
if: (runner.os == 'Windows' && (github.event_name == 'release' || github.event.inputs.sign-windows == 'true'))
uses: toitlang/action-sign-server@26db6e4021bfbd79af777d15964f1ab70bcfd3a4 # v1.0.7
with:
uri: ${{ vars.CERTUM_URI }}
password: ${{ secrets.CERTUM_PWD }}
path: ${{ env.DISTPATH }}
- name: Sign macOS binary
if: (runner.os == 'macOS' && (github.event_name == 'release' || github.event.inputs.sign-macos == 'true'))
uses: toitlang/action-macos-sign-notarize@64b6d845b70ccd71bde584769280c612d48211db # v1.2.1
with:
certificate: ${{ secrets.MACOS_CERTIFICATE }}
certificate-password: ${{ secrets.MACOS_CERTIFICATE_PWD }}
username: ${{ secrets.AC_USERNAME }}
password: ${{ secrets.AC_PASSWORD }}
apple-team-id: ${{ vars.MACOS_TEAM_ID }}
app-path: |
./${{ env.DISTPATH }}/esptool
./${{ env.DISTPATH }}/espefuse
./${{ env.DISTPATH }}/espsecure
./${{ env.DISTPATH }}/esp_rfc2217_server
- name: Test binaries
shell: bash
run: |
EXTEN=""
if [[ "${{ matrix.platform }}" == windows* ]]; then
EXTEN=".exe"
export PYTHONIOENCODING=utf-8
fi
./${{ env.DISTPATH }}/esptool$EXTEN -h
./${{ env.DISTPATH }}/espefuse$EXTEN -h
./${{ env.DISTPATH }}/espsecure$EXTEN -h
./${{ env.DISTPATH }}/esp_rfc2217_server$EXTEN -h
- name: Verify universal2 binaries (macOS)
if: runner.os == 'macOS'
run: |
for bin in esptool espefuse espsecure esp_rfc2217_server; do
echo "Checking $bin..."
lipo -info ./${{ env.DISTPATH }}/$bin
arch -x86_64 ./${{ env.DISTPATH }}/$bin -h
done
- name: Add license and readme
shell: bash
run: mv LICENSE README.md ./${{ env.DISTPATH }}
- name: Create archive
if: runner.os != 'Windows'
shell: bash
run: |
tar c -vzf "${{ env.ARCHIVE_NAME }}" ${{ env.DISTPATH }}
- name: Create archive for Windows
if: runner.os == 'Windows'
shell: bash
run: |
7z a -tzip ${{ env.ARCHIVE_NAME }} ${{ env.DISTPATH }}
- name: Archive artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.DISTPATH }}
path: ${{ env.ARCHIVE_NAME }}
- name: Upload release
if: github.event_name == 'release'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.ARCHIVE_NAME }}
tag: ${{ github.event.release.tag_name }}
overwrite: true
- name: Upload macOS release aliases
if: github.event_name == 'release' && runner.os == 'macOS'
shell: bash
run: |
for alias in macos-aarch64 macos-amd64; do
cp "${{ env.ARCHIVE_NAME }}" "esptool-${alias}.tar.gz"
done
- name: Upload macOS release (macos-aarch64)
if: github.event_name == 'release' && runner.os == 'macOS'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: esptool-macos-aarch64.tar.gz
tag: ${{ github.event.release.tag_name }}
overwrite: true
- name: Upload macOS release (macos-amd64)
if: github.event_name == 'release' && runner.os == 'macOS'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: esptool-macos-amd64.tar.gz
tag: ${{ github.event.release.tag_name }}
overwrite: true