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

This commit is contained in:
2026-08-03 16:37:40 +08:00
commit dac37fd077
14095 changed files with 5603119 additions and 0 deletions
+127
View File
@@ -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)
+382
View File
@@ -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
+27
View File
@@ -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
+105
View File
@@ -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 }}
+25
View File
@@ -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
+128
View File
@@ -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}`);
}
+151
View File
@@ -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,
});
}