chore: add README, Makefile, CI, lint config and --version

The repo had no README, Makefile, CI, linter config or version string.

- README.md: requirements (ffmpeg/ffprobe, plus yt-dlp for SoundCloud), build,
  the per-source credentials table, usage, the quality scale and the download
  database's migration behaviour. Every claim was checked against the code
  rather than written from memory, which is how the quality-range bug below was
  found. It also records the two deferred refactors (no shared HTTP layer, and
  metadata as map[string]any) so they are documented rather than lore, and
  notes that there is no LICENSE file.
- Makefile: build, install, test, race, cover, fmt, fmt-check, vet, lint,
  check, clean, help. `make build` stamps version/commit/date via -ldflags.
- .github/workflows/ci.yml: gofmt, vet, build, test and test -race, plus a
  lint job. The linter is intentionally unpinned, with a comment: a
  golangci-lint built against an older Go cannot analyse a go1.25 module, which
  is the same reason a locally installed staticcheck built with go1.24 cannot
  run here.
- .golangci.yml: standard set plus bodyclose, errorlint, nilerr and
  govet/copylocks. copylocks matters now that config.Config carries a mutex;
  bodyclose and errorlint target defects this codebase actually has.
- `rip --version` / `-V`, documented in the help output, falling back to the
  VCS revision the toolchain embeds for `go install` builds.

Fixes a bug introduced in the previous commit: Validate capped deezer quality
at 2 and soundcloud at 1, but config.toml.example documents deezer as 2/3/4 and
the global -q flag accepts 0-4, so a documented config would have failed to
load. deezer's buildFormatPriority treats anything >= 2 as FLAC and soundcloud
ignores the value entirely, so the real ceiling is 4 everywhere; only the Qobuz
and Beatport floor of 1 is a genuine constraint. Pinned with a test that walks
the whole documented range.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
JorenandClaude Opus 5 committed 2026-10-03 17:14:59 +02:00
1 parent 384f32cd67
commit ff5fb1cdb5
10 files changed
+433 -6

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
BINARY := rip
PKG := ./cmd/rip
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
COMMIT ?= $(shell git rev-parse HEAD 2>/dev/null)
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS := -X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.date=$(DATE)
.DEFAULT_GOAL := build
.PHONY: build
build: ## Build the rip binary
go build -ldflags "$(LDFLAGS)" -o $(BINARY) $(PKG)
.PHONY: install
install: ## Install rip into GOBIN
go install -ldflags "$(LDFLAGS)" $(PKG)
.PHONY: test
test: ## Run the test suite
go test ./...
.PHONY: race
race: ## Run the test suite under the race detector
go test -race ./...
.PHONY: cover
cover: ## Run tests and report per-package coverage
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out | tail -1
.PHONY: fmt
fmt: ## Format all Go files
gofmt -w .
.PHONY: fmt-check
fmt-check: ## Fail if any file is not gofmt-clean
@out="$$(gofmt -l .)"; \
if [ -n "$$out" ]; then echo "not gofmt-clean:"; echo "$$out"; exit 1; fi
.PHONY: vet
vet: ## Run go vet
go vet ./...
.PHONY: lint
lint: ## Run golangci-lint if it is installed
@if command -v golangci-lint >/dev/null 2>&1; then \
golangci-lint run; \
else \
echo "golangci-lint not installed; skipping"; \
echo " go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \
fi
.PHONY: check
check: fmt-check vet test ## Everything CI runs
.PHONY: clean
clean: ## Remove build and coverage artifacts
rm -f $(BINARY) coverage.out
.PHONY: help
help: ## List targets
@grep -hE '^[a-z-]+:.*?## ' $(MAKEFILE_LIST) | awk -F':.*?## ' '{printf " %-12s %s\n", $$1, $$2}'