[teamai] Push 87 resource(s) from XingfenD
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# Auditing Dependencies
|
||||
|
||||
## Test-Only vs Binary Dependencies
|
||||
|
||||
Go's `go.mod` does **not** distinguish between test-only and production dependencies. All modules appear together, with `// indirect` marking transitive dependencies.
|
||||
|
||||
### What Gets Included in Your Binary
|
||||
|
||||
- `*_test.go` files are **never** compiled by `go build` — only by `go test`
|
||||
- Packages imported only by test files are not linked into the final binary
|
||||
- However, their modules still appear in `go.mod`
|
||||
|
||||
### Module Graph Pruning (Go 1.17+)
|
||||
|
||||
With `go 1.17` or higher in `go.mod`, Go prunes the module graph: transitive dependencies needed only for tests of other modules are excluded from the build graph. This reduces `go.mod` size and avoids downloading unnecessary modules.
|
||||
|
||||
### Upgrading With or Without Test Dependencies
|
||||
|
||||
```bash
|
||||
go get -u ./... # Upgrade deps, EXCLUDING test-only deps
|
||||
go get -u -t ./... # Upgrade deps, INCLUDING test-only deps
|
||||
```
|
||||
|
||||
### Impact on Binary Size
|
||||
|
||||
To check whether a large dependency is actually linked into your binary (vs. only used in tests), use `goweight` or `go-size-analyzer` — if the package doesn't appear in the binary breakdown, it's test-only and not contributing to binary size.
|
||||
|
||||
## Vulnerability Scanning with govulncheck
|
||||
|
||||
`govulncheck` reports known vulnerabilities that affect your code. It uses static analysis to narrow reports to vulnerabilities in code paths your project actually calls — unlike generic CVE scanners that flag every dependency regardless of usage.
|
||||
|
||||
```bash
|
||||
# Scan source code (most common)
|
||||
govulncheck ./...
|
||||
# Or, when govulncheck is pinned with a Go 1.24+ tool directive:
|
||||
go tool govulncheck ./...
|
||||
|
||||
# Scan a compiled binary
|
||||
govulncheck -mode=binary ./bin/myapp
|
||||
|
||||
# JSON output (for CI integration)
|
||||
govulncheck -format json ./...
|
||||
|
||||
# Include test code in analysis
|
||||
govulncheck -test ./...
|
||||
```
|
||||
|
||||
Output shows the vulnerability ID, affected module, fixed version, and the call trace from your code to the vulnerable function. If a vulnerability exists in a dependency but your code never calls the affected function, `govulncheck` does not flag it.
|
||||
|
||||
For CI pipeline integration, see the `samber/cc-skills-golang@golang-continuous-integration` skill.
|
||||
|
||||
## Tracking Outdated Dependencies with go-mod-outdated
|
||||
|
||||
`psampaz/go-mod-outdated` lists outdated direct dependencies with available updates.
|
||||
|
||||
```bash
|
||||
# Show outdated direct dependencies with available updates
|
||||
go list -u -m -json all | go-mod-outdated -update -direct
|
||||
|
||||
# Fail in CI if dependencies are outdated
|
||||
go list -u -m -json all | go-mod-outdated -update -direct -ci
|
||||
|
||||
# Markdown output
|
||||
go list -u -m -json all | go-mod-outdated -update -direct -style markdown
|
||||
```
|
||||
|
||||
Output columns: MODULE, CURRENT version, WANTED (latest minor/patch), LATEST (latest overall), and VALID TIMESTAMPS (warns if an "update" is chronologically older than current).
|
||||
|
||||
## Analyzing Dependency Size with goweight
|
||||
|
||||
`jondot/goweight` lists every package linked into the binary sorted by size contribution. It helps identify bloated dependencies and evaluate whether a lighter alternative exists.
|
||||
|
||||
```bash
|
||||
goweight # Sort by size
|
||||
goweight --json # JSON output for CI tracking
|
||||
```
|
||||
|
||||
**Modern alternative**: [go-size-analyzer](https://github.com/Zxilly/go-size-analyzer) (`gsa`) supports ELF, Mach-O, PE, and WebAssembly formats with interactive HTML/SVG visualization:
|
||||
|
||||
```bash
|
||||
go get -tool github.com/Zxilly/go-size-analyzer/cmd/gsa@latest
|
||||
go build -o ./myapp ./cmd/myapp
|
||||
go tool gsa -f html -o size-report.html ./myapp
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
# Automated Dependency Updates
|
||||
|
||||
Automate minor/patch dependency updates to reduce maintenance burden and stay current with security fixes. This requires a solid CI pipeline — tests and linting must pass before any auto-merge.
|
||||
|
||||
## Dependabot vs Renovate
|
||||
|
||||
| Feature | Dependabot | Renovate |
|
||||
| --- | --- | --- |
|
||||
| Platform | GitHub only | GitHub, GitLab, Bitbucket, self-hosted |
|
||||
| `go mod tidy` | Automatic | Opt-in (`gomodTidy`) |
|
||||
| Automerge | Separate workflow | Native support |
|
||||
| Grouping | Pattern-based | More flexible rules |
|
||||
| Monorepo support | Basic | Go workspaces aware |
|
||||
| Regex managers | No | Yes (Dockerfiles, Makefiles, etc) |
|
||||
|
||||
**Renovate is generally more mature and configurable.** Dependabot is simpler to set up for GitHub-only projects.
|
||||
|
||||
## Auto-Merge Strategy
|
||||
|
||||
- **Minor and patch updates**: Auto-merge only after CI passes (tests + lint + govulncheck) and the package is low-risk for the project
|
||||
- **Major updates**: Create PR for manual review (may contain breaking changes)
|
||||
- **Security updates**: Auto-merge regardless of version bump type
|
||||
|
||||
For workflow configuration files (dependabot.yml, renovate.json, auto-merge workflows), see the `samber/cc-skills-golang@golang-continuous-integration` skill.
|
||||
|
||||
## Update Verification
|
||||
|
||||
Before committing a dependency update:
|
||||
|
||||
0. Changelogs may suggest improvements applicable to the project.
|
||||
1. Run `go test ./...` and `go build ./...`
|
||||
2. Scan with `govulncheck ./...` or `go tool govulncheck ./...`
|
||||
3. Release notes/changelogs for libraries that affect persistence, serialization, networking, authentication, authorization, cryptography, or public APIs may contain important information about breaking changes
|
||||
4. Major version upgrades may contain breaking changes — the package's changelog documents them
|
||||
5. New APIs or patterns introduced in the updated version may offer improvements worth considering
|
||||
@@ -0,0 +1,75 @@
|
||||
# Dependency Conflicts & Resolution
|
||||
|
||||
## Diagnosing Conflicts
|
||||
|
||||
```bash
|
||||
# See why a module is in your build
|
||||
go mod why -m github.com/some/module
|
||||
|
||||
# See which version is selected
|
||||
go list -m github.com/some/module
|
||||
|
||||
# See the full requirement graph
|
||||
go mod graph
|
||||
|
||||
# List all modules in the build
|
||||
go list -m all
|
||||
```
|
||||
|
||||
## Resolution Strategies
|
||||
|
||||
**Force a specific version** (when two deps require incompatible versions):
|
||||
|
||||
```bash
|
||||
go mod edit -replace=example.com/pkg@v1.2.0=example.com/pkg@v1.3.1
|
||||
```
|
||||
|
||||
```go
|
||||
// go.mod
|
||||
replace example.com/pkg v1.2.0 => example.com/pkg v1.3.1
|
||||
```
|
||||
|
||||
**Use a local fork** (for debugging or patching):
|
||||
|
||||
```go
|
||||
replace example.com/pkg => ../my-local-fork
|
||||
```
|
||||
|
||||
**Block a problematic version**:
|
||||
|
||||
```bash
|
||||
go mod edit -exclude=example.com/pkg@v1.3.0
|
||||
```
|
||||
|
||||
When a version is excluded, any requirement on that version is redirected to the next higher available version.
|
||||
|
||||
**Force upgrade a transitive dependency**:
|
||||
|
||||
```bash
|
||||
go get github.com/transitive/dep@v1.5.0
|
||||
```
|
||||
|
||||
This adds an explicit requirement in your `go.mod`, overriding whatever the transitive dependency chain would select via MVS.
|
||||
|
||||
## Resolution Workflow
|
||||
|
||||
1. Run `go mod graph` and `go mod why -m <module>` to understand the dependency chain
|
||||
2. Identify which of your direct dependencies pulls in the conflicting version
|
||||
3. Try upgrading the direct dependency first: `go get github.com/direct/dep@latest`
|
||||
4. If that doesn't resolve it, use `replace` or `exclude` as a temporary fix
|
||||
5. Run `go mod tidy` to clean up
|
||||
6. Verify with `go build ./...` and `go test ./...`
|
||||
|
||||
**Important**: `replace` and `exclude` directives only take effect in the **main module's** `go.mod`. They are ignored when your module is used as a dependency. Remove `replace` directives before publishing a library.
|
||||
|
||||
## Retract (For Module Authors)
|
||||
|
||||
Mark versions as broken or accidentally published:
|
||||
|
||||
```go
|
||||
// go.mod
|
||||
retract v1.0.0 // Contains critical bug in auth
|
||||
retract [v1.1.0, v1.2.0] // Range of broken versions
|
||||
```
|
||||
|
||||
Retracted versions are still downloadable but `go get` will not select them by default, and `go list -m -u` warns about them.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Versioning & Minimal Version Selection
|
||||
|
||||
## Semantic Versioning (SemVer)
|
||||
|
||||
Go modules use **`vMAJOR.MINOR.PATCH`** (the `v` prefix is required):
|
||||
|
||||
- **MAJOR**: Breaking changes to the public API
|
||||
- **MINOR**: Backward-compatible new functionality
|
||||
- **PATCH**: Backward-compatible bug fixes
|
||||
|
||||
### Stability Rules
|
||||
|
||||
| Version | Stability |
|
||||
| ----------- | ----------------------------------------- |
|
||||
| `v0.x.x` | Unstable — no compatibility guarantees |
|
||||
| `v1.x.x`+ | Stable — backward-compatible within major |
|
||||
| Pre-release | Unstable (e.g., `v1.5.0-beta.1`) |
|
||||
|
||||
### Major Version Suffix Rule
|
||||
|
||||
For `v2` and above, the module path must include a `/vN` suffix. This is Go's import compatibility rule — different major versions are treated as entirely separate modules, allowing them to coexist in the same build:
|
||||
|
||||
```go
|
||||
// go.mod
|
||||
module github.com/example/pkg/v2
|
||||
|
||||
// Import in code
|
||||
import "github.com/example/pkg/v2/subpkg"
|
||||
```
|
||||
|
||||
Tags: `v2.0.0`, `v2.1.0`, etc. The `v0` and `v1` versions have no suffix.
|
||||
|
||||
### Special Cases
|
||||
|
||||
- **Pseudo-versions**: For untagged commits — `v0.0.0-20210101120000-abcdef123456` (base version + timestamp + commit hash)
|
||||
- **`+incompatible`**: Marks `v2+` modules that have not adopted the `/vN` path convention
|
||||
- **`gopkg.in`**: Always uses a version suffix with a dot — `gopkg.in/yaml.v3`
|
||||
|
||||
## Minimal Version Selection (MVS)
|
||||
|
||||
Go's dependency resolution algorithm is fundamentally different from npm, pip, or cargo.
|
||||
|
||||
### How It Works
|
||||
|
||||
Most package managers select the **latest** compatible version of each dependency. Go does the opposite: it selects the **minimum version that satisfies all requirements**. If module A requires `pkg@v1.2.0` and module B requires `pkg@v1.3.0`, MVS selects `v1.3.0` — the highest minimum required, not the latest available.
|
||||
|
||||
### Why This Design
|
||||
|
||||
- **Deterministic without a lock file**: Given the same `go.mod` inputs, MVS always produces the same build list. `go.sum` is just integrity verification.
|
||||
- **High fidelity**: Builds closely match what module authors tested against, since the nearest compatible version is selected rather than the latest.
|
||||
- **No solver needed**: The algorithm is simple graph traversal (under 50 lines of code), not an NP-hard constraint satisfaction problem.
|
||||
- **Reproducible across machines**: No "works on my machine" from different lock file states.
|
||||
|
||||
### Upgrades and Downgrades
|
||||
|
||||
- **Upgrade**: `go get pkg@v1.5.0` adds an edge to `v1.5.0` in the module graph and reruns MVS. Only the minimum necessary changes propagate.
|
||||
- **Downgrade**: `go get pkg@v1.2.0` removes all versions above `v1.2.0` from the graph, then walks backward to find the latest remaining versions of affected dependencies.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Visualizing the Dependency Graph
|
||||
|
||||
## go mod graph (Built-in)
|
||||
|
||||
```bash
|
||||
go mod graph
|
||||
```
|
||||
|
||||
Output: each line contains two space-separated fields (module and its requirement) in `path@version` format:
|
||||
|
||||
```
|
||||
example.com/main github.com/google/uuid@v1.6.0
|
||||
example.com/main golang.org/x/text@v0.3.7
|
||||
github.com/google/uuid@v1.6.0 golang.org/x/sys@v0.0.0-20210615035016
|
||||
```
|
||||
|
||||
## go mod why
|
||||
|
||||
```bash
|
||||
go mod why -m github.com/some/module
|
||||
```
|
||||
|
||||
Shows the shortest import path from your code to the module — useful for understanding why an unexpected dependency exists.
|
||||
|
||||
## Generate a Graph Image with modgraphviz
|
||||
|
||||
Pin `modgraphviz` as a module tool, then pipe `go mod graph` into it.
|
||||
|
||||
```bash
|
||||
go get -tool golang.org/x/exp/cmd/modgraphviz@latest
|
||||
go mod graph | go tool modgraphviz | dot -Tpng -o deps.png
|
||||
```
|
||||
|
||||
Green nodes represent versions selected by MVS (in the final build list). Grey nodes are versions that exist in the requirement graph but are not used.
|
||||
|
||||
## Interactive Visualization with go-mod-graph
|
||||
|
||||
`go-mod-graph` (samber/go-mod-graph) is a web-based interactive dependency explorer with zoomable graph, module weight indicators, searchable module list, and MVS algorithm visualization.
|
||||
|
||||
## Complementary Analysis
|
||||
|
||||
Pin `digraph` as a module tool for graph queries.
|
||||
|
||||
```bash
|
||||
go get -tool golang.org/x/tools/cmd/digraph@latest
|
||||
# General graph queries on go mod graph output
|
||||
go mod graph | go tool digraph reverse example.com/some/module
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
# Go Workspaces (go.work)
|
||||
|
||||
## go.work vs go.mod
|
||||
|
||||
| Scenario | Use |
|
||||
| ---------------------------------------------- | --------- |
|
||||
| Single module project | `go.mod` |
|
||||
| Developing multiple related local modules | `go.work` |
|
||||
| Monorepo with separate Go modules | `go.work` |
|
||||
| Testing local changes across module boundaries | `go.work` |
|
||||
| Published library consumed by others | `go.mod` |
|
||||
|
||||
## Workspace Commands
|
||||
|
||||
```bash
|
||||
go work init # Initialize workspace
|
||||
go work use ./services/auth # Add module to workspace
|
||||
go work use -rm ./old-module # Remove module from workspace
|
||||
go work sync # Sync workspace with module changes
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Workspaces eliminate the need for `replace` directives during local development — the workspace automatically resolves local modules
|
||||
- **Do not commit `go.work.sum`** to version control (add to `.gitignore`)
|
||||
- `go.work` is for development only — it does not affect how consumers of your published modules resolve dependencies
|
||||
- For workspace directory structure examples, see the `samber/cc-skills-golang@golang-project-layout` skill
|
||||
Reference in New Issue
Block a user