Files
mesh-forge/.github/workflows/custom_build.yml
T

180 lines
6.6 KiB
YAML

name: Repo PlatformIO Build
on:
workflow_dispatch:
inputs:
owner:
required: true
type: string
repo:
required: true
type: string
ref:
required: true
type: string
target_env:
required: true
type: string
repo_build_id:
required: true
type: string
build_key:
required: true
type: string
resolved_source_sha:
required: true
type: string
convex_url:
required: true
type: string
jobs:
build:
runs-on: ubuntu-latest
env:
CONVEX_URL: ${{ inputs.convex_url }}
REPO_BUILD_ID: ${{ inputs.repo_build_id }}
CONVEX_BUILD_TOKEN: ${{ secrets.CONVEX_BUILD_TOKEN }}
CI_PROGRESS_TOTAL: "5"
steps:
- uses: actions/checkout@v4
- name: Notify Convex — running
shell: bash
run: |
curl -sSf -X POST "$CONVEX_URL/ingest-repo-build" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CONVEX_BUILD_TOKEN" \
-d "{\"repo_build_id\":\"$REPO_BUILD_ID\",\"state\":\"running\",\"github_run_id\":${{ github.run_id }}}"
- name: CI progress — build started
shell: bash
env:
STEP_INDEX: 1
LABEL: Build started on Actions
run: python3 "${{ github.workspace }}/scripts/report-convex-ci-progress.py"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: CI progress — tooling ready
shell: bash
env:
STEP_INDEX: 2
LABEL: Runner tooling ready
run: python3 "${{ github.workspace }}/scripts/report-convex-ci-progress.py"
- name: Download source archive
shell: bash
env:
OWNER: ${{ inputs.owner }}
REPO: ${{ inputs.repo }}
REF: ${{ inputs.ref }}
run: |
STEP_INDEX=3 LABEL="Downloading source archive" python3 "${{ github.workspace }}/scripts/report-convex-ci-progress.py"
ENC_REF=$(python3 -c "import urllib.parse,os; print(urllib.parse.quote(os.environ['REF'], safe=''))")
curl -fsSL -o /tmp/src.zip "https://codeload.github.com/${OWNER}/${REPO}/zip/${ENC_REF}"
- name: Cache PlatformIO global store
uses: actions/cache@v4
with:
path: |
~/.platformio/.cache
~/.platformio/packages
key: platformio-${{ runner.os }}-v1-${{ hashFiles('.github/workflows/custom_build.yml', '.github/workflows/custom_build_test.yml') }}
restore-keys: |
platformio-${{ runner.os }}-v1-
- name: Extract and build
id: pio
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }}
shell: bash
run: |
STEP_INDEX=4 LABEL="Building firmware (PlatformIO)" python3 "${{ github.workspace }}/scripts/report-convex-ci-progress.py"
set -e
sudo apt-get update -qq && sudo apt-get install -y -qq unzip
unzip -q /tmp/src.zip -d /tmp/src
ROOT=$(find /tmp/src -mindepth 1 -maxdepth 1 -type d | head -1)
cd "$ROOT"
python -m pip install -q --upgrade pip
pip install -q platformio
pio pkg install -e "${{ inputs.target_env }}"
MKLITTLEFS_BIN=$(find "$HOME/.platformio/packages" -type f -name mklittlefs 2>/dev/null | head -1)
if [ -n "$MKLITTLEFS_BIN" ]; then
export PATH="$(dirname "$MKLITTLEFS_BIN"):$PATH"
fi
command -v mklittlefs >/dev/null 2>&1 || echo "WARNING: mklittlefs not on PATH; LittleFS build may fail"
pio run -e "${{ inputs.target_env }}" 2>&1 | tee /tmp/pio.log
BUILD_DIR=".pio/build/${{ inputs.target_env }}"
if [ ! -d "$BUILD_DIR" ]; then
echo "Build output directory missing"
exit 1
fi
python3 "${{ github.workspace }}/scripts/emit-flash-manifest.py" "$ROOT/$BUILD_DIR" "$ROOT" "${{ inputs.target_env }}"
ARTIFACT_NAME="firmware-${{ inputs.build_key }}-${{ github.run_id }}.tar.gz"
STAGE=/tmp/fw-bundle
rm -rf "$STAGE"
mkdir -p "$STAGE"
shopt -s nullglob
for f in "$BUILD_DIR"/*.bin "$BUILD_DIR"/*.uf2 "$BUILD_DIR"/*.hex; do
cp -a "$f" "$STAGE/"
done
shopt -u nullglob
if [ -f "$BUILD_DIR/flash-manifest.json" ]; then
cp -a "$BUILD_DIR/flash-manifest.json" "$STAGE/"
fi
if [ -z "$(find "$STAGE" -mindepth 1 -maxdepth 1 -type f -print -quit)" ]; then
echo "No firmware artifacts found in $BUILD_DIR"
exit 1
fi
tar -czf "/tmp/$ARTIFACT_NAME" -C "$STAGE" .
OBJECT_PATH="${R2_BUCKET_NAME}/${ARTIFACT_NAME}"
bunx wrangler r2 object put "$OBJECT_PATH" --file "/tmp/$ARTIFACT_NAME" --remote
STEP_INDEX=5 LABEL="Firmware bundle uploaded" python3 "${{ github.workspace }}/scripts/report-convex-ci-progress.py"
echo "r2_key=${ARTIFACT_NAME}" >> "$GITHUB_OUTPUT"
- name: Notify Convex — success
if: success()
shell: bash
env:
R2_KEY: ${{ steps.pio.outputs.r2_key }}
run: |
curl -sSf -X POST "$CONVEX_URL/ingest-repo-build" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CONVEX_BUILD_TOKEN" \
-d "{\"repo_build_id\":\"$REPO_BUILD_ID\",\"state\":\"succeeded\",\"github_run_id\":${{ github.run_id }},\"r2ObjectKey\":\"$R2_KEY\"}"
- name: Notify Convex — failure
if: failure()
shell: bash
env:
GITHUB_RUN_ID: ${{ github.run_id }}
run: |
python3 -c "
import json, os, urllib.request
err = open('/tmp/pio.log').read()[-4000:] if os.path.exists('/tmp/pio.log') else 'build failed'
body = {
'repo_build_id': os.environ['REPO_BUILD_ID'],
'state': 'failed',
'github_run_id': int(os.environ['GITHUB_RUN_ID']),
'errorSummary': err,
}
req = urllib.request.Request(
os.environ['CONVEX_URL'] + '/ingest-repo-build',
data=json.dumps(body).encode(),
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer ' + os.environ['CONVEX_BUILD_TOKEN']},
method='POST',
)
urllib.request.urlopen(req)
"