Jenkins 如何在保留构建的天数和保留的最大构建数之间做出决定?

How does Jenkins decide between days to keep builds and max number of builds to keep?

在 Jenkins 作业的 'Discard old builds' 设置中,您可以为 'Days to keep builds' 和 'Max # of builds to keep.' 输入一个值,Jenkins 如何响应这两个设置?它只是选择一个,还是结合了行为,以便构建历史必须早于时间限制并超过构建的最大数量?

Jenkins 日志轮换示例

考虑以下示例

buildDiscarder(logRotator(daysToKeepStr: '30', numToKeepStr: '100'))

此日志轮换政策将在每个构建 运行 之后删除任何超过 100 天的构建,以及超过 30 天的任何构建(即使少于 100 个构建)。 Jenkins 将查看每个特定的构建,如果它只满足其中一个标准,它将被删除

伪代码

if( build.age > 30 || build.number > 100 ) {
   delete build
}

Keep in mind that this will override any global log rotate settings you have configured

这里是Jenkins核心使用的LogRotator class。这是 Jenkins 用来执行 log rotate

的确切代码
    if(numToKeep!=-1) {
        // Note that RunList.size is deprecated, and indeed here we are loading all the builds of the job.
        // However we would need to load the first numToKeep anyway, just to skip over them;
        // and we would need to load the rest anyway, to delete them.
        // (Using RunMap.headMap would not suffice, since we do not know if some recent builds have been deleted for other reasons,
        // so simply subtracting numToKeep from the currently last build number might cause us to delete too many.)
        RunList<? extends Run<?,?>> builds = job.getBuilds();
        for (Run r : builds.subList(Math.min(builds.size(), numToKeep), builds.size())) {
            if (shouldKeepRun(r, lsb, lstb)) {
                continue;
            }
            LOGGER.log(FINE, "{0} is to be removed", r);
            try { r.delete(); }
            catch (IOException ex) { exceptionMap.computeIfAbsent(r, key -> new HashSet<>()).add(ex); }
        }
    }

    if(daysToKeep!=-1) {
        Calendar cal = new GregorianCalendar();
        cal.add(Calendar.DAY_OF_YEAR,-daysToKeep);
        Run r = job.getFirstBuild();
        while (r != null) {
            if (tooNew(r, cal)) {
                break;
            }
            if (!shouldKeepRun(r, lsb, lstb)) {
                LOGGER.log(FINE, "{0} is to be removed", r);
                try { r.delete(); }
                catch (IOException ex) { exceptionMap.computeIfAbsent(r, key -> new HashSet<>()).add(ex); }
            }
            r = r.getNextBuild();
        }
    }