Skip to content

About

Github action for building a packaged executable which programs your esp code using esptool and the binaries provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Latest commit

 

History

42 Commits

Folders and files

Repository files navigation

ESP Packaged Programmer Action

This repository provides a reusable action for turning your esp-idf binaries into executables which program the esp chip. It may work for other platforms on espressif chips such as Arduino / Platform.IO, but I have not designed / tested it with those environments.

For an example repository which uses this action, please see esp-usb-ble-hid.

Table of Contents

About

The output of this action is a binary which requires no other dependencies, files, or installation, but allows anyone to flash your code onto the appropriate espressif chip.

It simply packages esptool.py with your binaries/flash_args (from your build). The esptool packaged should be the version your build used, since the flash arguments ESP-IDF writes into flasher_args.json and the *-flash_args files follow the tool (ESP-IDF 5.x uses esptool 4.x, ESP-IDF 6.x uses esptool 5.x, which spells options with dashes). The easiest way is to have the build job record it: one extra command in the build step writes the version ESP-IDF's own esptool reports into the build folder, the zip carries it, and this action picks it up. The esptool-version input overrides that.

      - name: Build the code
        uses: espressif/esp-idf-ci-action@v1
        with:
          esp_idf_version: v6.1
          target: esp32s3
          path: '.'
          # record the esptool version this build used, for the packaging job
          command: idf.py build && python -m esptool version | tail -1 > build/esptool_version.txt

This action will upload the resultant executable to the Github Action Job, and (if triggered from release) to the release as well.

The primary use case for this action is to be run on releases, so that the executable will be automatically generated and added to the release for ease of use.

  package:
    name: Package the binaries into an executables for Windows, MacOS, and Linux (Ubuntu)
    needs: build
    strategy:
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: esp-cpp/esp-packaged-programmer-action@v1.0.5
        with:
          zipfile-name: 'your-build-artifacts'
          programmer-name: 'your_programmer_name'
          # the esptool version comes from build/esptool_version.txt in the
          # zip (see above); to pin it instead:
          # esptool-version: 'v5.6.0'

NOTE: you can use either zipfile-name or zipfile-id as input to this script. If you are using MATRIX strategy (for which you may struggle to get the zipfile id output for each step), you may want to use the zipfile-name instead.

See the example in Using this action for a more complete example showing how to build your code and zip it for use by this action.

Required Build Artifacts

It requires:

  • firmware.bin (or whatever the name of your project is, e.g. .bin)
  • bootloader.bin
  • partition-table.bin
  • flasher_args.json

Optional Build Artifacts

May optionally contain filesystem binaries and associated -flash_args files such as:

  • littlefs.bin
  • littlefs-flash_args

It also supports other partition image data such as

  • ota_data_initial.bin

Using this action

Below is an example workflow file that:

  1. Builds the binaries using esp-idf's github action espressif/esp-idf-ci-action
  2. Zips the binaries and flash args into a single archive, uploading it for other jobs to use
  3. Runs this action (esp-cpp/esp-packaged-programmer-action) to build those binaries into executable flashing programs for windows, macos, and linux.

In the example below, we are using the zipfile-id input and hard-linking that to the build job output. You could instead use the zipfile-name input and provide it the name of the artifact (firmware) in this case.

on: 
  push:
    branches: [main]
  release:
    types: [published]
  workflow_dispatch:

jobs:
  # this would be your normal build job to build your esp binaries
  build:
    runs-on: ubuntu-latest
    name: Build the binaries and upload them for packaging
    # you need this to link the zip file name to the packaging job(s)
    outputs:
      zipfile-id: ${{ steps.zip_step.outputs.artifact-id }}
    steps:
      - uses: actions/checkout@v4
      - name: Build the code
        uses: espressif/esp-idf-ci-action@v1
          with:
          esp_idf_version: v5.4.1
          target: esp32s3
          path: '.'
          # the second command records the esptool version ESP-IDF v5.4.1
          # builds with (4.x), so the packaging job packages the same one
          command: idf.py build && python -m esptool version | tail -1 > build/esptool_version.txt
      - name: Upload build files in a single zip
        id: zip_step
        uses: actions/upload-artifact@v4
        with:
          name: 'firmware'
          path: |
            build/*.bin
            build/*.elf
            build/bootloader/bootloader.bin
            build/partition_table/partition-table.bin
            build/flasher_args.json
            build/flash_args
            build/*-flash_args
            build/esptool_version.txt

  package:
    name: Package the binaries into an executables for Windows, MacOS, and Linux (Ubuntu)
    needs: build
    strategy:
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: esp-cpp/esp-packaged-programmer-action@v1.0.5
        with:
          zipfile-id: ${{ needs.build.outputs.zipfile-id }}
          programmer-name: 'your_programmer_name'
          exclude-file-globs: '*.elf, app-flash_args, bootloader-flash_args, partition-table-flash_args'
          # esptool-version is not set: it is read from build/esptool_version.txt
          # in the zip, written by the build job above

Inputs

- uses: esp-cpp/download-artifact@v1.0.5
  with:
    # The ID of the artifact to download. 
    # Mutually exclusive with `zipfile-name`. 
    # The artifact should be a zip that contains the files and folder 
    # structure of the build output. Can be created by passing relevant 
    # files to the actions/upload-artifact@v4 action.
    zipfile-id:

    # The name of the artifact to download. 
    # Mutually exclusive with `zipfile-id`. 
    # The artifact should be a zip that contains the files and folder 
    # structure of the build output. Can be created by passing relevant 
    # files to the actions/upload-artifact@v4 action.
    zipfile-name:

    # The base name of the programmer executable. 
    # Will have version tag (e.g. v1.0.0 or commit hash if no tags) and 
    # OS suffix (e.g. windows, macos, linux) added to it.
    programmer-name:

    # Comma-separated list of file names or globs which are present in 
    # the zipfile but which should be excluded from the packaging. 
    exclude-file-globs:

    # Git tag of espressif/esptool to package, e.g. v4.7.0 or v5.6.0 (a
    # leading "v" is added if missing). Use the version your build used:
    # the flash arguments ESP-IDF generates into flasher_args.json /
    # *-flash_args follow the tool (esptool 5 spells options with dashes,
    # e.g. --flash-mode), so the packaged esptool must be the one they were
    # written for. ESP-IDF 5.x builds with esptool 4.x, ESP-IDF 6.x with
    # esptool 5.x. Leave it empty (the default) to take the version from
    # build/esptool_version.txt in the zipfile, which the build job writes
    # with `python -m esptool version | tail -1 > build/esptool_version.txt`
    # (see the examples). With neither, v4.7.0 is packaged, with a warning.
    esptool-version:

    # Python version to build the programmer with. esptool 4.x needs 3.7 or
    # newer, esptool 5.x needs 3.10 or newer, so the default serves both;
    # raise it when a future esptool asks for more (pip refuses an esptool
    # whose requires-python the interpreter does not satisfy, and the build
    # fails there, before packaging). Default: 3.10
    python-version:

If you would rather pass the version explicitly (a matrix of ESP-IDF versions, say), read the file in the build job and hand it over as a job output:

  build:
    outputs:
      zipfile-id: ${{ steps.zip_step.outputs.artifact-id }}
      esptool-version: ${{ steps.esptool_version.outputs.version }}
    steps:
      # ... build with `&& python -m esptool version | tail -1 > build/esptool_version.txt`
      - id: esptool_version
        run: echo "version=$(cat build/esptool_version.txt)" >> "$GITHUB_OUTPUT"
      # ... zip
  package:
    needs: build
    steps:
      - uses: esp-cpp/esp-packaged-programmer-action@v1
        with:
          zipfile-id: ${{ needs.build.outputs.zipfile-id }}
          esptool-version: ${{ needs.build.outputs.esptool-version }}

About

Github action for building a packaged executable which programs your esp code using esptool and the binaries provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages