name: CI 'on': push: branches: [master] pull_request: permissions: contents: read pull-requests: write jobs: label: runs-on: ubuntu-latest steps: - uses: actions/labeler@v5 clang-format: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: submodules: recursive - uses: actions/setup-python@v6 with: python-version: '3.14' - name: Install clang-format-21 run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 21 sudo apt-get update sudo apt-get install -y clang-format-21 - name: Run clang-format run: PATH="/usr/lib/llvm-21/bin:$PATH" ./bin/clang-format-fix && git diff --exit-code || (echo "Please run 'bin/clang-format-fix' to fix formatting issues" && exit 1) cppcheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: submodules: recursive - uses: actions/setup-python@v6 with: python-version: '3.14' - name: Install PlatformIO Core run: pip install --upgrade platformio - name: Run cppcheck run: pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: submodules: recursive - uses: actions/setup-python@v6 with: python-version: '3.14' - name: Install PlatformIO Core run: pip install --upgrade platformio - name: Build CrossPoint run: | set -euo pipefail pio run | tee pio.log - name: Extract firmware stats id: fw_stats run: | set -euo pipefail ram_line="$(grep -E "RAM:\\s" -m1 pio.log || true)" flash_line="$(grep -E "Flash:\\s" -m1 pio.log || true)" echo "ram_line=${ram_line}" >> "$GITHUB_OUTPUT" echo "flash_line=${flash_line}" >> "$GITHUB_OUTPUT" { echo "## Firmware build stats" if [ -n "$ram_line" ]; then echo "- ${ram_line}"; else echo "- RAM: not found"; fi if [ -n "$flash_line" ]; then echo "- ${flash_line}"; else echo "- Flash: not found"; fi } >> "$GITHUB_STEP_SUMMARY" - name: Upload firmware.bin artifact uses: actions/upload-artifact@v4 with: name: ${{ github.event_name == 'pull_request' && format('firmware-bin-pr-{0}-{1}', github.event.pull_request.number, github.sha) || format('firmware-bin-{0}', github.sha) }} path: .pio/build/default/firmware.bin if-no-files-found: error - name: Comment PR with firmware stats and firmware.bin if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const marker = ''; const ram = `${{ steps.fw_stats.outputs.ram_line }}`.trim(); const flash = `${{ steps.fw_stats.outputs.flash_line }}`.trim(); const prNumber = context.payload.pull_request?.number; const artifactName = prNumber ? `firmware-bin-pr-${prNumber}-${context.sha}` : `firmware-bin-${context.sha}`; let firmwareLine = 'Firmware: artifact not found'; try { const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, run_id: context.runId, }); const firmwareArtifact = artifacts.artifacts.find((artifact) => artifact.name === artifactName); if (firmwareArtifact) { const artifactUiUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/artifacts/${firmwareArtifact.id}`; firmwareLine = `Firmware: [firmware.bin artifact](${artifactUiUrl})`; } else { firmwareLine = `Firmware: artifact not found (${artifactName})`; } } catch (error) { firmwareLine = `Firmware: artifact lookup failed (${error.message})`; } const body = `${marker}\n**Firmware build stats**\n\n\`\`\`\n${ram || 'RAM: not found'}\n${flash || 'Flash: not found'}\n\`\`\`\n\n**Firmware binary**\n${firmwareLine}`; const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); const existing = comments.find((comment) => comment.body && comment.body.includes(marker)); if (existing) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, body, }); } else { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body, }); }