Skip to content

luci-app-attendedsysupgrade: add uci-defaults script support#8703

Open
firlin123 wants to merge 3 commits into
openwrt:masterfrom
firlin123:luci-app-attendedsysupgrade-defaults
Open

luci-app-attendedsysupgrade: add uci-defaults script support#8703
firlin123 wants to merge 3 commits into
openwrt:masterfrom
firlin123:luci-app-attendedsysupgrade-defaults

Conversation

@firlin123

@firlin123 firlin123 commented Jun 14, 2026

Copy link
Copy Markdown

Pull request details

Description

Added the ability to specify uci-defaults script (defaults field in request to ASU) to be sent to ASU server during firmware generation.

Note: This is my first PR ever and I'm an ESL speaker. Let me know if changes are needed!

Screenshot or video of changes (if applicable)

Configuration tab screenshot:
Screenshot_20260615_211510

Upgrade modal screenshot:
Screenshot_20260614_052231

Warning in upgrade modal screenshot:
Screenshot_20260615_211324


Tested on

Board: Raspberry Pi Compute Module 4 (bcm27xx/bcm2711)
OpenWrt version: OpenWrt 25.12.2 (r32802-f505120278) and 25.12.4 (r32933-4ccb782af7)
LuCI version: LuCI openwrt-25.12 branch (26.158.67103e99e132) and LuCI openwrt-25.12 branch (26.163.740245476212)
Web browser(s): Brave 1.90.121 (Official Build) (64-bit), Chromium: 148.0.7778.96


Checklist

  • This PR is not from my main or master branch 💩, but a separate branch. ✅
  • Each commit has a valid ✒️ Signed-off-by: <my@email.address> row (via git commit --signoff).
  • Each commit and PR title has a valid 📝 <package name>: title first line subject for packages.
  • Incremented 🆙 any PKG_VERSION in the Makefile.
  • (Optional) Includes what Issue it closes (e.g. openwrt/luci#issue-number).
  • (Optional) Includes what it depends on (e.g. openwrt/packages#pr-number in sister repo).

@github-actions

This comment has been minimized.

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the single new commit. The change is well-scoped: the new 40_luci-attendedsysupgrade uci-defaults script matches the established cache-clear/rpcd-reload convention used by other luci apps, the rpcd ucode get_defaults method (fs.stat/fs.readfile, size cap) is correct API usage, the ACL entry is wired to the new method, and the defaults field is correctly omitted from the build request when unset. Two minor inline notes below (trailing whitespace; silent rejection of oversized/invalid files). The commit message line-length warning is already reported by the formality bot.


Generated by Claude Code

@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from 1888178 to d5eb355 Compare June 14, 2026 11:42
Allow users to specify a custom first-boot script (uci-defaults) to be
included in the firmware build request to the ASU server.

Signed-off-by: Vladislav Pereyaslov <firlin123@gmail.com>
@github-actions

This comment has been minimized.

Introduce dedicated error codes for uci-defaults script handling to display
explicit frontend warnings if the file is missing, empty, or exceeds the
40 KiB ASU server limit.

Signed-off-by: Vladislav Pereyaslov <firlin123@gmail.com>
@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from d5eb355 to d4e5e16 Compare June 14, 2026 15:53
};
}
// Enforce the 40 KiB official ASU server limit
if (st.size > 40960) {

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.

You can't hard code this number as it varies between servers and can change arbitrarily even on the "official" upstream. You need to fetch it from the server limits: curl https://sysupgrade.openwrt.org/json/v1/overview.json | jsonfilter -e '$.server.max_defaults_length'

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed the hard-coded number and now using server's max_defaults_length in the latest commit.

const ERR_FILE_TOO_BIG = 3;

function get_defaults() {
const path = uci.cursor().get("attendedsysupgrade", "client", "defaults_path");

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.

This value is already in the config in attendedsysupgrade.owut.init_script. See https://openwrt.org/docs/guide-user/installation/sysupgrade.owut#using_a_uci-defaults_script

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I was not aware that a config for this already existed. Switched to using attendedsysupgrade.owut.init_script in the latest commit.

profile,
version: candidates[0][0],
packages: Object.keys(packages).sort(),
defaults_checked: '1'

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.

Shouldn't this be a bool?

@firlin123 firlin123 Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I tried making it bool but the form.Flag only accepts "1" and 1 (which it type-coerces to "1" anyway).

form.Value,
'defaults_path',
_('Defaults file path'),
_('Specify the path to your first-boot script (e.g., <code>/rom/etc/uci-defaults/99-asu-defaults</code> inserted by the Firmware Selector.)')

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.

If no config value exists, but the /rom/.../99-asu-defaults file exists, this field should auto-populate with the existing file path.

@firlin123 firlin123 Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Because I switched to attendedsysupgrade.owut.init_script as you suggested, I don't control the defaults of this config anymore, owut does.

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed 1 new commit (d4e5e16 "improve uci-defaults validation"); no new issues found.

The new commit cleanly addresses both notes from my prior review: oversized/invalid/empty files now surface an explicit alert-message warning instead of silently dropping the option, and the trailing whitespace is gone. The ucode error-code handling (fs.stat type/size checks, length(trim(contents)) emptiness check) is correct, the expect/resolveDefault defaults were updated consistently, and the commit message matches the diff. Wrapping data.defaults_path in E('code', {}, ...).outerHTML also correctly escapes the path before it reaches innerHTML.

The substantive open points (hardcoded 40 KiB limit vs. the server's max_defaults_length, reuse of attendedsysupgrade.owut.init_script, the bool question, and path auto-population) are already covered in @efahl's inline comments on this head, so I won't duplicate them.


Generated by Claude Code

@github-actions

This comment has been minimized.

@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from 33b9e93 to 1327ff7 Compare June 15, 2026 03:00

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed 1 new commit (1327ff7 "switch to owut config and server-driven limits"). The switch to attendedsysupgrade.owut.init_script and the server-supplied max_defaults_length correctly addresses @efahl's earlier notes, and the new ERR_EMPTY_FILE/ERR_SERVER_FAILED/ERR_INIT_DISALLOWED error paths are wired consistently between the rpcd ucode and the frontend. One inline note on a TypeError reachable when the overview request rejects for a SNAPSHOT device.


Generated by Claude Code

@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from 1327ff7 to c5482d5 Compare June 15, 2026 08:46

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed 1 new commit (c5482d5, replacing the previously-reviewed 1327ff7); no new issues found.

The only delta since my last review is the overview.js refactor that hoists init_script_path out of the branches and guards results[0] with optional chaining (results[0]?.ok). This correctly addresses the TypeError I flagged previously: when the overview request rejects (e.g. for a SNAPSHOT device), results[0] is the resolveDefault fallback rather than a response object, and ?.ok now yields nullserver_info = nullERR_SERVER_FAILED. The added typeof server_info.max_defaults_length !== 'number' check also avoids passing NaN into callGetInitScript(Math.floor(...)) when the server advertises allow_defaults without a numeric limit. The commit subject (75 chars) and message match the diff, and Test Formalities now passes on this head.


Generated by Claude Code

@firlin123 firlin123 requested a review from efahl June 16, 2026 05:42
@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from c5482d5 to 4311997 Compare June 23, 2026 17:56
@firlin123

firlin123 commented Jun 23, 2026

Copy link
Copy Markdown
Author

Fixed eslint no-case-declarations error in the latest force push

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the force-pushed head (4311997e, replacing the previously-reviewed c5482d5); no new issues found.

The only delta since my last review is wrapping the default: case body in overview.js (handleCheck's switch (init_script_error)) in a block { }. This correctly resolves the eslint no-case-declarations error caused by the lexical declarations (let msg, let alertBox, const kib) in that case, with no behavioral change. The reworded third commit subject is now 75 chars and matches its diff.


Generated by Claude Code

@@ -61,6 +66,22 @@ return view.extend({
o.default = '0';
o.rmempty = false;

// For now, only display if the owut section exists in uci (owut installed or section is manually added).
// We should probably move init script path from attendedsysupgrade.owut.init_script to some common place

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.

Yeah, too late now. That would require a significant rewrite of how owut gather's uci default values, and corresponding upgrade scripting, so not going to happen. LuCI already grabs another owut value (rootfs_size), and will always be a second class citizen compared to the far-more-capable owut.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

So should we not display that config at all and only make it configurable via cli (like the owut.rootfs_size)? Or just remove the "for now" phrasing from the comment?

#!/bin/sh
rm -rf /var/luci-modulecache/; rm -f /var/luci-indexcache;
[ -x /etc/init.d/rpcd ] && /etc/init.d/rpcd reload
exit 0

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.

Why is this whole file here? The tmp directories are deleted on reboot, and the rpcd reloading isn't anything that attended sysupgrade should care about.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I honestly don't know. I just looked at other luci apps with ucode rpcd service and they all seem to have this file so I copied it here too. Is it not needed in this case?

return {
contents: "",
path: path,
error: ERR_EMPTY_FILE

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.

If people want to include an empty placeholder script, I don't see any reason to disallow that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Allowed empty files in latest revision.

@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from 4311997 to 83ae949 Compare June 24, 2026 18:10
…limits

Reuse exiting 'owut.init_script' instead of separate 'client.defaults_path'.
Use ASU server's 'max_defaults_length' instead of hardcoded 40 KiB limit.

Signed-off-by: Vladislav Pereyaslov <firlin123@gmail.com>
@firlin123 firlin123 force-pushed the luci-app-attendedsysupgrade-defaults branch from 83ae949 to ae849bc Compare June 24, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants