name: Custom Firmware Build on: workflow_dispatch: inputs: target: description: 'Target board (e.g. rak4631)' required: true type: string flags: description: 'Build flags (e.g. -DMESHTASTIC_EXCLUDE_MQTT)' required: false type: string version: description: 'Firmware Version (Tag/Branch)' required: true build_id: description: 'Convex Build ID' required: true type: string build_hash: description: 'Build hash for artifact naming' required: true type: string convex_url: description: 'Convex Site URL' required: true type: string jobs: build: runs-on: ubuntu-latest env: CONVEX_URL: ${{ inputs.convex_url }} BUILD_ID: ${{ inputs.build_id }} steps: - name: Setup status update helper shell: bash run: | cat > /tmp/update_status.sh << 'EOF' update_status() { curl -sSf -X POST "$CONVEX_URL/github-webhook" \ -H "Content-Type: application/json" \ -d "{\"action\": \"status_update\", \"build_id\": \"$BUILD_ID\", \"status\": \"$1\"}" || true } EOF chmod +x /tmp/update_status.sh - name: Update Status - Build Started shell: bash run: | source /tmp/update_status.sh update_status checking_out - name: Checkout Web Flasher (this repo) uses: actions/checkout@v4 - name: Update Status - Checked Out Web Flasher shell: bash run: | source /tmp/update_status.sh update_status checked_out_web_flasher - name: Checkout Firmware uses: actions/checkout@v4 with: repository: meshtastic/firmware ref: ${{ inputs.version }} path: firmware submodules: recursive fetch-depth: 1 - name: Update Status - Checked Out Firmware shell: bash run: | source /tmp/update_status.sh update_status checked_out_firmware - name: Cache PlatformIO uses: actions/cache@v4 with: path: | ~/.platformio firmware/.pio/libdeps key: ${{ runner.os }}-pio-${{ hashFiles('firmware/platformio.ini') }} restore-keys: | ${{ runner.os }}-pio- - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.x' - name: Update Status - Installing Dependencies shell: bash run: | source /tmp/update_status.sh update_status installing_dependencies - name: Install PlatformIO run: | python -m pip install --upgrade pip pip install platformio - name: Update Status - Dependencies Installed shell: bash run: | source /tmp/update_status.sh update_status dependencies_installed - name: Update Status - Building shell: bash run: | source /tmp/update_status.sh update_status building - name: Build Firmware working-directory: firmware run: | echo "Building for target: ${{ inputs.target }}" echo "Flags: ${{ inputs.flags }}" # Inject flags into platformio.ini or environment export PLATFORMIO_BUILD_FLAGS="${{ inputs.flags }}" echo "PLATFORMIO_BUILD_FLAGS set to: $PLATFORMIO_BUILD_FLAGS" pio run -e ${{ inputs.target }} - name: Update Status - Build Complete if: success() shell: bash run: | source /tmp/update_status.sh update_status build_complete - name: Install AWS CLI (for R2) if: success() shell: bash run: | source /tmp/update_status.sh update_status preparing_upload pip install awscli - name: Upload to R2 if: success() env: AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} AWS_ENDPOINT_URL: ${{ secrets.R2_ENDPOINT_URL }} shell: bash run: | source /tmp/update_status.sh update_status uploading # Determine file extension based on target (most are .bin, some might be .uf2) BUILD_FILE="firmware/.pio/build/${{ inputs.target }}/firmware.bin" if [ ! -f "$BUILD_FILE" ]; then BUILD_FILE="firmware/.pio/build/${{ inputs.target }}/firmware.uf2" fi # Upload to R2 with hash as filename aws s3 cp "$BUILD_FILE" "s3://${{ secrets.R2_BUCKET_NAME }}/${{ inputs.build_hash }}.uf2" \ --endpoint-url "$AWS_ENDPOINT_URL" echo "✅ Uploaded to R2: ${{ inputs.build_hash }}.uf2" - name: Update Status - Upload Complete if: success() shell: bash run: | source /tmp/update_status.sh update_status upload_complete - name: Update Build Status - Final if: always() run: | STATUS="${{ job.status }}" if [ "$STATUS" = "success" ]; then STATUS_MSG="success" else STATUS_MSG="failure" fi curl -X POST "${{ inputs.convex_url }}/github-webhook" \ -H "Content-Type: application/json" \ -d "{\"action\": \"completed\", \"build_id\": \"${{ inputs.build_id }}\", \"status\": \"$STATUS_MSG\"}"