Documentation
¶
Overview ¶
Package npmrelease coordinates an approved npm publication workflow without ever handling npm credentials. The repository owns the GitHub Actions workflow; WB dispatches it, records the exact run/head receipt, verifies the requested package version in the npm registry, and returns release events for the shared dependency-wave engine.
Index ¶
- Constants
- func EventsFor(report Report) ([]deps.ReleaseEvent, error)
- func IsSecretLikeWorkflowInputKey(key string) bool
- func OperationIDFor(releases []Release) string
- func PublicationClaimOperationIDs(releases []Release) []string
- func ReportExists(directory string) (bool, error)
- func ValidateOptions(options Options) error
- func ValidateRelease(release Release) error
- func WriteReport(directory string, report Report) error
- type CommandResult
- type CommandRunner
- type OSCommandRunner
- type Options
- type Receipt
- type Release
- type Report
Constants ¶
const ( SchemaVersion = 3 StatusPlanned = "planned" StatusRunning = "running" StatusPublished = "published" StatusDispatchUnknown = "dispatch_unknown" StatusDispatchFailed = "dispatch_failed" StatusAwaitingRun = "awaiting_run" StatusAwaitingRegistry = "awaiting_registry" StatusFailed = "failed" )
Variables ¶
This section is empty.
Functions ¶
func EventsFor ¶
func EventsFor(report Report) ([]deps.ReleaseEvent, error)
EventsFor returns only registry-confirmed events. A caller must not hand planned or failed receipts to deps bump.
func IsSecretLikeWorkflowInputKey ¶
IsSecretLikeWorkflowInputKey recognizes names that might carry a credential in a workflow_dispatch field. Callers must reject these before a release is normalized, persisted, or rendered into subprocess arguments.
func OperationIDFor ¶
OperationIDFor returns a deterministic operation name for the publication identity: repository/workflow/package/version/ref only. Workflow inputs are deliberately excluded so every request to publish the same version shares one operation lock and default report directory. Resume performs the stricter input-fingerprinted releaseIdentity comparison separately.
func PublicationClaimOperationIDs ¶
PublicationClaimOperationIDs returns deterministic, package-version claim lock names for already-normalized releases. Unlike a campaign operation, a claim deliberately ignores workflow inputs, repository, workflow, ref, and neighboring tuples: npm can publish one exact package version only once, so overlapping subset/superset campaigns must serialize that publication.
func ReportExists ¶
ReportExists recognizes either durable representation. A JSON-only remnant is intentionally treated as existing (and therefore refuses a fresh apply) rather than silently allowing a duplicate workflow dispatch.
func ValidateOptions ¶
ValidateOptions performs every no-I/O publication option check. Command handlers use it before fleet discovery or a workflow dispatch, and Run uses it again so package callers get the same boundary.
func ValidateRelease ¶
ValidateRelease checks all explicit user-controlled identifiers before any command is run. Workflow names are limited to repository-owned workflow files, rather than arbitrary shell fragments or a hidden remote action.
func WriteReport ¶
WriteReport persists the resumable report. Both canonical YAML and JSON are independently atomically replaced so a crash cannot expose a half-written document to a resume or machine reader. It is intentionally separate from stdout formatting so failure paths keep the same durable receipt.
Types ¶
type CommandResult ¶
CommandResult is the small subprocess seam used by tests and by the real GitHub/npm command runner. Code and Output are retained separately so a non-zero gh status can still carry a useful JSON receipt.
type CommandRunner ¶
type CommandRunner interface {
Run(context.Context, string, ...string) CommandResult
}
CommandRunner executes an external command. It must use the caller's existing gh/npm credential helpers; WB never accepts or constructs tokens.
type OSCommandRunner ¶
type OSCommandRunner struct{}
func (OSCommandRunner) Run ¶
func (OSCommandRunner) Run(ctx context.Context, dir string, args ...string) CommandResult
type Options ¶
type Options struct {
Apply bool
DryRun bool
Resume bool
Ref string
Timeout time.Duration
PollInterval time.Duration
Registry string
ReportDir string
Runner CommandRunner
Now func() time.Time
Persist func(Report) error
Previous *Report
Progress progress.Reporter
// contains filtered or unexported fields
}
Options controls publication safety and polling. Apply is the only option that permits workflow dispatch; dry-run never contacts GitHub or npm.
type Receipt ¶
type Receipt struct {
Release
Status string `json:"status" yaml:"status"`
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
DispatchAt time.Time `json:"dispatch_at,omitempty" yaml:"dispatch_at,omitempty"`
HeadSHA string `json:"head_sha,omitempty" yaml:"head_sha,omitempty"`
// DispatchBaselineAt and DispatchBaselineRunIDs are captured before the
// workflow_dispatch request. They are the primary identity fence for a
// resume: only an exact-head run absent from this set can be the run WB
// dispatched. A timestamp is retained solely as a bounded secondary check
// against a delayed, pre-existing run that was absent from GitHub's list.
DispatchBaselineAt time.Time `json:"dispatch_baseline_at,omitempty" yaml:"dispatch_baseline_at,omitempty"`
DispatchBaselineRunIDs []string `json:"dispatch_baseline_run_ids,omitempty" yaml:"dispatch_baseline_run_ids,omitempty"`
RunID string `json:"run_id,omitempty" yaml:"run_id,omitempty"`
RunURL string `json:"run_url,omitempty" yaml:"run_url,omitempty"`
RunHeadSHA string `json:"run_head_sha,omitempty" yaml:"run_head_sha,omitempty"`
RunStatus string `json:"run_status,omitempty" yaml:"run_status,omitempty"`
RunConclusion string `json:"run_conclusion,omitempty" yaml:"run_conclusion,omitempty"`
RunCreatedAt time.Time `json:"run_created_at,omitempty" yaml:"run_created_at,omitempty"`
RunCompletedAt time.Time `json:"run_completed_at,omitempty" yaml:"run_completed_at,omitempty"`
RegistryVersion string `json:"registry_version,omitempty" yaml:"registry_version,omitempty"`
RegistryURL string `json:"registry_url,omitempty" yaml:"registry_url,omitempty"`
RegistryCheckedAt time.Time `json:"registry_checked_at,omitempty" yaml:"registry_checked_at,omitempty"`
}
Receipt is the durable evidence for one workflow publication. A receipt is retained when a later registry check or dependency wave fails so --resume never dispatches an already accepted workflow again.
type Release ¶
type Release struct {
Repository string `json:"repository" yaml:"repository"`
Workflow string `json:"workflow" yaml:"workflow"`
Package string `json:"package" yaml:"package"`
Version string `json:"version" yaml:"version"`
Ref string `json:"ref" yaml:"ref"`
InputFingerprint string `json:"input_fingerprint,omitempty" yaml:"input_fingerprint,omitempty"`
// Inputs are deliberately process-local. Even safe-looking workflow field
// values can carry a credential by mistake, so reports and stdout retain
// only InputFingerprint for resume identity and never serialize raw values.
Inputs map[string]string `json:"-" yaml:"-"`
}
Release is one explicit provider/workflow/package/version tuple. Keeping the tuple intact prevents a multi-package provider campaign from silently pairing the wrong workflow with a package.
type Report ¶
type Report struct {
SchemaVersion int `json:"schema_version" yaml:"schema_version"`
Operation string `json:"operation" yaml:"operation"`
Generation string `json:"generation,omitempty" yaml:"generation,omitempty"`
Status string `json:"status" yaml:"status"`
Ref string `json:"ref" yaml:"ref"`
Releases []Receipt `json:"releases" yaml:"releases"`
Events []deps.ReleaseEvent `json:"events,omitempty" yaml:"events,omitempty"`
PropagationOperation string `json:"propagation_operation,omitempty" yaml:"propagation_operation,omitempty"`
// Propagation is the same persisted BumpReport the regular `wb deps bump
// npm` engine produces. Keeping it here makes the publication receipt
// independently resumable and machine-readable without a parallel wave
// orchestration format.
Propagation *deps.BumpReport `json:"propagation,omitempty" yaml:"propagation,omitempty"`
}
Report is persisted before any external action and after every state transition. It is intentionally independent of deps.BumpReport: release evidence can be resumed even if the downstream wave has not started.
func LoadReport ¶
LoadReport loads the canonical YAML resume artifact.
func Run ¶
Run executes the publication phase. If Apply is false it returns a deterministic planned report without invoking gh or npm. If Apply is true, every receipt is persisted before dispatch and after each external state transition. Resume reuses all receipts and never dispatches a tuple already carrying a dispatch timestamp or run identity.
func (Report) WithGeneration ¶
JSON and YAML are intentionally exposed by the package so command handlers and integration tests use the same field names and deterministic encoding. Both carry one logical generation, allowing --resume to fail closed if a crash happens between their individual atomic renames.