5 Commits

Author SHA1 Message Date
Eric Ratliff
6b6ba058b7 chore: Release v1.0.0 - First stable release
Update version references from 1.0.0-rc2 to 1.0.0 across documentation.

This marks the first production-ready stable release of Weevil with complete
cross-platform support, robust Windows deployment, and comprehensive project
management features.

Changes:
- Update README.md current version to 1.0.0
- Remove "Next Release" section from ROADMAP.md (now tracking post-1.0 features)

Weevil is now stable and ready for FTC teams to use in production. 🎉
2026-01-26 19:39:11 -06:00
Eric Ratliff
8add733514 Updated email to eric@nxlearn.net 2026-01-26 19:18:26 -06:00
Eric Ratliff
8f12a0a09d Updated versioning information to align to RC2 2026-01-26 19:16:02 -06:00
Eric Ratliff
655a213113 docs: Add project roadmap for v1.0.0 and beyond
Add ROADMAP.md documenting planned features and improvements for the
initial stable release and future versions.

Roadmap includes:
- Pre-1.0.0: Critical fixes for Windows deployment and documentation
- v1.0.0 features: Enhanced project templates, improved error handling
- Post-1.0.0: Advanced features like custom templates, project analytics,
  multi-robot support, and CI/CD integration

This provides transparency for users and contributors about the project's
direction and planned capabilities.
2026-01-26 18:43:44 -06:00
Eric Ratliff
64826e2ce2 fix: Complete Windows deployment pipeline
Fixes critical bugs in Windows APK deployment workflow including APK path
resolution, adb integration, and config file parsing.

Changes:
- Fix APK search to look for TeamCode-debug.apk instead of *app-debug.apk
- Strip both single and double quotes from batch file path parsing
- Add android_sdk_path to project configuration (.weevil.toml)
- Resolve adb.exe from Android SDK platform-tools directory
- Check adb install exit code and report deployment failures correctly
- Add migration support for old .weevil.toml files missing android_sdk_path
- Update all tests to use new ProjectConfig::new() signature

The deployment workflow now properly finds the generated APK, locates adb,
and reports success/failure accurately on Windows.
2026-01-26 18:42:06 -06:00
7 changed files with 73 additions and 25 deletions

17
CHANGELOG.md Normal file
View File

@@ -0,0 +1,17 @@
# Changelog
## [1.0.0] - 2026-01-27
First stable release! 🎉
### Added
- Complete Windows deployment support
- Android SDK path in project configuration
- Robust cross-platform build and deployment scripts
- Project upgrade command with config migration
- Comprehensive test suite
### Fixed
- Windows APK discovery and deployment
- Batch file path parsing (quote handling)
- ADB integration and error reporting

View File

@@ -511,7 +511,7 @@ Built with frustration at unnecessarily complex robotics frameworks, and hope th
## Project Status
**Current Version:** 1.0.0-rc1
**Current Version:** 1.0.0
**What Works:**
- ✅ Project generation
@@ -532,7 +532,7 @@ Built with frustration at unnecessarily complex robotics frameworks, and hope th
**Questions? Issues? Suggestions?**
📧 Email: [eric@nxws.dev](mailto:eric@nxws.dev)
📧 Email: [eric@nxlearn.net](mailto:eric@nxlearn.net)
🐛 Issues: Open an issue on the repository
Building better tools so you can build better robots. 🤖

View File

@@ -2,9 +2,6 @@
This document outlines the planned feature development for Weevil across multiple versions. Features are subject to change based on user feedback, technical constraints, and market needs.
**Current Version:** 1.0.0-rc1
**Next Release:** 1.1.0 (Target: TBD)
---
## Version 1.1.0 - Core Stability & Team Adoption

View File

@@ -32,7 +32,7 @@ pub fn upgrade_project(path: &str) -> Result<()> {
let project_name = project_path.file_name()
.and_then(|n| n.to_str())
.unwrap_or("unknown");
crate::project::ProjectConfig::new(project_name, sdk_config.ftc_sdk_path.clone())?
crate::project::ProjectConfig::new(project_name, sdk_config.ftc_sdk_path.clone(), sdk_config.android_sdk_path.clone())?
};
println!("Current SDK: {}", project_config.ftc_sdk_path.display());

View File

@@ -9,10 +9,16 @@ pub struct ProjectConfig {
pub weevil_version: String,
pub ftc_sdk_path: PathBuf,
pub ftc_sdk_version: String,
#[serde(default = "default_android_sdk_path")]
pub android_sdk_path: PathBuf,
}
fn default_android_sdk_path() -> PathBuf {
PathBuf::new()
}
impl ProjectConfig {
pub fn new(project_name: &str, ftc_sdk_path: PathBuf) -> Result<Self> {
pub fn new(project_name: &str, ftc_sdk_path: PathBuf, android_sdk_path: PathBuf) -> Result<Self> {
let ftc_sdk_version = crate::sdk::ftc::get_version(&ftc_sdk_path)
.unwrap_or_else(|_| "unknown".to_string());
@@ -21,6 +27,7 @@ impl ProjectConfig {
weevil_version: "1.0.0".to_string(),
ftc_sdk_path,
ftc_sdk_version,
android_sdk_path,
})
}
@@ -34,9 +41,15 @@ impl ProjectConfig {
let contents = fs::read_to_string(&config_path)
.context("Failed to read .weevil.toml")?;
let config: ProjectConfig = toml::from_str(&contents)
let mut config: ProjectConfig = toml::from_str(&contents)
.context("Failed to parse .weevil.toml")?;
// Migrate old configs that don't have android_sdk_path
if config.android_sdk_path.as_os_str().is_empty() {
let sdk_config = crate::sdk::SdkConfig::new()?;
config.android_sdk_path = sdk_config.android_sdk_path;
}
Ok(config)
}
@@ -77,6 +90,7 @@ impl ProjectConfig {
println!();
println!("{:.<20} {}", "FTC SDK Path", self.ftc_sdk_path.display().to_string().bright_white());
println!("{:.<20} {}", "FTC SDK Version", self.ftc_sdk_version.bright_white());
println!("{:.<20} {}", "Android SDK Path", self.android_sdk_path.display().to_string().bright_white());
println!();
}
}

View File

@@ -77,7 +77,7 @@ impl ProjectBuilder {
fn create_project_files(&self, project_path: &Path, sdk_config: &SdkConfig) -> Result<()> {
// Create .weevil.toml config
let project_config = ProjectConfig::new(&self.name, sdk_config.ftc_sdk_path.clone())?;
let project_config = ProjectConfig::new(&self.name, sdk_config.ftc_sdk_path.clone(), sdk_config.android_sdk_path.clone())?;
project_config.save(project_path)?;
// README.md
@@ -334,47 +334,62 @@ echo "✓ Deployed!"
let deploy_bat = r#"@echo off
setlocal enabledelayedexpansion
REM Read SDK path from config
for /f "tokens=2 delims==" %%a in ('findstr /c:"ftc_sdk_path" .weevil.toml') do (
set SDK_DIR=%%a
)
REM Read SDK paths from config
for /f "tokens=2 delims==" %%a in ('findstr /c:"ftc_sdk_path" .weevil.toml') do set SDK_DIR=%%a
for /f "tokens=2 delims==" %%a in ('findstr /c:"android_sdk_path" .weevil.toml') do set ANDROID_SDK=%%a
REM Strip all quotes (both single and double)
set SDK_DIR=%SDK_DIR:"=%
set SDK_DIR=%SDK_DIR:'=%
set SDK_DIR=%SDK_DIR: =%
set ANDROID_SDK=%ANDROID_SDK:"=%
set ANDROID_SDK=%ANDROID_SDK:'=%
set ANDROID_SDK=%ANDROID_SDK: =%
if not defined SDK_DIR (
echo Error: Could not read FTC SDK path from .weevil.toml
exit /b 1
)
if not defined ANDROID_SDK (
echo Error: Could not read Android SDK path from .weevil.toml
exit /b 1
)
REM Set ADB path
set ADB_PATH=%ANDROID_SDK%\platform-tools\adb.exe
echo Building APK...
call gradlew.bat buildApk
echo.
echo Deploying to Control Hub...
echo.
echo DEBUG: SDK_DIR = %SDK_DIR%
echo DEBUG: Searching for: %SDK_DIR%\TeamCode-debug.apk
echo.
REM Find APK - look for TeamCode-debug.apk
for /f "delims=" %%i in ('dir /s /b "%SDK_DIR%\TeamCode-debug.apk" 2^>nul') do set APK=%%i
if not defined APK (
echo Error: APK not found
echo.
echo DEBUG: Tried searching in: %SDK_DIR%
echo DEBUG: Let's see what APKs exist:
dir /s /b "%SDK_DIR%\*.apk" 2>nul
echo.
exit /b 1
)
echo Found APK: %APK%
REM Check for adb
if not exist "%ADB_PATH%" (
echo Error: adb not found at %ADB_PATH%
echo Run: weevil sdk install
exit /b 1
)
echo Installing: %APK%
adb install -r "%APK%"
"%ADB_PATH%" install -r "%APK%"
if errorlevel 1 (
echo.
echo Deployment failed!
exit /b 1
)
echo.
echo Deployed!

View File

@@ -13,6 +13,7 @@ use weevil::sdk::SdkConfig;
fn test_config_create_and_save() {
let temp_dir = TempDir::new().unwrap();
let sdk_path = temp_dir.path().join("mock-sdk");
let android_sdk_path = temp_dir.path().join("android-sdk");
// Create minimal SDK structure
fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap();
@@ -20,10 +21,11 @@ fn test_config_create_and_save() {
fs::write(sdk_path.join("build.gradle"), "// test").unwrap();
fs::write(sdk_path.join(".version"), "v10.1.1").unwrap();
let config = ProjectConfig::new("test-robot", sdk_path.clone()).unwrap();
let config = ProjectConfig::new("test-robot", sdk_path.clone(), android_sdk_path.clone()).unwrap();
assert_eq!(config.project_name, "test-robot");
assert_eq!(config.ftc_sdk_path, sdk_path);
assert_eq!(config.android_sdk_path, android_sdk_path);
assert_eq!(config.weevil_version, "1.0.0");
// Save and reload
@@ -34,12 +36,14 @@ fn test_config_create_and_save() {
let loaded = ProjectConfig::load(&project_path).unwrap();
assert_eq!(loaded.project_name, config.project_name);
assert_eq!(loaded.ftc_sdk_path, config.ftc_sdk_path);
assert_eq!(loaded.android_sdk_path, config.android_sdk_path);
}
#[test]
fn test_config_toml_format() {
let temp_dir = TempDir::new().unwrap();
let sdk_path = temp_dir.path().join("sdk");
let android_sdk_path = temp_dir.path().join("android-sdk");
// Create minimal SDK
fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap();
@@ -47,7 +51,7 @@ fn test_config_toml_format() {
fs::write(sdk_path.join("build.gradle"), "// test").unwrap();
fs::write(sdk_path.join(".version"), "v10.1.1").unwrap();
let config = ProjectConfig::new("my-robot", sdk_path).unwrap();
let config = ProjectConfig::new("my-robot", sdk_path, android_sdk_path).unwrap();
let project_path = temp_dir.path().join("project");
fs::create_dir_all(&project_path).unwrap();
@@ -59,6 +63,7 @@ fn test_config_toml_format() {
assert!(content.contains("weevil_version = \"1.0.0\""));
assert!(content.contains("ftc_sdk_path"));
assert!(content.contains("ftc_sdk_version"));
assert!(content.contains("android_sdk_path"));
}
#[test]