6.2 KiB
6.2 KiB
AGENTS.md - Development Guidelines for my-log-wynter
Project Overview
my-log-wynter is a Go CLI application that extends the codeberg.org/danjones000/my-log CLI library with custom commands. It integrates with youtube-dl/yt-dlp for video metadata fetching. It uses and github.com/lrstanley/go-ytdlp for yt-dlp integration.
Build/Lint/Test Commands
Building
# Build all packages
go build ./...
# Build the CLI binary
go build -o my-log ./cmd/my-log
# Run the CLI
go run ./cmd/my-log
Testing
# Run all tests
go test ./...
# Run a single test by name
go test -run <TestName> ./...
# Run tests with verbose output
go test -v ./...
# Run tests with coverage
go test -cover ./...
# Run benchmarks
go test -bench=. ./...
Linting
# Run golangci-lint (comprehensive linter)
golangci-lint run ./...
# Run golangci-lint with auto-fix
golangci-lint run ./... --fix
# Run go vet
go vet ./...
# Format code (gofmt)
gofmt -w .
gofmt -d .
# Check for unused imports and other issues
goimports -w .
Dependencies
# Update dependencies
go get -u ./...
# Tidy go.mod
go mod tidy
# List dependencies
go list -m all
Code Style Guidelines
General Conventions
- Follow Effective Go and Go Code Review Comments
- Use Go 1.26.0 or later (as specified in go.mod)
- Run
go fmtandgofmtbefore committing - Run
golangci-lint run ./...before committing
Naming Conventions
- Packages: Use short, lowercase names (e.g.,
ytdlp, notyt-dlporyoutube_dlp) - Variables/Functions: Use camelCase (e.g.,
fetchURL, notfetch_url) - Exported Functions/Types: Use PascalCase (e.g.,
Fetch, notfetch) - Constants: Use PascalCase (e.g.,
MaxRetries) or camelCase for unexported (e.g.,maxRetries) - Acronyms: Keep original casing (e.g.,
URL, notUrl;ID, notId) - Files: Use lowercase with underscores for multiple words (e.g.,
fetch_video.go)
Import Organization
Imports should be organized in three groups separated by blank lines:
- Standard library packages
- External/third-party packages
- Internal packages (if applicable)
import (
"context"
"fmt"
"os"
"codeberg.org/danjones000/my-log/cli"
"github.com/lrstanley/go-ytdlp"
)
Error Handling
- Return errors where possible; avoid panics except for truly unrecoverable conditions
- Wrap errors with context using
fmt.Errorf("description: %w", err)or%v - Handle errors explicitly; don't ignore them with
_ - Place error checks immediately after the operation that can fail
// Good
result, err := fetchURL(ctx, url)
if err != nil {
return nil, fmt.Errorf("failed to fetch %s: %w", url, err)
}
// Avoid
result, _ := fetchURL(ctx, url) // Don't ignore errors
Context Usage
- Pass
context.Contextas the first parameter for functions that may timeout or be cancelled - Use
context.Background()for top-level operations andcontext.WithTimeout()for bounded operations - Check for context cancellation with
ctx.Err()when appropriate
func Fetch(ctx context.Context, url string) (*Result, error) {
// ...
}
Types and Interfaces
- Define interfaces close to where they are used
- Prefer concrete types unless interface polymorphism is needed
- Use pointer receivers (
*T) for methods that modify the receiver or when nil is meaningful
Testing Conventions
- Test files should be named
*_test.go - Test functions should start with
Test(e.g.,TestFetch) - Benchmark functions should start with
Benchmark(e.g.,BenchmarkFetch) - Use the github.com/nalgeon/be for assertions:
be.Equal,be.Err, andbe.True - Use table-driven tests when testing multiple cases:
func TestFetch(t *testing.T) {
tests := []struct {
name string
url string
wantErr bool
}{
{"valid youtube", "https://youtube.com/watch?v=xxx", false},
{"invalid url", "not-a-url", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// test logic
be.Equal(t, 2*5, 10)
be.True(t, !false)
be.Err(t, err, nil) // No error
be.Err(t, ioErr, io.EOF) // ioErr should be an io.EOF
be.Err(t, otherErr, "bad stuff") // error message contains "bad stuff"
})
}
}
Concurrency
- Use goroutines with
gokeyword for concurrent operations - Use
sync.WaitGroupor channels for synchronization - Prefer
errgroupfor coordinating multiple goroutines with error handling - Never leak goroutines; ensure they can complete or be cancelled
Documentation
- Document exported functions, types, and constants with doc comments
- Comments should start with the identifier name (no need to repeat the name)
- Keep comments concise but explanatory
// Fetch retrieves video metadata from yt-dlp compatible sources.
func Fetch(ctx context.Context, url string) (*Info, error) {
// ...
}
Logging
- Print user-friendly messages to stderr
Project Structure
my-log-wynter/
├── cmd/my-log/ # CLI entry point
│ └── main.go
├── ytdlp/ # yt-dlp integration package
│ └── fetch.go
├── go.mod
├── go.sum
└── AGENTS.md # This file
Common Tasks
Adding a new command
- Add the command to the my-log library (this project imports it)
- Update this repository's code as needed
Adding a new yt-dlp feature
- Modify
ytdlp/fetch.go - Add tests in
ytdlp/fetch_test.go - Run tests with
go test -v ./ytdlp/
Pre-commit Checklist
- Code is formatted:
gofmt -w . - Imports are organized:
goimports -w . - No lint errors:
golangci-lint run ./... - Tests pass:
go test ./... - Code builds:
go build ./...
Git Commit Guidelines
- Format: Prepend commit messages with a gitmoji emoji (see https://gitmoji.dev)
- Style: Write detailed commit messages that explain what changed and why
- Examples:
✨ Add JSON export functionality for log entries,🐛 Fix date parsing for RFC3339 timestamps,📝 Update README with configuration examples - Do not commit files not yet staged unless explicitly asked to do so.