Skip to content

Conversation

@leggewie
Copy link
Contributor

@leggewie leggewie commented Dec 16, 2025

another carve-out from #9000

Apparently, it might be advantageous / necessary to add a hook to the framework to allow for customization of the rootfs just after debootstrap has done its thing. Now, this is certainly way ahead of my comprehension so I add this here only as an RFD to see if this would be a step in the right direction and if I got anything completely wrong.

  • is this in about the right place in terms of sequence
  • is this a good choice of naming for the hook
  • anything to expand in terms of hook description
  • ....

this is completely untested as of now.

Summary by CodeRabbit

  • New Features
    • Introduced a new customization extension point in the build pipeline for enhanced flexibility.

✏️ Tip: You can customize this high-level summary in your review settings.

@leggewie leggewie requested a review from a team as a code owner December 16, 2025 05:39
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

Walkthrough

A new extension hook post_debootstrap_customize is introduced in the rootfs creation process. This hook is invoked after desktop package installation and before MD5 checksum verification, providing an optional customization point for the build pipeline.

Changes

Cohort / File(s) Change Summary
Rootfs Customization Hook
lib/functions/rootfs/rootfs-create.sh
Adds post_debootstrap_customize extension hook invocation in the rootfs creation flow after the debootstrap and desktop package installation phases

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

  • Single line addition with minimal logic density
  • Hook invocation follows established extension pattern
  • No error handling or control flow changes

Poem

🐰 A hook finds its home in the rootfs flow,
Post-debootstrap magic, customization's glow,
Before checksums dance and files align,
Extension points now let builders refine!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main change: adding a post-debootstrap hook to the rootfs-create script.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 size/small PR with less then 50 lines 02 Milestone: First quarter release Needs review Seeking for review Framework Framework components labels Dec 16, 2025
@leggewie leggewie marked this pull request as draft December 16, 2025 05:39
@leggewie leggewie changed the title lib / rootfs-create: add post-debootstrap hook [RFD] lib / rootfs-create: add post-debootstrap hook Dec 16, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (1)
lib/functions/rootfs/rootfs-create.sh (1)

304-305: Expand the hook description for extension developers.

The current description is brief. Consider documenting the rootfs state and available resources to help extension developers understand what operations are safe and supported at this hook point.

Apply this diff to provide more context:

 	call_extension_method "post_debootstrap_customize" <<- 'POST_DEBOOTSTRAP_CUSTOMIZE'
-		allow customization of rootfs after debootstrap has completed
+		Customize the rootfs after debootstrap and all package installations.
+		At this point: chroot is mounted, qemu binary is deployed, all main and desktop packages are installed.
+		Use this hook for modifications requiring a working chroot environment before cleanup operations begin.
 	POST_DEBOOTSTRAP_CUSTOMIZE
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f2dd38e and fd9dc5c.

📒 Files selected for processing (1)
  • lib/functions/rootfs/rootfs-create.sh (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: In lib/functions/rootfs/rootfs-create.sh, the FIXME comment about mmdebstrap usage with --aptopt is a future note related to PR #8785, which hasn't been merged yet.
Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: The `debootstrap` tool doesn't use `apt`, which is important context when reviewing apt-related configuration in rootfs creation code.
Learnt from: EvilOlaf
Repo: armbian/build PR: 8211
File: extensions/linux-source-package.sh:7-10
Timestamp: 2025-05-21T06:04:48.711Z
Learning: In the Armbian build system's extension framework, function names follow the pattern `hook_point__unique_identifier()`. The part before `__` defines when in the build process the function is executed (the hook point), while the part after `__` is just a unique identifier and doesn't need to match the extension name. Functions with the same hook point are executed in alphanumerical order.
📚 Learning: 2025-10-24T04:46:22.901Z
Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: In lib/functions/rootfs/rootfs-create.sh, the FIXME comment about mmdebstrap usage with --aptopt is a future note related to PR #8785, which hasn't been merged yet.

Applied to files:

  • lib/functions/rootfs/rootfs-create.sh
📚 Learning: 2025-10-24T04:46:22.901Z
Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: The `debootstrap` tool doesn't use `apt`, which is important context when reviewing apt-related configuration in rootfs creation code.

Applied to files:

  • lib/functions/rootfs/rootfs-create.sh

Comment on lines +303 to +306
# customization hook after debootstrap phase
call_extension_method "post_debootstrap_customize" <<- 'POST_DEBOOTSTRAP_CUSTOMIZE'
allow customization of rootfs after debootstrap has completed
POST_DEBOOTSTRAP_CUSTOMIZE
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 16, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for call_extension_method patterns and read context around lines 303-306
rg -n "call_extension_method" lib/functions/rootfs/rootfs-create.sh -A 2 -B 2

Repository: armbian/build

Length of output: 300


🏁 Script executed:

# Also read the specific lines mentioned in the review
sed -n '280,370p' lib/functions/rootfs/rootfs-create.sh | cat -n

Repository: armbian/build

Length of output: 5423


Hook placement is appropriate; verify with test implementation.

The hook is correctly positioned after all package installations and while the chroot is still mounted (line 365 for unmount). This provides a functional environment for rootfs customization before cleanup operations begin (autoremove at line 330, qemu undeploy at line 357).

Since this is completely untested, verify by:

  • Creating a test extension implementing post_debootstrap_customize__test_hook
  • Confirming the chroot environment is accessible for customization operations
  • Validating that changes persist through cleanup and final image creation
🤖 Prompt for AI Agents
In lib/functions/rootfs/rootfs-create.sh around lines 303 to 306, the new
post_debootstrap_customize hook is placed correctly but untested; add a small
test extension named post_debootstrap_customize__test_hook that runs inside the
chroot (e.g., creates a marker file and modifies a simple config), run the full
create flow to ensure the chroot is writeable and the marker persists after
autoremove/qemu-undeploy and final image creation, and update CI or local test
script to execute this test extension and assert the marker file exists in the
final rootfs image; if the marker is not present, adjust hook invocation context
(mount/chroot environment variables, bind-mounts, or call_extension_method
invocation) so the hook runs with the same chroot environment used for package
installs.

Copy link
Collaborator

Choose a reason for hiding this comment

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

fwiw this concept has been tested [but not this specific code] in #9000.
So yes, it should be tested to be sure there isn't a trivial error, but the concept and placement is reasonably solid.

Copy link
Contributor

Choose a reason for hiding this comment

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

@tabrisnet, thank you for the clarification! It's reassuring to know that the concept and placement have been validated through testing in PR #9000. That gives much more confidence in the approach.

Given that context, my recommendation shifts to simply verifying the specific implementation details here—checking for any trivial errors like typos in the hook name, ensuring the heredoc syntax is correct, and confirming the hook is callable from extensions. A quick smoke test with a minimal extension implementing post_debootstrap_customize__test_hook should be sufficient to validate this specific code works as expected.

The placement after package installations and before cleanup operations is indeed the right spot for rootfs customization.


✏️ Learnings added
Learnt from: tabrisnet
Repo: armbian/build PR: 9085
File: lib/functions/rootfs/rootfs-create.sh:303-306
Timestamp: 2025-12-16T12:22:12.924Z
Learning: The post_debootstrap_customize hook concept in lib/functions/rootfs/rootfs-create.sh has been tested in PR #9000. The hook placement after package installations (including desktop packages) and before cleanup operations (autoremove, qemu undeploy) is validated as appropriate for rootfs customization.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: In lib/functions/rootfs/rootfs-create.sh, the FIXME comment about mmdebstrap usage with --aptopt is a future note related to PR #8785, which hasn't been merged yet.

Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: The `debootstrap` tool doesn't use `apt`, which is important context when reviewing apt-related configuration in rootfs creation code.

Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-12-13T23:44:04.995Z
Learning: In lib/functions/rootfs/rootfs-create.sh, the schedule_deletion for /var/lib/dbus/machine-id is necessary because: (1) the file is created by the dbus package during installation, (2) package installation timing varies during the build process and is being actively worked on, (3) scheduling the deletion ensures it's removed at the end regardless of when the package gets installed, (4) the file must not exist on first-boot so the system generates a fresh machine-id.

Learnt from: leggewie
Repo: armbian/build PR: 8133
File: extensions/apa.sh:1-2
Timestamp: 2025-04-28T08:27:26.890Z
Learning: In the Armbian build system, extension scripts in the `extensions/` directory contain hook functions and are meant to be sourced, not executed directly. These scripts don't require a shebang or `set -euo pipefail`.

Learnt from: EvilOlaf
Repo: armbian/build PR: 8211
File: extensions/linux-source-package.sh:7-10
Timestamp: 2025-05-21T06:04:48.711Z
Learning: In the Armbian build system's extension framework, function names follow the pattern `hook_point__unique_identifier()`. The part before `__` defines when in the build process the function is executed (the hook point), while the part after `__` is just a unique identifier and doesn't need to match the extension name. Functions with the same hook point are executed in alphanumerical order.

@leggewie leggewie mentioned this pull request Dec 16, 2025
8 tasks
@leggewie
Copy link
Contributor Author

leggewie commented Dec 16, 2025

  • is this in about the right place in terms of sequence
  • is this a good choice of naming for the hook
  • anything to expand in terms of hook description
  • ....

Thank you, @tabrisnet for the confirmation. Do you have anything to add in terms of above questions or something else to take into consideration? The implementation of the hook is slightly different to what you had in #9000

@leggewie leggewie marked this pull request as ready for review December 17, 2025 03:19
@EvilOlaf EvilOlaf removed their request for review December 17, 2025 04:59
@leggewie
Copy link
Contributor Author

function post_debootstrap_customize__testcall() {
       display_alert "newly introduced _postdebootstrap_customize hook called successfully" "${EXTENSION}" "info"
}

https://paste.armbian.com/fixejefawa

I cannot confirm that the hook is actually called. I used above snippet in extensions/apa.sh but grepping the log for 'newly' returns nothing.

@tabrisnet
Copy link
Collaborator

function post_debootstrap_customize__testcall() {
       display_alert "newly introduced _postdebootstrap_customize hook called successfully" "${EXTENSION}" "info"
}

https://paste.armbian.com/fixejefawa

I cannot confirm that the hook is actually called. I used above snippet in extensions/apa.sh but grepping the log for 'newly' returns nothing.

You may need to delete cache/rootfs/* or make some significant change so that cached rootfs tarballs aren't available. I see no call to mmdebstrap in your log.
You can always use ARTIFACT_IGNORE_CACHE=yes, but that will of course make you build everything.
OTOH... this hook should be called if you change from build to artifact WHAT=rootfs

@tabrisnet
Copy link
Collaborator

  • is this a good choice of naming for the hook
  • anything to expand in terms of hook description
  • ....

Thank you, @tabrisnet for the confirmation. Do you have anything to add in terms of above questions or something else to take into consideration? The implementation of the hook is slightly different to what you had in #9000

the name matches the existing patterns, but I'm a bit concerned over the other post_debootstrap_ hook name. how does the meaning/semantics of the words tweaks vs customize differ? worse, and this of course isn't your fault, post_debootstrap_tweaks happens extremely late in the rootfs process & our hook happens right after mmdebstrap runs.
let's see if @coderabbitai has anything useful to contribute.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 17, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find where post_debootstrap_tweaks is called
echo "=== Searching for post_debootstrap_tweaks hook ==="
rg -n "post_debootstrap_tweaks" -A 5 -B 5

echo -e "\n=== Searching for the new post_debootstrap_customize hook ==="
rg -n "post_debootstrap_customize" -A 5 -B 5

echo -e "\n=== Getting the full context of rootfs-create.sh to understand the sequence ==="
cat lib/functions/rootfs/rootfs-create.sh | head -400

Length of output: 24923


@tabrisnet, great catch on the naming confusion! After examining the code, I can see the issue clearly: both hooks have post_debootstrap_ prefixes but occur at vastly different stages of the build process.

The Temporal Problem

post_debootstrap_customize (new hook):

  • Runs during rootfs cache creation in create_new_rootfs_cache_via_debootstrap()
  • Called after all package installations (base + desktop packages)
  • Called while chroot is still mounted and QEMU is still deployed
  • Happens before the rootfs is packed into a cache tarball

post_debootstrap_tweaks (existing):

  • Runs during image creation phase in lib/functions/main/rootfs-image.sh
  • Called after the cached rootfs has been extracted for image building
  • Much later in the overall build sequence - it's not really "post-debootstrap" anymore

Naming Suggestions

The semantic difference between "tweaks" vs "customize" doesn't address the real issue - the temporal separation. Consider these alternatives:

For the new hook (currently post_debootstrap_customize):

  • pre_cache_rootfs - clearly indicates it runs before caching
  • post_packages_install - emphasizes it's after package installation phase
  • customize_cached_rootfs - shows it modifies what will be cached

For the existing hook (currently post_debootstrap_tweaks):

  • post_rootfs_extract - reflects that it runs after cache extraction
  • pre_image_finalize - indicates it's in the image creation phase
  • Keep the name but improve documentation to clarify timing

Recommendation

I'd suggest renaming the new hook to something like pre_cache_rootfs or post_packages_rootfs to make it clear this is the last customization point before the rootfs is cached. This would eliminate confusion with the much-later post_debootstrap_tweaks.

Would you like me to search for any documentation or usage patterns of similar hooks in the codebase to ensure consistency?


🧠 Learnings used
Learnt from: tabrisnet
Repo: armbian/build PR: 9085
File: lib/functions/rootfs/rootfs-create.sh:303-306
Timestamp: 2025-12-16T12:22:12.924Z
Learning: The post_debootstrap_customize hook concept in lib/functions/rootfs/rootfs-create.sh has been tested in PR #9000. The hook placement after package installations (including desktop packages) and before cleanup operations (autoremove, qemu undeploy) is validated as appropriate for rootfs customization.

Learnt from: EvilOlaf
Repo: armbian/build PR: 8211
File: extensions/linux-source-package.sh:7-10
Timestamp: 2025-05-21T06:04:48.711Z
Learning: In the Armbian build system's extension framework, function names follow the pattern `hook_point__unique_identifier()`. The part before `__` defines when in the build process the function is executed (the hook point), while the part after `__` is just a unique identifier and doesn't need to match the extension name. Functions with the same hook point are executed in alphanumerical order.

Learnt from: tabrisnet
Repo: armbian/build PR: 0
File: :0-0
Timestamp: 2025-10-24T04:46:22.901Z
Learning: In lib/functions/rootfs/rootfs-create.sh, the FIXME comment about mmdebstrap usage with --aptopt is a future note related to PR #8785, which hasn't been merged yet.

Copy link
Member

@rpardini rpardini left a comment

Choose a reason for hiding this comment

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

While this is in principle OK, hooks implementing it will need to be hashed into the rootfs artifact_version, otherwise it becomes inconsistent.

@tabrisnet
Copy link
Collaborator

While this is in principle OK, hooks implementing it will need to be hashed into the rootfs artifact_version, otherwise it becomes inconsistent.

I think this understates the problem. what things it does need to be inserted into the hash. not just the pkg names but also pkg versions and/or the dependencies that it pulls in.
Which btw isn't strictly a component of this PR, but rather the actual hook functions.

@tabrisnet
Copy link
Collaborator

so looking a bit deeper, we need another hook that must be used hand-in-hand.
lib/functions/rootfs/create-cache.sh
we need a hook in calculate_rootfs_cache_id that spits out all of the packages we will install, so it can be added to either packages_hash or extension_hooks_hashed

@tabrisnet
Copy link
Collaborator

proposal for new hook in create-cache.sh: 1cb0a8a
rootfs_customize_package_list
NOTE: name isn't final.

@leggewie
Copy link
Contributor Author

leggewie commented Dec 18, 2025

I think this understates the problem. what things it does need to be inserted into the hash. not just the pkg names but also pkg versions and/or the dependencies that it pulls in.

Frankly, this whole caching mechanism sounds super-fragile and prone to error. I touch one file somewhere in the rootfs and that likely doesn't invalidate the cache when it should. This appears to be a bug in the current implementation. Of course, it doesn't help there is essentially no documentation.

What are the inputs to the hash? Does the rootfs filelist go in it?

@tabrisnet
Copy link
Collaborator

tabrisnet commented Dec 18, 2025 via email

@leggewie
Copy link
Contributor Author

leggewie commented Dec 18, 2025

Please write some. Note: I've learned that the best documentation can come from someone who starts out knowing the least about it, because they lack presuppositions/foreknowledge. It's also a great way for said person to learn.

I certainly agree.

I still wonder what inputs go into the hash and in particular if the filelist is part of it. Because if it's not, I think it probably should. It appears that currently the burden is on the defined process and the hooks to "not forget to define and provide" valid input for the hashing while the filelist would be something that can be easily and automatically collected.

Having a cache miss is less of a problem than having a cache hit when actually the artifact isn't truly identical. So, I'm more concerned about that as it creates a nightmare down the line.

@tabrisnet
Copy link
Collaborator

I still wonder what inputs go into the hash and in particular if the filelist is part of it

lib/functions/rootfs/create-cache.sh
is what creates the hashes for rootfs.
there is some more grepping/chasing to get the full picture, but this is where to start in any case.

Note that you may need to be specific as to what you mean by "filelist"

@rpardini
Copy link
Member

Why don't you stop speculating and read the code? it's all there.

@rpardini
Copy link
Member

I'm also unsubscribing from this PR, as I don't have the mental health to spare.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

02 Milestone: First quarter release Framework Framework components Needs review Seeking for review size/small PR with less then 50 lines

Development

Successfully merging this pull request may close these issues.

3 participants