Documentation
¶
Overview ¶
Package depupdate provides direct dependency update functionality that bypasses the Smith AI worker. It reuses depcheck scanners to discover outdated packages, groups them, applies updates via package-manager commands, verifies them with Temper, and wires changelog generation + PR creation.
Index ¶
- func CheckoutUpdateBranch(ctx context.Context, anvilPath string) (string, error)
- func CloseMatchingDepBeads(ctx context.Context, anvilPath string, groups []UpdateGroup) error
- func CommitGroup(ctx context.Context, anvilPath string, group UpdateGroup) error
- func CreatePR(ctx context.Context, anvilPath, anvilName, branch string, groups []UpdateGroup) (string, error)
- func DetectBilingual(anvilPath string) bool
- func FormatSummaryLine(results []AnvilResult, opts Options) string
- func GenerateChangelog(anvilPath string, groups []UpdateGroup, isBilingual bool) error
- func InstallDotnetGroup(ctx context.Context, projectDir string, group UpdateGroup) error
- func InstallGoGroup(ctx context.Context, moduleDir string, group UpdateGroup) error
- func InstallNpmGroup(ctx context.Context, projectDir string, group UpdateGroup) error
- func PrintSummary(w io.Writer, results []AnvilResult, opts Options) int
- func RollbackGroup(_ context.Context, anvilPath string, group UpdateGroup, reason error) error
- func VerifyGroup(ctx context.Context, anvilPath string, anvilConfig config.AnvilConfig) (*temper.Result, error)
- type Anvil
- type AnvilReport
- type AnvilResult
- type Options
- type Result
- type Runner
- type UpdateGroup
- func ExecuteGroups(ctx context.Context, anvilPath string, anvilCfg config.AnvilConfig, ...) []UpdateGroup
- func FilterGroups(groups []UpdateGroup, opts Options) []UpdateGroup
- func GroupUpdates(ctx context.Context, results []*depcheck.CheckResult) []UpdateGroup
- func SelectGroups(r io.Reader, w io.Writer, groups []UpdateGroup, yesAll bool) []UpdateGroup
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckoutUpdateBranch ¶
CheckoutUpdateBranch creates or checks out the batch-update branch for the current date (deps/batch-update-<YYYY-MM-DD>) in the given anvil directory. The branch is based on origin's default branch so that the diff never includes unrelated changes from a feature branch or detached HEAD. If the branch already exists locally it is checked out. If it exists only on the remote it is fetched and tracked. Returns the branch name and an error if the branch cannot be created or checked out.
func CloseMatchingDepBeads ¶
func CloseMatchingDepBeads(ctx context.Context, anvilPath string, groups []UpdateGroup) error
CloseMatchingDepBeads closes any open depcheck beads whose title references a package covered by one of the provided UpdateGroups. It is called after CreatePR returns successfully so that stale "Deps(<eco>): update <pkg> …" beads are removed from the queue instead of accumulating as resolved work.
func CommitGroup ¶
func CommitGroup(ctx context.Context, anvilPath string, group UpdateGroup) error
CommitGroup stages all changes and creates a commit for the successfully installed group. The commit message follows the conventional format: "chore(deps): update <group-name> (<kind>)".
func CreatePR ¶
func CreatePR(ctx context.Context, anvilPath, anvilName, branch string, groups []UpdateGroup) (string, error)
CreatePR pushes the given branch to origin and opens a single pull request summarising all updated groups for the given anvil. The branch must have already been created and checked out by CheckoutUpdateBranch. Returns the PR URL reported by gh, or an error if any step fails.
func DetectBilingual ¶
DetectBilingual reports whether the changelog.d/ directory in anvilPath contains bilingual fragments (files ending in .en.md or .nb.md). This mirrors the convention used by other projects that maintain separate English and Norwegian changelog files.
func FormatSummaryLine ¶
func FormatSummaryLine(results []AnvilResult, opts Options) string
FormatSummaryLine returns a one-line summary like "12 outdated dependencies across 3 anvils".
func GenerateChangelog ¶
func GenerateChangelog(anvilPath string, groups []UpdateGroup, isBilingual bool) error
GenerateChangelog writes one or two changelog fragment files for the given set of dependency update groups into <anvilPath>/changelog.d/, then git-adds and commits them.
Fragment naming:
- Monolingual: deps-batch-<YYYY-MM-DD-HHmmss>.md
- Bilingual: deps-batch-<YYYY-MM-DD-HHmmss>.en.md (English) deps-batch-<YYYY-MM-DD-HHmmss>.nb.md (Norwegian — same content)
The timestamp suffix makes each invocation collision-safe so that multiple runs on the same day do not overwrite each other.
The isBilingual flag can be set explicitly by the caller, or the caller can use DetectBilingual to derive it from the existing changelog directory.
func InstallDotnetGroup ¶
func InstallDotnetGroup(ctx context.Context, projectDir string, group UpdateGroup) error
InstallDotnetGroup runs `dotnet add <csproj> package <name> -v <version>` for each package in the group. It searches the project directory for the .csproj file that contains a PackageReference for each package.
func InstallGoGroup ¶
func InstallGoGroup(ctx context.Context, moduleDir string, group UpdateGroup) error
InstallGoGroup runs `go get pkg1@v1 pkg2@v2 ...` followed by `go mod tidy` in the given module directory. Returns an error if either command fails.
func InstallNpmGroup ¶
func InstallNpmGroup(ctx context.Context, projectDir string, group UpdateGroup) error
InstallNpmGroup runs `npm install pkg1@v1 pkg2@v2 ...` with all packages in the group at once. Returns an error if the install fails (peer dep conflict, network error, etc.).
If group.SourceDir is set, npm install runs there (the directory containing the relevant package.json). Otherwise projectDir (the anvil root) is used as a fallback.
func PrintSummary ¶
func PrintSummary(w io.Writer, results []AnvilResult, opts Options) int
PrintSummary writes a human-readable summary of outdated dependencies to w. Returns the total number of updates displayed.
func RollbackGroup ¶
RollbackGroup discards all uncommitted changes in the anvil directory by running `git reset --hard` (resets both index and working tree) followed by `git clean -fdx` (removes untracked files including ignored artifacts such as node_modules/, bin/, obj/). It logs which group failed and why. Uses a fresh context with a 30-second timeout so that rollback still succeeds even when the caller's context has been cancelled.
func VerifyGroup ¶
func VerifyGroup(ctx context.Context, anvilPath string, anvilConfig config.AnvilConfig) (*temper.Result, error)
VerifyGroup runs temper (build + lint + test) against the anvil to confirm that the group's updates haven't broken anything. Returns the temper result so the caller can decide to commit or rollback.
Types ¶
type Anvil ¶
type Anvil struct {
// Name is the anvil's logical identifier (used in display and logging).
Name string
// Path is the absolute filesystem path to the repository root.
Path string
// Config carries per-anvil settings (temper flags, race detection, etc.).
Config config.AnvilConfig
// DB is used for event logging during scans. May be nil to disable logging.
DB *state.DB
// Timeout is the per-anvil scan timeout. Zero defaults to 5 minutes.
Timeout time.Duration
}
Anvil describes a repository workspace for dependency scanning and updates.
type AnvilReport ¶
type AnvilReport struct {
// Anvil is the source descriptor used when scanning.
Anvil Anvil
// Groups holds the update groups ready for Apply or Preview.
Groups []UpdateGroup
// Errors contains per-ecosystem scan errors (ecosystem name → error).
// A nil map means all ecosystems scanned successfully.
Errors map[string]error
}
AnvilReport summarizes the available updates and pre-grouped changes for one anvil. Returned by Scan so callers (Hearth, Ledger) can display or apply updates without going through the CLI.
func Scan ¶
Scan runs dependency checks across the given anvils and returns per-anvil reports with updates pre-grouped for display or application. Per-anvil scan failures are captured in AnvilReport.Errors rather than aborting the whole scan, so callers always receive a report for every requested anvil.
This function provides the programmatic equivalent of `forge update-deps` without the interactive CLI layer, allowing Hearth and Ledger to query available updates directly.
type AnvilResult ¶
type AnvilResult struct {
Anvil string
Path string
Ecosystems []*depcheck.CheckResult
}
AnvilResult holds scan results for a single anvil, potentially spanning multiple ecosystems (Go, npm, NuGet).
func (*AnvilResult) TotalUpdates ¶
func (ar *AnvilResult) TotalUpdates(opts Options) int
TotalUpdates returns the total number of outdated dependencies across all ecosystems for this anvil, respecting the given filter options.
type Options ¶
type Options struct {
// PatchOnly limits results to patch-level updates only.
PatchOnly bool
// NoMajor excludes major version updates from results.
NoMajor bool
}
Options controls which updates are included in a scan.
type Result ¶
type Result struct {
// Group is the UpdateGroup that was processed.
Group UpdateGroup
// Applied is true when the group was installed, verified, and committed.
Applied bool
// Err holds the error that caused the group to be skipped or rolled back.
// Nil when Applied is true.
Err error
}
Result records the outcome of applying a single UpdateGroup.
func Apply ¶
func Apply(ctx context.Context, anvilPath string, anvilCfg config.AnvilConfig, groups []UpdateGroup) ([]Result, error)
Apply executes the given groups against the specified anvil by installing packages, verifying with Temper (build + lint + test), and committing on success or rolling back on failure. It returns one Result per input group.
This function provides the programmatic equivalent of the apply phase in `forge update-deps --create-pr`, without the branch/PR/changelog steps. Callers (Hearth, Ledger) can wrap it with their own PR and changelog logic.
func Preview ¶
func Preview(groups []UpdateGroup) []Result
Preview returns a Result slice describing what Apply would do for the given groups without making any changes to disk or running any package-manager commands. It is the dry-run variant used by Hearth's overlay preview so users can inspect pending updates before confirming application.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner orchestrates dependency scanning across anvils using the existing depcheck scanners. Future sub-tasks will add update execution, grouping, and PR creation methods.
func NewRunner ¶
NewRunner creates a Runner that uses the provided depcheck Scanner for discovering outdated dependencies.
type UpdateGroup ¶
type UpdateGroup struct {
Name string // e.g. "vite ecosystem", "@tailwindcss packages", "lodash"
Updates []depcheck.ModuleUpdate // packages in this group
Kind string // worst-case kind: "major" > "minor" > "patch"
Ecosystem string // e.g. "Go", "npm", "NuGet"
SourceDir string // directory containing the manifest (e.g. package.json); empty means repo root
}
UpdateGroup represents a set of related package updates that should be installed together atomically.
func ExecuteGroups ¶
func ExecuteGroups(ctx context.Context, anvilPath string, anvilCfg config.AnvilConfig, groups []UpdateGroup) []UpdateGroup
ExecuteGroups applies each UpdateGroup to the given anvil by installing packages, running Temper verification, and committing on success or rolling back on failure. It returns the subset of groups that were successfully applied and committed.
func FilterGroups ¶
func FilterGroups(groups []UpdateGroup, opts Options) []UpdateGroup
FilterGroups returns only the groups whose Kind is allowed by opts. Groups whose kind is excluded by PatchOnly or NoMajor are dropped.
func GroupUpdates ¶
func GroupUpdates(ctx context.Context, results []*depcheck.CheckResult) []UpdateGroup
GroupUpdates takes scan results for a single anvil and groups related packages so they can be installed atomically.
Grouping strategies are applied in order:
- Peer dep groups (npm only) — packages sharing peer dependencies
- Scope groups — packages sharing an npm scope (@scope/*)
- Standalone — each remaining package becomes its own group
func SelectGroups ¶
func SelectGroups(r io.Reader, w io.Writer, groups []UpdateGroup, yesAll bool) []UpdateGroup
SelectGroups presents each UpdateGroup to the user and collects a yes/no response. When yesAll is true every group is accepted without prompting. The function reads responses from r and writes prompts to w.