Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Codacy configuration for starlet.
#
# Exclude the vendored, pinned third-party JSON-repair runtime from static
# analysis. lib/json/internal/jsonrepair is a verbatim copy of
# analysis. internal/jsonrepair is a verbatim copy of
# kaptinlin/jsonrepair v0.2.2 (MIT); its style/complexity is upstream's to
# own, and the copy is kept byte-for-byte so it can be re-vendored cleanly.
exclude_paths:
- 'lib/json/internal/jsonrepair/**'
- 'internal/jsonrepair/**'
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ A new module must satisfy **all three**, otherwise it goes to `starpkg/*`:
2. **Universally needed.** Broad, domain-neutral utility. Domain modules (sqlite, web, llm, mq, s3…) are starpkg's job no matter how clean they are.
3. **Zero third-party dependencies.** Stdlib-only (or an extension of an existing core module). Any `go.sum` entry is inherited by every downstream — one third-party requirement sends the module to starpkg.

**The vendoring exception** (the `lib/json/internal/jsonrepair` precedent): a frozen, **same-license (MIT)**, **stdlib-only** third-party runtime may be vendored under `lib/<m>/internal/<pkg>/` to keep `go.sum` clean, when the capability is judged worth it. Requirements: pin to a specific upstream release (record it), copy runtime `.go` files only (no `_test.go`, no upstream test deps), keep the upstream LICENSE in the directory, add a `doc.go` stating provenance + "do not edit by hand; re-vendor to update", golden-lock the observed behavior in our tests, and exclude the path in `codecov.yml` and `.codacy.yml`. Measure the binary delta in the go1.19 container before committing to it.
**The vendoring exception** (the `internal/jsonrepair` precedent): a frozen, **same-license (MIT)**, **stdlib-only** third-party runtime may be vendored under the top-level `internal/<pkg>/` — all vendored third-party code lives under the single `internal/` so it is easy to find and license-audit in one place — to keep `go.sum` clean, when the capability is judged worth it. Requirements: pin to a specific upstream release (record it), copy runtime `.go` files only (no `_test.go`, no upstream test deps), keep the upstream LICENSE in the directory, add a `doc.go` stating provenance + "do not edit by hand; re-vendor to update", golden-lock the observed behavior in our tests, and exclude the path in `codecov.yml` and `.codacy.yml`. Measure the binary delta in the go1.19 container before committing to it.

**License hygiene caps vendoring.** Never vendor differently-licensed source — even permissive (Apache-2.0) — into this MIT repository: the copied files keep their license and the repo becomes mixed-license. For a capability worth a differently-licensed library, use a **module dependency** instead, and only when it passes the evaluation bar: its go.mod must not exceed this repo's Go floor, it should bring zero (or near-zero) transitive dependencies into `go.sum`, the binary delta is measured in the go1.19 container, and its panic surface is audited + hostile-input tested (the `lib/json` jsonschema decision: Apache-2.0, go1.19 exactly, zero requires, +256 KiB measured → module dep, repo stays pure MIT).

Expand Down
6 changes: 3 additions & 3 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Codecov configuration for starlet.
#
# Exclude the vendored, pinned third-party JSON-repair runtime from coverage.
# lib/json/internal/jsonrepair is a verbatim copy of kaptinlin/jsonrepair
# internal/jsonrepair is a verbatim copy of kaptinlin/jsonrepair
# v0.2.2 (MIT), frozen at its go1.18/1.19-compatible release. It is exercised
# through the json.repair tests, but mirroring its upstream branch coverage is
# not a gate this repository maintains.
ignore:
- "lib/json/internal/jsonrepair"
- "lib/json/internal/jsonrepair/**/*"
- "internal/jsonrepair"
- "internal/jsonrepair/**/*"
94 changes: 0 additions & 94 deletions doc_coverage_test.go

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion lib/json/repair.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"regexp"
"strings"

"github.com/1set/starlet/lib/json/internal/jsonrepair"
"github.com/1set/starlet/internal/jsonrepair"
"go.starlark.net/starlark"
)

Expand Down
86 changes: 86 additions & 0 deletions module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"io"
"io/fs"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"testing"

Expand Down Expand Up @@ -1360,3 +1362,87 @@ func TestGetBuiltinModuleNamesWithoutCapabilities(t *testing.T) {
}
}
}

// --- documentation coverage (folded in from the former doc_coverage_test.go) ---

// libReadmeDir maps a builtin module name to its lib/<dir> documentation
// directory. The only non-identity case is go_idiomatic -> goidiomatic;
// modules backed by go.starlark.net (math, struct, time) have no lib README
// and are skipped below.
func libReadmeDir(module string) string {
return strings.ReplaceAll(module, "_", "")
}

// moduleSurface enumerates the script-visible names a module exports, across
// the three registration shapes: a starlarkstruct.Module (its Members), a
// starlarkstruct.Struct (its AttrNames), or a flat StringDict (its keys).
func moduleSurface(t *testing.T, name string) []string {
loader := starlet.GetBuiltinModule(name)
if loader == nil {
return nil
}
sd, err := loader()
if err != nil {
t.Fatalf("load module %q: %v", name, err)
}
var out []string
for k, v := range sd {
switch m := v.(type) {
case *starlarkstruct.Module:
for mk := range m.Members {
out = append(out, mk)
}
case *starlarkstruct.Struct:
out = append(out, m.AttrNames()...)
default:
out = append(out, k)
}
}
sort.Strings(out)
return out
}

// TestDocCoverage asserts that every script-visible member of every lib/*
// module is documented in that module's README. The matching logic lives in
// tools/doccov/coverage.star and runs through a starlet Machine, so the check
// dogfoods the regex module.
func TestDocCoverage(t *testing.T) {
script, err := os.ReadFile(filepath.Join("tools", "doccov", "coverage.star"))
if err != nil {
t.Fatalf("read coverage script: %v", err)
}

surface := map[string]interface{}{}
docs := map[string]interface{}{}
var skipped []string
for _, name := range starlet.GetAllBuiltinModuleNames() {
readme, err := os.ReadFile(filepath.Join("lib", libReadmeDir(name), "README.md"))
if err != nil {
skipped = append(skipped, name) // external module without a lib README
continue
}
docs[name] = string(readme)
names := moduleSurface(t, name)
members := make([]interface{}, len(names))
for i, n := range names {
members[i] = n
}
surface[name] = members
}

m := starlet.NewWithNames(starlet.StringAnyMap{"surface": surface, "docs": docs}, nil, []string{"regex"})
m.SetScriptContent(script)
out, err := m.Run()
if err != nil {
t.Fatalf("doc coverage script failed: %v", err)
}
if report, ok := out["report"].(string); ok {
t.Log("\n" + report)
}
sort.Strings(skipped)
t.Logf("skipped (go.starlark.net modules, no lib README): %v", skipped)

if missing, ok := out["missing"].([]interface{}); ok && len(missing) > 0 {
t.Errorf("%d module member(s) are not documented in their README — see the report above", len(missing))
}
}
Loading