/** * Pinned-version upgrade detection for k8s, gcp, docker, gitlab lexicons. * * For each lexicon with a pinned upstream version constant, this module: * 1. Reads the currently pinned version from the source file. * 2. Queries upstream for the latest stable release tag (no pre-release/rc). * 3. Compares using semver ordering. If a newer version exists: * a. Edits the version constant in the source file. * b. Invokes regenLexicon to regenerate and surface-diff. * c. Reverts the constant edit (dry-run mode — never commits the bump). * 4. Returns a structured report per lexicon. * * The upstream-query functions are injectable — pass a mock for unit tests. * The actual HTTP calls use the GitHub Releases/Tags API. * * Design decisions: * - "Latest stable" = highest semver excluding tags containing rc/alpha/beta/preview. * - The bump is always reverted after regen so the working tree is unchanged. * Only the CLI reporter (#527) actually creates branches/PRs. * - Each lexicon's upstream query is a pure async function: () => Promise * (returns the latest version tag, or null when no stable release is found). */ import { type RegenResult } from "./lexicon-regen.js"; import { type UpstreamPin } from "../lexicon.js"; /** * A pinned, self-upgradable lexicon's name (e.g. "k8s"). Any lexicon whose * plugin declares `upstreamPin` (../lexicon.ts) is eligible — the set is no * longer hard-coded here. */ export type LexiconId = string; export type { UpstreamPin }; export interface UpgradeCheckResult { /** Lexicon identifier. */ lexicon: LexiconId; /** Whether a newer stable upstream version was found. */ hasUpgrade: boolean; /** Current pinned version string (e.g. "v1.32.0"). */ from: string; /** Latest upstream version string, if one was found (e.g. "v1.33.0"). */ to: string | null; /** Regen/surface-diff result — only present when hasUpgrade is true. */ validation: RegenResult | null; /** Human-readable error when the upstream query itself failed. */ fetchError: string | null; } /** Injectable upstream version resolver. Returns the latest stable tag or null. */ export type UpstreamResolver = () => Promise; export interface CheckPinnedUpgradeOptions { /** Resolved path to the lexicon root (e.g. /repo/lexicons/k8s). */ lexiconDir: string; /** Which lexicon to check. */ lexicon: LexiconId; /** * Override the upstream resolver (useful in tests to inject mocks). * When omitted the real GitHub API is called. */ resolverOverride?: UpstreamResolver; /** * When true, pass force=true to regenLexicon so the spec cache is bypassed. * Default: false (use cached spec for the upgrade check). */ force?: boolean; /** Forward to regenLexicon. */ verbose?: boolean; /** Forward to regenLexicon — skip tsc step for speed in tests. */ skipBuild?: boolean; /** Forward to regenLexicon. */ skipBundle?: boolean; /** Forward to regenLexicon. */ skipLint?: boolean; } /** * Parse a version string into numeric segments. * * Strips leading "v" and any build-metadata suffix after "-". * Returns null when the string is not a parseable version. */ export declare function parseVersion(tag: string): number[] | null; /** * Compare two version tuples lexicographically. * Returns -1 when a < b, 0 when equal, +1 when a > b. */ export declare function compareVersionTuples(a: number[], b: number[]): -1 | 0 | 1; /** * Return true when `candidate` is strictly newer than `current`. * * Strips build-metadata suffixes (e.g. "-ee") before comparing so that * "v17.9.0-ee" and "v17.9.0" compare by numeric part only. */ export declare function isNewer(candidate: string, current: string): boolean; /** * Return true when a release tag looks like a pre-release. * Filters out rc, alpha, beta, preview, nightly, dev, canary suffixes. */ export declare function isPreRelease(tag: string): boolean; interface PinLocation { /** Absolute path to the file containing the version constant. */ filePath: string; /** Regex that matches the full constant line (must have a capture for the version). */ pattern: RegExp; /** Function to build the replacement line given the new version string. */ buildReplacement: (newVersion: string, oldVersion: string, line: string) => string; } /** * Read the current pinned version from a source file using a regex pattern. * Returns null when the pattern is not found. */ export declare function readPinnedVersion(location: PinLocation): string | null; /** * Apply a version bump by replacing the constant in the source file. * Returns the original file content so it can be reverted. */ export declare function applyVersionBump(location: PinLocation, newVersion: string): string; /** * Revert a file to its original content (undo a bump). */ export declare function revertVersionBump(filePath: string, original: string): void; /** * Load a lexicon's `upstreamPin` descriptor from its plugin package * (`@intentius/chant-lexicon-`) — the lexicon's own declaration of where * its version constant lives and which upstream repo to check. Returns null * when the package can't be resolved or declares no `upstreamPin` (i.e. it is * not self-upgradable). Mirrors ../components/capability-plugin-loader.ts's * lexicon-borne loading. */ export declare function loadUpstreamPin(lexicon: LexiconId): Promise; /** * Check whether a newer upstream release exists for a pinned lexicon. * * When a newer version is found: * 1. Applies the version bump to the source constant. * 2. Runs regenLexicon (surface-diff pipeline). * 3. Reverts the bump unconditionally. * * The caller receives the full result including the regen validation output * without any lasting change to the working tree. */ export declare function checkPinnedUpgrade(opts: CheckPinnedUpgradeOptions): Promise; /** * Apply a version bump for a lexicon permanently (without reverting). * * Called by LexiconUpgradeOp when it has already decided to commit the bump * to a branch. Returns the absolute path to the modified file so the caller * can stage it with `git add`. * * Unlike `applyVersionBump` (which is generic), this function takes only a * lexicon id and directory — it resolves the pin location from the lexicon's * declared `upstreamPin` descriptor. */ export declare function applyPinnedVersionBump(lexicon: LexiconId, lexiconDir: string, newVersion: string): Promise<{ filePath: string; }>; //# sourceMappingURL=pinned-upgrade.d.ts.map