Skip to content

feat(ccache-remote): parse password from DNS-SD TXT for redis backend#9864

Merged
iav merged 2 commits into
armbian:mainfrom
iav:feat/ccache-remote-password-discovery
May 21, 2026
Merged

feat(ccache-remote): parse password from DNS-SD TXT for redis backend#9864
iav merged 2 commits into
armbian:mainfrom
iav:feat/ccache-remote-password-discovery

Conversation

@iav

@iav iav commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Extend ccache_discover_remote_storage to consume an optional password=
    TXT record alongside type=redis (both avahi-browse and DNS-SRV branches).
    When present, embed it in the resulting CCACHE_REMOTE_STORAGE URL so
    ccache authenticates against requirepass-enabled backends discovered
    via mDNS without the user setting the URL manually.
  • Restrict the discovered password to RFC 3986 unreserved characters
    ([A-Za-z0-9._~-]) before interpolating it into the URL — any URL
    delimiter (/ : @ # ? = + space), the ccache attribute separator |,
    or the percent-encoding marker % would break parsing or AUTH-form
    disambiguation. Unsafe announces are skipped with a warning so discovery
    falls through to the next service (e.g. HTTP).
  • Drive-by fix: numfmt in do_with_ccache_statistics() (ccache.sh:103)
    was passing ccache_dir_size_diff as a positional argument without an
    option-terminator. When ccache cleanups during a build shrink the cache,
    the diff is negative and numfmt parses the leading dash as a short-option
    chain, exiting with invalid option -- '2'. The SUBSHELL trap then
    aborts the whole build right after a successful u-boot compile. Add --
    so the leading dash is treated as part of the numeric argument.

URL form rationale

Plain redis://<password>@<host>:<port>|... userinfo — no leading colon,
no username: prefix. Two other reasonable candidates break:

  • redis://:<password>@<host>:<port> — ccache 4.9.1 parses but silently
    never sends AUTH; backend rejects every command with NOAUTH.
  • redis://default:<password>@<host>:<port> — ccache sends the
    Redis-6 ACL two-arg AUTH default <password>, which KvRocks
    <= 2.15.0 rejects with ERR wrong number of arguments.

The chosen form sends the legacy one-arg AUTH <password> that both
Redis and KvRocks accept.

ccache_mask_storage_url already strips the userinfo, so the password
stays out of build logs:

DNS-SD: discovered Redis ccache  redis://****@m1:6666|connect-timeout=500

Test plan

Verified end-to-end with ./compile.sh uboot BOARD=helios64 BRANCH=edge USE_CCACHE=yes ENABLE_EXTENSIONS=ccache-remote ARTIFACT_IGNORE_CACHE=yes SHOW_CCACHE=yes against three redis-backend configurations on one LAN host:

  • KvRocks 2.15.0 (port 6666) with requirepass and avahi TXT
    password=<secret> — discovery finds it, AUTH succeeds inside docker,
    93 s build, Remote ccache result hit=0 miss=75 write=20 err=0.
  • redis-server 7.0 (port 6379) with runtime CONFIG SET requirepass
    and avahi TXT password=<secret> — same path, 81 s build,
    Remote ccache result hit=0 miss=53 write=8 err=0.
  • Native build (PREFER_DOCKER=no) against KvRocks — discovery
    runs from extension_prepare_config, AUTH succeeds, 1736 writes,
    err=0. (Surfaced the numfmt bug above, which this PR also fixes.)
  • redis-server without auth (no password= TXT) — backwards
    compatibility preserved, URL built without userinfo.
  • Announce with URL-unsafe password (e.g. bad:colon) — discovery
    warns and skips, falls through to advertised HTTP backend.

Commits

  1. feat(ccache-remote): parse password from DNS-SD TXT for redis backend
  2. fix(ccache): pass dir-size diff to numfmt past '--' to allow negatives

Summary by CodeRabbit

  • New Features

    • Discovery accepts an optional password for Redis and HTTP remote caches, validates it against a safe pattern, and embeds it into connection URLs when safe; legacy discovery remains used if unsafe.
    • Added DNS-SD/Avahi publication examples showing optional shared-secret password usage and an authenticated DNS SRV/TXT example.
  • Bug Fixes

    • Fixed cache-size formatting to handle values starting with a minus sign.
    • Improved parsing of Redis credentials for remote stats to accept user:pass, :pass, or bare-password forms.

Review Change Stack

@iav iav requested review from a team and igorpecovnik as code owners May 18, 2026 23:59
@iav iav requested review from tystuyfzand and removed request for a team May 18, 2026 23:59
@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds optional Redis/HTTP password discovery from DNS‑SD TXT/SRV records (validated against a URL-safe whitelist) and embeds safe passwords into generated backend URLs; extends Redis stats userinfo parsing to extract passwords from several userinfo forms; and adds an explicit -- to numfmt invocations.

Changes

Redis password support in DNS-SD discovery

Layer / File(s) Summary
Redis password feature documentation and DNS-SD browse discovery
extensions/ccache-remote/ccache-remote.sh
Documentation adds Avahi DNS‑SD examples with password=<secret> TXT. avahi-browse parsing now recognizes an optional password TXT key, validates it against a URL-safe whitelist ([A-Za-z0-9._~-]+), skips services with unsafe passwords, and embeds valid passwords into generated redis://... or http://:<password>@host:port... backend URLs (Redis includes connect-timeout).
DNS SRV/TXT discovery with password handling
extensions/ccache-remote/ccache-remote.sh
SRV/TXT resolution reads TXT records for an optional password, applies the same URL-safe validation, skips targets with unsafe passwords (allowing the legacy ccache.local fallback), and otherwise generates backend URLs with the password in userinfo for Redis and HTTP.
Redis stats userinfo parsing
extensions/ccache-remote/ccache-remote.sh
Stats collection parsing treats Redis URL userinfo as user:pass, :pass, or a bare password and extracts the password accordingly before invoking redis-cli.

ccache numfmt option parsing safety

Layer / File(s) Summary
numfmt end-of-options safety
lib/functions/compilation/ccache.sh
Adds an explicit -- marker before the numeric argument to numfmt when formatting ccache_dir_size_diff, preventing negative values from being parsed as options.

Sequence Diagram

sequenceDiagram
  participant Avahi as avahi-browse
  participant Discover as ccache_discover_remote_storage
  participant Validator as password_validator
  participant Builder as backend_url_builder
  participant RedisCLI as redis-cli
  Avahi->>Discover: advertise/browse service + TXT (password?)
  Discover->>Validator: extract TXT/TXT from SRV, validate [A-Za-z0-9._~-]+
  alt valid
    Validator->>Builder: provide password
    Builder->>Discover: produce backend URL (redis://<password>`@host`:port|connect-timeout=...)
    Discover->>RedisCLI: stats/operations using extracted password
  else invalid
    Validator-->>Discover: skip candidate (allow fallback)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit nudged the DNS night air,
Hid secrets safe in TXT lair,
Redis doors opened with a key,
numfmt learned to heed the dash,
Builds hopped forward, light and merry. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 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 main change: adding password parsing from DNS-SD TXT records for Redis backend discovery in ccache-remote.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@github-actions github-actions Bot added 05 Milestone: Second quarter release size/medium PR with more then 50 and less then 250 lines Needs review Seeking for review Framework Framework components labels May 18, 2026

@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: 2

🤖 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 `@extensions/ccache-remote/ccache-remote.sh`:
- Around line 274-277: The current check in ccache_discover_remote_storage()
treats an unsafe svc_password as fatal by calling "return 1", which aborts the
entire discovery and prevents Method 3 (ccache.local) from running; change this
to skip only the current SRV/TXT candidate (e.g., replace "return 1" with a
non-fatal control flow such as "continue" inside the SRV-processing loop or
otherwise proceed to the next candidate) so display_alert still runs but
discovery continues and ccache.local fallback remains reachable; keep the
svc_password check, keep display_alert, and ensure no other callers rely on this
function returning early for validation.
- Around line 198-219: The stats probe is not handling the new password-only
Redis URL form (redis://${svc_password}@...) so ccache_get_remote_stats() fails
to authenticate; update ccache_get_remote_stats() to parse the discovered
redis_url for a userinfo that may be just a password (no colon) and pass that
password to redis-cli (e.g., via -a/--pass or REDISCLI_AUTH) when present, while
preserving the existing behavior for user:pass and no-userinfo cases; look for
code that constructs/consumes redis_url and add a branch that detects the
^[^:]+@ pattern (password-only) and forwards that password to redis-cli during
the probe.
🪄 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

Run ID: 87559d7a-e7ce-48ad-8ca6-8fae043e751a

📥 Commits

Reviewing files that changed from the base of the PR and between 501dfca and 9c06c85.

📒 Files selected for processing (2)
  • extensions/ccache-remote/ccache-remote.sh
  • lib/functions/compilation/ccache.sh

Comment thread extensions/ccache-remote/ccache-remote.sh
Comment thread extensions/ccache-remote/ccache-remote.sh Outdated
@iav iav force-pushed the feat/ccache-remote-password-discovery branch 2 times, most recently from 9fcb3d6 to bfa6084 Compare May 20, 2026 07:01

@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

🤖 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 `@extensions/ccache-remote/ccache-remote.sh`:
- Around line 271-283: The validation that rejects non-whitelisted svc_password
currently runs for all SRV records; change it so the regex check is only
performed when svc_type == "redis" (i.e. gate the existing if [[ -n
"${svc_password}" && ! "${svc_password}" =~ ... ]] branch behind a check that
svc_type equals "redis"), leaving the HTTP branch untouched; update the logic
around svc_type, svc_password and the export of CCACHE_REMOTE_STORAGE (and keep
ccache_format_host_port usage) so HTTP records with a password= TXT key are not
skipped.
🪄 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

Run ID: 035cf8b2-8b5b-46dd-89aa-2e10014e6a90

📥 Commits

Reviewing files that changed from the base of the PR and between 9fcb3d6 and bfa6084.

📒 Files selected for processing (2)
  • extensions/ccache-remote/ccache-remote.sh
  • lib/functions/compilation/ccache.sh
✅ Files skipped from review due to trivial changes (1)
  • lib/functions/compilation/ccache.sh

Comment thread extensions/ccache-remote/ccache-remote.sh
@iav iav force-pushed the feat/ccache-remote-password-discovery branch from bfa6084 to 2433d21 Compare May 20, 2026 07:28
iav added 2 commits May 20, 2026 10:30
Extend ccache_discover_remote_storage to consume an optional `password=`
TXT record alongside `type=redis` (avahi-browse branch) and `type=redis`
DNS-SRV TXT (the dig branch). When present, embed it in the resulting
CCACHE_REMOTE_STORAGE URL so ccache authenticates against `requirepass`-
enabled backends discovered via mDNS or DNS-SD without the user having
to set CCACHE_REMOTE_STORAGE manually.

URL form: `redis://<password>@<host>:<port>|...` — plain userinfo with
no leading colon and no `username:` prefix. The other two reasonable
candidates both break:

  * `redis://:<password>@<host>:<port>` — ccache 4.9.1 parses but
    silently never sends AUTH; backend then rejects every command with
    `NOAUTH Authentication required`.
  * `redis://default:<password>@<host>:<port>` — ccache sends the
    Redis-6 ACL two-arg `AUTH default <password>`, which KvRocks
    <= 2.15.0 rejects with `ERR wrong number of arguments`.

The chosen form sends the legacy one-arg `AUTH <password>` that both
Redis and KvRocks accept.

ccache_mask_storage_url() already strips the userinfo, so the password
stays out of build logs:

    DNS-SD: discovered Redis ccache  redis://****@m1:6666|connect-timeout=500

Verified end-to-end on a KvRocks 2.15.0 instance behind avahi-publish-service
with `requirepass` and `password=<secret>` TXT: ccache logs
`Redis AUTH ********` followed by `Redis GET <key>`,
`remote_storage_error` is 0, and `remote_storage_write` increments on
miss.
@iav iav force-pushed the feat/ccache-remote-password-discovery branch from 2433d21 to 1d585ff Compare May 20, 2026 07:31

@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

🤖 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 `@extensions/ccache-remote/ccache-remote.sh`:
- Around line 271-280: The DNS TXT extraction currently uses txt_output and
assigns svc_password via the regex password=([^\"[:space:]]+), which stops at
the first space and yields truncated credentials; change the extraction so
svc_password captures the full quoted password (align with the Avahi branch) —
e.g., update the regex that reads from txt_output to capture the entire quoted
value for the password (so svc_password receives the full string) before the
RFC3986 whitelist check in the same function, leaving the subsequent validation
of svc_password against ^[A-Za-z0-9._~-]+$ unchanged so unsafe passwords will
correctly fall through to Method 3.
🪄 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

Run ID: 7328144f-4dde-466b-8ba8-47316e6aee34

📥 Commits

Reviewing files that changed from the base of the PR and between bfa6084 and 2433d21.

📒 Files selected for processing (2)
  • extensions/ccache-remote/ccache-remote.sh
  • lib/functions/compilation/ccache.sh

Comment thread extensions/ccache-remote/ccache-remote.sh

@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: 2

🤖 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 `@extensions/ccache-remote/ccache-remote.sh`:
- Around line 286-298: The code currently treats any non-"http" svc_type as
Redis; change the conditional so only svc_type == "redis" sets
CCACHE_REMOTE_STORAGE to a redis:// URL (using svc_password, host_port and
CCACHE_REDIS_CONNECT_TIMEOUT as before) and let any other svc_type fall through
(do not export CCACHE_REMOTE_STORAGE or return 0); update the branch that calls
display_alert and return to only run when a supported type was handled (i.e.,
after the http and explicit "redis" branches), referencing the svc_type
variable, the CCACHE_REMOTE_STORAGE export, the ccache_mask_storage_url call and
display_alert to locate the logic to modify.
- Around line 368-374: The stats probe currently discards the ACL username by
parsing userinfo into only password (variables userinfo and password); update
the parser to also extract a username variable (e.g., username="${userinfo%%:*}"
when userinfo contains a colon, and default to empty or omit otherwise) and
ensure the stats probe invocation of redis-cli includes the --user "$username"
flag when username is non-empty so ACL-backed Redis hosts authenticate
correctly; keep existing password extraction logic for legacy bare-password
forms and only supply --user when a username was present.
🪄 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

Run ID: 4c5eaefc-3b06-4676-95c8-fe0017c2ca9a

📥 Commits

Reviewing files that changed from the base of the PR and between 2433d21 and 1d585ff.

📒 Files selected for processing (2)
  • extensions/ccache-remote/ccache-remote.sh
  • lib/functions/compilation/ccache.sh
✅ Files skipped from review due to trivial changes (1)
  • lib/functions/compilation/ccache.sh

Comment thread extensions/ccache-remote/ccache-remote.sh
Comment thread extensions/ccache-remote/ccache-remote.sh

@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.

♻️ Duplicate comments (1)
extensions/ccache-remote/ccache-remote.sh (1)

286-299: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Unknown type= values are silently treated as Redis.

A typo like type=redsi in the TXT record would set svc_type="redsi" (line 265-266), fail the == "http" check, and fall through to generate a Redis URL. This could cause confusing runtime failures instead of a clear warning.

Consider adding explicit svc_type == "redis" checks and warning/falling through for unknown types:

🔧 Suggested fix
 				if [[ "${svc_type}" == "http" ]]; then
 					if [[ -n "${svc_password}" ]]; then
 						export CCACHE_REMOTE_STORAGE="http://:${svc_password}@${host_port}${svc_path}"
 					else
 						export CCACHE_REMOTE_STORAGE="http://${host_port}${svc_path}"
 					fi
-				elif [[ -n "${svc_password}" ]]; then
+				elif [[ "${svc_type}" == "redis" && -n "${svc_password}" ]]; then
 					export CCACHE_REMOTE_STORAGE="redis://${svc_password}@${host_port}|connect-timeout=${CCACHE_REDIS_CONNECT_TIMEOUT}"
-				else
+				elif [[ "${svc_type}" == "redis" ]]; then
 					export CCACHE_REMOTE_STORAGE="redis://${host_port}|connect-timeout=${CCACHE_REDIS_CONNECT_TIMEOUT}"
+				else
+					display_alert "DNS SRV: unsupported service type — skipping" \
+						"_ccache._tcp.${CCACHE_REMOTE_DOMAIN} type=${svc_type}" "wrn"
 				fi
-				display_alert "DNS SRV: discovered ccache" "$(ccache_mask_storage_url "${CCACHE_REMOTE_STORAGE}")" "info"
-				return 0
+				if [[ -n "${CCACHE_REMOTE_STORAGE}" ]]; then
+					display_alert "DNS SRV: discovered ccache" "$(ccache_mask_storage_url "${CCACHE_REMOTE_STORAGE}")" "info"
+					return 0
+				fi
🤖 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 `@extensions/ccache-remote/ccache-remote.sh` around lines 286 - 299, The
current branch treats any non-"http" svc_type as Redis and silently builds
CCACHE_REMOTE_STORAGE, so typos like svc_type="redsi" go unnoticed; update the
conditional logic around svc_type (the block that sets CCACHE_REMOTE_STORAGE and
calls display_alert/return) to explicitly check for svc_type == "redis" (in
addition to "http"), only construct a Redis URL when svc_type == "redis", and
otherwise emit a clear warning/error (use display_alert with the masked URL via
ccache_mask_storage_url or a descriptive message) and return a failure code or
skip setting CCACHE_REMOTE_STORAGE so unknown types do not silently fall back to
Redis.
🤖 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.

Duplicate comments:
In `@extensions/ccache-remote/ccache-remote.sh`:
- Around line 286-299: The current branch treats any non-"http" svc_type as
Redis and silently builds CCACHE_REMOTE_STORAGE, so typos like svc_type="redsi"
go unnoticed; update the conditional logic around svc_type (the block that sets
CCACHE_REMOTE_STORAGE and calls display_alert/return) to explicitly check for
svc_type == "redis" (in addition to "http"), only construct a Redis URL when
svc_type == "redis", and otherwise emit a clear warning/error (use display_alert
with the masked URL via ccache_mask_storage_url or a descriptive message) and
return a failure code or skip setting CCACHE_REMOTE_STORAGE so unknown types do
not silently fall back to Redis.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8b323d23-6fea-4d5d-8521-0a3f22a077e6

📥 Commits

Reviewing files that changed from the base of the PR and between 2433d21 and 1d585ff.

📒 Files selected for processing (2)
  • extensions/ccache-remote/ccache-remote.sh
  • lib/functions/compilation/ccache.sh

@github-actions github-actions Bot added the Ready to merge Reviewed, tested and ready for merge label May 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ This PR has been reviewed and approved — all set for merge!

@github-actions github-actions Bot removed the Needs review Seeking for review label May 21, 2026
@iav iav merged commit e8b4906 into armbian:main May 21, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

05 Milestone: Second quarter release Framework Framework components Ready to merge Reviewed, tested and ready for merge size/medium PR with more then 50 and less then 250 lines

Development

Successfully merging this pull request may close these issues.

2 participants