Co-authored-by: Charon (snider-linux) <charon@lethean.io> Co-authored-by: Snider <snider@host.uk.com> Co-authored-by: Virgil <virgil@lethean.io> Co-authored-by: Claude <developers@lethean.io> Reviewed-on: core/cli#2 Co-authored-by: Snider <snider@lethean.io> Co-committed-by: Snider <snider@lethean.io>
366 lines
15 KiB
Markdown
366 lines
15 KiB
Markdown
# Package Analysis — Batch 4
|
|
|
|
Generated by: gemini-batch-runner.sh
|
|
Models: gemini-2.5-flash-lite → gemini-3-flash-preview → gemini-3-pro-preview
|
|
Date: 2026-02-09
|
|
Packages: git repos gitea forge release
|
|
Total tokens: 92202
|
|
|
|
---
|
|
|
|
Here is the technical documentation for the analyzed packages, written from the perspective of a Senior Go Engineer.
|
|
|
|
# Framework Package Documentation
|
|
|
|
## 1. Package: `pkg/git`
|
|
|
|
### Overview
|
|
The `git` package provides a high-level abstraction over local Git operations, specifically designed for multi-repo workspace management. It combines direct shell execution for complex operations (push/pull with interactive auth) with concurrent status checking. It is designed to run both as a standalone utility library and as a registered `framework.Service` within the Core application.
|
|
|
|
### Public API
|
|
|
|
**Types**
|
|
```go
|
|
type RepoStatus struct {
|
|
Name, Path string
|
|
Modified, Untracked, Staged, Ahead, Behind int
|
|
Branch string
|
|
Error error
|
|
}
|
|
func (s *RepoStatus) IsDirty() bool
|
|
func (s *RepoStatus) HasUnpushed() bool
|
|
func (s *RepoStatus) HasUnpulled() bool
|
|
|
|
type StatusOptions struct {
|
|
Paths []string
|
|
Names map[string]string
|
|
}
|
|
|
|
type PushResult struct {
|
|
Name, Path string
|
|
Success bool
|
|
Error error
|
|
}
|
|
|
|
// Service integration
|
|
type Service struct { ... }
|
|
type ServiceOptions struct { WorkDir string }
|
|
```
|
|
|
|
**Functions**
|
|
```go
|
|
// Concurrent status checking
|
|
func Status(ctx context.Context, opts StatusOptions) []RepoStatus
|
|
|
|
// Interactive operations (hooks into os.Stdin/Stdout)
|
|
func Push(ctx context.Context, path string) error
|
|
func Pull(ctx context.Context, path string) error
|
|
func PushMultiple(ctx context.Context, paths []string, names map[string]string) []PushResult
|
|
|
|
// Error handling
|
|
func IsNonFastForward(err error) bool
|
|
|
|
// Service Factory
|
|
func NewService(opts ServiceOptions) func(*framework.Core) (any, error)
|
|
```
|
|
|
|
### Internal Design
|
|
* **Shell Wrapper**: Uses `os/exec` to invoke the system `git` binary rather than using a native Go implementation (like go-git). This ensures 100% compatibility with the user's local git configuration (SSH keys, hooks, GPG signing).
|
|
* **Concurrency**: `Status()` uses a `sync.WaitGroup` pattern to check multiple repository statuses in parallel, significantly speeding up workspace checks.
|
|
* **Interactive Mode**: `Push` and `Pull` explicitly wire `os.Stdin` and `os.Stdout` to the subprocess to allow SSH passphrase prompts or GPG pin entry to function correctly in a terminal environment.
|
|
* **Service Pattern**: Implements the `framework.ServiceRuntime` interface, registering distinct Queries (`QueryStatus`) and Tasks (`TaskPush`) to decouple the UI/CLI from the git logic.
|
|
|
|
### Dependencies
|
|
* `os/exec`: For invoking git commands.
|
|
* `forge.lthn.ai/core/cli/pkg/framework`: For service registration and message passing types.
|
|
|
|
### Test Coverage Notes
|
|
* **Mocking**: Testing requires abstracting `exec.Command`. Since this package calls `exec.CommandContext` directly, tests likely require overriding a package-level variable or using a "fake exec" pattern during test initialization.
|
|
* **Parsing**: Unit tests should cover the parsing logic of `git status --porcelain` in `getStatus` to ensure modified/staged/untracked counts are accurate.
|
|
* **Concurrency**: Race detection should be enabled to ensure `Status()` result slice assignment is thread-safe (it uses index-based assignment, which is safe).
|
|
|
|
### Integration Points
|
|
* **CLI**: The CLI command `core git status` consumes the `Service` via the framework's message bus.
|
|
* **Workspace Managers**: Packages managing multi-repo setups (like `pkg/repos`) use this to report health.
|
|
|
|
---
|
|
|
|
## 2. Package: `pkg/repos`
|
|
|
|
### Overview
|
|
This package manages the "Registry" of a multi-repository ecosystem. It acts as the source of truth for repository locations, types (foundation, module, product), and dependencies. It supports loading from a static `repos.yaml` or scanning the filesystem as a fallback.
|
|
|
|
### Public API
|
|
|
|
**Types**
|
|
```go
|
|
type Registry struct {
|
|
Repos map[string]*Repo
|
|
Defaults RegistryDefaults
|
|
...
|
|
}
|
|
|
|
type Repo struct {
|
|
Name, Type, Description, CI, Domain string
|
|
DependsOn []string
|
|
Docs bool
|
|
Path string // Computed
|
|
}
|
|
|
|
type RepoType string // "foundation", "module", "product", "template"
|
|
```
|
|
|
|
**Functions**
|
|
```go
|
|
// Loading
|
|
func LoadRegistry(m io.Medium, path string) (*Registry, error)
|
|
func FindRegistry(m io.Medium) (string, error)
|
|
func ScanDirectory(m io.Medium, dir string) (*Registry, error)
|
|
|
|
// Registry Methods
|
|
func (r *Registry) List() []*Repo
|
|
func (r *Registry) Get(name string) (*Repo, bool)
|
|
func (r *Registry) ByType(t string) []*Repo
|
|
func (r *Registry) TopologicalOrder() ([]*Repo, error)
|
|
|
|
// Repo Methods
|
|
func (repo *Repo) Exists() bool
|
|
func (repo *Repo) IsGitRepo() bool
|
|
```
|
|
|
|
### Internal Design
|
|
* **Abstraction**: Uses `io.Medium` to abstract filesystem access, making the registry testable without disk I/O.
|
|
* **Computed Fields**: The YAML struct is separate from the logic; `LoadRegistry` enriches the raw data with computed absolute paths and back-references.
|
|
* **Graph Theory**: `TopologicalOrder` implements a Depth-First Search (DFS) with cycle detection (`visiting` vs `visited` maps) to resolve build orders based on the `depends_on` field.
|
|
|
|
### Dependencies
|
|
* `gopkg.in/yaml.v3`: For parsing `repos.yaml`.
|
|
* `forge.lthn.ai/core/cli/pkg/io`: For filesystem abstraction (`io.Medium`).
|
|
|
|
### Test Coverage Notes
|
|
* **Circular Dependencies**: Critical test cases must define a registry with `A->B->A` dependencies to ensure `TopologicalOrder` returns a clear error and doesn't stack overflow.
|
|
* **Path Expansion**: Verify `~` expansion logic works across different OS mocks in `LoadRegistry`.
|
|
|
|
### Integration Points
|
|
* **Build System**: The build package uses `TopologicalOrder()` to determine the sequence in which to build libraries before products.
|
|
* **CI/CD**: Uses `Repo.Type` to apply different linting/testing rules (e.g., Foundation repos might require stricter coverage).
|
|
|
|
---
|
|
|
|
## 3. Packages: `pkg/gitea` & `pkg/forge`
|
|
|
|
*(Note: These packages share a very similar design pattern. `pkg/forge` is essentially a port of `pkg/gitea` for Forgejo.)*
|
|
|
|
### Overview
|
|
These packages provide typed clients for Gitea and Forgejo instances. They abstract the underlying SDKs to provide "Configuration-Aware" clients that automatically resolve authentication (Config vs Env vs Flags) and provide specialized helper methods for AI-driven metadata extraction (`PRMeta`).
|
|
|
|
### Public API (Common to both)
|
|
|
|
**Types**
|
|
```go
|
|
type Client struct { ... }
|
|
|
|
// Structural signals for AI analysis
|
|
type PRMeta struct {
|
|
Number int64
|
|
Title, State, Author, Branch, BaseBranch string
|
|
Labels, Assignees []string
|
|
IsMerged bool
|
|
CommentCount int
|
|
...
|
|
}
|
|
```
|
|
|
|
**Functions**
|
|
```go
|
|
// Construction
|
|
func New(url, token string) (*Client, error)
|
|
func NewFromConfig(flagURL, flagToken string) (*Client, error)
|
|
|
|
// Meta-data Extraction
|
|
func (c *Client) GetPRMeta(owner, repo string, pr int64) (*PRMeta, error)
|
|
func (c *Client) GetCommentBodies(...)
|
|
func (c *Client) GetIssueBody(...)
|
|
|
|
// Repo Management
|
|
func (c *Client) CreateMirror(...) // Gitea specific migration
|
|
func (c *Client) MigrateRepo(...) // Forgejo specific migration
|
|
func (c *Client) ListOrgRepos(...)
|
|
func (c *Client) ListUserRepos(...)
|
|
```
|
|
|
|
### Internal Design
|
|
* **Config Precedence Layer**: `ResolveConfig` implements a strict hierarchy: CLI Flags > Environment Variables > Config File (`~/.core/config.yaml`). This allows seamless switching between local dev and CI environments.
|
|
* **Dual-End Reader**: The `GetPRMeta` method aggregates data from multiple API endpoints (PR details + Issue Comments + Labels) into a flattened struct designed specifically to be fed into an LLM or policy engine.
|
|
* **Workarounds**: `pkg/forge/prs.go` implements a raw `net/http` PATCH request for `SetPRDraft` because the specific feature was missing or broken in the imported version of the Forgejo SDK.
|
|
|
|
### Dependencies
|
|
* `code.gitea.io/sdk/gitea` (for `pkg/gitea`)
|
|
* `codeberg.org/mvdkleijn/forgejo-sdk` (for `pkg/forge`)
|
|
* `forge.lthn.ai/core/cli/pkg/config`: For persistent auth storage.
|
|
|
|
### Test Coverage Notes
|
|
* **Draft Status**: The raw HTTP patch in `pkg/forge` needs integration testing against a real instance or a high-fidelity HTTP mock to ensure payload format matches Forgejo's API expectation.
|
|
* **Pagination**: `List*` methods implement manual pagination loops. Tests should simulate API responses with multiple pages to verify all items are collected.
|
|
|
|
### Integration Points
|
|
* **CI Pipelines**: Used to fetch PR context for "Smart CI" decisions.
|
|
* **Migration Tools**: The `CreateMirror`/`MigrateRepo` functions are used to synchronize repositories between GitHub and local Gitea/Forgejo instances.
|
|
|
|
---
|
|
|
|
## 4. Package: `pkg/release`
|
|
|
|
### Overview
|
|
The `release` package allows fully automated releases. It handles Semantic Versioning detection, Conventional Commit parsing for changelogs, build orchestration, and publishing to multiple downstream targets (GitHub, Docker, LinuxKit, etc.).
|
|
|
|
### Public API
|
|
|
|
**Types**
|
|
```go
|
|
type Config struct { ... } // Maps to release.yaml
|
|
type Release struct {
|
|
Version string
|
|
Artifacts []build.Artifact
|
|
Changelog string
|
|
...
|
|
}
|
|
```
|
|
|
|
**Functions**
|
|
```go
|
|
// Main Entry Points
|
|
func Run(ctx context.Context, cfg *Config, dryRun bool) (*Release, error)
|
|
func Publish(ctx context.Context, cfg *Config, dryRun bool) (*Release, error)
|
|
func RunSDK(ctx context.Context, cfg *Config, dryRun bool) (*SDKRelease, error)
|
|
|
|
// Utilities
|
|
func DetermineVersion(dir string) (string, error)
|
|
func Generate(dir, fromRef, toRef string) (string, error) // Changelog
|
|
func IncrementVersion(current string) string
|
|
```
|
|
|
|
### Internal Design
|
|
* **Pipeline Architecture**: `Run()` executes a linear pipeline:
|
|
1. **Versioner**: Checks Git tags -> parses SemVer -> increments patch (default).
|
|
2. **Changelog**: Parses `git log` via `ParseCommitType` (Conventional Commits regex) -> Buckets by type (Feat, Fix) -> Renders Markdown.
|
|
3. **Builder**: Delegates to `pkg/build` to compile binaries and generate checksums.
|
|
4. **Publisher**: Iterates over `Config.Publishers`, instantiates specific strategies via a Factory pattern (`getPublisher`), and executes them.
|
|
* **Separation of Concerns**: `Publish()` exists separately from `Run()` to support CI workflows where the *Build* step is separate from the *Release* step. It locates pre-existing artifacts in `dist/`.
|
|
* **SDK Generation**: Includes a specialized sub-pipeline (`RunSDK`) that handles OpenAPI diffing and client generation.
|
|
|
|
### Dependencies
|
|
* `forge.lthn.ai/core/cli/pkg/build`: For compiling artifacts.
|
|
* `forge.lthn.ai/core/cli/pkg/release/publishers`: Interface definitions for publishing targets.
|
|
* `golang.org/x/text`: For title casing in changelogs.
|
|
|
|
### Test Coverage Notes
|
|
* **SemVer Logic**: Extensive unit tests needed for `DetermineVersion` and `IncrementVersion` covering edge cases (v-prefix, no tags, pre-releases).
|
|
* **Regex**: Validate `conventionalCommitRegex` against a corpus of valid and invalid commit messages to ensure changelogs are generated correctly.
|
|
* **Config Unmarshaling**: `LoadConfig` uses complex nesting; tests should verify that `release.yaml` maps correctly to the internal structs, especially the `map[string]any` used for publisher-specific config.
|
|
|
|
### Integration Points
|
|
* **CI Runner**: This is the engine behind `core ci release`.
|
|
* **Build System**: Tightly coupled with `pkg/build`—it assumes artifacts are placed in `dist/` and accompanied by a `CHECKSUMS.txt`.
|
|
|
|
---
|
|
|
|
## Quick Reference (Flash Summary)
|
|
|
|
### Package: `pkg/git`
|
|
Provides utilities for git operations across multiple repositories and a service runtime for managing repository states.
|
|
|
|
**Key Exported Types and Functions**
|
|
- `RepoStatus`: Struct representing the state of a repository (ahead/behind counts, dirty status, branch).
|
|
- `Status()`: Checks git status for multiple repositories in parallel using goroutines.
|
|
- `Push()` / `Pull()`: Performs git operations in interactive mode to support SSH passphrase prompts.
|
|
- `PushMultiple()`: Executes pushes for multiple repositories sequentially.
|
|
- `Service`: A framework-compatible service that handles git-related tasks and queries.
|
|
- `IsNonFastForward()`: Utility to detect specific git push rejection errors.
|
|
|
|
**Dependencies**
|
|
- `pkg/framework`
|
|
|
|
**Complexity Rating**
|
|
Moderate
|
|
|
|
---
|
|
|
|
### Package: `pkg/repos`
|
|
Manages multi-repo workspaces by parsing a registry configuration and handling repository discovery.
|
|
|
|
**Key Exported Types and Functions**
|
|
- `Registry`: Represents a collection of repositories defined in `repos.yaml`.
|
|
- `Repo`: Represents a single repository with metadata and dependency information.
|
|
- `LoadRegistry()`: Loads and parses the repository registry from a given storage medium.
|
|
- `FindRegistry()`: Searches for a `repos.yaml` file in local and config directories.
|
|
- `ScanDirectory()`: Fallback mechanism to generate a registry by scanning a filesystem for git folders.
|
|
- `TopologicalOrder()`: Sorts repositories based on their dependency graph for build ordering.
|
|
|
|
**Dependencies**
|
|
- `pkg/io`
|
|
|
|
**Complexity Rating**
|
|
Moderate
|
|
|
|
---
|
|
|
|
### Package: `pkg/gitea`
|
|
A wrapper around the Gitea Go SDK for managing repositories, issues, and pull requests.
|
|
|
|
**Key Exported Types and Functions**
|
|
- `Client`: Primary wrapper for the Gitea API client.
|
|
- `NewFromConfig()`: Resolves authentication (token/URL) from flags, environment, or config files.
|
|
- `GetPRMeta()`: Extracts structural metadata from a pull request for pipeline analysis.
|
|
- `ListOrgRepos()` / `ListUserRepos()`: Lists repositories for organizations or the authenticated user.
|
|
- `CreateMirror()`: Uses the migration API to set up a pull mirror from a remote source.
|
|
- `GetCommentBodies()`: Retrieves all text content for PR comments.
|
|
|
|
**Dependencies**
|
|
- `pkg/log`
|
|
- `pkg/config`
|
|
|
|
**Complexity Rating**
|
|
Moderate
|
|
|
|
---
|
|
|
|
### Package: `pkg/forge`
|
|
A wrapper around the Forgejo Go SDK for repository management, issue tracking, and PR orchestration.
|
|
|
|
**Key Exported Types and Functions**
|
|
- `Client`: Primary wrapper for the Forgejo API client.
|
|
- `NewFromConfig()`: Tiered configuration loader for Forgejo instance connectivity.
|
|
- `GetPRMeta()`: Collects PR metadata, including state, labels, and comment counts.
|
|
- `MergePullRequest()`: Merges a PR using squash, rebase, or merge styles.
|
|
- `SetPRDraft()`: Manages draft status via raw HTTP PATCH (working around SDK limitations).
|
|
- `MigrateRepo()`: Imports repositories and metadata from external services.
|
|
|
|
**Dependencies**
|
|
- `pkg/log`
|
|
- `pkg/config`
|
|
|
|
**Complexity Rating**
|
|
Moderate
|
|
|
|
---
|
|
|
|
### Package: `pkg/release`
|
|
Orchestrates release automation, including changelog generation, versioning, and publishing to various targets.
|
|
|
|
**Key Exported Types and Functions**
|
|
- `Generate()`: Parses conventional commits to create markdown changelogs.
|
|
- `DetermineVersion()`: Calculates the next semantic version based on git tags and commit history.
|
|
- `Run()` / `Publish()`: Orchestrates the full process of building, archiving, and distributing artifacts.
|
|
- `RunSDK()`: Handles OpenAPI-based SDK generation and breaking change detection.
|
|
- `LoadConfig()`: Parses `.core/release.yaml` to configure build targets and publishers.
|
|
- `Config`: Struct defining project metadata, build targets, and distribution channels (Docker, Homebrew, etc.).
|
|
|
|
**Dependencies**
|
|
- `pkg/build`
|
|
- `pkg/io`
|
|
- `pkg/config`
|
|
- `pkg/log`
|
|
|
|
**Complexity Rating**
|
|
Complex
|