diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..04245a0 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "default": true, + "MD013": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + "MD033": false, + "MD041": false +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6be3e75 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,351 @@ +# AGENTS.md + +Instructions for AI coding agents working on this project. + +## Project Overview + +This is a Serverspec-based testing framework for validating Docker images. +The project tests Node.js Docker images built from custom Dockerfiles by +creating containers, running Serverspec tests against them, and cleaning up +resources. + +**Tech Stack:** + +- Ruby 3.4+ and Ruby 4.0+ +- Serverspec 2.43+ +- Docker API gem 2.4+ +- RSpec 3.13+ +- Docker BuildKit + +**Current Node.js versions tested:** + +- Node.js 22.22.0 (Maintenance LTS) +- Node.js 24.13.0 (Active LTS) + +## Setup Commands + +```bash +# Install dependencies locally (no sudo required) +bundle install + +# Docker BuildKit is enabled by default in Rakefile +# Verify Docker is running +docker info +``` + +## Running Tests + +```bash +# Run all tests in parallel (~18 seconds) +bundle exec rake + +# Run tests for a specific Node.js version +bundle exec rspec spec/22/Dockerfile_spec.rb +bundle exec rspec spec/24/Dockerfile_spec.rb + +# Run with verbose output +bundle exec rake --trace +``` + +## Project Structure + +```text +. +├── 22/ # Node.js 22 Dockerfile +├── 24/ # Node.js 24 Dockerfile +├── spec/ +│ ├── 22/Dockerfile_spec.rb # Tests for Node.js 22 +│ ├── 24/Dockerfile_spec.rb # Tests for Node.js 24 +│ ├── spec_helper.rb # Helper methods (create_image, delete_image) +│ ├── node_tests.rb # Shared Node.js version tests +│ └── npm_tests.rb # Shared npm tests +├── Rakefile # Test runner with parallel execution +├── Gemfile # Ruby dependencies +└── .github/workflows/ruby.yml # CI with Ruby 3.4 & 4.0 matrix +``` + +## Development Workflow + +### Adding a New Node.js Version + +1. Create new directory: `mkdir XX/` (where XX is the version) +2. Copy Dockerfile from existing version and update `NODE_VERSION` +3. Create test spec: `spec/XX/Dockerfile_spec.rb` +4. Update Rakefile to include new task +5. Test locally: `bundle exec rake` +6. Update README.md to mention new version + +### Modifying Dockerfiles + +- Always update the `NODE_VERSION` environment variable +- Verify GPG keys are current from nodejs/docker-node +- Test on both amd64 and arm64 if possible +- Use Debian trixie-slim as base image + +### Updating Dependencies + +```bash +# Update specific gem +bundle update + +# Update all gems (be careful) +bundle update + +# Always remove BUNDLED WITH section from Gemfile.lock for CI compatibility +``` + +## Documentation Standards + +### Markdown Linting + +All markdown files must pass markdownlint validation before committing. + +```bash +# Check all markdown files +npx markdownlint-cli *.md + +# Auto-fix issues where possible +npx markdownlint-cli --fix *.md +``` + +**Configuration**: See `.markdownlint.json` for project rules. + +**Key Rules**: + +- Line length: 120 characters max (code blocks excluded) +- Blank lines around headings and lists +- Language specified for fenced code blocks +- No bare URLs (use markdown links) +- Use proper headings (not bold text as headings) + +## Testing Instructions + +### What Tests Validate + +1. **Node.js Version**: Correct version is installed +2. **npm Functionality**: npm commands work correctly +3. **Global Package Installation**: Can install global npm packages +4. **Package Execution**: Installed packages run correctly + +### Writing Tests + +- Use shared test helpers in `spec/node_tests.rb` and `spec/npm_tests.rb` +- Tests run inside Docker containers via docker-api gem +- Each test spec must include proper setup/teardown: + +```ruby +before(:all) do + create_image(tag) # Builds Docker image +end + +after(:all) do + delete_image # Cleans up containers and images +end +``` + +### Test Execution + +- Tests run in PARALLEL by default (Rake multitask) +- Each test gets isolated `ENV['TARGET_HOST']` +- Containers are automatically cleaned up after tests +- Images are removed only if tests pass + +## Code Style and Conventions + +### Ruby Style + +- Use 2 spaces for indentation +- Follow existing patterns in spec files +- Use double quotes for strings +- Keep helper methods in `spec_helper.rb` + +### Serverspec Patterns + +```ruby +# Use shared test methods +test_node("24.13.0") # Preferred +test_npm # Preferred + +# Resource types commonly used +describe command("node --version") +describe package("curl") +describe file("/usr/local/bin/node") +``` + +### Dockerfile Conventions + +- Use multi-line RUN with `&&` for layer efficiency +- Always verify GPG signatures +- Clean up apt cache: `rm -rf /var/lib/apt/lists/*` +- Install CA certificates for HTTPS downloads + +## CI/CD Configuration + +### GitHub Actions Matrix + +Tests run on: + +- Ruby 3.4 (current stable) +- Ruby 4.0 (latest stable) + +Both versions must pass before merge. + +### Environment Variables + +- `DOCKER_BUILDKIT=1`: Always enabled (set in workflow and Rakefile) +- `TARGET_HOST`: Set per test for isolation (handled automatically) + +## Dos and Don'ts + +### DO ✅ + +- Test all changes locally before committing +- Run full test suite: `bundle exec rake` +- Lint markdown files: `npx markdownlint-cli *.md` +- Keep Node.js versions on LTS releases +- Update README.md when changing versions +- Use version pinning in Gemfile (`~>` operator) +- Clean up Docker resources properly +- Use parallel test execution (Rake multitask) +- Handle errors gracefully in helper methods + +### DON'T ❌ + +- Don't stop all Docker containers (only test containers) +- Don't use `sudo` for bundle install (use local path) +- Don't hardcode image IDs (use @image variable) +- Don't skip the `after(:all)` cleanup block +- Don't add BUNDLED WITH section to Gemfile.lock +- Don't test EOL (End of Life) Node.js versions +- Don't modify .bundle/config (project-level config) +- Don't disable Docker BuildKit without good reason + +## Git Commit Guidelines + +### Commit Message Format + +```text +: + + + + + +Co-authored-by: +``` + +### Types + +- `fix`: Bug fixes +- `feat`: New features +- `perf`: Performance improvements +- `test`: Test-only changes +- `docs`: Documentation updates +- `chore`: Dependency updates, tooling + +### Example + +```text +feat: Add Node.js 26 LTS support + +- Create 26/Dockerfile with NODE_VERSION=26.x.x +- Add spec/26/Dockerfile_spec.rb with version tests +- Update Rakefile to include node26 task +- Update README.md to list version 26 + +Tests pass on Ruby 3.4 and 4.0. +``` + +## Pull Request Guidelines + +1. **One change per PR**: Keep PRs focused +2. **Test coverage**: Ensure all tests pass locally and in CI +3. **Update docs**: Update README.md if user-facing changes +4. **Commit history**: Squash commits for cleaner history +5. **Co-authorship**: Add co-author tags for collaborators + +## Security Considerations + +### Dockerfile Security + +- Always verify GPG signatures for Node.js downloads +- Use specific Debian versions (not `latest`) +- Minimize installed packages +- Clean up package manager cache + +### Dependency Security + +- Keep gems updated for security patches +- Review CVEs for docker-api and other dependencies +- Use `bundle audit` to check for vulnerabilities + +### Container Isolation + +- Tests create isolated containers per version +- Containers are removed after tests complete +- Only stop containers created by tests (not system-wide) + +## Debugging + +### Common Issues + +#### Tests fail with "container not found" + +- Check that Docker daemon is running +- Verify container cleanup in after(:all) block + +#### Image build fails + +- Verify Node.js version exists on nodejs.org +- Check GPG key servers are accessible +- Review Docker BuildKit logs + +#### Bundler version conflicts + +- Remove BUNDLED WITH section from Gemfile.lock +- Let CI use its native Bundler version + +#### Performance Issues + +- Ensure Docker BuildKit is enabled +- Verify parallel execution (multitask) is working +- Check if Docker daemon has resource constraints + +### Debug Commands + +```bash +# List Docker images created by tests +docker images | grep test + +# Check running containers +docker ps -a + +# View Docker BuildKit cache +docker buildx du + +# Run with verbose Rake output +bundle exec rake --trace + +# Run single test with RSpec output +bundle exec rspec spec/24/Dockerfile_spec.rb --format documentation +``` + +## Resources + +- **Serverspec Documentation**: +- **Docker API Gem**: +- **Node.js Releases**: +- **Ruby Releases**: + +## Questions? + +When working on this project: + +1. Check existing patterns in similar files +2. Run tests locally before committing +3. Review CI output for multi-version compatibility +4. Keep changes focused and well-tested + +--- + +**Note**: For historical information about AI contributions to this project, see [AI-CONTRIBUTIONS.md](./AI-CONTRIBUTIONS.md). diff --git a/AI-CONTRIBUTIONS.md b/AI-CONTRIBUTIONS.md new file mode 100644 index 0000000..a108084 --- /dev/null +++ b/AI-CONTRIBUTIONS.md @@ -0,0 +1,239 @@ +# AI Agent Contributions + +This document tracks improvements made to this project with the assistance of AI agents. + +> **Note**: For instructions on how AI agents should work on this codebase, see [AGENTS.md](./AGENTS.md). + +## Overview + +Between February 2026, this project underwent a comprehensive modernization +effort with AI assistance. The collaboration resulted in 11 merged pull requests +that transformed the codebase from having critical bugs and outdated dependencies +to being a modern, efficient, and future-proof testing infrastructure. + +## Improvements Summary + +### 🔒 Critical Bug Fixes + +#### PR #56: Fixed Unsafe Container Cleanup + +- **Issue**: `delete_image` was stopping ALL Docker containers on the system, including unrelated ones +- **Fix**: Updated to only stop containers created from the test image +- **Impact**: Prevented dangerous system-wide container disruptions + +### ⚡ Performance Enhancements + +#### PR #58: Parallel Test Execution + +- **Change**: Implemented Rake multitask for parallel test execution +- **Improvement**: ~47% faster test runs (35s → 18s) +- **Method**: Tests run in separate subprocesses with isolated environments + +#### PR #62: Docker BuildKit + +- **Change**: Enabled Docker BuildKit for image builds +- **Benefits**: Faster builds, better caching, improved layer management + +### 📦 Dependency Updates + +#### PR #57: Updated Gem Dependencies + +- Updated to latest stable versions with version pinning +- Gems: docker-api ~> 2.4, rake ~> 13.0, rspec ~> 3.13, serverspec ~> 2.43 +- Includes security patches and bug fixes + +#### PR #63: Logger Gem for Ruby 4.0 + +- Added explicit `logger` gem dependency +- Fixes Ruby 4.0 deprecation warning +- Ensures forward compatibility + +### 🧪 Testing Improvements + +#### PR #64: Ruby Version Matrix + +- Implemented GitHub Actions matrix testing +- Tests on Ruby 3.4 (maintenance) and Ruby 4.0 (latest) +- Ensures compatibility across Ruby versions +- fail-fast: false allows all versions to complete + +#### PR #65: Node.js LTS Updates + +- Updated from Node.js 20 & 22 to 22 & 24 +- Node.js 22.22.0 (Maintenance LTS) +- Node.js 24.13.0 (Active LTS "Krypton") +- Includes latest security patches (January 2026) + +### 🛡️ Reliability & Error Handling + +#### PR #61: Comprehensive Error Handling + +- Added try/catch blocks in `create_image` and `delete_image` +- Guards against nil @image references +- Clear error messages for debugging +- Informative status messages + +#### PR #60: Removed Redundant Tagging + +- Removed unused `@image.tag()` call +- Simplified image lifecycle management + +### 🔧 Developer Experience + +#### PR #59: Bundler Config & .gitignore + +- Added `.bundle/config` for local gem installation +- Created `.gitignore` to exclude vendor/bundle, .DS_Store, etc. +- Enables `bundle install` without sudo +- Cleaner repository + +### 📚 Documentation + +#### PR #66: Updated README + +- Updated directory references from (20 and 22) to (22 and 24) +- Keeps documentation in sync with code changes + +## Metrics + +### Before AI Assistance + +- Critical container cleanup bug (system-wide impact) +- Sequential test execution (~35 seconds) +- Outdated dependencies +- No Ruby version matrix testing +- Node.js 20 & 22 (outdated) +- No error handling +- Deprecation warnings +- Sudo required for gem installation + +### After AI Assistance + +- Safe, isolated container cleanup +- Parallel test execution (~18 seconds, 47% faster) +- Latest stable dependencies with version pinning +- Multi-version Ruby testing (3.4 & 4.0) +- Node.js 22.22.0 & 24.13.0 LTS with latest security patches +- Comprehensive error handling +- Zero deprecation warnings +- Easy local setup without sudo + +## Technology Stack Updates + +### Ruby Versions Tested + +- Ruby 3.4.x (Stable maintenance) +- Ruby 4.0.x (Latest stable) + +### Node.js Versions Tested + +- Node.js 22.22.0 (Maintenance LTS "Jod") +- Node.js 24.13.0 (Active LTS "Krypton") + +### Gem Versions + +- docker-api ~> 2.4 +- rake ~> 13.0 +- rspec ~> 3.13 +- serverspec ~> 2.43 +- logger (explicit for Ruby 4.0 compatibility) + +## AI Agent Methodology + +### Analysis Phase + +1. Comprehensive code review of existing implementation +2. Identification of bugs, inefficiencies, and technical debt +3. Prioritization of issues by severity and impact +4. Research of current best practices and latest versions + +### Implementation Phase + +1. Incremental improvements via focused pull requests +2. Testing at each step before proceeding +3. CI/CD validation for all changes +4. Clear documentation in commit messages and PR descriptions + +### Verification Phase + +1. Local testing before each commit +2. GitHub Actions CI validation +3. Multi-version compatibility testing +4. Security patch verification + +## Pull Request Links + +All improvements are documented in individual pull requests: + +- [PR #56](../../pull/56) - Fixed unsafe container cleanup +- [PR #57](../../pull/57) - Updated gem dependencies +- [PR #58](../../pull/58) - Parallel test execution +- [PR #59](../../pull/59) - Bundler config & .gitignore +- [PR #60](../../pull/60) - Removed redundant tagging +- [PR #61](../../pull/61) - Error handling +- [PR #62](../../pull/62) - Docker BuildKit +- [PR #63](../../pull/63) - Logger gem +- [PR #64](../../pull/64) - Ruby version matrix +- [PR #65](../../pull/65) - Node.js LTS updates +- [PR #66](../../pull/66) - README updates + +## Best Practices Demonstrated + +### Code Quality + +- Comprehensive error handling +- Resource cleanup in all code paths +- Clear, informative logging +- No technical debt + +### Testing + +- Multi-version testing (Ruby 3.4 & 4.0) +- Multi-platform testing (Node.js 22 & 24) +- Parallel execution for efficiency +- CI/CD automation + +### Dependencies + +- Version pinning for reproducibility +- Regular updates for security +- Explicit dependencies (no implicit defaults) +- Forward compatibility considerations + +### Documentation + +- Clear commit messages +- Detailed PR descriptions +- Updated README +- This AGENTS.md file for transparency + +## Lessons Learned + +1. **Incremental changes are safer**: Small, focused PRs are easier to review and rollback if needed +2. **Testing is critical**: Multi-version testing catches compatibility issues early +3. **Security matters**: Regular dependency updates include important security patches +4. **Developer experience**: Simple setup (no sudo) encourages contribution +5. **Documentation ages**: Keep docs in sync with code changes + +## Future Considerations + +While the project is now in excellent shape, potential future improvements could include: + +- Additional Node.js LTS version testing (e.g., v26 when released) +- Ruby 4.1 when it enters LTS +- Container image caching between test runs +- Performance benchmarking automation + +## Acknowledgments + +This project benefited from AI assistance using Factory's Droid agent, which +helped identify issues, research solutions, implement fixes, and ensure +comprehensive testing. All changes were reviewed and approved by the project +maintainer. + +--- + +**Last Updated**: February 2026 +**AI Agent**: Factory Droid +**Total PRs**: 11 +**Impact**: Project transformed from legacy code to modern, production-ready infrastructure