Improve CLI tool detection in Advanced Settings

- Match WelcomeView behavior by checking if vt file physically exists
- Show green checkmark and 'CLI tool is installed' message when installed
- Display installation path when tool is already installed
- Add progress indicator during installation
- Check installation status on view appear

Also updated release scripts to set version before building to prevent version mismatches in About window
This commit is contained in:
Peter Steinberger 2025-06-17 03:26:05 +02:00
parent 2085eb7f1a
commit f4b0fa6b54
6 changed files with 113 additions and 41 deletions

View file

@ -25,7 +25,7 @@ struct AboutView: View {
descriptionSection
linksSection
Spacer(minLength: 20)
Spacer(minLength: 10)
copyrightSection
}

View file

@ -6,6 +6,7 @@ struct AdvancedSettingsView: View {
private var debugMode = false
@AppStorage("cleanupOnStartup")
private var cleanupOnStartup = true
@State private var cliInstaller = CLIInstaller()
var body: some View {
NavigationStack {
@ -16,14 +17,42 @@ struct AdvancedSettingsView: View {
HStack {
Text("Install CLI Tool")
Spacer()
Button("Install 'vt' Command") {
installCLITool()
if cliInstaller.isInstalled {
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
Text("CLI tool is installed")
.foregroundColor(.secondary)
}
} else {
Button("Install 'vt' Command") {
Task {
await cliInstaller.install()
}
}
.buttonStyle(.bordered)
.disabled(cliInstaller.isInstalling)
}
.buttonStyle(.bordered)
}
Text("Install the 'vt' command line tool to /usr/local/bin for terminal access.")
.font(.caption)
.foregroundStyle(.secondary)
if cliInstaller.isInstalling {
ProgressView()
.scaleEffect(0.8)
}
if let error = cliInstaller.lastError {
Text(error)
.font(.caption)
.foregroundColor(.red)
} else if cliInstaller.isInstalled {
Text("The 'vt' command line tool is installed at /usr/local/bin/vt")
.font(.caption)
.foregroundStyle(.secondary)
} else {
Text("Install the 'vt' command line tool to /usr/local/bin for terminal access.")
.font(.caption)
.foregroundStyle(.secondary)
}
}
} header: {
Text("Integration")
@ -60,10 +89,8 @@ struct AdvancedSettingsView: View {
.scrollContentBackground(.hidden)
.navigationTitle("Advanced Settings")
}
}
private func installCLITool() {
let installer = CLIInstaller()
installer.installCLITool()
.onAppear {
cliInstaller.checkInstallationStatus()
}
}
}

View file

@ -1,7 +1,7 @@
// VibeTunnel Version Configuration
// This file contains the version and build number for the app
MARKETING_VERSION = 1.0
MARKETING_VERSION = 1.0-beta.1
CURRENT_PROJECT_VERSION = 103
// Domain and GitHub configuration

View file

@ -111,7 +111,7 @@ echo "=============================="
echo ""
# Step 1: Run pre-flight check
echo -e "${BLUE}📋 Step 1/7: Running pre-flight check...${NC}"
echo -e "${BLUE}📋 Step 1/8: Running pre-flight check...${NC}"
if ! "$SCRIPT_DIR/preflight-check.sh"; then
echo ""
echo -e "${RED}❌ Pre-flight check failed. Please fix the issues above.${NC}"
@ -149,13 +149,44 @@ echo " Tag: $TAG_NAME"
echo ""
# Step 2: Clean build directory
echo -e "${BLUE}📋 Step 2/7: Cleaning build directory...${NC}"
echo -e "${BLUE}📋 Step 2/8: Cleaning build directory...${NC}"
rm -rf "$PROJECT_ROOT/build"
rm -rf "$PROJECT_ROOT/DerivedData"
rm -rf "$PROJECT_ROOT/.build"
rm -rf ~/Library/Developer/Xcode/DerivedData/VibeTunnel-*
echo "✓ Cleaned all build artifacts"
# Step 3: Update version in version.xcconfig
echo ""
echo -e "${BLUE}📋 Step 3/8: Setting version...${NC}"
# Backup version.xcconfig
cp "$VERSION_CONFIG" "$VERSION_CONFIG.bak"
# Determine the version string to set
if [[ "$RELEASE_TYPE" == "stable" ]]; then
# For stable releases, ensure MARKETING_VERSION doesn't have pre-release suffix
# Extract base version (remove any existing pre-release suffix)
BASE_VERSION=$(echo "$MARKETING_VERSION" | sed 's/-.*$//')
VERSION_TO_SET="$BASE_VERSION"
else
# For pre-releases, set the full version with suffix
VERSION_TO_SET="$RELEASE_VERSION"
fi
# Update MARKETING_VERSION in version.xcconfig
echo "📝 Updating MARKETING_VERSION to: $VERSION_TO_SET"
sed -i '' "s/MARKETING_VERSION = .*/MARKETING_VERSION = $VERSION_TO_SET/" "$VERSION_CONFIG"
# Verify the update
NEW_MARKETING_VERSION=$(grep 'MARKETING_VERSION' "$VERSION_CONFIG" | sed 's/.*MARKETING_VERSION = //')
if [[ "$NEW_MARKETING_VERSION" != "$VERSION_TO_SET" ]]; then
echo -e "${RED}❌ Failed to update MARKETING_VERSION${NC}"
exit 1
fi
echo -e "${GREEN}✅ Version updated to: $VERSION_TO_SET${NC}"
# Check if Xcode project was modified and commit if needed
if ! git diff --quiet "$PROJECT_ROOT/VibeTunnel.xcodeproj/project.pbxproj"; then
echo "📝 Committing Xcode project changes..."
@ -164,9 +195,9 @@ if ! git diff --quiet "$PROJECT_ROOT/VibeTunnel.xcodeproj/project.pbxproj"; then
echo -e "${GREEN}✅ Xcode project changes committed${NC}"
fi
# Step 3: Build the app
# Step 4: Build the app
echo ""
echo -e "${BLUE}📋 Step 3/7: Building application...${NC}"
echo -e "${BLUE}📋 Step 4/8: Building application...${NC}"
# For pre-release builds, set the environment variable
if [[ "$RELEASE_TYPE" != "stable" ]]; then
@ -196,12 +227,12 @@ echo -e "${GREEN}✅ Build complete${NC}"
# Step 4: Sign and notarize
echo ""
echo -e "${BLUE}📋 Step 4/7: Signing and notarizing...${NC}"
echo -e "${BLUE}📋 Step 5/8: Signing and notarizing...${NC}"
"$SCRIPT_DIR/sign-and-notarize.sh" --sign-and-notarize
# Step 5: Create DMG
echo ""
echo -e "${BLUE}📋 Step 5/7: Creating DMG...${NC}"
echo -e "${BLUE}📋 Step 6/8: Creating DMG...${NC}"
DMG_NAME="VibeTunnel-$RELEASE_VERSION.dmg"
DMG_PATH="$PROJECT_ROOT/build/$DMG_NAME"
"$SCRIPT_DIR/create-dmg.sh" "$APP_PATH" "$DMG_PATH"
@ -215,7 +246,7 @@ echo -e "${GREEN}✅ DMG created: $DMG_NAME${NC}"
# Step 6: Create GitHub release
echo ""
echo -e "${BLUE}📋 Step 6/7: Creating GitHub release...${NC}"
echo -e "${BLUE}📋 Step 7/8: Creating GitHub release...${NC}"
# Check if tag already exists
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
@ -306,7 +337,7 @@ echo -e "${GREEN}✅ GitHub release created${NC}"
# Step 7: Update appcast
echo ""
echo -e "${BLUE}📋 Step 7/7: Updating appcast...${NC}"
echo -e "${BLUE}📋 Step 8/8: Updating appcast...${NC}"
# Generate appcast
echo "🔐 Generating appcast with EdDSA signatures..."
@ -325,16 +356,30 @@ fi
echo -e "${GREEN}✅ Appcast updated${NC}"
# Commit and push appcast files
# Commit and push appcast and version files
echo ""
echo "📤 Committing and pushing appcast..."
echo "📤 Committing and pushing changes..."
# Add version.xcconfig changes
git add "$VERSION_CONFIG" 2>/dev/null || true
# Add appcast files
git add "$PROJECT_ROOT/appcast.xml" "$PROJECT_ROOT/appcast-prerelease.xml" 2>/dev/null || true
if ! git diff --cached --quiet; then
git commit -m "Update appcast for $RELEASE_VERSION"
git commit -m "Update appcast and version for $RELEASE_VERSION"
git push origin main
echo -e "${GREEN}✅ Appcast changes pushed${NC}"
echo -e "${GREEN}Changes pushed${NC}"
else
echo " No appcast changes to commit"
echo " No changes to commit"
fi
# For pre-releases, optionally restore base version
if [[ "$RELEASE_TYPE" != "stable" ]]; then
echo ""
echo "📝 Note: MARKETING_VERSION is now set to '$VERSION_TO_SET'"
echo " To restore base version for development, run:"
echo " git checkout -- $VERSION_CONFIG"
fi
# Optional: Verify appcast

View file

@ -38,31 +38,31 @@ usage() {
echo ""
}
# Get current version from Project.swift
# Get current version from version.xcconfig
get_current_version() {
grep 'MARKETING_VERSION' "$PROJECT_ROOT/Project.swift" | sed 's/.*"MARKETING_VERSION": "\(.*\)".*/\1/'
grep 'MARKETING_VERSION' "$PROJECT_ROOT/VibeTunnel/version.xcconfig" | sed 's/.*MARKETING_VERSION = //'
}
# Get current build number from Project.swift
# Get current build number from version.xcconfig
get_current_build() {
grep 'CURRENT_PROJECT_VERSION' "$PROJECT_ROOT/Project.swift" | sed 's/.*"CURRENT_PROJECT_VERSION": "\(.*\)".*/\1/'
grep 'CURRENT_PROJECT_VERSION' "$PROJECT_ROOT/VibeTunnel/version.xcconfig" | sed 's/.*CURRENT_PROJECT_VERSION = //'
}
# Update version in Project.swift
# Update version in version.xcconfig
update_project_version() {
local new_version="$1"
local new_build="$2"
# Create backup
cp "$PROJECT_ROOT/Project.swift" "$PROJECT_ROOT/Project.swift.bak"
cp "$PROJECT_ROOT/VibeTunnel/version.xcconfig" "$PROJECT_ROOT/VibeTunnel/version.xcconfig.bak"
# Update marketing version
sed -i '' "s/\"MARKETING_VERSION\": \".*\"/\"MARKETING_VERSION\": \"$new_version\"/" "$PROJECT_ROOT/Project.swift"
sed -i '' "s/MARKETING_VERSION = .*/MARKETING_VERSION = $new_version/" "$PROJECT_ROOT/VibeTunnel/version.xcconfig"
# Update build number
sed -i '' "s/\"CURRENT_PROJECT_VERSION\": \".*\"/\"CURRENT_PROJECT_VERSION\": \"$new_build\"/" "$PROJECT_ROOT/Project.swift"
sed -i '' "s/CURRENT_PROJECT_VERSION = .*/CURRENT_PROJECT_VERSION = $new_build/" "$PROJECT_ROOT/VibeTunnel/version.xcconfig"
echo "✅ Updated Project.swift:"
echo "✅ Updated version.xcconfig:"
echo " Version: $new_version"
echo " Build: $new_build"
}
@ -276,18 +276,18 @@ main() {
echo "✅ Version updated successfully!"
echo ""
echo "📋 Next steps:"
echo " 1. Review the changes: git diff Project.swift"
echo " 2. Commit the version bump: git add Project.swift && git commit -m \"Bump version to $new_version\""
echo " 3. Create the release: ./scripts/release-auto.sh stable"
echo " 1. Review the changes: git diff VibeTunnel/version.xcconfig"
echo " 2. Commit the version bump: git add VibeTunnel/version.xcconfig && git commit -m \"Bump version to $new_version\""
echo " 3. Create the release: ./scripts/release.sh stable"
if [[ "$new_version" =~ -[a-z]+\.[0-9]+$ ]]; then
echo " 3. Create the pre-release: ./scripts/release-auto.sh ${prerelease_type} ${new_version##*.}"
fi
echo ""
}
# Validate Project.swift exists
if [[ ! -f "$PROJECT_ROOT/Project.swift" ]]; then
echo "Project.swift not found in $PROJECT_ROOT"
# Validate version.xcconfig exists
if [[ ! -f "$PROJECT_ROOT/VibeTunnel/version.xcconfig" ]]; then
echo "version.xcconfig not found in $PROJECT_ROOT/VibeTunnel"
exit 1
fi