"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateArtifacts = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const p_map_1 = tslib_1.__importDefault(require("p-map"));
const shlex_1 = require("shlex");
const error_messages_1 = require("../../../constants/error-messages");
const logger_1 = require("../../../logger");
const exec_1 = require("../../../util/exec");
const fs_1 = require("../../../util/fs");
const git_1 = require("../../../util/git");
const hostRules = tslib_1.__importStar(require("../../../util/host-rules"));
const yaml = tslib_1.__importStar(require("../../../util/yaml"));
const docker_1 = require("../../datasource/docker");
const helm_1 = require("../../datasource/helm");
const common_1 = require("./common");
const utils_1 = require("./utils");
async function helmCommands(execOptions, manifestPath, repositories) {
    const cmd = [];
    // get OCI registries and detect host rules
    const registries = repositories
        .filter(utils_1.isOCIRegistry)
        .map((value) => {
        return {
            ...value,
            repository: value.repository.replace('oci://', ''),
            hostRule: hostRules.find({
                url: value.repository.replace('oci://', 'https://'), //TODO we need to replace this, as oci:// will not be accepted as protocol
                hostType: docker_1.DockerDatasource.id,
            }),
        };
    });
    // if credentials for the registry have been found, log into it
    await (0, p_map_1.default)(registries, async (value) => {
        const loginCmd = await (0, common_1.generateLoginCmd)(value, 'helm registry login');
        if (loginCmd) {
            cmd.push(loginCmd);
        }
    });
    // find classic Chart repositories and fitting host rules
    const classicRepositories = repositories
        .filter((repository) => !(0, utils_1.isOCIRegistry)(repository))
        .map((value) => {
        return {
            ...value,
            hostRule: hostRules.find({
                url: value.repository,
                hostType: helm_1.HelmDatasource.id,
            }),
        };
    });
    // add helm repos if an alias or credentials for the url are defined
    classicRepositories.forEach((value) => {
        const { username, password } = value.hostRule;
        const parameters = [`${(0, shlex_1.quote)(value.repository)}`, `--force-update`];
        const isPrivateRepo = username && password;
        if (isPrivateRepo) {
            parameters.push(`--username ${(0, shlex_1.quote)(username)}`);
            parameters.push(`--password ${(0, shlex_1.quote)(password)}`);
        }
        cmd.push(`helm repo add ${(0, shlex_1.quote)(value.name)} ${parameters.join(' ')}`);
    });
    cmd.push(`helm dependency update ${(0, shlex_1.quote)((0, fs_1.getParentDir)(manifestPath))}`);
    await (0, exec_1.exec)(cmd, execOptions);
}
async function updateArtifacts({ packageFileName, updatedDeps, newPackageFileContent, config, }) {
    logger_1.logger.debug(`helmv3.updateArtifacts(${packageFileName})`);
    const isLockFileMaintenance = config.updateType === 'lockFileMaintenance';
    const isUpdateOptionAddChartArchives = config.postUpdateOptions?.includes('helmUpdateSubChartArchives');
    if (!isLockFileMaintenance &&
        (updatedDeps === undefined || updatedDeps.length < 1)) {
        logger_1.logger.debug('No updated helmv3 deps - returning null');
        return null;
    }
    const lockFileName = (0, fs_1.getSiblingFileName)(packageFileName, 'Chart.lock');
    const existingLockFileContent = await (0, fs_1.readLocalFile)(lockFileName, 'utf8');
    if (!existingLockFileContent && !isUpdateOptionAddChartArchives) {
        logger_1.logger.debug('No Chart.lock found');
        return null;
    }
    try {
        // get repositories and registries defined in the package file
        // TODO: use schema (#9610)
        const packages = yaml.parseSingleYaml(newPackageFileContent);
        const locks = existingLockFileContent
            ? yaml.parseSingleYaml(existingLockFileContent)
            : { dependencies: [] };
        const chartDefinitions = [];
        // prioritize registryAlias naming for Helm repositories
        if (config.registryAliases) {
            chartDefinitions.push({
                dependencies: (0, utils_1.aliasRecordToRepositories)(config.registryAliases),
            });
        }
        chartDefinitions.push(packages, locks);
        const repositories = (0, utils_1.getRepositories)(chartDefinitions);
        await (0, fs_1.writeLocalFile)(packageFileName, newPackageFileContent);
        logger_1.logger.debug('Updating Helm artifacts');
        const helmToolConstraint = {
            toolName: 'helm',
            constraint: config.constraints?.helm,
        };
        const execOptions = {
            docker: {},
            extraEnv: (0, common_1.generateHelmEnvs)(),
            toolConstraints: [helmToolConstraint],
        };
        await helmCommands(execOptions, packageFileName, repositories);
        logger_1.logger.debug('Returning updated Helm artifacts');
        const fileChanges = [];
        if (is_1.default.truthy(existingLockFileContent)) {
            const newHelmLockContent = await (0, fs_1.readLocalFile)(lockFileName, 'utf8');
            const isLockFileChanged = existingLockFileContent !== newHelmLockContent;
            if (isLockFileChanged) {
                fileChanges.push({
                    file: {
                        type: 'addition',
                        path: lockFileName,
                        contents: newHelmLockContent,
                    },
                });
            }
            else {
                logger_1.logger.debug('Chart.lock is unchanged');
            }
        }
        // add modified helm chart archives to artifacts
        if (is_1.default.truthy(isUpdateOptionAddChartArchives)) {
            const chartsPath = (0, fs_1.getSiblingFileName)(packageFileName, 'charts');
            const status = await (0, git_1.getRepoStatus)();
            const chartsAddition = status.not_added ?? [];
            const chartsDeletion = status.deleted ?? [];
            for (const file of chartsAddition) {
                // only add artifacts in the chart sub path
                if (!(0, utils_1.isFileInDir)(chartsPath, file)) {
                    continue;
                }
                fileChanges.push({
                    file: {
                        type: 'addition',
                        path: file,
                        contents: await (0, fs_1.readLocalFile)(file),
                    },
                });
            }
            for (const file of chartsDeletion) {
                // only add artifacts in the chart sub path
                if (!(0, utils_1.isFileInDir)(chartsPath, file)) {
                    continue;
                }
                fileChanges.push({
                    file: {
                        type: 'deletion',
                        path: file,
                    },
                });
            }
        }
        return fileChanges.length > 0 ? fileChanges : null;
    }
    catch (err) {
        // istanbul ignore if
        if (err.message === error_messages_1.TEMPORARY_ERROR) {
            throw err;
        }
        logger_1.logger.debug({ err }, 'Failed to update Helm lock file');
        return [
            {
                artifactError: {
                    lockFile: lockFileName,
                    stderr: err.message,
                },
            },
        ];
    }
}
exports.updateArtifacts = updateArtifacts;
//# sourceMappingURL=artifacts.js.map