renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
160 lines (159 loc) • 6.71 kB
JavaScript
import { SYSTEM_INSUFFICIENT_DISK_SPACE } from "../../../constants/error-messages.js";
import { regEx } from "../../../util/regex.js";
import { coerceString } from "../../../util/string.js";
import { logger } from "../../../logger/index.js";
import { find, findAll } from "../../../util/host-rules.js";
import { deleteLocalFile, ensureCacheDir, ensureLocalDir, getSiblingFileName, localPathExists, readLocalFile, writeLocalFile } from "../../../util/fs/index.js";
import { Json } from "../../../util/schema-utils/index.js";
import { exec } from "../../../util/exec/index.js";
import { getRepoStatus } from "../../../util/git/index.js";
import { GitTagsDatasource } from "../../datasource/git-tags/index.js";
import { PackagistDatasource } from "../../datasource/packagist/index.js";
import { findGithubToken, takePersonalAccessTokenIfPossible } from "../../../util/check-token.js";
import { Lockfile, PackageFile } from "./schema.js";
import { extractConstraints, getComposerArguments, getComposerUpdateArguments, getPhpConstraint, isArtifactAuthEnabled, requireComposerDependencyInstallation } from "./utils.js";
import { isEmptyObject, isString } from "@sindresorhus/is";
import { z } from "zod/v4";
import { quote } from "shlex";
//#region lib/modules/manager/composer/artifacts.ts
function getAuthJson() {
const authJson = {};
const githubHostRule = find({
hostType: "github",
url: "https://api.github.com/"
});
const gitTagsHostRule = find({
hostType: GitTagsDatasource.id,
url: "https://github.com"
});
const selectedGithubToken = takePersonalAccessTokenIfPossible(isArtifactAuthEnabled(githubHostRule) ? findGithubToken(githubHostRule) : void 0, isArtifactAuthEnabled(gitTagsHostRule) ? findGithubToken(gitTagsHostRule) : void 0);
if (selectedGithubToken) authJson["github-oauth"] = { "github.com": selectedGithubToken };
for (const gitlabHostRule of findAll({ hostType: "gitlab" })) {
if (!isArtifactAuthEnabled(gitlabHostRule)) continue;
if (gitlabHostRule?.token) {
const host = coerceString(gitlabHostRule.resolvedHost, "gitlab.com");
authJson["gitlab-token"] = authJson["gitlab-token"] ?? {};
authJson["gitlab-token"][host] = gitlabHostRule.token;
authJson["gitlab-domains"] = [host, ...authJson["gitlab-domains"] ?? []];
}
}
for (const packagistHostRule of findAll({ hostType: PackagistDatasource.id })) {
if (!isArtifactAuthEnabled(packagistHostRule)) continue;
const { resolvedHost, username, password, token } = packagistHostRule;
if (resolvedHost && username && password) {
authJson["http-basic"] = authJson["http-basic"] ?? {};
authJson["http-basic"][resolvedHost] = {
username,
password
};
} else if (resolvedHost && token) {
authJson.bearer = authJson.bearer ?? {};
authJson.bearer[resolvedHost] = token;
}
}
return isEmptyObject(authJson) ? null : JSON.stringify(authJson);
}
async function updateArtifacts({ packageFileName, updatedDeps, newPackageFileContent, config }) {
logger.debug(`composer.updateArtifacts(${packageFileName})`);
const file = Json.pipe(PackageFile).parse(newPackageFileContent);
const lockFileName = packageFileName.replace(regEx(/\.json$/), ".lock");
const lockfile = await z.string().transform((f) => readLocalFile(f, "utf8")).pipe(Json).pipe(Lockfile).nullable().catch(null).parseAsync(lockFileName);
if (!lockfile) {
logger.debug("Composer: unable to read lockfile");
return null;
}
const vendorDir = getSiblingFileName(packageFileName, "vendor");
const commitVendorFiles = await localPathExists(vendorDir);
await ensureLocalDir(vendorDir);
try {
await writeLocalFile(packageFileName, newPackageFileContent);
const constraints = {
...extractConstraints(file, lockfile),
...config.constraints
};
const composerToolConstraint = {
toolName: "composer",
constraint: constraints.composer
};
const phpToolConstraint = {
toolName: "php",
constraint: getPhpConstraint(constraints)
};
const execOptions = {
cwdFile: packageFileName,
extraEnv: {
COMPOSER_CACHE_DIR: await ensureCacheDir("composer"),
COMPOSER_AUTH: getAuthJson()
},
toolConstraints: [phpToolConstraint, composerToolConstraint],
docker: {}
};
const commands = [];
if (requireComposerDependencyInstallation(lockfile)) {
const preCmd = "composer";
const preArgs = `install${getComposerArguments(config, composerToolConstraint)}`;
logger.trace({
preCmd,
preArgs
}, "composer pre-update command");
commands.push("git stash -- composer.json");
commands.push(`${preCmd} ${preArgs}`);
commands.push({
command: [
"git",
"stash",
"pop"
],
ignoreFailure: true
});
}
if (config.isLockFileMaintenance) {
logger.debug(`Removing ${lockFileName} first due to lock file maintenance upgrade`);
await deleteLocalFile(lockFileName);
}
const cmd = "composer";
let args;
if (config.isLockFileMaintenance) args = "update";
else args = ("update " + updatedDeps.map((dep) => dep.newVersion ? quote(`${dep.depName}:${dep.newVersion}`) : quote(dep.depName)).filter(isString).map((dep) => quote(dep)).join(" ")).trim() + (config.postUpdateOptions?.includes("composerWithAll") ? " --with-all-dependencies" : " --with-dependencies");
args += getComposerUpdateArguments(config, composerToolConstraint);
logger.trace({
cmd,
args
}, "composer command");
commands.push(`${cmd} ${args}`);
await exec(commands, execOptions);
const status = await getRepoStatus();
if (!status.modified.includes(lockFileName)) return null;
logger.debug("Returning updated composer.lock");
const res = [{ file: {
type: "addition",
path: lockFileName,
contents: await readLocalFile(lockFileName)
} }];
if (!commitVendorFiles) return res;
logger.debug(`Committing vendor files in ${vendorDir}`);
for (const f of [...status.modified, ...status.not_added]) if (f.startsWith(vendorDir)) res.push({ file: {
type: "addition",
path: f,
contents: await readLocalFile(f)
} });
for (const f of status.deleted) res.push({ file: {
type: "deletion",
path: f
} });
return res;
} catch (err) {
// istanbul ignore if
if (err.message === "temporary-error") throw err;
if (err.message?.includes("Your requirements could not be resolved to an installable set of packages.")) logger.info("Composer requirements cannot be resolved");
else if (err.message?.includes("write error (disk full?)")) throw new Error(SYSTEM_INSUFFICIENT_DISK_SPACE);
else logger.debug({ err }, "Failed to generate composer.lock");
return [{ artifactError: {
fileName: lockFileName,
stderr: err.message
} }];
}
}
//#endregion
export { updateArtifacts };
//# sourceMappingURL=artifacts.js.map