Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@ This directory contains automated CI/CD workflows for the INAV project.
### Build and Test

#### `ci.yml` - Build Firmware
**Triggers:** Pull requests, pushes to maintenance branches
**Triggers:** Pull requests (`workflow_call` too, used by `nightly-build.yml`).
Also declares an `on: push:` trigger, but it's currently a no-op — a
`branches:` list containing only a negative pattern (`'!maintenance-8.x.x'`)
matches nothing per GitHub's own docs, confirmed empirically (zero
push-triggered runs of this workflow exist in this repo's history). Direct
push builds happen via `nightly-build.yml` instead (see below).
**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
#### `nightly-build.yml` - "Build pre-release"
**Triggers:** `push` to `master`, `maintenance-8.x.x`, `maintenance-9.x`,
`maintenance-10.x`, `release/9.1` — **not** a schedule, despite the
filename. Invokes `ci.yml`'s jobs via `workflow_call`, then publishes a
prerelease to the companion `iNavFlight/inav-nightly` repo.
**Purpose:** Creates nightly development builds for testing, and is the
actual per-push validation + baseline-generation point for
`ci-size-report.yml` (see below) since `ci.yml`'s own push trigger doesn't
fire.

### Documentation

Expand Down Expand Up @@ -49,7 +60,8 @@ This directory contains automated CI/CD workflows for the INAV project.
### Pull Request Helpers

#### `ci-size-report.yml` - RAM/Flash Usage Delta PR Comment
**Triggers:** `workflow_run` after "Build firmware" (`ci.yml`) completes
**Triggers:** `workflow_run` after "Build firmware" (`ci.yml`, PR builds) or
"Build pre-release" (`nightly-build.yml`, branch-push builds) completes
**Purpose:** Posts/updates a PR comment showing flash and RAM usage delta vs.
the PR's base branch, for 4 representative targets spanning flash/RAM size
tiers (MATEKF405, MATEKF722, MATEKF765, MATEKH743 — note MATEKF722 and
Expand All @@ -61,10 +73,18 @@ every PR.
1. `ci.yml` extracts a small per-target size report (`arm-none-eabi-size`
on each built `.elf`) right after each build and uploads it as an
artifact — no second build anywhere in this flow.
2. On pushes to a branch, `ci-size-report.yml` persists that size report as
a release asset (`size-baseline-<branch>`) in the companion
`iNavFlight/pr-test-builds` repo — the "known good" baseline for that
branch, overwritten on every push.
2. On pushes to `master`/`maintenance-9.x`/`maintenance-10.x`/`release/9.1`,
`nightly-build.yml` ("Build pre-release") invokes `ci.yml` via
`workflow_call` as part of building nightly releases — this already
produces the size report above at no extra build cost. When that
completes, `ci-size-report.yml` persists it as a release asset
(`size-baseline-<branch>`) in the companion `iNavFlight/pr-test-builds`
repo — the "known good" baseline for that branch, overwritten on every
push. (`ci.yml`'s *own* `on: push:` trigger is broken — a `branches:`
list containing only a negative pattern matches nothing per GitHub's
docs — so this deliberately listens to `nightly-build.yml` instead of
trying to fix that separately; verified empirically that `ci.yml` alone
has zero push-triggered runs in this repo's history.)
3. On PR builds, it fetches the PR's base branch's persisted baseline (no
rebuild), diffs it against the PR's own size report, and posts/updates a
comment (marker `<!-- pr-size-diff -->`).
Expand Down
79 changes: 62 additions & 17 deletions .github/workflows/ci-size-report.yml
Original file line number Diff line number Diff line change
@@ -1,54 +1,98 @@
name: CI Size Report

# Runs after "Build firmware" completes. Uses workflow_run (rather than
# pull_request/push directly) so that secrets are available even for PRs
# from forks — same reasoning as pr-test-builds.yml.
# Uses workflow_run (rather than pull_request/push directly) so that
# secrets are available even for PRs from forks — same reasoning as
# pr-test-builds.yml.
#
# Two jobs:
# - publish-baseline: on any branch push that triggers ci.yml (in practice,
# almost always maintenance-9.x/maintenance-10.x — see ci.yml's own push
# trigger for the exact filter), persists the size report as a release
# asset in the companion iNavFlight/pr-test-builds repo, so PR runs never
# need to rebuild the base branch to get a comparison point. Stale
# baselines for since-deleted branches aren't cleaned up automatically
# (same known limitation pr-test-builds has for old PR releases).
# - pr-comment: on PR builds, fetches that persisted baseline, diffs the
# 4 representative targets, and posts/updates a PR comment.
# Listens to two different upstream workflows, for two different jobs:
# - publish-baseline listens for "Build pre-release" (nightly-build.yml),
# NOT "Build firmware" directly. ci.yml's own `on: push:` trigger is
# broken (a branches: list with only a negative pattern matches
# nothing — confirmed empirically, zero push-triggered "Build firmware"
# runs exist). "Build pre-release" is push-triggered correctly and
# already invokes ci.yml's jobs via `uses:` (workflow_call) as part of
# building nightly releases — piggybacking here costs nothing extra,
# no second build. Persists the size report as a release asset in the
# companion iNavFlight/pr-test-builds repo, so PR runs never need to
# rebuild the base branch to get a comparison point. Only fires for
# branches nightly-build.yml's own push trigger covers (currently
# master, maintenance-9.x, maintenance-10.x, release/9.1 — see that
# file). Stale baselines for since-deleted branches aren't cleaned up
Comment on lines +17 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Informational

2. Branch coverage comment wrong 🐞 Bug ⚙ Maintainability

ci-size-report.yml’s header comment claims baseline publishing only covers master,
maintenance-9.x, maintenance-10.x, and release/9.1, but nightly-build.yml also triggers
“Build pre-release” on maintenance-8.x.x, so baselines will also be published for that branch.
Agent Prompt
### Issue description
The comment describing which branches are covered by `nightly-build.yml` is inconsistent with the actual `nightly-build.yml` trigger list, which includes `maintenance-8.x.x`.

### Issue Context
This is a documentation mismatch inside the workflow file itself; it can mislead future maintainers about which branches will have baselines published.

### Fix Focus Areas
- .github/workflows/ci-size-report.yml[17-20]
- .github/workflows/nightly-build.yml[6-13]

### Suggested change
Update the comment to include `maintenance-8.x.x` (or, if unintended, remove that branch from the `nightly-build.yml` trigger list).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

# automatically (same known limitation pr-test-builds has for old PR
# releases).
# - pr-comment listens for "Build firmware" (ci.yml) directly — PR builds
# genuinely do trigger it via `pull_request`, that part isn't broken.
# Fetches the persisted baseline, diffs the 4 representative targets,
# and posts/updates a PR comment.
#
# Requires the same repository secret PR_BUILDS_TOKEN as pr-test-builds.yml
# (Contents: write access to iNavFlight/pr-test-builds).
on:
workflow_run:
workflows: ["Build firmware"]
workflows: ["Build firmware", "Build pre-release"]
types: [completed]

jobs:
publish-baseline:
runs-on: ubuntu-latest
if: >
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.conclusion == 'success'
github.event.workflow_run.name == 'Build pre-release' &&
github.event.workflow_run.event == 'push'
concurrency:
group: size-baseline-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true
permissions:
actions: read # to download artifacts from the triggering workflow run
actions: read # to download artifacts and query job conclusions from the triggering workflow run
steps:
# Don't gate on github.event.workflow_run.conclusion: "Build
# pre-release" also runs a separate Release job (nightly upload to
# iNavFlight/inav-nightly) that can fail for reasons unrelated to the
# build itself (e.g. an expired NIGHTLY_TOKEN) and drags the whole
# run's conclusion to failure even when the build succeeded and
# produced the artifacts we actually need. Check the specific job
# that produces them instead.
- name: Check build job succeeded
id: check
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
CONCLUSION=$(gh api "repos/${{ github.repository }}/actions/runs/${RUN_ID}/jobs" --paginate \
--jq '.jobs[] | select(.name == "build / upload-artifacts") | .conclusion')
Comment on lines +60 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Brittle job-name gate 🐞 Bug ☼ Reliability

ci-size-report.yml gates baseline publishing on finding a job named exactly `"build /
upload-artifacts"` in the upstream run; any caller job rename (nightly-build) or callee job rename
(ci.yml) will cause proceed=false and baseline publishing will be skipped.
Agent Prompt
### Issue description
`publish-baseline` checks upstream success by querying workflow-run jobs and selecting a single hard-coded job name (`build / upload-artifacts`). This is fragile because GitHub job display names can change when either the caller job name (in `nightly-build.yml`) or the callee job id/name (in `ci.yml`) changes, causing baseline publishing to be skipped.

### Issue Context
- Caller workflow `nightly-build.yml` defines the reusable-workflow caller job name as `build`.
- Callee workflow `ci.yml` contains a job id `upload-artifacts`.
- The current jq filter requires an exact combined display name string.

### Fix Focus Areas
- .github/workflows/ci-size-report.yml[54-76]

### Suggested change
Update the jq selection to be resilient, e.g. match by suffix:
- select(.name | endswith("/ upload-artifacts") or endswith(" / upload-artifacts") or .name == "upload-artifacts")

Optionally:
- assert exactly one match and emit an error/warning if multiple matches occur
- include the matched job name in logs for easier debugging

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

if [ -z "$CONCLUSION" ]; then
# Job not found at all usually means the caller/callee job names
# changed (e.g. nightly-build.yml's "build" job or ci.yml's
# "upload-artifacts" job got renamed) — that's a workflow
# structure mismatch, not an expected build failure, and is
# exactly the kind of thing that silently broke baseline
# publishing before. Warn louder than a plain failed build.
echo "::warning::build / upload-artifacts job not found in run ${RUN_ID} — job name may have changed, skipping baseline publish"
echo "proceed=false" >> "$GITHUB_OUTPUT"
elif [ "$CONCLUSION" != "success" ]; then
echo "::notice::build / upload-artifacts did not succeed (conclusion: ${CONCLUSION}), skipping baseline publish"
echo "proceed=false" >> "$GITHUB_OUTPUT"
else
echo "proceed=true" >> "$GITHUB_OUTPUT"
fi

- name: Download size report
if: steps.check.outputs.proceed == 'true'
uses: actions/download-artifact@v4
with:
name: size-report
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Download branch name
if: steps.check.outputs.proceed == 'true'
uses: actions/download-artifact@v4
with:
name: branch-name
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Publish baseline
if: steps.check.outputs.proceed == 'true'
env:
GH_TOKEN: ${{ secrets.PR_BUILDS_TOKEN }}
run: |
Expand All @@ -73,6 +117,7 @@ jobs:
pr-comment:
runs-on: ubuntu-latest
if: >
github.event.workflow_run.name == 'Build firmware' &&
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
concurrency:
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,16 @@ jobs:
path: base_ref.txt
retention-days: 1
- name: Save branch name
if: github.event_name == 'push'
# Covers both a direct push and being invoked via workflow_call
# (e.g. from nightly-build.yml) — github.event_name reports
# 'workflow_call' in the latter case, not 'push', even though
# github.ref_name still correctly reflects the branch either way.
if: github.event_name != 'pull_request'
env:
REF_NAME: ${{ github.ref_name }}
run: echo "$REF_NAME" > branch.txt
- name: Upload branch name
if: github.event_name == 'push'
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: branch-name
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/nightly-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ on:
- master
- maintenance-8.x.x
- maintenance-9.x
- maintenance-10.x
- release/9.1
paths:
- 'src/**'
- '.github/**'
Expand Down
Loading