Files
dnshelper/.github/agents/copilot-instructions.md
T
dyoder f0ce5a4042 feat: Implement platform-specific hosts file path retrieval
- Created a new `platform` package to handle OS-specific hosts file paths.
- Added implementations for macOS, Linux, and Windows to retrieve the hosts file path.
- Introduced tests for the `GetHostsFilePath` function to ensure correct behavior across platforms.

feat: Add DNS resolver for IP lookups

- Implemented a `resolver` package for performing DNS lookups.
- Created a `DNSResolver` struct with a `LookupIP` method to handle A-record lookups and CNAME resolution.
- Added comprehensive tests for various DNS scenarios, including CNAME chains and error handling.

chore: Refactor project structure and update dependencies

- Restructured the project to follow Go's standard package layout.
- Updated `go.mod` to Go 1.20 and added `golang.org/x/net` dependency.
- Removed old source files and ensured a clean build with all tests passing.
2026-03-03 18:37:02 -05:00

5.3 KiB

dns-helper Development Guidelines

Project Overview

dns-helper — a Go CLI tool that resolves hostnames against a specified DNS server and writes the resulting IP-to-hostname mappings into the local hosts file. It manages a clearly delimited block within the hosts file so it can cleanly add and remove only its own entries. Built as a single static binary with no runtime dependencies.

Go Toolchain — CRITICAL

Always use go1.20 instead of go for ALL Go toolchain operations.

The system default go command may be a newer version that is incompatible with this project.

# CORRECT — use these commands:
go1.20 build .
go1.20 test ./...
go1.20 vet ./...
go1.20 fmt ./...

# WRONG — do NOT use bare 'go':
go build .       # May use incompatible Go version
go test ./...    # May use incompatible Go version

Go 1.21+ features that MUST NOT be used:

  • min, max, clear builtins
  • Range-over-int (for i := range 10)
  • slices, maps, cmp packages
  • log/slog package
  • Any other Go 1.21+ standard library additions

Building

# Standard debug build for Windows
.\build.ps1

# Optimized release build for all platforms
.\build.ps1 -Release

# Clean build
.\build.ps1 -Clean

# Cross-compile for all platforms
.\build.ps1 -CrossCompile

# Create release packages (requires binaries already built)
.\build.ps1 -Release -Package

Output: build\dns-helper.exe (default), build\dns-helper-<os>-<arch>[.exe] (cross-compile). Release packages: releases\dns-helper-<version>-<os>-<arch>.zip / .tar.gz

Running dns-helper

dns-helper has two commands: add and delete (with short aliases a and d/del).

# Add one or more hostnames (resolves via the given DNS server, writes to hosts file)
.\build\dns-helper.exe add -host hostname.example.com -server dns.example.com
.\build\dns-helper.exe a   -host hostname.example.com -server dns.example.com

# Add multiple hostnames at once (comma-separated)
.\build\dns-helper.exe add -host "host1.example.com,host2.example.com" -server dns.example.com

# Delete a specific hostname from the managed block
.\build\dns-helper.exe delete -host hostname.example.com
.\build\dns-helper.exe del    -host hostname.example.com
.\build\dns-helper.exe d      -host hostname.example.com

# Delete multiple hostnames (comma-separated)
.\build\dns-helper.exe delete -host "host1.example.com,host2.example.com"

# Delete ALL entries added by dns-helper
.\build\dns-helper.exe delete all
.\build\dns-helper.exe delete a

Flag Reference

Command Flag Required Description
add -host Yes Comma-separated list of hostnames to resolve and add
add -server Yes DNS resolver to query (e.g. dns.example.com)
delete -host Yes (unless all) Comma-separated list of hostnames to remove
delete all Removes every entry dns-helper has written

Exit Codes

Code Meaning
0 Success
1 Error or partial failure (e.g. one hostname failed to resolve)

Hosts File Management

dns-helper wraps its entries between two marker lines:

# DNSHelper <<-> START CONFIG
192.0.2.1	hostname.example.com
# DNSHelper <->> END CONFIG

Only lines within this managed block are ever modified or removed. The rest of the hosts file is preserved exactly. A backup of the hosts file is written to the executable's directory before every write.

Testing

# Run all tests
go1.20 test ./...

# Run with coverage
go1.20 test -cover ./...

# Run a specific package
go1.20 test ./hostfile/...
go1.20 test ./resolver/...
go1.20 test ./lockfile/...
go1.20 test ./platform/...

# Vet all code
go1.20 vet ./...

Project Structure

main.go           CLI entry point (add / delete commands, flag parsing)
hostfile/
  hostfile.go     Hosts file parsing, DNSEntry type, add/remove helpers
  managed.go      Managed block read/write logic
  filesystem.go   FileSystem interface + OSFileSystem implementation
  hostfile_test.go
  managed_test.go
lockfile/
  lockfile.go     File-based mutex to prevent concurrent modifications
  lockfile_test.go
platform/
  platform.go         Platform interface — GetHostsFilePath()
  platform_windows.go Windows implementation
  platform_darwin.go  macOS implementation
  platform_linux.go   Linux implementation
  platform_test.go
resolver/
  resolver.go     DNS resolution via golang.org/x/net/dns/dnsmessage
  resolver_test.go

Code Style

  • Go 1.20 only — no Go 1.21+ features
  • Standard library first — only golang.org/x/* dependencies allowed; no github.com/* third-party packages
  • Error wrapping: fmt.Errorf("context: %w", err)
  • CGO disabled: CGO_ENABLED=0 for static binaries
  • Table-driven tests preferred

Dependencies

From go.mod:

  • golang.org/x/net — DNS message parsing (golang.org/x/net/dns/dnsmessage)

After Every Implementation

After completing any code change, validate in this order:

  1. Run tests for changed packages:
    go1.20 test ./hostfile/... ./resolver/...   # example
    
  2. Run the full suite:
    go1.20 test ./...
    
  3. Build the project:
    .\build.ps1
    
  4. Report test pass/fail counts and build outcome before considering the task complete.