Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tui] Implement #135 for update #246

Merged
merged 6 commits into from
Jan 20, 2025
Merged

[tui] Implement #135 for update #246

merged 6 commits into from
Jan 20, 2025

Conversation

goldyfruit
Copy link
Member

@goldyfruit goldyfruit commented Jan 18, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced backup functionality during uninstallation
    • Added dynamic feature state management
    • Introduced profile management capabilities
    • Implemented update confirmation dialog
  • Improvements

    • Added state directory management
    • Introduced temporary files for features and profiles
    • Improved localization support for update process
  • Bug Fixes

    • Refined cleanup process during uninstallation

@goldyfruit goldyfruit added the enhancement New feature or request label Jan 18, 2025
@goldyfruit goldyfruit added this to the Commander Keen milestone Jan 18, 2025
@goldyfruit goldyfruit self-assigned this Jan 18, 2025
Copy link
Contributor

coderabbitai bot commented Jan 18, 2025

Walkthrough

This pull request introduces enhancements to the Open Voice OS (OVOS) installer, focusing on state management, profile configuration, and installation/uninstallation processes. The changes include adding new directories for backup, implementing dynamic feature and profile management, and introducing new utility functions for state tracking. The modifications aim to improve the installer's flexibility and user experience by providing more granular control over installation settings and preserving user configurations.

Changes

File Change Summary
ansible/roles/ovos_installer/tasks/ovos.yml Added .local/state/ovos/* to backup directories
ansible/roles/ovos_installer/tasks/virtualenv/systemd.yml Added .local/state/ovos to directories for removal during uninstallation
setup.sh Added state_directory command
tui/features.sh Introduced dynamic feature state management with new arrays
tui/locales/en-us/update.sh New localization script for update notifications
tui/profiles.sh Added profile management logic with dynamic profile selection
tui/uninstall.sh Updated to source update localization script
tui/update.sh New script for update confirmation dialog
utils/common.sh Added state_directory function for managing local state
utils/constants.sh Added temporary file paths for features and profiles

Possibly related PRs

Suggested labels

bug, enhancement, installer

Poem

🐰 A Rabbit's Ode to OVOS Installer Magic

In state and profile, we now dance with glee
Backup and update, as smooth as can be
Directories whisper their secrets so bright
Installer's embrace, a technological delight!
Hop, hop, configuration's new frontier! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@goldyfruit goldyfruit marked this pull request as ready for review January 20, 2025 18:24
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: 6

🧹 Nitpick comments (2)
tui/update.sh (1)

9-14: Add validation for TUI window dimensions.

The script uses $TUI_WINDOW_HEIGHT and $TUI_WINDOW_WIDTH without validation.

Add dimension validation:

+# Validate TUI dimensions
+if [ -z "$TUI_WINDOW_HEIGHT" ] || [ -z "$TUI_WINDOW_WIDTH" ]; then
+  echo "Error: TUI window dimensions not set" >&2
+  exit 1
+fi
+
 whiptail --yesno --no-button "$NO_BUTTON" --yes-button "$YES_BUTTON" \
   --title "$TITLE" "$CONTENT" "$TUI_WINDOW_HEIGHT" "$TUI_WINDOW_WIDTH"
utils/common.sh (1)

551-565: Consider enhancing the state directory function with better error handling and validation.

While the implementation is functional, consider the following improvements:

  1. Add error handling for directory creation and ownership changes.
  2. Validate the JSON structure of the state file.

Here's a suggested implementation with improved error handling and validation:

 function state_directory() {
     OVOS_LOCAL_STATE_DIRECTORY="$RUN_AS_HOME/.local/state/ovos"
     export INSTALLER_STATE_FILE="$OVOS_LOCAL_STATE_DIRECTORY/installer.json"
     if [ ! -d "$OVOS_LOCAL_STATE_DIRECTORY" ]; then
-        mkdir -p "$OVOS_LOCAL_STATE_DIRECTORY" &>>"$LOG_FILE"
-        chown -R "$RUN_AS":"$(id -ng "$RUN_AS")" "$OVOS_LOCAL_STATE_DIRECTORY" &>>"$LOG_FILE"
+        if ! mkdir -p "$OVOS_LOCAL_STATE_DIRECTORY" &>>"$LOG_FILE"; then
+            echo "Failed to create state directory" &>>"$LOG_FILE"
+            return 1
+        fi
+        if ! chown -R "$RUN_AS":"$(id -ng "$RUN_AS")" "$OVOS_LOCAL_STATE_DIRECTORY" &>>"$LOG_FILE"; then
+            echo "Failed to set state directory ownership" &>>"$LOG_FILE"
+            return 1
+        fi
     fi
     if [ -f "$INSTALLER_STATE_FILE" ]; then
-        [ -s "$INSTALLER_STATE_FILE" ] || rm "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"
+        if [ -s "$INSTALLER_STATE_FILE" ]; then
+            if ! jq empty "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"; then
+                echo "Invalid JSON in state file" &>>"$LOG_FILE"
+                return 1
+            fi
+        else
+            rm "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"
+        fi
     fi
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b79faca and d4d1d3c.

📒 Files selected for processing (10)
  • ansible/roles/ovos_installer/tasks/ovos.yml (1 hunks)
  • ansible/roles/ovos_installer/tasks/virtualenv/systemd.yml (1 hunks)
  • setup.sh (1 hunks)
  • tui/features.sh (2 hunks)
  • tui/locales/en-us/update.sh (1 hunks)
  • tui/profiles.sh (2 hunks)
  • tui/uninstall.sh (1 hunks)
  • tui/update.sh (1 hunks)
  • utils/common.sh (1 hunks)
  • utils/constants.sh (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tui/locales/en-us/update.sh
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: shell-testing
🔇 Additional comments (3)
ansible/roles/ovos_installer/tasks/ovos.yml (1)

13-13: LGTM! The state directory is now properly included in the backup process.

The addition of .local/state/ovos/* to the backup list ensures that state information is preserved during uninstallation, which aligns well with the new state management functionality.

Let's verify the integration with other changes:

✅ Verification successful

Verified: State directory is properly managed and consistently implemented

The state directory .local/state/ovos is correctly set up, managed, and included in the backup process across all relevant parts of the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the state directory is consistently handled across the codebase.

# Test 1: Check if the state directory is properly managed in other tasks
rg -A 5 "\.local/state/ovos"

# Test 2: Check if there are any other state-related paths that should be included
rg -A 5 "state.*directory"

Length of output: 4873

setup.sh (1)

48-48: LGTM! The state directory initialization is properly sequenced.

The state_directory function is called at an appropriate point in the installation process, ensuring state management is initialized after system checks but before proceeding with the installation.

Let's verify the function call sequence:

✅ Verification successful

Verification confirms proper function sequencing

The state_directory function is correctly positioned in the installation flow:

  • After system dependencies and hardware detection
  • Before scenario-specific operations
  • With proper error handling in place
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the sequence of function calls and error handling.

# Test 1: Check the sequence of function calls around state_directory
rg -B 5 -A 5 "state_directory"

# Test 2: Check if there are any dependencies between the functions
ast-grep --pattern 'function $func() {
  $$$
  state_directory
  $$$
}'

Length of output: 1160

ansible/roles/ovos_installer/tasks/virtualenv/systemd.yml (1)

138-138: LGTM! The state directory is properly included in the cleanup process.

The addition of .local/state/ovos to the cleanup list ensures proper removal of state information during uninstallation, complementing the backup functionality.

Let's verify the cleanup process:

✅ Verification successful

State directory cleanup implementation is verified and complete

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the consistency of directory cleanup during uninstallation.

# Test 1: Check if all state-related directories are properly cleaned up
rg -A 5 "state: absent.*ovos"

# Test 2: Check for any potential leftover directories
rg -A 5 "\.local/state"

Length of output: 1527

#!/bin/env bash

# shellcheck source=locales/en-us/misc.sh
source "tui/locales/$LOCALE/misc.sh"
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for locale file sourcing.

The script assumes locale files exist but doesn't handle cases where they might be missing.

Add error checking:

-source "tui/locales/$LOCALE/misc.sh"
+if [ ! -f "tui/locales/$LOCALE/misc.sh" ]; then
+  echo "Error: Missing locale file tui/locales/$LOCALE/misc.sh" >&2
+  exit 1
+fi
+source "tui/locales/$LOCALE/misc.sh"

Also applies to: 7-7

Comment on lines +17 to +18
# shellcheck source=update.sh
source tui/update.sh
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and improve user flow clarity.

When uninstall is declined, the script directly sources update.sh without error handling or user notification.

Add error handling and user notification:

-  # shellcheck source=update.sh
-  source tui/update.sh
+  # shellcheck source=update.sh
+  if [ ! -f "tui/update.sh" ]; then
+    echo "Error: Update script not found" >&2
+    exit 1
+  fi
+  whiptail --msgbox --title "$TITLE" "Proceeding to update menu..." \
+    "$TUI_WINDOW_HEIGHT" "$TUI_WINDOW_WIDTH"
+  source tui/update.sh
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# shellcheck source=update.sh
source tui/update.sh
# shellcheck source=update.sh
if [ ! -f "tui/update.sh" ]; then
echo "Error: Update script not found" >&2
exit 1
fi
whiptail --msgbox --title "$TITLE" "Proceeding to update menu..." \
"$TUI_WINDOW_HEIGHT" "$TUI_WINDOW_WIDTH"
source tui/update.sh

@@ -31,3 +41,6 @@ if [ -z "$PROFILE" ]; then
source tui/channels.sh
source tui/profiles.sh
fi

jq -en --arg profile "$PROFILE" '.profile += $profile' > "$TEMP_PROFILE_FILE"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle potential race conditions with temporary files.

The script writes to a temporary file without proper locking mechanisms.

Add file locking:

-jq -en --arg profile "$PROFILE" '.profile += $profile' > "$TEMP_PROFILE_FILE"
+(
+  flock -w 10 200 || {
+    echo "Error: Failed to acquire lock" >&2
+    exit 1
+  }
+  jq -en --arg profile "$PROFILE" '.profile += $profile' > "$TEMP_PROFILE_FILE"
+) 200>"${TEMP_PROFILE_FILE}.lock"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jq -en --arg profile "$PROFILE" '.profile += $profile' > "$TEMP_PROFILE_FILE"
(
flock -w 10 200 || {
echo "Error: Failed to acquire lock" >&2
exit 1
}
jq -en --arg profile "$PROFILE" '.profile += $profile' > "$TEMP_PROFILE_FILE"
) 200>"${TEMP_PROFILE_FILE}.lock"

Comment on lines +11 to +16
if [ -f "$INSTALLER_STATE_FILE" ]; then
if jq -e 'has("profile")' "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"; then
current_profile=$(jq -re '.profile' "$INSTALLER_STATE_FILE")
active_profile="$current_profile"
available_profiles=("$current_profile")
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for JSON operations.

The script uses jq without proper error handling, which could lead to silent failures.

Add error handling:

 if [ -f "$INSTALLER_STATE_FILE" ]; then
-  if jq -e 'has("profile")' "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"; then
-    current_profile=$(jq -re '.profile' "$INSTALLER_STATE_FILE")
+  if ! jq -e 'has("profile")' "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"; then
+    echo "Error: Invalid state file format" >&2
+    exit 1
+  fi
+  current_profile=$(jq -re '.profile' "$INSTALLER_STATE_FILE") || {
+    echo "Error: Failed to read profile from state file" >&2
+    exit 1
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ -f "$INSTALLER_STATE_FILE" ]; then
if jq -e 'has("profile")' "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"; then
current_profile=$(jq -re '.profile' "$INSTALLER_STATE_FILE")
active_profile="$current_profile"
available_profiles=("$current_profile")
fi
if [ -f "$INSTALLER_STATE_FILE" ]; then
if ! jq -e 'has("profile")' "$INSTALLER_STATE_FILE" &>>"$LOG_FILE"; then
echo "Error: Invalid state file format" >&2
exit 1
fi
current_profile=$(jq -re '.profile' "$INSTALLER_STATE_FILE") || {
echo "Error: Failed to read profile from state file" >&2
exit 1
}
active_profile="$current_profile"
available_profiles=("$current_profile")
fi

Comment on lines +67 to +71
if [ "$exit_status" -ne 1 ]; then
jq -en '.features += $ARGS.positional' --args "${FEATURES_STATE[@]}" > "$TEMP_FEATURES_FILE"
jq -es '.[0] * .[1]' "$TEMP_PROFILE_FILE" "$TEMP_FEATURES_FILE" > "$INSTALLER_STATE_FILE"
rm "$TEMP_FEATURES_FILE" "$TEMP_PROFILE_FILE"
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve temporary file handling and cleanup.

The script needs better error handling and cleanup for temporary files.

Add proper cleanup and error handling:

+cleanup() {
+  rm -f "$TEMP_FEATURES_FILE" "$TEMP_PROFILE_FILE"
+}
+trap cleanup EXIT
+
 if [ "$exit_status" -ne 1 ]; then
-  jq -en '.features += $ARGS.positional' --args "${FEATURES_STATE[@]}" > "$TEMP_FEATURES_FILE"
-  jq -es '.[0] * .[1]' "$TEMP_PROFILE_FILE" "$TEMP_FEATURES_FILE" > "$INSTALLER_STATE_FILE"
-  rm "$TEMP_FEATURES_FILE" "$TEMP_PROFILE_FILE"
+  jq -en '.features += $ARGS.positional' --args "${FEATURES_STATE[@]}" > "$TEMP_FEATURES_FILE" || {
+    echo "Error: Failed to create features file" >&2
+    exit 1
+  }
+  jq -es '.[0] * .[1]' "$TEMP_PROFILE_FILE" "$TEMP_FEATURES_FILE" > "$INSTALLER_STATE_FILE" || {
+    echo "Error: Failed to merge state files" >&2
+    exit 1
+  }
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ "$exit_status" -ne 1 ]; then
jq -en '.features += $ARGS.positional' --args "${FEATURES_STATE[@]}" > "$TEMP_FEATURES_FILE"
jq -es '.[0] * .[1]' "$TEMP_PROFILE_FILE" "$TEMP_FEATURES_FILE" > "$INSTALLER_STATE_FILE"
rm "$TEMP_FEATURES_FILE" "$TEMP_PROFILE_FILE"
fi
cleanup() {
rm -f "$TEMP_FEATURES_FILE" "$TEMP_PROFILE_FILE"
}
trap cleanup EXIT
if [ "$exit_status" -ne 1 ]; then
jq -en '.features += $ARGS.positional' --args "${FEATURES_STATE[@]}" > "$TEMP_FEATURES_FILE" || {
echo "Error: Failed to create features file" >&2
exit 1
}
jq -es '.[0] * .[1]' "$TEMP_PROFILE_FILE" "$TEMP_FEATURES_FILE" > "$INSTALLER_STATE_FILE" || {
echo "Error: Failed to merge state files" >&2
exit 1
}
fi

Comment on lines +57 to +58
export TEMP_FEATURES_FILE=/tmp/features.json
export TEMP_PROFILE_FILE=/tmp/profile.json
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use secure temporary file paths.

Using hardcoded paths in /tmp could lead to security issues in multi-user environments.

Use mktemp for secure temporary files:

-export TEMP_FEATURES_FILE=/tmp/features.json
-export TEMP_PROFILE_FILE=/tmp/profile.json
+export TEMP_FEATURES_FILE
+export TEMP_PROFILE_FILE
+TEMP_FEATURES_FILE=$(mktemp -t ovos-features.XXXXXX.json)
+TEMP_PROFILE_FILE=$(mktemp -t ovos-profile.XXXXXX.json)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export TEMP_FEATURES_FILE=/tmp/features.json
export TEMP_PROFILE_FILE=/tmp/profile.json
export TEMP_FEATURES_FILE
export TEMP_PROFILE_FILE
TEMP_FEATURES_FILE=$(mktemp -t ovos-features.XXXXXX.json)
TEMP_PROFILE_FILE=$(mktemp -t ovos-profile.XXXXXX.json)

@goldyfruit goldyfruit merged commit 183637e into main Jan 20, 2025
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant