Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .amazonq/rules/dev-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,45 @@ Before performing ANY coding task, **read `.dev/00-README.md`** for complete pro
- Use `zerv::error::ZervError` for all custom errors
- Implement proper error propagation with `?` operator
- Include context in error messages for debugging
- Use `io::Error::other()` instead of `io::Error::new(io::ErrorKind::Other, ...)`

**Error Standard Violations Check:**

When user mentions:

- "check error standards"
- "find error violations"
- "audit error handling"
- "error compliance check"

→ Search codebase for violations:

- `io::Error::new(io::ErrorKind::Other` patterns
- Missing `ZervError` usage in custom error cases
- Direct `unwrap()` or `expect()` in production code
- Error messages without context

## Code Reuse Standards

**ALWAYS check existing utilities first:**

- Check `src/test_utils/` before creating new test utilities
- Reuse `TestDir`, `DockerGit`, and other existing infrastructure
- Avoid duplicating code across different files
- Look for existing helper functions before implementing new ones

**Code Reuse Violations Check:**

When user mentions:

- "check code reuse"
- "find duplicated code"
- "audit code duplication"
- "redundant code check"

→ Search codebase for violations:

- Duplicated test setup patterns
- Reimplemented utility functions
- Similar helper functions across files
- Unused existing utilities in `src/test_utils/`
37 changes: 37 additions & 0 deletions .amazonq/rules/testing-standards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Testing Standards

## Docker Isolation for VCS Tests

**MANDATORY: Use Docker for VCS operations that modify state**

- Use Docker for all Git/VCS tests to avoid interfering with local machine state
- Isolate test environment completely from host git config and repositories
- Use `DockerGit` utility from `src/test_utils/git.rs` for git operations in tests

## Race Condition Prevention

**Atomic Operations Required:**

- Use single Docker commands with shell scripts instead of multiple separate commands
- Combine git operations like `git init && git add . && git commit` in one Docker call
- Avoid multi-step Docker operations that can cause filesystem race conditions

**Flaky Test Detection:**

When user mentions:

- "check for flaky tests"
- "test stability"
- "race condition"
- "sometimes pass sometimes fail"

→ Run `make test` in a loop (default 10 iterations) to detect instability

## Test Stability Requirements

**Before committing:**

- All tests must pass consistently
- Use `make test` multiple times to verify stability
- Fix any intermittent failures before proceeding
- Document any Docker or environment dependencies
163 changes: 163 additions & 0 deletions .dev/02-docker-git-testing-bug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Docker Git Testing Bug - Complete Fix Guide

## Bug Symptoms

- Tests pass locally but fail in GitHub Actions CI
- Error: `fatal: not in a git directory`
- Multiple git-related test failures (typically 11+ tests)
- Docker commands work locally but not in CI environment

## Root Cause

**Docker Image Entrypoint Issue**: `alpine/git:latest` has `git` as the default entrypoint, not `sh`. This means:

- Local Docker might behave differently than CI
- Commands like `docker run alpine/git:latest "git init"` try to execute `git "git init"` instead of `sh -c "git init"`

## Complete Fix Pattern

### 1. Use Correct Docker Image and Entrypoint

```rust
// WRONG - Will fail in CI
let output = Command::new("docker")
.args(["run", "--rm", "-v", &mount, "alpine/git:latest", "git", "init"])
.output()?;

// CORRECT - Works everywhere
let output = Command::new("docker")
.args([
"run", "--rm", "-v", &mount,
"--entrypoint", "sh",
"alpine/git:latest",
"-c", "git init"
])
.output()?;
```

### 2. Git Commands After Init Need --git-dir Flag

```rust
// WRONG - Will fail after git init
let output = Command::new("docker")
.args([
"run", "--rm", "-v", &mount,
"--entrypoint", "sh",
"alpine/git:latest",
"-c", "git add ."
])
.output()?;

// CORRECT - Include --git-dir=.git
let output = Command::new("docker")
.args([
"run", "--rm", "-v", &mount,
"--entrypoint", "sh",
"alpine/git:latest",
"-c", "git --git-dir=.git add ."
])
.output()?;
```

### 3. Initial Commit Required for Tags

```rust
// Git tags need HEAD reference, so init_repo must create initial commit
pub fn init_repo(&self) -> Result<(), ZervError> {
// 1. Git init
self.run_git_command("git init")?;

// 2. Configure user (required for commits)
self.run_git_command("git config user.name 'Test User'")?;
self.run_git_command("git config user.email 'test@example.com'")?;

// 3. Create initial commit (REQUIRED for tags)
self.run_git_command("echo 'initial' > README.md")?;
self.run_git_command("git --git-dir=.git add .")?;
self.run_git_command("git --git-dir=.git commit -m 'Initial commit'")?;

Ok(())
}
```

## Complete Working Pattern

```rust
fn run_git_command(&self, command: &str) -> Result<String, ZervError> {
let mount = format!("{}:/repo", self.temp_dir.path().display());

let output = Command::new("docker")
.args([
"run", "--rm", "-v", &mount,
"-w", "/repo",
"--entrypoint", "sh",
"alpine/git:latest",
"-c", command
])
.output()
.map_err(|e| ZervError::Io(io::Error::other(format!("Docker command failed: {}", e))))?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(ZervError::Io(io::Error::other(format!(
"Git command failed: {}\nCommand: {}", stderr, command
))));
}

Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
```

## Debugging Steps

### 1. Test Docker Locally First

```bash
# Test the exact Docker command
docker run --rm -v $(pwd):/repo -w /repo --entrypoint sh alpine/git:latest -c "git init"
```

### 2. Check CI Logs for Exact Error

- Look for "fatal: not in a git directory"
- Check if Docker commands are being executed correctly
- Verify mount paths and working directories

### 3. Verify Test Isolation

```bash
# Run tests multiple times to check for race conditions
make test
make test
make test
```

## Prevention Checklist

- [ ] Use `--entrypoint sh` with `alpine/git:latest`
- [ ] Include `--git-dir=.git` for git commands after init
- [ ] Create initial commit in `init_repo()`
- [ ] Test Docker commands locally before CI
- [ ] Verify all git operations work in isolated containers
- [ ] Check that temp directories are properly mounted

## Files to Update When Fixing

1. `src/test_utils/git.rs` - Docker git utility functions
2. `src/vcs/git.rs` - Git VCS implementation test helpers
3. Any other files using Docker git commands

## Testing Verification

```bash
# Local test
make test

# Check specific git tests
cargo test git --include-ignored

# Verify CI will pass
git push # Check GitHub Actions
```

This bug has occurred multiple times - always refer to this guide when Docker git tests fail in CI but pass locally.
147 changes: 147 additions & 0 deletions .dev/02-vcs-implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# VCS Implementation Session Summary

## Overview

Implemented complete VCS (Version Control System) module for zerv project with Git integration, Docker-based testing infrastructure, and unified test utilities.

## Key Accomplishments

### 1. VCS Module Implementation

- **Core VCS trait** (`src/vcs/mod.rs`) - Defines interface for VCS operations
- **VcsData structure** - Repository metadata container with commit hashes, timestamps, branch info, distance, and dirty state
- **Git implementation** (`src/vcs/git.rs`) - Complete Git VCS with all required operations
- **Utility functions** - VCS detection and root finding capabilities

### 2. Docker-Based Git Testing

- **DockerGit utility** (`src/test_utils/git.rs`) - Isolated Git operations using alpine/git Docker container
- **Atomic operations** - Single Docker commands to prevent race conditions
- **Race condition resolution** - Fixed flaky tests by implementing atomic Git operations
- **Test stability** - Achieved 100% success rate across multiple test runs

### 3. Test Utilities Unification

- **Unified TestDir** (`src/test_utils/dir.rs`) - Single test directory utility using `tempfile::TempDir` internally
- **Feature gating** - `test-utils` feature for making utilities available to integration tests
- **Consistent API** - Standardized interface across all test utilities

### 4. Code Quality Improvements

- **Docker command refactoring** - Eliminated duplication with `run_docker_command` helper method
- **Readable formatting** - Improved long command lines with array-based formatting
- **Error handling** - Consistent error messages and proper error propagation
- **Coverage improvement** - Increased from 97.36% to 97.39%

## Technical Details

### VCS Architecture

```rust
pub trait Vcs {
fn get_vcs_data(&self) -> Result<VcsData>;
fn is_available(&self, path: &Path) -> bool;
}

pub struct VcsData {
pub commit_hash: String,
pub commit_hash_short: String,
pub commit_timestamp: i64,
pub is_dirty: bool,
pub current_branch: Option<String>,
pub tag_version: Option<String>,
pub tag_timestamp: Option<i64>,
pub distance: u64,
}
```

### Git Implementation Features

- **Repository detection** - Finds `.git` directory or VCS root
- **Commit information** - Full and short hashes, timestamps
- **Branch detection** - Current branch with detached HEAD handling
- **Tag operations** - Latest tag detection with distance calculation
- **Working tree status** - Dirty state detection
- **Shallow clone warning** - Alerts for inaccurate distance calculations

### Docker Testing Strategy

```rust
fn run_docker_command(&self, test_dir: &TestDir, script: &str) -> io::Result<String> {
Command::new("docker")
.args([
"run", "--rm", "--entrypoint", "sh", "-v",
&format!("{}:/workspace", test_dir.path().display()),
"-w", "/workspace", "alpine/git:latest", "-c", script,
])
.output()
}
```

### Test Infrastructure

- **Atomic Git setup** - Single Docker commands for repo initialization
- **Race condition prevention** - Eliminated multi-step Docker operations
- **Consistent test environment** - Isolated Git operations per test
- **Feature-gated utilities** - Available for both unit and integration tests

## Files Modified/Created

### Core Implementation

- `src/vcs/mod.rs` - VCS trait and utilities
- `src/vcs/git.rs` - Git VCS implementation
- `src/lib.rs` - Module exports and feature gating

### Test Infrastructure

- `src/test_utils/mod.rs` - Unified test utilities module
- `src/test_utils/dir.rs` - TestDir implementation
- `src/test_utils/git.rs` - DockerGit implementation

### Configuration

- `Cargo.toml` - Added `tempfile` dependency with `test-utils` feature
- `Makefile` - Updated test command to include feature flag

## Key Insights

### Race Condition Resolution

- **Root cause**: Multiple Docker container executions caused filesystem state inconsistencies
- **Solution**: Atomic operations using single Docker commands with shell scripts
- **Result**: 100% test stability across 20 consecutive runs

### Code Refactoring Benefits

- **Eliminated ~40 lines** of duplicated Docker setup code
- **Centralized error handling** for Docker operations
- **Improved maintainability** with single source of truth for Docker commands
- **Better readability** with structured command formatting

### Testing Strategy

- **Docker isolation** prevents local Git configuration interference
- **Atomic operations** ensure consistent test state
- **Feature gating** allows utilities in both unit and integration tests
- **Comprehensive coverage** of all Git operations and edge cases

## Test Results

- **All tests passing**: 1079 tests, 0 failures
- **Coverage**: 97.39% (improved from 97.36%)
- **Stability**: 100% success rate over multiple test runs
- **Performance**: Consistent 10-11 second test execution time

## Next Steps

The VCS implementation is complete and stable. Future enhancements could include:

1. **Additional VCS support** - Mercurial, SVN implementations
2. **Performance optimization** - Batched Git commands for large repositories
3. **Advanced Git features** - Submodule support, worktree handling
4. **Configuration options** - Custom tag patterns, branch filtering

## Session Outcome

Successfully implemented a robust, well-tested VCS module that provides comprehensive Git integration for the zerv dynamic versioning system. The implementation includes proper error handling, race condition prevention, and maintains high code quality standards.
Loading