docs: allow approved third-party packages #59
@@ -2,8 +2,22 @@
|
||||
|
||||
## Language & Dependencies
|
||||
|
||||
- Go standard library only — no external dependencies.
|
||||
- Target the latest stable Go release.
|
||||
- **STRICT ALLOWLIST:** Only packages listed below may be imported. No exceptions.
|
||||
|
||||
### Approved Third-Party Packages
|
||||
|
||||
| Package | Use Case |
|
||||
|---------|----------|
|
||||
| `gopkg.in/yaml.v3` | YAML parsing (persona files, config) |
|
||||
| `github.com/google/go-cmp` | Test comparisons (`cmp.Diff`) |
|
||||
|
||||
|
|
||||
**Any import not in this table or the Go standard library is forbidden.**
|
||||
|
||||
To request a new dependency:
|
||||
1. Open a PR that ONLY updates this table with justification
|
||||
2. Requires explicit approval from Aaron
|
||||
3. After merge, a separate PR may use the package
|
||||
|
sonnet-review-bot
commented
[NIT] The sentence 'Transitive dependencies of approved packages are automatically allowed' is a policy statement that the check-deps.sh script does NOT currently verify (it only checks direct deps via **[NIT]** The sentence 'Transitive dependencies of approved packages are automatically allowed' is a policy statement that the check-deps.sh script does NOT currently verify (it only checks direct deps via `go list -m`). This is correct behavior—you generally don't want to enumerate all transitive deps—but the wording could be clearer: something like 'Transitive dependencies pulled in by approved packages do not need to be listed here' to make it clear this is intentional, not an oversight.
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.PHONY: build test test-integration lint clean coverage
|
||||
.PHONY: build test test-integration lint clean coverage check-deps
|
||||
|
||||
build:
|
||||
go build -o review-bot ./cmd/review-bot/
|
||||
@@ -12,9 +12,15 @@ test-integration:
|
||||
lint:
|
||||
go vet ./...
|
||||
|
||||
check-deps:
|
||||
|
gpt-review-bot
commented
[NIT] The check-deps script requires Bash 4+. On macOS, default /bin/bash is 3.x; while the script emits guidance, you might consider documenting this requirement alongside the new precommit target for developer setup clarity. **[NIT]** The check-deps script requires Bash 4+. On macOS, default /bin/bash is 3.x; while the script emits guidance, you might consider documenting this requirement alongside the new precommit target for developer setup clarity.
|
||||
@./scripts/check-deps.sh
|
||||
|
||||
clean:
|
||||
rm -f review-bot
|
||||
|
||||
coverage:
|
||||
go test -coverprofile=coverage.out ./...
|
||||
go tool cover -func=coverage.out
|
||||
|
||||
# Precommit runs all checks required before pushing
|
||||
precommit: check-deps lint test
|
||||
|
[MINOR] The new **[MINOR]** The new `precommit` target runs the dependency check, but unless CI invokes this target, policy enforcement may not occur in CI. Ensure CI runs `make precommit` (or otherwise invokes `check-deps`) to prevent unapproved dependencies from being merged.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# check-deps.sh - Enforces the strict dependency allowlist from CONVENTIONS.md
|
||||
# Exit 1 if any unapproved import is found.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Approved third-party packages (from CONVENTIONS.md)
|
||||
ALLOWED=(
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/google/go-cmp"
|
||||
)
|
||||
|
||||
# Build regex pattern from allowed list
|
||||
ALLOWED_PATTERN=""
|
||||
for pkg in "${ALLOWED[@]}"; do
|
||||
if [ -z "$ALLOWED_PATTERN" ]; then
|
||||
ALLOWED_PATTERN="$pkg"
|
||||
else
|
||||
ALLOWED_PATTERN="$ALLOWED_PATTERN|$pkg"
|
||||
fi
|
||||
done
|
||||
|
||||
# Get all imports from go.mod (excluding the module itself and stdlib)
|
||||
|
gpt-review-bot
commented
[MINOR] Uses 'grep -P' (Perl regex), which is not available on macOS/BSD grep by default. This reduces cross-platform developer usability for the precommit hook. **[MINOR]** Uses 'grep -P' (Perl regex), which is not available on macOS/BSD grep by default. This reduces cross-platform developer usability for the precommit hook.
|
||||
IMPORTS=$(go list -m all 2>/dev/null | tail -n +2 | awk '{print $1}' || true)
|
||||
|
||||
if [ -z "$IMPORTS" ]; then
|
||||
echo "✅ No external dependencies"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
VIOLATIONS=""
|
||||
while IFS= read -r import; do
|
||||
|
gpt-review-bot
commented
[NIT] Parsing the markdown table with **[NIT]** Parsing the markdown table with `grep`/`awk` is somewhat brittle (e.g., relies on backticks around package names and exact column positions). This is acceptable given the documented process, but a brief note in CONVENTIONS.md to preserve formatting would help avoid accidental breakage.
|
||||
# Skip empty lines
|
||||
[ -z "$import" ] && continue
|
||||
|
||||
|
gpt-review-bot
commented
[MINOR] The filter **[MINOR]** The filter `[[ "$pkg" =~ ^[a-zA-Z] ]]` rejects valid import paths that begin with a digit (e.g., 9fans.net/go). Consider relaxing to `^[[:alnum:]]` or removing the check, since the header row is already excluded by the grep.
|
||||
# Check if import matches any allowed pattern (prefix match for subpackages)
|
||||
MATCHED=false
|
||||
for allowed in "${ALLOWED[@]}"; do
|
||||
if [[ "$import" == "$allowed" ]] || [[ "$import" == "$allowed/"* ]]; then
|
||||
MATCHED=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$MATCHED" = false ]; then
|
||||
VIOLATIONS="$VIOLATIONS\n - $import"
|
||||
fi
|
||||
done <<< "$IMPORTS"
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo "❌ UNAPPROVED DEPENDENCIES DETECTED"
|
||||
echo -e "The following imports are not in the allowlist:$VIOLATIONS"
|
||||
echo ""
|
||||
echo "To add a dependency:"
|
||||
echo " 1. Open a PR that ONLY updates CONVENTIONS.md"
|
||||
echo " 2. Get explicit approval from Aaron"
|
||||
echo " 3. After merge, use the package in a separate PR"
|
||||
|
sonnet-review-bot
commented
[NIT] The comment says 'POSIX-compatible' for the awk parsing but the outer loop uses a Bash process substitution **[NIT]** The comment says 'POSIX-compatible' for the awk parsing but the outer loop uses a Bash process substitution `< <(...)` which is Bash-specific. The comment is mildly misleading — it means awk itself is POSIX, not the overall approach.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All dependencies are approved"
|
||||
[NIT] The table lists
github.com/google/go-cmpwith scope 'test only', but the enforcement script (check-deps.sh) does not differentiate between production and test-only scope — it checks all direct go.mod dependencies uniformly. Ifgo-cmpends up in go.mod as a direct dependency (which it will when used in_test.gofiles), it passes the allowlist check regardless of where it's imported. The 'test only' scope annotation is purely documentation with no mechanical enforcement. This is acceptable but worth noting so future maintainers don't assume it's enforced.[NIT] The note 'Transitive dependencies of approved packages are automatically allowed' is a policy statement, but the enforcement script only checks direct module dependencies (via
go list -m ... allwith.Indirectfiltered out). This is correct and intentional, but it's worth confirming the wording matches: transitive deps won't appear as violations, which aligns with the statement.