cfad 0.2.0

Cloudflare Admin CLI - Rust-based management tool for Cloudflare
Documentation
# Contributing to CFAD (Cloudflare Admin CLI)


Thank you for your interest in contributing to CFAD! This document provides guidelines and instructions for contributing.

## Code of Conduct


This project adheres to a Code of Conduct (see CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.

## How Can I Contribute?


### Reporting Bugs


Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include:

- **Clear title and description**
- **Steps to reproduce** the issue
- **Expected behavior** vs actual behavior
- **Environment details** (OS, Rust version, cfad version)
- **Error messages** or logs if applicable

Use the bug report template when creating a new issue.

### Suggesting Features


Feature suggestions are welcome! When suggesting a feature:

- **Explain the use case** - why is this feature needed?
- **Describe the solution** - what would you like to happen?
- **Consider alternatives** - have you thought of other approaches?

Use the feature request template when creating a new issue.

### Pull Requests


1. **Fork** the repository and create your branch from `main`
2. **Make your changes** with clear, focused commits
3. **Add tests** for new functionality
4. **Update documentation** if needed
5. **Run tests** - ensure all tests pass (`cargo test`)
6. **Run clippy** - ensure no warnings (`cargo clippy -- -D warnings`)
7. **Format code** - run `cargo fmt`
8. **Submit PR** with a clear description

#### Pull Request Guidelines


- **One feature per PR** - keep PRs focused
- **Write good commit messages** - use conventional commits format
- **Include tests** - minimum 80% coverage for new code
- **Update CHANGELOG.md** - add entry under "Unreleased"
- **Reference issues** - link related issues in PR description

## Development Setup


### Prerequisites


- **Rust** 1.70 or later ([rustup.rs]https://rustup.rs)
- **Git** for version control
- **Cloudflare account** with API token (for testing against real API)

### Getting Started


```bash
# Clone your fork

git clone https://github.com/YOUR_USERNAME/cloudflare-cli-rs.git
cd cloudflare-cli-rs

# Build the project

cargo build

# Run tests

cargo test

# Run clippy

cargo clippy -- -D warnings

# Format code

cargo fmt

# Build release binary

cargo build --release
```

### Project Structure


```
cloudflare-cli-rs/
├── src/
│   ├── main.rs          # CLI entry point
│   ├── lib.rs           # Library exports for testing
│   ├── api/             # API type definitions
│   ├── cli/             # CLI command definitions
│   ├── client/          # HTTP client and auth
│   ├── config/          # Configuration management
│   ├── error/           # Error types
│   ├── ops/             # API operations (DNS, Zone, Cache)
│   ├── output/          # Output formatting
│   └── utils/           # Utility functions
├── tests/
│   ├── integration/     # Integration tests with wiremock
│   └── common/          # Test helpers
├── docs/
│   └── examples/        # Example files (CSV, BIND)
└── Cargo.toml
```

## Testing


### Running Tests


```bash
# All tests

cargo test

# Unit tests only

cargo test --lib

# Integration tests only

cargo test --test integration

# Specific test

cargo test test_name

# With output

cargo test -- --nocapture
```

### Writing Tests


- **Unit tests** - Add `#[cfg(test)]` modules in source files
- **Integration tests** - Use `tests/integration/` directory
- **Use wiremock** - Mock Cloudflare API responses
- **Test coverage** - Aim for 80%+ on new code

Example unit test:

```rust
#[cfg(test)]

mod tests {
    use super::*;

    #[test]
    fn test_parse_csv_valid() {
        let csv = "type,name,content\nA,www,203.0.113.1";
        let records = parse_csv_format(csv).unwrap();
        assert_eq!(records.len(), 1);
    }
}
```

Example integration test:

```rust
use wiremock::{Mock, MockServer, ResponseTemplate};
use wiremock::matchers::{method, path};

#[tokio::test]

async fn test_list_zones() {
    let mock_server = MockServer::start().await;

    Mock::given(method("GET"))
        .and(path("/zones"))
        .respond_with(ResponseTemplate::new(200)
            .set_body_json(/* ... */))
        .mount(&mock_server)
        .await;

    // Test implementation
}
```

## Code Style


### Rust Guidelines


- Follow [Rust API Guidelines]https://rust-lang.github.io/api-guidelines/
- Use `cargo fmt` for formatting (enforced in CI)
- Use `cargo clippy` for linting (no warnings allowed)
- Write clear, self-documenting code
- Add comments for complex logic only

### Commit Messages


Use [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <description>

[optional body]

[optional footer]
```

Types:

- `feat:` - New feature
- `fix:` - Bug fix
- `docs:` - Documentation changes
- `test:` - Test additions/changes
- `refactor:` - Code refactoring
- `perf:` - Performance improvements
- `chore:` - Build/tooling changes

Examples:

```
feat(dns): add BIND zone file import support
fix(client): handle rate limiting correctly
docs(readme): update installation instructions
test(dns): add CSV parser edge case tests
```

## Documentation


### Code Documentation


- **Public APIs** - Must have doc comments (`///`)
- **Examples** - Include usage examples in doc comments
- **Modules** - Add module-level documentation

```rust
/// Lists DNS records for a zone.
///
/// # Arguments
///
/// * `client` - Authenticated Cloudflare client
/// * `zone_id` - Zone identifier
/// * `record_type` - Optional filter by record type (e.g., "A", "CNAME")
///
/// # Example
///
/// ```
/// let records = list_records(&client, "zone123", Some("A")).await?;
/// ```
pub async fn list_records(
    client: &CloudflareClient,
    zone_id: &str,
    record_type: Option<&str>,
) -> Result<Vec<DnsRecord>> {
    // Implementation
}
```

### User Documentation


- Update **README.md** for user-facing changes
- Add examples to **docs/examples/** if needed
- Update **CHANGELOG.md** for all changes

## Release Process


Releases are managed by maintainers:

1. Update version in `Cargo.toml`
2. Update `CHANGELOG.md` - move "Unreleased" to version section
3. Commit: `chore(release): prepare v0.3.0`
4. Tag: `git tag -a v0.3.0 -m "Release v0.3.0"`
5. Push: `git push && git push --tags`
6. GitHub Actions builds and creates release

## Getting Help


- **Questions** - Open a discussion or issue
- **Chat** - (Coming soon)
- **Email** - <davidcforbes@aol.com>

## Recognition


Contributors are recognized in:

- GitHub contributors page
- Release notes
- CHANGELOG.md (for significant contributions)

## License


By contributing, you agree that your contributions will be licensed under the MIT License.

---

**Thank you for contributing to CFAD!** 🎉