Sync inav to Gitea
Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s
Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# GitHub Actions Workflows
|
||||
|
||||
This directory contains automated CI/CD workflows for the INAV project.
|
||||
|
||||
## Active Workflows
|
||||
|
||||
### Build and Test
|
||||
|
||||
#### `ci.yml` - Build Firmware
|
||||
**Triggers:** Pull requests, pushes to maintenance branches
|
||||
**Purpose:** Compiles INAV firmware for all targets to verify builds succeed
|
||||
**Matrix:** 15 parallel build jobs for faster CI
|
||||
|
||||
#### `nightly-build.yml` - Nightly Builds
|
||||
**Triggers:** Scheduled nightly
|
||||
**Purpose:** Creates nightly development builds for testing
|
||||
|
||||
### Documentation
|
||||
|
||||
#### `docs.yml` - Documentation Build
|
||||
**Triggers:** Pull requests affecting documentation
|
||||
**Purpose:** Validates documentation builds correctly
|
||||
|
||||
### Code Quality
|
||||
|
||||
#### `pg-version-check.yml` - Parameter Group Version Check
|
||||
**Triggers:** Pull requests to maintenance-9.x and maintenance-10.x
|
||||
**Purpose:** Detects parameter group struct modifications and verifies version increments
|
||||
**Why:** Prevents settings corruption when struct layout changes without version bump
|
||||
|
||||
**How it works:**
|
||||
1. Scans changed .c/.h files for `PG_REGISTER` entries
|
||||
2. Detects if associated struct typedefs were modified
|
||||
3. Checks if the PG version parameter was incremented
|
||||
4. Posts helpful comment if version not incremented
|
||||
|
||||
**Reference:** See `docs/development/parameter_groups/` for PG system documentation
|
||||
|
||||
**Script:** `.github/scripts/check-pg-versions.sh`
|
||||
|
||||
**When to increment PG versions:**
|
||||
- ✅ Adding/removing fields from struct
|
||||
- ✅ Changing field types or sizes
|
||||
- ✅ Reordering fields
|
||||
- ✅ Adding/removing packing attributes
|
||||
- ❌ Only changing `PG_RESET_TEMPLATE` default values
|
||||
- ❌ Only changing comments
|
||||
|
||||
### Pull Request Helpers
|
||||
|
||||
#### `pr-branch-suggestion.yml` - Branch Targeting Suggestion
|
||||
**Triggers:** PRs targeting master branch
|
||||
**Purpose:** Suggests using maintenance-9.x or maintenance-10.x instead
|
||||
|
||||
#### `non-code-change.yaml` - Non-Code Change Detection
|
||||
**Triggers:** Pull requests
|
||||
**Purpose:** Detects PRs with only documentation/formatting changes
|
||||
|
||||
## Configuration Files
|
||||
|
||||
- `../.github/stale.yml` - Stale issue/PR management
|
||||
- `../.github/no-response.yml` - Auto-close issues without response
|
||||
- `../.github/issue_label_bot.yaml` - Automatic issue labeling
|
||||
|
||||
## Adding New Workflows
|
||||
|
||||
When adding workflows:
|
||||
|
||||
1. **Use descriptive names** - Make purpose clear from filename
|
||||
2. **Document in this README** - Add entry above with purpose and triggers
|
||||
3. **Set appropriate permissions** - Principle of least privilege
|
||||
4. **Test in fork first** - Verify before submitting to main repo
|
||||
5. **Handle errors gracefully** - Don't block CI unnecessarily
|
||||
|
||||
### Common Patterns
|
||||
|
||||
**Checkout with history:**
|
||||
```yaml
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
```
|
||||
|
||||
**Post PR comments:**
|
||||
```yaml
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: 'Comment text'
|
||||
});
|
||||
```
|
||||
|
||||
**Run bash scripts:**
|
||||
```yaml
|
||||
- run: bash .github/scripts/script-name.sh
|
||||
env:
|
||||
GITHUB_BASE_REF: ${{ github.base_ref }}
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
Workflows use GitHub's fine-grained permissions:
|
||||
|
||||
- `contents: read` - Read repository code
|
||||
- `pull-requests: write` - Post/update PR comments
|
||||
- `actions: read` - Read workflow run data
|
||||
|
||||
## Local Testing
|
||||
|
||||
Scripts in `.github/scripts/` can be run locally:
|
||||
|
||||
```bash
|
||||
cd inav
|
||||
export GITHUB_BASE_REF=maintenance-9.x
|
||||
export GITHUB_HEAD_REF=feature-branch
|
||||
bash .github/scripts/check-pg-versions.sh
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||
- [Workflow Syntax](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
|
||||
- [GitHub Script Action](https://github.com/actions/github-script)
|
||||
@@ -0,0 +1,382 @@
|
||||
name: Build firmware
|
||||
# Don't enable CI on push, just on PR. If you
|
||||
# are working on the main repo and want to trigger
|
||||
# a CI build submit a draft PR.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '!maintenance-8.x.x'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '.github/**'
|
||||
- 'cmake/**'
|
||||
- 'lib/**'
|
||||
- 'docs/Settings.md'
|
||||
- 'CMakeLists.txt'
|
||||
- '*.sh'
|
||||
|
||||
workflow_call:
|
||||
#inputs:
|
||||
# release_build:
|
||||
# description: 'Specifies if it is a build that should include commit hash in hex file names or not'
|
||||
# default: false
|
||||
# required: false
|
||||
# type: boolean
|
||||
|
||||
|
||||
jobs:
|
||||
detect:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
single_target: ${{ steps.check.outputs.single_target }}
|
||||
target_names: ${{ steps.check.outputs.target_names }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Detect single-target PR
|
||||
id: check
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" != "pull_request" ]; then
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
|
||||
|
||||
if [ -z "$CHANGED" ]; then
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fail fast if any changed file is outside src/main/target/<dir>/
|
||||
NON_TARGET=$(echo "$CHANGED" | grep -Ev '^src/main/target/[^/]+/.+' | head -1)
|
||||
if [ -n "$NON_TARGET" ]; then
|
||||
echo "Non-target file changed: $NON_TARGET — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Count how many distinct target directories were touched
|
||||
TARGET_DIRS=$(echo "$CHANGED" | sed -n 's|^src/main/target/\([^/]*\)/.*|\1|p' | sort -u)
|
||||
DIR_COUNT=$(echo "$TARGET_DIRS" | wc -l)
|
||||
if [ "$DIR_COUNT" != "1" ]; then
|
||||
echo "$DIR_COUNT target directories changed — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TARGET_DIR="$TARGET_DIRS"
|
||||
CMAKE="src/main/target/${TARGET_DIR}/CMakeLists.txt"
|
||||
if [ ! -f "$CMAKE" ]; then
|
||||
echo "No CMakeLists.txt for $TARGET_DIR — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TARGET_NAMES=$(grep -oP '(?<=\()[^)]+' "$CMAKE" | tr '\n' ' ' | xargs)
|
||||
if [ -z "$TARGET_NAMES" ]; then
|
||||
echo "No target names in CMakeLists.txt — full build required"
|
||||
echo "single_target=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Single-target PR: building $TARGET_NAMES"
|
||||
echo "single_target=true" >> $GITHUB_OUTPUT
|
||||
echo "target_names=$TARGET_NAMES" >> $GITHUB_OUTPUT
|
||||
|
||||
build:
|
||||
needs: [detect]
|
||||
if: needs.detect.outputs.single_target != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
id: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: downloads
|
||||
key: ${{ runner.os }}-downloads-${{ hashFiles('CMakeLists.txt') }}-${{ hashFiles('**/cmake/*')}}
|
||||
- name: Build targets (${{ matrix.id }})
|
||||
run: mkdir -p build && cd build && cmake -DWARNINGS_AS_ERRORS=ON -DCI_JOB_INDEX=${{ matrix.id }} -DCI_JOB_COUNT=${{ strategy.job-total }} -DBUILD_SUFFIX=${{ env.BUILD_SUFFIX }} -DMAIN_COMPILE_OPTIONS=-pipe -G Ninja .. && ninja -j${{ env.NUM_CORES }} ci
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: matrix-${{ env.BUILD_NAME }}.${{ matrix.id }}
|
||||
path: ./build/*.hex
|
||||
retention-days: 1
|
||||
|
||||
build-single-target:
|
||||
needs: [detect]
|
||||
if: needs.detect.outputs.single_target == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: downloads
|
||||
key: ${{ runner.os }}-downloads-${{ hashFiles('CMakeLists.txt') }}-${{ hashFiles('**/cmake/*')}}
|
||||
- name: Build targets (${{ needs.detect.outputs.target_names }})
|
||||
run: mkdir -p build && cd build && cmake -DWARNINGS_AS_ERRORS=ON -DBUILD_SUFFIX=${{ env.BUILD_SUFFIX }} -DMAIN_COMPILE_OPTIONS=-pipe -G Ninja .. && ninja -j${{ env.NUM_CORES }} ${{ needs.detect.outputs.target_names }}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: matrix-${{ env.BUILD_NAME }}.single
|
||||
path: ./build/*.hex
|
||||
retention-days: 1
|
||||
|
||||
upload-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, build-single-target]
|
||||
if: always() && !cancelled() && (needs.build.result == 'success' || needs.build-single-target.result == 'success')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: matrix-inav-*
|
||||
merge-multiple: true
|
||||
path: binaries
|
||||
- name: Build target list
|
||||
run: |
|
||||
ls -1 binaries/*.hex | cut -d/ -f2 > targets.txt
|
||||
- name: Upload firmware images
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}
|
||||
path: binaries/*.hex
|
||||
- name: Upload firmware images
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: targets
|
||||
path: targets.txt
|
||||
- name: Save PR number
|
||||
if: github.event_name == 'pull_request'
|
||||
run: echo "${{ github.event.pull_request.number }}" > pr_number.txt
|
||||
- name: Upload PR number
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-number
|
||||
path: pr_number.txt
|
||||
retention-days: 1
|
||||
|
||||
build-SITL-Linux-arm64:
|
||||
runs-on: ubuntu-22.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Build SITL
|
||||
run: mkdir -p build_SITL && cd build_SITL && cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -G Ninja .. && ninja -j${{ env.NUM_CORES }}
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in build_SITL/*_SITL; do
|
||||
mv $f $(echo $f | sed -e 's/_[0-9]\+\.[0-9]\+\.[0-9]\+//')
|
||||
done
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-Linux-aarch64
|
||||
path: ./build_SITL/*_SITL
|
||||
|
||||
build-SITL-Linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Build SITL
|
||||
run: mkdir -p build_SITL && cd build_SITL && cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -G Ninja .. && ninja -j${{ env.NUM_CORES }}
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in build_SITL/*_SITL; do
|
||||
mv $f $(echo $f | sed -e 's/_[0-9]\+\.[0-9]\+\.[0-9]\+//')
|
||||
done
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-Linux
|
||||
path: ./build_SITL/*_SITL
|
||||
|
||||
build-SITL-Mac:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install ruby
|
||||
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }')
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "NUM_CORES=$(grep processor /proc/cpuinfo | wc -l)" >> $GITHUB_ENV
|
||||
- name: Build SITL
|
||||
run: |
|
||||
mkdir -p build_SITL && cd build_SITL
|
||||
cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -G Ninja ..
|
||||
ninja -j4
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in build_SITL/*_SITL; do
|
||||
mv -v $f $(echo $f | sed -Ee 's/_[0-9]+\.[0-9]+\.[0-9]+//')
|
||||
done
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-MacOS
|
||||
path: ./build_SITL/*_SITL
|
||||
|
||||
build-SITL-Windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: C:\tools\cygwin\bin\bash.exe -o igncr '{0}'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Cygwin
|
||||
uses: egor-tensin/setup-cygwin@v4
|
||||
with:
|
||||
packages: cmake ruby ninja gcc-g++ rubygems
|
||||
- name: Setup environment
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
run: |
|
||||
# This is the hash of the commit for the PR
|
||||
# when the action is triggered by PR, empty otherwise
|
||||
COMMIT_ID=${{ github.event.pull_request.head.sha }}
|
||||
# This is the hash of the commit when triggered by push
|
||||
# but the hash of refs/pull/<n>/merge, which is different
|
||||
# from the hash of the latest commit in the PR, that's
|
||||
# why we try github.event.pull_request.head.sha first
|
||||
COMMIT_ID=${COMMIT_ID:-${{ github.sha }}}
|
||||
BUILD_SUFFIX=ci-$(date '+%Y%m%d')-$(git rev-parse --short ${COMMIT_ID})
|
||||
VERSION=$( grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t)]/, "", $2); print $2 }' )
|
||||
echo "BUILD_SUFFIX=${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
echo "BUILD_NAME=inav-${VERSION}-${BUILD_SUFFIX}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build SITL
|
||||
run: gem install getoptlong && mkdir -p build_SITL && cd build_SITL && cmake -DSITL=ON -DWARNINGS_AS_ERRORS=ON -G Ninja .. && ninja -j4
|
||||
- name: Strip version number
|
||||
run: |
|
||||
for f in ./build_SITL/*_SITL.exe; do
|
||||
mv $f $(echo $f | sed -e 's/_[0-9]\+\.[0-9]\+\.[0-9]\+//')
|
||||
done
|
||||
- name: Copy cygwin1.dll
|
||||
run: cp /bin/cygwin1.dll ./build_SITL/
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUILD_NAME }}_SITL-WIN
|
||||
path: |
|
||||
./build_SITL/*.exe
|
||||
./build_SITL/cygwin1.dll
|
||||
|
||||
test:
|
||||
#needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Run Tests
|
||||
run: mkdir -p build && cd build && cmake -DTOOLCHAIN=none -G Ninja .. && ninja check
|
||||
@@ -0,0 +1,27 @@
|
||||
name: Make sure docs are updated
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- src/main/fc/settings.yaml
|
||||
- docs/Settings.md
|
||||
push:
|
||||
paths:
|
||||
- src/main/fc/settings.yaml
|
||||
- docs/Settings.md
|
||||
|
||||
jobs:
|
||||
settings_md:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install python3-yaml
|
||||
- name: Check that Settings.md is up to date
|
||||
run: |
|
||||
cp docs/Settings.md{,.ci}
|
||||
python3 src/utils/update_cli_docs.py -q
|
||||
if ! diff -q docs/Settings.md{,.ci} >/dev/null; then
|
||||
echo "::error ::\"docs/Settings.md\" is not up to date, please run \"src/utils/update_cli_docs.py\""
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,105 @@
|
||||
name: Build pre-release
|
||||
# Don't enable CI on push, just on PR. If you
|
||||
# are working on the main repo and want to trigger
|
||||
# a CI build submit a draft PR.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- maintenance-8.x.x
|
||||
- maintenance-9.x
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '.github/**'
|
||||
- 'cmake/**'
|
||||
- 'lib/**'
|
||||
- 'docs/Settings.md'
|
||||
- 'CMakeLists.txt'
|
||||
- '*.sh'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
uses: ./.github/workflows/ci.yml
|
||||
|
||||
release:
|
||||
name: Release
|
||||
needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get version
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(grep project CMakeLists.txt|awk -F VERSION '{ gsub(/[ \t\)]/, "", $2); print $2 }')
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "today=$(date '+%Y%m%d')" >> $GITHUB_OUTPUT
|
||||
- name: download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: hexes
|
||||
pattern: matrix-inav-*
|
||||
merge-multiple: true
|
||||
- name: download sitl linux
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/linux
|
||||
pattern: inav-*SITL-Linux
|
||||
merge-multiple: true
|
||||
- name: download sitl linux aarch64
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/linux/arm64
|
||||
pattern: inav-*SITL-Linux-aarch64
|
||||
merge-multiple: true
|
||||
- name: download sitl windows
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/windows
|
||||
pattern: inav-*SITL-WIN
|
||||
merge-multiple: true
|
||||
- name: download sitl mac
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: resources/sitl/macos
|
||||
pattern: inav-*SITL-MacOS
|
||||
merge-multiple: true
|
||||
- name: Consolidate sitl files
|
||||
run: |
|
||||
zip -r -9 sitl-resources.zip resources/
|
||||
- name: Upload release artifacts
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: inav-${{ steps.version.outputs.version }}-dev-${{ steps.date.outputs.today }}-${{ github.run_number }}-${{ github.sha }}
|
||||
tag_name: v${{ steps.version.outputs.version }}-${{ steps.date.outputs.today }}.${{ github.run_number }}
|
||||
# To create release on a different repo, we need a token setup
|
||||
token: ${{ secrets.NIGHTLY_TOKEN }}
|
||||
repository: iNavFlight/inav-nightly
|
||||
prerelease: true
|
||||
draft: false
|
||||
#generate_release_notes: true
|
||||
make_latest: false
|
||||
files: |
|
||||
hexes/*.hex
|
||||
sitl-resources.zip
|
||||
body: |
|
||||
${{ steps.notes.outputs.notes }}
|
||||
|
||||
### Flashing
|
||||
These are nightly builds and configuration settings can be added and removed often. Flashing with Full chip erase is strongly recommended to avoid issues.
|
||||
Firmware related issues should be opened in the iNavflight/inav repository, not in inav-nightly.
|
||||
|
||||
### Repository:
|
||||
${{ github.repository }} ([link](${{ github.event.repository.html_url }}))
|
||||
|
||||
### Branch:
|
||||
${{ github.ref_name }} ([link](${{ github.event.repository.html_url }}/tree/${{ github.ref_name }}))
|
||||
|
||||
### Latest changeset:
|
||||
${{ github.event.head_commit.id }} ([link](${{ github.event.head_commit.url }}))
|
||||
|
||||
### Changes:
|
||||
${{ github.event.head_commit.message }}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Build firmware
|
||||
# Don't enable CI on push, just on PR. If you
|
||||
# are working on the main repo and want to trigger
|
||||
# a CI build submit a draft PR.
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'src/**'
|
||||
- '.github/**'
|
||||
- 'cmake/**'
|
||||
- 'lib/**'
|
||||
- 'docs/Settings.md'
|
||||
- 'CMakeLists.txt'
|
||||
- '*.sh'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
#needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get -y install ninja-build
|
||||
- name: Run Tests
|
||||
run: mkdir -p build && cd build && cmake -DTOOLCHAIN=none -G Ninja .. && ninja check
|
||||
@@ -0,0 +1,128 @@
|
||||
name: Parameter Group Version Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- maintenance-9.x
|
||||
- maintenance-10.x
|
||||
paths:
|
||||
- 'src/**/*.c'
|
||||
- 'src/**/*.h'
|
||||
|
||||
jobs:
|
||||
check-pg-versions:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout PR code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Need full history to compare with base branch
|
||||
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}
|
||||
|
||||
- name: Run PG version check script
|
||||
id: pg_check
|
||||
run: |
|
||||
set +e # Don't fail the workflow, just capture exit code
|
||||
# Run script and capture output. Exit code 1 is expected for issues.
|
||||
# The output is captured and encoded to be passed between steps.
|
||||
output=$(bash .github/scripts/check-pg-versions.sh 2>&1)
|
||||
exit_code=$?
|
||||
echo "exit_code=${exit_code}" >> $GITHUB_OUTPUT
|
||||
echo "output<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$output" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GITHUB_BASE_REF: ${{ github.base_ref }}
|
||||
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
||||
|
||||
- name: Post comment if issues found
|
||||
if: steps.pg_check.outputs.exit_code == '1'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Use the captured output from the previous step
|
||||
const output = '${{ steps.pg_check.outputs.output }}';
|
||||
let issuesContent = '';
|
||||
|
||||
try {
|
||||
// Extract issues from output (everything after the warning line)
|
||||
const lines = output.split('\n');
|
||||
let capturing = false;
|
||||
let issues = [];
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.includes('###')) {
|
||||
capturing = true;
|
||||
}
|
||||
if (capturing) {
|
||||
issues.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
issuesContent = issues.join('\n');
|
||||
} catch (err) {
|
||||
console.log('Error capturing issues:', err);
|
||||
issuesContent = '*Unable to extract detailed issues*';
|
||||
}
|
||||
|
||||
const commentBody = '## ⚠️ Parameter Group Version Check\n\n' +
|
||||
'The following parameter groups may need version increments:\n\n' +
|
||||
issuesContent + '\n\n' +
|
||||
'**Why this matters:**\n' +
|
||||
'Modifying PG struct fields without incrementing the version can cause settings corruption when users flash new firmware. The `pgLoad()` function validates versions and will use defaults if there\'s a mismatch, preventing corruption.\n\n' +
|
||||
'**When to increment the version:**\n' +
|
||||
'- ✅ Adding/removing fields\n' +
|
||||
'- ✅ Changing field types or sizes\n' +
|
||||
'- ✅ Reordering fields\n' +
|
||||
'- ✅ Adding/removing packing attributes\n' +
|
||||
'- ❌ Only changing default values in `PG_RESET_TEMPLATE`\n' +
|
||||
'- ❌ Only changing comments\n\n' +
|
||||
'**Reference:**\n' +
|
||||
'- [Parameter Group Documentation](../docs/development/parameter_groups/)\n' +
|
||||
'- Example: [PR #11236](https://github.com/iNavFlight/inav/pull/11236) (field removal requiring version increment)\n\n' +
|
||||
'---\n' +
|
||||
'*This is an automated check. False positives are possible. If you believe the version increment is not needed, please explain in a comment.*';
|
||||
|
||||
try {
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(comment =>
|
||||
comment.user.login === 'github-actions[bot]' &&
|
||||
comment.body.includes('Parameter Group Version Check')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
// Update existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: commentBody
|
||||
});
|
||||
console.log('Updated existing PG version check comment');
|
||||
} else {
|
||||
// Post new comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: commentBody
|
||||
});
|
||||
console.log('Posted new PG version check comment');
|
||||
}
|
||||
} catch (err) {
|
||||
core.setFailed(`Failed to post comment: ${err}`);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
name: PR Branch Suggestion
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
suggest-branch:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Suggest maintenance branch
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = `### Branch Targeting Suggestion
|
||||
|
||||
You've targeted the \`master\` branch with this PR. Please consider if a version branch might be more appropriate:
|
||||
|
||||
- **\`maintenance-9.x\`** - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.
|
||||
|
||||
- **\`maintenance-10.x\`** - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x
|
||||
|
||||
If \`master\` is the correct target for this change, no action is needed.
|
||||
|
||||
---
|
||||
*This is an automated suggestion to help route contributions to the appropriate branch.*`;
|
||||
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
} catch (err) {
|
||||
core.setFailed(`Failed to post suggestion comment: ${err}`);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
name: PR Test Builds
|
||||
|
||||
# Runs after "Build firmware" completes. Uses workflow_run (rather than
|
||||
# pull_request directly) so that secrets are available even for PRs from forks.
|
||||
#
|
||||
# Requires a repository secret PR_BUILDS_TOKEN with Contents: write access
|
||||
# to iNavFlight/pr-test-builds (fine-grained PAT or classic PAT with repo scope).
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Build firmware"]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
# Only act on pull_request-triggered runs that succeeded.
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
# Prevent concurrent runs for the same PR branch racing on the
|
||||
# release delete/create cycle.
|
||||
concurrency:
|
||||
group: pr-test-build-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}
|
||||
cancel-in-progress: true
|
||||
permissions:
|
||||
actions: read # to download artifacts from the triggering workflow run
|
||||
issues: write # github.rest.issues.* endpoints used to post PR comments
|
||||
pull-requests: write # to post the PR comment
|
||||
|
||||
steps:
|
||||
- name: Download PR number
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-number
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Read PR number
|
||||
id: pr
|
||||
run: |
|
||||
PR_NUM=$(tr -dc '0-9' < pr_number.txt)
|
||||
if [ -z "$PR_NUM" ]; then
|
||||
echo "::error::Invalid PR number in artifact"
|
||||
exit 1
|
||||
fi
|
||||
echo "number=${PR_NUM}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download firmware artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: matrix-inav-*
|
||||
merge-multiple: true
|
||||
path: hexes
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get build info
|
||||
id: info
|
||||
run: |
|
||||
COUNT=$(find hexes -name '*.hex' -type f | wc -l)
|
||||
if [ "$COUNT" -eq 0 ]; then
|
||||
echo "::error::No .hex files found in downloaded artifacts"
|
||||
exit 1
|
||||
fi
|
||||
echo "count=${COUNT}" >> $GITHUB_OUTPUT
|
||||
echo "short_sha=$(echo '${{ github.event.workflow_run.head_sha }}' | cut -c1-7)" >> $GITHUB_OUTPUT
|
||||
|
||||
# Delete the previous release for this PR (if any) so assets are replaced
|
||||
# cleanly on each new commit. --cleanup-tag removes the old tag so it is
|
||||
# recreated fresh pointing to the new commit.
|
||||
- name: Delete existing PR release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
|
||||
run: |
|
||||
gh release delete "pr-${{ steps.pr.outputs.number }}" \
|
||||
--repo iNavFlight/pr-test-builds --cleanup-tag --yes 2>/dev/null || true
|
||||
|
||||
- name: Create PR release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
|
||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||
SHORT_SHA: ${{ steps.info.outputs.short_sha }}
|
||||
HEX_COUNT: ${{ steps.info.outputs.count }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
PR_URL="https://github.com/${REPO}/pull/${PR_NUMBER}"
|
||||
printf '%s\n\n%s\n\n%s\n' \
|
||||
"Test build for [PR #${PR_NUMBER}](${PR_URL}) — commit \`${SHORT_SHA}\`" \
|
||||
"**${HEX_COUNT} targets built.** Find your board's \`.hex\` file by name (e.g. \`MATEKF405SE.hex\`)." \
|
||||
"> Development build for testing only. Use Full Chip Erase when flashing." \
|
||||
> release-notes.md
|
||||
gh release create "pr-${PR_NUMBER}" hexes/*.hex \
|
||||
--repo iNavFlight/pr-test-builds \
|
||||
--prerelease \
|
||||
--title "PR #${PR_NUMBER} (${SHORT_SHA})" \
|
||||
--notes-file release-notes.md
|
||||
|
||||
- name: Post or update PR comment
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||
SHORT_SHA: ${{ steps.info.outputs.short_sha }}
|
||||
HEX_COUNT: ${{ steps.info.outputs.count }}
|
||||
with:
|
||||
script: |
|
||||
const prNumber = parseInt(process.env.PR_NUMBER, 10);
|
||||
if (isNaN(prNumber)) throw new Error(`Invalid PR number: ${process.env.PR_NUMBER}`);
|
||||
const shortSha = process.env.SHORT_SHA;
|
||||
const count = process.env.HEX_COUNT;
|
||||
const releaseUrl = `https://github.com/iNavFlight/pr-test-builds/releases/tag/pr-${prNumber}`;
|
||||
|
||||
const body = [
|
||||
'<!-- pr-test-build -->',
|
||||
'**Test firmware build ready** — commit `' + shortSha + '`',
|
||||
'',
|
||||
`[Download firmware for PR #${prNumber}](${releaseUrl})`,
|
||||
'',
|
||||
`${count} targets built. Find your board's \`.hex\` file by name on that page ` +
|
||||
'(e.g. `MATEKF405SE.hex`). Files are individually downloadable — no GitHub login required.',
|
||||
'',
|
||||
'> Development build for testing only. Use Full Chip Erase when flashing.',
|
||||
].join('\n');
|
||||
|
||||
const comments = await github.paginate(
|
||||
github.rest.issues.listComments,
|
||||
{
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
}
|
||||
);
|
||||
|
||||
const existing = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('<!-- pr-test-build -->')
|
||||
);
|
||||
|
||||
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: prNumber,
|
||||
body,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user