repometa

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 10 Imported by: 0

README

repometa

A Go library that scans a source repository and reports the components (buildable units) it contains, plus any monorepo workspace layouts it recognizes.

CI Release Go Reference Go Report Card Conventional Commits

Table of Contents

Overview

repometa scans a directory tree and returns a manifest describing each buildable component it recognizes (Go module, Rust crate, Python package, Node package, CMake project, …) along with any monorepo workspace layout that groups them. It exists to unblock downstream tools that need to reason about arbitrary repositories without re-implementing discovery. Behavioral detection ("does the team use uv") is deliberately out of scope — only artifacts present are reported.

Status

v0 — API is unstable and will break without notice. This library exists to unblock a small set of first-party consumer tools; when a second consumer appears, the API will be reviewed for stability.

Non-goals
  • CLI. Import the library.
  • JSON schema stability. Encode to whatever format you want in the caller.
  • Behavioral detection. Only artifacts present are reported.
  • Full ecosystem coverage. Detectors are added when a consumer needs them.

Features

  • Bounded, symlink-safe directory traversal with a hardcoded skip list (.git, node_modules, .venv, vendor, target, dist, build, .next, .angular, …).
  • Per-ecosystem detectors returning typed component and workspace records.
  • Framework attributes on node-package (js.framework=nextjs, js.framework=angular).
  • Package-manager attributes on python-package (python.pm={uv,poetry,pipenv,pip}).
  • Configurable bounds (max depth, max directories visited, max file size read) via Option functions.
Supported detectors (v0)
Ecosystem Component kinds Workspace kinds
Go go-module go-workspace (from go.work)
Rust rust-crate, rust-workspace cargo-workspace
Python python-package uv-workspace
Node / JS / TS node-package npm-yarn-workspace, pnpm-workspace, nx, turborepo
CMake cmake-project
Make make-project
C c-source-tree (only when no structured build system)
Assembly asm-source-tree (only when no structured build system)

Requirements

  • Go 1.26 or newer (see go.mod).
  • No runtime dependencies beyond the Go standard library and the two transitive indirect deps listed in go.sum (github.com/BurntSushi/toml, gopkg.in/yaml.v3).

Installation

go get github.com/jedi-knights/repometa@latest

Pin to a specific version:

go get github.com/jedi-knights/repometa@v0.1.0

Usage

package main

import (
    "fmt"

    "github.com/jedi-knights/repometa"
)

func main() {
    manifest, err := repometa.Scan("/path/to/repo")
    if err != nil {
        panic(err)
    }
    for _, c := range manifest.Components {
        fmt.Println(c.Kind, c.Root, c.Attributes)
        for _, ws := range c.Workspaces {
            fmt.Println("  workspace:", ws.Kind, ws.Members)
        }
    }
}

API Documentation

Full API reference is published on pkg.go.dev. Every exported type, function, and option carries a godoc comment; treat pkg.go.dev as the authoritative reference and this README as an introduction.

Configuration

Scan accepts Option functions to override traversal bounds. Defaults live in options.go.

Option Default Purpose
WithMaxDepth(n) defaultMaxDepth Cap directory descent depth.
WithMaxDirs(n) defaultMaxDirs Cap total directories visited.
WithMaxFileSize(n) defaultMaxFileSize Cap bytes read per file when inspecting content.

The walker refuses to descend into a hardcoded skip list and skips all symlinks. These bounds are not tunable — they are safety invariants, not preferences.

Development

git clone https://github.com/jedi-knights/repometa.git
cd repometa
go mod download
go build ./...

Lint locally (matches CI):

golangci-lint run
Project layout
  • scan.go — entry point (Scan, ScanWith).
  • walker.go — bounded, symlink-safe directory traversal.
  • detect_*.go — one file per ecosystem detector.
  • detectors.go — detector registry and dispatch.
  • manifest.goManifest, Component, Workspace types.
  • options.go — traversal-bound Option functions and defaults.

Testing

go test -race ./...

Coverage report:

go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

CI enforces a 70% coverage floor. The floor is deliberately below the current level so a modest regression does not block merges; raise it in .github/workflows/ci.yml once coverage stabilizes above 80%.

Roadmap

Milestones roughly correspond to detector coverage and API stability.

  • v0.x — additional detectors added on demand as consumers appear. API may break.
  • v1.0 — API frozen once a second first-party consumer exists and stresses the shape of Manifest, Component, and Workspace.
  • Post-v1 — detector plugins loaded at runtime (only if a consumer needs custom ecosystem detection).

Open issues track individual detector requests. Detector requests without a concrete consumer are declined by default — see Non-goals.

Releases

Releases are automated by go-semantic-release. On every push to main:

  1. CI runs lint, tests, and the 70% coverage gate.
  2. On success, the Release workflow analyzes conventional commits since the last tag.
  3. If a release is warranted, semantic-release writes CHANGELOG.md and VERSION, pushes a vX.Y.Z tag, and creates the matching GitHub Release.

Consumers pull the tagged version via go get github.com/jedi-knights/repometa@vX.Y.Z.

Commit messages must follow Conventional Commits: feat: and fix: drive minor/patch bumps, feat!: or a BREAKING CHANGE: footer drives a major bump.

Versioning

repometa follows Semantic Versioning 2.0.0. While the library is in v0, minor version bumps may include breaking API changes — pin to an exact version in production. Once v1 ships, breaking changes will only appear in major version bumps.

Changelog

See CHANGELOG.md. The changelog is generated automatically from conventional commits by the release workflow — do not edit it by hand.

Contributing

Contributions are welcome. Please open an issue before starting substantial work so the direction can be agreed on.

  • Fork the repository and create a topic branch from main.
  • Write tests for new behavior; keep coverage above the CI floor.
  • Ensure golangci-lint run and go test -race ./... pass locally.
  • Use Conventional Commits so the release pipeline can compute the next version.
  • Open a pull request against main describing the change and its motivation.

One PR should carry one type(scope): pair — split unrelated changes into separate PRs.

Code of Conduct

This project follows the Contributor Covenant v2.1. By participating, you agree to abide by its terms. Report unacceptable behavior to the maintainer at omar.crosby@gmail.com.

Security

Do not open public issues for security vulnerabilities. Instead, email omar.crosby@gmail.com with a description of the issue and, if possible, a reproduction. You will receive an acknowledgment within 72 hours and a coordinated disclosure timeline for the fix.

Support

This is a spare-time project; response times are best-effort.

Acknowledgments

  • go-semantic-release — automates the release pipeline.
  • golangci-lint — meta-linter used in CI.
  • The maintainers of each ecosystem's build-system conventions (Cargo, uv, pnpm, Turborepo, CMake, …) whose file formats this library reads.

Maintainers

License

MIT — see LICENSE.

Documentation

Overview

Package repometa scans a source repository and reports the components (buildable units) it contains, plus any monorepo workspace layouts it recognizes. It is intended to be imported by downstream tools that need to reason about arbitrary repositories without re-implementing discovery logic.

The API is unstable. See the repo README for scope and non-goals.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Component

type Component struct {
	Kind       Kind
	Root       string // path relative to Manifest.Root; "." for the repo root
	Evidence   []Evidence
	Confidence float64 // 0.0 – 1.0; heuristic hits report < 1.0
	Workspaces []Workspace
	Attributes map[string]string
}

Component describes a single buildable unit inside the repo, anchored at a specific directory. A directory may produce multiple Components when more than one ecosystem's manifest is present (e.g. a Rust crate with a co-located Node package).

type Evidence

type Evidence struct {
	Path   string
	Reason string
}

Evidence records a single fact that led to a Component being reported. Path is relative to Manifest.Root so evidence remains meaningful when the manifest is transported.

type Kind

type Kind string

Kind identifies the type of a Component. Values are open-ended strings so new detectors can be added without breaking consumers on enum drift.

const (
	KindGoModule      Kind = "go-module"
	KindRustCrate     Kind = "rust-crate"
	KindRustWorkspace Kind = "rust-workspace"
	KindPythonPackage Kind = "python-package"
	KindNodePackage   Kind = "node-package"
	KindCMakeProject  Kind = "cmake-project"
	KindMakeProject   Kind = "make-project"
	KindCSource       Kind = "c-source-tree"
	KindAsmSource     Kind = "asm-source-tree"
)

Kind values for every ecosystem detector shipped in this package. See the README's "Supported detectors" table for the mapping to ecosystem.

type Manifest

type Manifest struct {
	Root       string
	Components []Component
	Stats      ScanStats
}

Manifest is the result of scanning a repository. Consumers are expected to iterate Components; the ordering is deterministic (depth-first, lexicographic within a directory) so diff-friendly serializations are possible.

func Scan

func Scan(root string, opts ...Option) (*Manifest, error)

Scan walks root and returns a Manifest describing every detected component. The returned Manifest is non-nil on success.

Precondition: root must be an existing directory. The walk is bounded by the caps documented on Option constructors.

type Option

type Option func(*options)

Option configures a Scan call.

func WithMaxDepth

func WithMaxDepth(n int) Option

WithMaxDepth caps directory recursion depth. The scan root is depth 0.

func WithMaxDirs

func WithMaxDirs(n int) Option

WithMaxDirs caps the total number of directories visited during the scan. The walk aborts silently when this cap is hit; Stats.DirCapHits will be non-zero when this happens.

func WithMaxFileSize

func WithMaxFileSize(n int64) Option

WithMaxFileSize caps how many bytes any single manifest file may be read into memory. Files above this cap are skipped for content parsing but their presence is still recorded as evidence.

type ScanStats

type ScanStats struct {
	DirsVisited     int
	FilesSeen       int
	DepthCapHits    int
	DirCapHits      int
	SymlinksSkipped int
}

ScanStats reports counters from the walk, useful for downstream tools that want to know whether they hit a cap and should widen the scan.

type Workspace

type Workspace struct {
	Kind    WorkspaceKind
	Members []string
}

Workspace describes a monorepo layout anchored at a Component. Members are paths (relative to Manifest.Root) of the workspace's constituent packages. Members may be empty when the workspace kind was detected by file presence alone (see docs on each WorkspaceKind).

type WorkspaceKind

type WorkspaceKind string

WorkspaceKind identifies the workspace / monorepo tooling in use.

const (
	WorkspaceGo        WorkspaceKind = "go-workspace"
	WorkspaceCargo     WorkspaceKind = "cargo-workspace"
	WorkspaceNpmYarn   WorkspaceKind = "npm-yarn-workspace"
	WorkspacePnpm      WorkspaceKind = "pnpm-workspace"
	WorkspaceNx        WorkspaceKind = "nx"
	WorkspaceTurborepo WorkspaceKind = "turborepo"
	WorkspaceUv        WorkspaceKind = "uv-workspace"
)

WorkspaceKind values for every workspace layout recognized by the detectors in this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL