UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

146 lines (145 loc) 5.13 kB
import { escapeRegExp, regEx } from "../../../util/regex.js"; import { logger } from "../../../logger/index.js"; import { trimTrailingSlash } from "../../../util/url.js"; import { readLocalFile } from "../../../util/fs/index.js"; import { parseGitUrl } from "../../../util/git/url.js"; import { GitTagsDatasource } from "../../datasource/git-tags/index.js"; import { getDigest } from "../../datasource/index.js"; import { scm } from "../../platform/scm.js"; import { PackageResolvedJson } from "./schema.js"; //#region lib/modules/manager/swift/artifacts.ts async function findPackageResolvedFiles() { return (await scm.getFileList()).filter((f) => f.endsWith("Package.resolved")); } function normalizeUrl(url) { try { const parsed = parseGitUrl(url); if (parsed.resource && parsed.full_name) return `${parsed.resource}/${trimTrailingSlash(parsed.full_name)}`.toLowerCase(); } catch {} return url.replace(regEx(/\.git$/), "").replace(regEx(/\/$/), "").toLowerCase(); } function matchPinForDep(dep, pins) { let depUrl; if (dep.datasource === GitTagsDatasource.id) depUrl = dep.depName ?? ""; else depUrl = `${dep.registryUrls?.[0] ?? "https://github.com"}/${dep.depName}`; const normalizedDepUrl = normalizeUrl(depUrl); return pins.find((pin) => normalizeUrl(pin.location) === normalizedDepUrl) ?? null; } async function resolveCommitSha(dep, newVersion) { if (dep.newDigest) return dep.newDigest; const datasource = dep.datasource; const packageName = dep.packageName ?? dep.depName; if (!datasource || !packageName) return null; try { return await getDigest({ datasource, packageName, registryUrls: dep.registryUrls }, newVersion); } catch (err) { logger.debug({ err, packageName, newVersion }, "swift: failed to resolve commit SHA"); return null; } } function updatePinInJson(content, pin, newVersion, newRevision) { let updated = content; const identityMatch = regEx(`"identity"\\s*:\\s*"${escapeRegExp(pin.identity)}"`).exec(updated); /* istanbul ignore if: identity always exists after JSON parse + matchPinForDep */ if (!identityMatch) return content; const blockStart = updated.slice(0, identityMatch.index).lastIndexOf("{"); /* istanbul ignore if: valid JSON always has enclosing braces */ if (blockStart === -1) return content; let braceDepth = 0; let blockEnd = -1; for (let i = blockStart; i < updated.length; i++) if (updated[i] === "{") braceDepth++; else if (updated[i] === "}") { braceDepth--; if (braceDepth === 0) { blockEnd = i + 1; break; } } /* istanbul ignore if: valid JSON always has matching braces */ if (blockEnd === -1) return content; let pinBlock = updated.slice(blockStart, blockEnd); const versionPattern = regEx(/("version"\s*:\s*)"[^"]*"/); pinBlock = pinBlock.replace(versionPattern, `$1"${newVersion}"`); if (newRevision) { const revisionPattern = regEx(/("revision"\s*:\s*)"[^"]*"/); pinBlock = pinBlock.replace(revisionPattern, `$1"${newRevision}"`); } updated = updated.slice(0, blockStart) + pinBlock + updated.slice(blockEnd); return updated; } async function updateArtifacts({ updatedDeps, config }) { if (config.isLockFileMaintenance) { logger.debug("swift: lockFileMaintenance is not supported"); return null; } if (!updatedDeps.length) { logger.debug("swift: no updatedDeps, nothing to do"); return null; } const resolvedFiles = await findPackageResolvedFiles(); if (!resolvedFiles.length) { logger.debug("swift: no Package.resolved files found"); return null; } const results = []; for (const resolvedFile of resolvedFiles) { const content = await readLocalFile(resolvedFile, "utf8"); if (!content) { logger.debug({ resolvedFile }, "swift: could not read Package.resolved"); continue; } const parseResult = PackageResolvedJson.safeParse(content); if (!parseResult.success) { logger.debug({ resolvedFile, error: parseResult.error }, "swift: could not parse Package.resolved"); continue; } const parsed = parseResult.data; let updated = content; for (const dep of updatedDeps) { if (!dep.newValue) continue; if (!dep.newVersion) { logger.debug({ depName: dep.depName, newVersion: dep.newVersion, newValue: dep.newValue }, "swift: found a newValue but not a newVersion"); continue; } const pin = matchPinForDep(dep, parsed.pins); if (!pin) { logger.debug({ depName: dep.depName }, "swift: no matching pin found in Package.resolved"); continue; } const resolvedVersion = dep.newVersion.replace(regEx(/^v/), ""); if (pin.state.version === resolvedVersion) { logger.debug({ depName: dep.depName, resolvedVersion }, "swift: pin already at target version"); continue; } const newRevision = await resolveCommitSha(dep, dep.newVersion); updated = updatePinInJson(updated, pin, resolvedVersion, newRevision); } if (updated !== content) results.push({ file: { type: "addition", path: resolvedFile, contents: updated } }); } return results.length ? results : null; } //#endregion export { updateArtifacts }; //# sourceMappingURL=artifacts.js.map