Files
renovate/lib/modules/manager/swift/schema.ts
Bartosz Dolewski d735b9b6b8 fix(swift): support Package Registry pins in Package.resolved (#44358)
* fix(swift): allow Package.resolved pins without a `revision`

The swift manager's Package.resolved Zod schema requires
`state.revision: z.string()` on every pin. That is correct for
source-control pins (`kind: "remoteSourceControl"`), which always
have a git commit SHA, but wrong for SwiftPM Package Registry pins
(`kind: "registry"`) introduced by SE-0292: registry packages are
identified by a version alone and have no revision. As a result,
any Package.resolved that mixes source-control and registry pins
fails `PackageResolvedJson.safeParse`, `updateArtifacts` logs
`swift: could not parse Package.resolved` and returns `null`, and
Renovate silently stops writing lockfile updates on that repository.

This makes `state.revision` optional in the pin schema. The existing
`updateArtifacts` logic already guards the revision-replacement
branch with `if (newRevision)`, so registry pins are still safely
left untouched during source-control dep bumps.

Adds a regression test with a mixed-pins fixture. Before this change
that test panicked at parse time; after the change it demonstrates
the source-control pin gets updated and the registry pin is preserved
without gaining a spurious revision field.

Refs: #41534 (initial Package.resolved support, tested with
source-control pins only), #42303 (from: prefix strip).

* test(manager/swift): address review feedback on mixed-pins test

Per review on the Package.resolved mixed source-control/registry pins
test: inline the fixture into the test body, trim the comment to a
concise regression note, and assert on the parsed JSON with
toMatchObject instead of substring matching.

Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>

* test(manager/swift): assert full updateArtifacts result for mixed pins

Per review: replace the parse/find/toMatchObject assertions with a
single resolves.toEqual on the whole updateArtifacts result, comparing
against the expected Package.resolved output directly.

Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>

* test(manager/swift): trim mixed-pins regression comment

Apply review suggestion to shorten the comment to a single line.

Co-Authored-By: Claude (Cricut Security policy) <noreply@anthropic.com>

---------

Co-authored-by: Claude (Cricut Security policy) <noreply@anthropic.com>
2026-08-11 06:26:37 +00:00

33 lines
1.1 KiB
TypeScript

import { z } from 'zod/v4';
import { DeepNullish, Json } from '../../../util/schema-utils/index.ts';
const PackageResolvedPin = DeepNullish(
z.object({
identity: z.string(),
kind: z.string(),
location: z.string(),
state: z.object({
// `revision` is required for source-control pins (kind: "remoteSourceControl"),
// but absent for SwiftPM Package Registry pins (kind: "registry") per SE-0292:
// registry packages are identified by version alone, not by a commit SHA. A
// Package.resolved file mixing both kinds fails validation if we require
// `revision` unconditionally.
revision: z.string().optional(),
version: z.string().optional(),
branch: z.string().optional(),
}),
}),
);
export type PackageResolvedPin = z.infer<typeof PackageResolvedPin>;
export const PackageResolvedJson = Json.pipe(
z.object({
pins: z.array(PackageResolvedPin),
version: z.number().int().min(2),
originHash: z.string().optional(),
}),
);
export type PackageResolvedJson = z.infer<typeof PackageResolvedJson>;