Jenkins Pipeline "node внутри этапа" против "внутри node"

Поскольку как шаг node, так и шаг stage предоставляют расширенный синтаксис {}, какова наилучшая практика для определения их топологии внутри кода groovy?

Иллюстрация A

node ("NodeName") {
    stage ("a stage inside node"){
        // do stuff here
    }
}

Иллюстрация B

stage ("a stage holding a node") {
    node ("NodeName"){
        // do stuff here
    }
}

Ответ 1

Это зависит от ваших реальных потребностей.

До тех пор, пока вы можете запустить полный конвейер на одном node, я бы обернул stage в node, чтобы конвейер не был заблокирован операторами-занятыми.

Как только вы используете шаг parallel, у вас действительно нет выбора, кроме stage вокруг node.

Есть (по крайней мере, для меня) никаких проблем вокруг смешивания, т.е. первые 2-3 этапа выполняются на одном и том же node, а затем один этап, который выполняется на нескольких узлах в пределах parallel.

Ответ 2

С node { stage { ... } } каждый этап будет использовать одну и ту же рабочую папку, и все файлы предыдущего этапа будут там для следующего этапа.

С stage { node { ... } } вам нужно stash/unstash файлы между каждым этапом. Если у вас большой репозиторий, и особенно если у вас есть большая папка зависимостей, такая как node_modules, повторяющиеся stash/unstash могут в конечном итоге стать значительным, или даже большим, или вашим временем сборки.

ИМО Я бы, как правило, начал с первого синтаксиса, node { stage { ... } }, как предпочитается. Если у вас есть отдельные этапы сборки, которые требуют времени и могут извлечь выгоду из параллелизма, то переключение на stage { node { ... } } может быть лучше, если время, полученное при распараллеливании, не теряется при сборе.

Обновление:

Я проверил точный эффект обмена вложениями на одну из наших сборок. с кучей этапов внутри узла, общее время сборки составляет чуть более одной минуты. С узлом внутри каждой стадии общее время сборки составляет почти пять минут. Большая разница.

Build stage timing example