Skip to content

ci: restrict Develocity cache writes to trusted events - #6550

Merged
jamesarich merged 1 commit into
mainfrom
fix/develocity-cache-push-gate
Aug 3, 2026
Merged

ci: restrict Develocity cache writes to trusted events#6550
jamesarich merged 1 commit into
mainfrom
fix/develocity-cache-push-gate

Conversation

@jamesarich

@jamesarich jamesarich commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Pull-request builds are currently writing to the shared Develocity remote build
cache. They should not be.

The gap

MeshtasticDevelocitySettingsPlugin gates cache writes on CI plus a non-empty
access key:

isPush = isCI && !accessKey.isNullOrEmpty()

A same-repository pull request does receive repository secrets, so
pull-request.yml runs satisfy both conditions and push entries into the cache
that main and the merge queue then read. Unmerged code can serve build outputs
to trusted builds.

This is a regression introduced in #6531. The self-hosted HttpBuildCache that
preceded it gated on the event and excluded pull requests:

def trustedForPush = eventName == null || eventName == "push" || eventName == "merge_group"
push = (cacheUsername && cachePassword && trustedForPush)

That protection was lost when the cache moved to remote(develocity.buildCache).

The fix

Require GITHUB_EVENT_NAME to be push or merge_group as well.

Cache population is unaffected. main-check.yml (push to main) and
merge-queue.yml (merge_group) remain trusted writers — and they are the runs
whose outputs correspond to code that actually landed, which is exactly what the
cache should contain. pull-request.yml becomes pull-only, so PRs still get the
full read benefit.

Verification

Run against a CI-shaped environment rather than reasoned about:

CI=true GITHUB_EVENT_NAME=pull_request  -> pull-only
CI=true GITHUB_EVENT_NAME=push          -> writes enabled
CI=true GITHUB_EVENT_NAME=merge_group   -> writes enabled

./gradlew spotlessCheck detekt green (185 tasks). Settings-plugin-only change,
so no app code is touched.

Context

Found while onboarding the rest of the org's Gradle repos to the same
configuration — I copied this plugin's shape into six repos and CodeRabbit
caught the missing gate there. Fixed in all six
(meshtastic/kzstd#36, meshtastic/gradle-flatpak-sources#28,
meshtastic/MQTTastic-Client-KMP#118, meshtastic/meshtastic-sdk#91,
meshtastic/protobufs#1027, meshtastic/TAKPacket-SDK#124); this brings android
back in line with them.

Summary by CodeRabbit

  • New Features
    • Added support for additional LoRa regions, including EU narrow/lite and amateur radio bands.
    • Added newer channel presets, including lite, narrow, turbo, and tiny options.
    • Improved frequency and channel-slot calculations for regional spacing, padding, and overrides.
  • Bug Fixes
    • Region and preset lists now hide options unsupported by the device’s firmware.
    • The device’s current region remains available even when it is not supported by the detected firmware version.

@github-actions github-actions Bot added bugfix PR tag build Build system changes ci Pertains to ci/cd actions or workflows labels Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a93cd608-f472-497b-8165-39c03fc3d86d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds firmware-gated LoRa regions and presets, updates regional frequency calculations, filters unsupported settings options, adds model tests, and restricts remote build-cache writes to selected CI events.

Changes

LoRa capability and frequency support

Layer / File(s) Summary
Region metadata and frequency calculations
core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt
Adds regional spacing, padding, override slots, minimum firmware metadata, new regions and presets, and shared rounded slot-width calculations.
Firmware capability filtering
core/model/src/commonMain/kotlin/org/meshtastic/core/model/Capabilities.kt, feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt
Adds firmware checks for regions and presets. The settings list filters unsupported entries while retaining the current selection.
Region and capability validation
core/model/src/commonTest/kotlin/org/meshtastic/core/model/CapabilitiesTest.kt, core/model/src/commonTest/kotlin/org/meshtastic/core/model/RegionInfoTest.kt
Tests firmware gating, force-enable behavior, region mappings, frequency calculations, legacy behavior, and channel precedence.

CI cache write restrictions

Layer / File(s) Summary
Remote cache write policy
build-logic/settings-plugin/src/main/kotlin/MeshtasticDevelocitySettingsPlugin.kt
Allows remote cache writes only during CI push or merge_group events with a non-empty access key.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SettingsUI as LoRaConfigItemList
  participant Capabilities
  participant RegionInfo
  SettingsUI->>Capabilities: Check region and preset support
  Capabilities->>RegionInfo: Read minimum firmware metadata
  RegionInfo-->>Capabilities: Return support status
  Capabilities-->>SettingsUI: Return filtered options
Loading

Possibly related PRs

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Tests Prove The Path, Not The End State ⚠️ Warning Two added RegionInfo tests are non-discriminating: standard_regions_keep_legacy_slot_math and explicit_channel_num_wins_over_override_slot also pass with the pre-change numChannels/channelNum code. Assert new spacing/padding values and that channel_num=0 selects overrideSlot; do not use only legacy US math or a nonzero channel_num that bypasses the new logic.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary Develocity cache-write restriction in the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Sibling Call Sites And Presence Semantics ✅ Passed The diff adds only nullable minFirmware and frequency/slot metadata; all minFirmware/support call sites are accounted for, and no RSSI, temperature, current, voltage, or particulate field defaults...

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt (1)

111-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consolidate the duplicated "2.8.0" firmware-version constant.

ChannelOption.kt and Capabilities.kt each declare a separate DeviceVersion("2.8.0") constant for the same firmware release. Keeping two independent literals for the same version risks drift if the value is ever corrected or the release is renumbered.

  • core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt#L111-L116: keep FIRMWARE_2_8 as the single source of truth, or move a shared constant to a common location.
  • core/model/src/commonMain/kotlin/org/meshtastic/core/model/Capabilities.kt#L112-L119: replace the private V2_8_0 declaration with a reference to the shared constant instead of a second DeviceVersion("2.8.0") literal.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt`
around lines 111 - 116, Consolidate the duplicated 2.8.0 firmware version by
keeping ChannelOption.kt’s FIRMWARE_2_8 as the shared source of truth and
removing the separate V2_8_0 DeviceVersion declaration in Capabilities.kt;
update Capabilities’ references to use FIRMWARE_2_8, with no direct change
required in ChannelOption.kt.
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt (1)

104-112: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mark the retained-but-unsupported region as disabled, matching buildPresetItems.

buildPresetItems explicitly appends the current illegal preset with enabled = false so the UI communicates it cannot be freely re-selected. buildRegionItems retains the current unsupported region (Line 110) but returns a plain Pair<RegionCode, String> with no way to convey it is disabled, so it appears as a normal, fully selectable dropdown entry. This can mislead the user into thinking the region is valid for the connected firmware.

Align the two patterns, for example by having the region dropdown consume DropDownItem as the preset dropdown does, and disabling the retained-but-unsupported entry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt`
around lines 104 - 112, Update buildRegionItems to return the same
DropDownItem-based type used by buildPresetItems, marking the selected region
disabled when capabilities.supportsRegion returns false while leaving supported
regions enabled. Update the region dropdown consumer to use this richer item
type so the retained unsupported selection is visibly non-selectable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt`:
- Around line 84-98: Update LoRaConfig.channelNum() so the overrideSlot branch
bounds or coerces the regional override to the current numChannels before
returning it. Preserve the existing channel_num priority, zero-channel behavior,
and hashed fallback, while ensuring the returned override-based channel is valid
for the selected preset.

---

Nitpick comments:
In `@core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt`:
- Around line 111-116: Consolidate the duplicated 2.8.0 firmware version by
keeping ChannelOption.kt’s FIRMWARE_2_8 as the shared source of truth and
removing the separate V2_8_0 DeviceVersion declaration in Capabilities.kt;
update Capabilities’ references to use FIRMWARE_2_8, with no direct change
required in ChannelOption.kt.

In
`@feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt`:
- Around line 104-112: Update buildRegionItems to return the same
DropDownItem-based type used by buildPresetItems, marking the selected region
disabled when capabilities.supportsRegion returns false while leaving supported
regions enabled. Update the region dropdown consumer to use this richer item
type so the retained unsupported selection is visibly non-selectable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a23fb99-5c9f-4779-89be-b7bb8769e75e

📥 Commits

Reviewing files that changed from the base of the PR and between c09bf1a and 6673cd1.

📒 Files selected for processing (6)
  • build-logic/settings-plugin/src/main/kotlin/MeshtasticDevelocitySettingsPlugin.kt
  • core/model/src/commonMain/kotlin/org/meshtastic/core/model/Capabilities.kt
  • core/model/src/commonMain/kotlin/org/meshtastic/core/model/ChannelOption.kt
  • core/model/src/commonTest/kotlin/org/meshtastic/core/model/CapabilitiesTest.kt
  • core/model/src/commonTest/kotlin/org/meshtastic/core/model/RegionInfoTest.kt
  • feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt

Remote cache writes were gated on CI plus a non-empty DEVELOCITY_ACCESS_KEY.
A same-repository pull request DOES receive repository secrets, so PR builds
were writing entries into the shared cache — unmerged code could serve results
to main.

Require GITHUB_EVENT_NAME to be push or merge_group as well. Cache population is
unaffected: main-check.yml (push to main) and merge-queue.yml (merge_group) are
both still trusted writers, and they are the runs whose outputs correspond to
code that actually landed. pull-request.yml becomes pull-only, which is what it
should have been.

Verified against a CI-shaped environment:

    CI=true GITHUB_EVENT_NAME=pull_request  -> pull-only
    CI=true GITHUB_EVENT_NAME=push          -> writes enabled
    CI=true GITHUB_EVENT_NAME=merge_group   -> writes enabled

Fork PRs have no key and are excluded twice over; local builds are excluded by
isCI.

This restores the protection the self-hosted HttpBuildCache had before #6531 —
it gated on GITHUB_EVENT_NAME and excluded pull_request. The same gap was found
and fixed across the six repos being onboarded now (meshtastic/kzstd#36 and
siblings); this brings android back in line.
@jamesarich
jamesarich force-pushed the fix/develocity-cache-push-gate branch from 6673cd1 to 7d3a6af Compare August 3, 2026 01:08
@jamesarich
jamesarich added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit 5a8994a Aug 3, 2026
15 checks passed
@jamesarich
jamesarich deleted the fix/develocity-cache-push-gate branch August 3, 2026 01:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix PR tag build Build system changes ci Pertains to ci/cd actions or workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant