refactor(handlers): address CodeRabbit findings from first-boot fixes
- commit
- 3ee469f8b48f6f153e0322058c1e91d97f9016a6
- author
- brice · · 2026-03-02 06:13 UTC
- parent
- e32ab76
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
5 files · +13 -7
M install/mandatory/post-boot/all.sh +3 -3
| @@ -82,11 +82,11 @@ fi | |||
| 82 | 82 | ||
| 83 | 83 | # Install modern CLI toolkit | |
| 84 | 84 | if [ -f /usr/local/share/archup/post-boot/cli-tools.sh ]; then | |
| 85 | - | echo "Installing modern CLI toolkit..." | tee -a "$LOG_FILE" | |
| 85 | + | echo "Installing modern CLI toolkit..." >> "$LOG_FILE" | |
| 86 | 86 | if bash /usr/local/share/archup/post-boot/cli-tools.sh >> "$LOG_FILE" 2>&1; then | |
| 87 | - | echo "[OK] CLI tools installed" | tee -a "$LOG_FILE" | |
| 87 | + | echo "[OK] CLI tools installed" >> "$LOG_FILE" | |
| 88 | 88 | else | |
| 89 | - | echo "[KO] CLI tools installation failed (non-critical)" | tee -a "$LOG_FILE" | |
| 89 | + | echo "[KO] CLI tools installation failed (non-critical)" >> "$LOG_FILE" | |
| 90 | 90 | fi | |
| 91 | 91 | fi | |
| 92 | 92 | ||
| @@ -82,11 +82,11 @@ fi | |||||
| 82 | 82 | ||||
| 83 | # Install modern CLI toolkit | 83 | # Install modern CLI toolkit | ||
| 84 | if [ -f /usr/local/share/archup/post-boot/cli-tools.sh ]; then | 84 | if [ -f /usr/local/share/archup/post-boot/cli-tools.sh ]; then | ||
| 85 | - | echo "Installing modern CLI toolkit..." | tee -a "$LOG_FILE" | 85 | + | echo "Installing modern CLI toolkit..." >> "$LOG_FILE" |
| 86 | if bash /usr/local/share/archup/post-boot/cli-tools.sh >> "$LOG_FILE" 2>&1; then | 86 | if bash /usr/local/share/archup/post-boot/cli-tools.sh >> "$LOG_FILE" 2>&1; then | ||
| 87 | - | echo "[OK] CLI tools installed" | tee -a "$LOG_FILE" | 87 | + | echo "[OK] CLI tools installed" >> "$LOG_FILE" |
| 88 | else | 88 | else | ||
| 89 | - | echo "[KO] CLI tools installation failed (non-critical)" | tee -a "$LOG_FILE" | 89 | + | echo "[KO] CLI tools installation failed (non-critical)" >> "$LOG_FILE" |
| 90 | fi | 90 | fi | ||
| 91 | fi | 91 | fi | ||
| 92 | 92 | ||||
M internal/application/handlers/bootloader_handler.go +2 -1
| @@ -2,6 +2,7 @@ package handlers | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | + | "errors" | |
| 5 | 6 | "fmt" | |
| 6 | 7 | "os" | |
| 7 | 8 | "path/filepath" | |
| @@ -232,7 +233,7 @@ func (h *BootloaderHandler) configureLimine(ctx context.Context, cmd commands.In | |||
| 232 | 233 | "\n //%s-fallback\n protocol: linux\n path: boot():/vmlinuz-%s\n cmdline: %s\n module_path: boot():/initramfs-%s-fallback.img\n", | |
| 233 | 234 | kernelName, kernelName, kernelParams, kernelName, | |
| 234 | 235 | ) | |
| 235 | - | } else if !os.IsNotExist(err) { | |
| 236 | + | } else if !errors.Is(err, os.ErrNotExist) { | |
| 236 | 237 | h.logger.Warn("Could not stat fallback initramfs, omitting fallback entry", "path", fallbackImgPath, "error", err) | |
| 237 | 238 | } | |
| 238 | 239 | limineConfig = strings.ReplaceAll(limineConfig, "{{FALLBACK_ENTRY}}", fallbackEntry) | |
| @@ -2,6 +2,7 @@ package handlers | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | + | "errors" | |||
| 5 | "fmt" | 6 | "fmt" | ||
| 6 | "os" | 7 | "os" | ||
| 7 | "path/filepath" | 8 | "path/filepath" | ||
| @@ -232,7 +233,7 @@ func (h *BootloaderHandler) configureLimine(ctx context.Context, cmd commands.In | |||||
| 232 | "\n //%s-fallback\n protocol: linux\n path: boot():/vmlinuz-%s\n cmdline: %s\n module_path: boot():/initramfs-%s-fallback.img\n", | 233 | "\n //%s-fallback\n protocol: linux\n path: boot():/vmlinuz-%s\n cmdline: %s\n module_path: boot():/initramfs-%s-fallback.img\n", | ||
| 233 | kernelName, kernelName, kernelParams, kernelName, | 234 | kernelName, kernelName, kernelParams, kernelName, | ||
| 234 | ) | 235 | ) | ||
| 235 | - | } else if !os.IsNotExist(err) { | 236 | + | } else if !errors.Is(err, os.ErrNotExist) { |
| 236 | h.logger.Warn("Could not stat fallback initramfs, omitting fallback entry", "path", fallbackImgPath, "error", err) | 237 | h.logger.Warn("Could not stat fallback initramfs, omitting fallback entry", "path", fallbackImgPath, "error", err) | ||
| 237 | } | 238 | } | ||
| 238 | limineConfig = strings.ReplaceAll(limineConfig, "{{FALLBACK_ENTRY}}", fallbackEntry) | 239 | limineConfig = strings.ReplaceAll(limineConfig, "{{FALLBACK_ENTRY}}", fallbackEntry) | ||
M internal/application/handlers/bootloader_handler_test.go +4 -3
| @@ -46,7 +46,8 @@ func setupCommonMocks(mockFS *mocks.MockFileSystem, mockExec *mocks.MockCommandE | |||
| 46 | 46 | mockExec.EXPECT().Execute(gomock.Any(), "blkid", "-s", "UUID", "-o", "value", gomock.Any()).Return([]byte("uuid"), nil).AnyTimes() | |
| 47 | 47 | mockExec.EXPECT().Execute(gomock.Any(), "cp", gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | |
| 48 | 48 | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | |
| 49 | - | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | |
| 49 | + | // efibootmgr and other multi-arg chroot commands: match any number of trailing args | |
| 50 | + | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), "efibootmgr", gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | |
| 50 | 51 | } | |
| 51 | 52 | ||
| 52 | 53 | func TestBootloaderHandler_Handle_Limine(t *testing.T) { | |
| @@ -136,7 +137,7 @@ func TestConfigureLimine_FallbackAbsent(t *testing.T) { | |||
| 136 | 137 | // Capture the written config | |
| 137 | 138 | var writtenConfig string | |
| 138 | 139 | mockFS.EXPECT().WriteFile(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( | |
| 139 | - | func(path string, data []byte, perm interface{}) error { | |
| 140 | + | func(path string, data []byte, perm os.FileMode) error { | |
| 140 | 141 | if strings.HasSuffix(path, "limine.conf") { | |
| 141 | 142 | writtenConfig = string(data) | |
| 142 | 143 | } | |
| @@ -200,7 +201,7 @@ func TestConfigureLimine_FallbackPresent(t *testing.T) { | |||
| 200 | 201 | // Capture the written config | |
| 201 | 202 | var writtenConfig string | |
| 202 | 203 | mockFS.EXPECT().WriteFile(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( | |
| 203 | - | func(path string, data []byte, perm interface{}) error { | |
| 204 | + | func(path string, data []byte, perm os.FileMode) error { | |
| 204 | 205 | if strings.HasSuffix(path, "limine.conf") { | |
| 205 | 206 | writtenConfig = string(data) | |
| 206 | 207 | } | |
| @@ -46,7 +46,8 @@ func setupCommonMocks(mockFS *mocks.MockFileSystem, mockExec *mocks.MockCommandE | |||||
| 46 | mockExec.EXPECT().Execute(gomock.Any(), "blkid", "-s", "UUID", "-o", "value", gomock.Any()).Return([]byte("uuid"), nil).AnyTimes() | 46 | mockExec.EXPECT().Execute(gomock.Any(), "blkid", "-s", "UUID", "-o", "value", gomock.Any()).Return([]byte("uuid"), nil).AnyTimes() | ||
| 47 | mockExec.EXPECT().Execute(gomock.Any(), "cp", gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | 47 | mockExec.EXPECT().Execute(gomock.Any(), "cp", gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | ||
| 48 | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | 48 | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | ||
| 49 | - | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | 49 | + | // efibootmgr and other multi-arg chroot commands: match any number of trailing args |
| 50 | + | mockChrExec.EXPECT().ExecuteInChroot(gomock.Any(), gomock.Any(), "efibootmgr", gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | |||
| 50 | } | 51 | } | ||
| 51 | 52 | ||||
| 52 | func TestBootloaderHandler_Handle_Limine(t *testing.T) { | 53 | func TestBootloaderHandler_Handle_Limine(t *testing.T) { | ||
| @@ -136,7 +137,7 @@ func TestConfigureLimine_FallbackAbsent(t *testing.T) { | |||||
| 136 | // Capture the written config | 137 | // Capture the written config | ||
| 137 | var writtenConfig string | 138 | var writtenConfig string | ||
| 138 | mockFS.EXPECT().WriteFile(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( | 139 | mockFS.EXPECT().WriteFile(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( | ||
| 139 | - | func(path string, data []byte, perm interface{}) error { | 140 | + | func(path string, data []byte, perm os.FileMode) error { |
| 140 | if strings.HasSuffix(path, "limine.conf") { | 141 | if strings.HasSuffix(path, "limine.conf") { | ||
| 141 | writtenConfig = string(data) | 142 | writtenConfig = string(data) | ||
| 142 | } | 143 | } | ||
| @@ -200,7 +201,7 @@ func TestConfigureLimine_FallbackPresent(t *testing.T) { | |||||
| 200 | // Capture the written config | 201 | // Capture the written config | ||
| 201 | var writtenConfig string | 202 | var writtenConfig string | ||
| 202 | mockFS.EXPECT().WriteFile(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( | 203 | mockFS.EXPECT().WriteFile(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( | ||
| 203 | - | func(path string, data []byte, perm interface{}) error { | 204 | + | func(path string, data []byte, perm os.FileMode) error { |
| 204 | if strings.HasSuffix(path, "limine.conf") { | 205 | if strings.HasSuffix(path, "limine.conf") { | ||
| 205 | writtenConfig = string(data) | 206 | writtenConfig = string(data) | ||
| 206 | } | 207 | } | ||
M internal/application/handlers/post_install_handler.go +3 -0
| @@ -255,6 +255,9 @@ func (h *PostInstallHandler) sanitizeLimineSnapperSyncConfig(mountPoint string) | |||
| 255 | 255 | const limineDiskPlaceholder = "DISK_PLACEHOLDER" | |
| 256 | 256 | ||
| 257 | 257 | func (h *PostInstallHandler) installLimineHook(mountPoint, targetDisk string) error { | |
| 258 | + | if targetDisk == "" { | |
| 259 | + | return fmt.Errorf("target disk is required for limine hook installation") | |
| 260 | + | } | |
| 258 | 261 | hooksDir := filepath.Join(mountPoint, "etc", "pacman.d", "hooks") | |
| 259 | 262 | if err := h.fs.MkdirAll(hooksDir, 0755); err != nil { | |
| 260 | 263 | return fmt.Errorf("failed to create hooks dir: %w", err) | |
| @@ -255,6 +255,9 @@ func (h *PostInstallHandler) sanitizeLimineSnapperSyncConfig(mountPoint string) | |||||
| 255 | const limineDiskPlaceholder = "DISK_PLACEHOLDER" | 255 | const limineDiskPlaceholder = "DISK_PLACEHOLDER" | ||
| 256 | 256 | ||||
| 257 | func (h *PostInstallHandler) installLimineHook(mountPoint, targetDisk string) error { | 257 | func (h *PostInstallHandler) installLimineHook(mountPoint, targetDisk string) error { | ||
| 258 | + | if targetDisk == "" { | |||
| 259 | + | return fmt.Errorf("target disk is required for limine hook installation") | |||
| 260 | + | } | |||
| 258 | hooksDir := filepath.Join(mountPoint, "etc", "pacman.d", "hooks") | 261 | hooksDir := filepath.Join(mountPoint, "etc", "pacman.d", "hooks") | ||
| 259 | if err := h.fs.MkdirAll(hooksDir, 0755); err != nil { | 262 | if err := h.fs.MkdirAll(hooksDir, 0755); err != nil { | ||
| 260 | return fmt.Errorf("failed to create hooks dir: %w", err) | 263 | return fmt.Errorf("failed to create hooks dir: %w", err) | ||
M internal/application/services/installation_service_test.go +1 -0
| @@ -35,6 +35,7 @@ func createTestService(ctrl *gomock.Controller) *InstallationService { | |||
| 35 | 35 | mockLogger.EXPECT().Info(gomock.Any()).AnyTimes() | |
| 36 | 36 | mockLogger.EXPECT().Info(gomock.Any(), gomock.Any()).AnyTimes() | |
| 37 | 37 | mockLogger.EXPECT().Warn(gomock.Any()).AnyTimes() | |
| 38 | + | mockLogger.EXPECT().Warn(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() | |
| 38 | 39 | mockLogger.EXPECT().Error(gomock.Any(), gomock.Any()).AnyTimes() | |
| 39 | 40 | mockLogger.EXPECT().LogPath().Return("/var/log/archup-install.log").AnyTimes() | |
| 40 | 41 | mockExec.EXPECT().Execute(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | |
| @@ -35,6 +35,7 @@ func createTestService(ctrl *gomock.Controller) *InstallationService { | |||||
| 35 | mockLogger.EXPECT().Info(gomock.Any()).AnyTimes() | 35 | mockLogger.EXPECT().Info(gomock.Any()).AnyTimes() | ||
| 36 | mockLogger.EXPECT().Info(gomock.Any(), gomock.Any()).AnyTimes() | 36 | mockLogger.EXPECT().Info(gomock.Any(), gomock.Any()).AnyTimes() | ||
| 37 | mockLogger.EXPECT().Warn(gomock.Any()).AnyTimes() | 37 | mockLogger.EXPECT().Warn(gomock.Any()).AnyTimes() | ||
| 38 | + | mockLogger.EXPECT().Warn(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() | |||
| 38 | mockLogger.EXPECT().Error(gomock.Any(), gomock.Any()).AnyTimes() | 39 | mockLogger.EXPECT().Error(gomock.Any(), gomock.Any()).AnyTimes() | ||
| 39 | mockLogger.EXPECT().LogPath().Return("/var/log/archup-install.log").AnyTimes() | 40 | mockLogger.EXPECT().LogPath().Return("/var/log/archup-install.log").AnyTimes() | ||
| 40 | mockExec.EXPECT().Execute(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | 41 | mockExec.EXPECT().Execute(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte{}, nil).AnyTimes() | ||