Article in English can be found on dev.to/arxeiss/shell-conditions-in-gitlab-ci-545
Tento článek předpokládá, že CI executor je nastaven na Docker. Což je defaultní nastavení pro sdílené runnery. S vlastním runnerem lze využít přímo Shell na hostitelském PC.
Při vytvoření .gitlab-ci.yml souboru se definuje Docker image, který se spustí, a následně příkazy, které se provádí. Tyto příkazy ale mohou obsahovat podmínky či jiné konstrukce a každý Shell může vyžadovat či podporovat jinou syntaxi. A pokud použitý Docker image obsahuje více různých Shell implementací, je potřeba zjistit, který si Gitlab Runner vybere jako ten hlavní.
Určení Shellu s externím souborem
Pokud skripty nejsou zapsány přímo v .gitlab-ci.yml
souboru, ale v externím souboru, stačí definovat cestu k Shellu, cestu k souboru a je hotovo. Pak je úplně jedno, jaký hlavní Shell si Gitlab Runner vybere, protože se vždy spustí zde vybraný /bin/bash
. Pipeline pak může vypadat takto:
deploy: image: registry.gitlab.com/pavel.kutac/docker-ftp-deployer:php81 script: - /bin/bash /usr/local/bin/execute-deployment.sh
Podmínky přímo v .gitlab-ci.yml
souboru
Podmínky lze zapsat přímo do YAML souboru ideálně pomocí Literal block style konstrukce. Příklad takové pipeline může být následující. Použité skripty a image je z Docker FTP Deployeru.
deploy: image: registry.gitlab.com/pavel.kutac/docker-ftp-deployer:php81 script: | if [[ ${CI_COMMIT_MESSAGE,,} != "[skip-maintenance]"* ]]; then wget --no-verbose -O - https://kutac.cz/some/path/to/turn/on/maintenance-mode fi ./.ci/deploy/run-lftp-incremental-sync.sh
Jenže jak zjistit, jaký Shell bude tyto skripty vykonávat? Zmíněný image obsahuje Busybox sh
ale také bash
. A tuto informaci nelze dohledat v dokumentaci. Proto jsem prošel zdrojové kódy Gitlab Runneru, kde jsem našel kousek kódu zobrazeného níže.
V něm je zřetelné, že prvně Gitlab Runner pomocí /bin/sh
spustí skript, který testuje existenci různých Shell implementací v několika lokacích. A pokud je nalezena, je následně spuštěna. A tento Shell je pak využit i ke spouštění všech skriptů v .gitlab-ci.yml
souboru. V případě zmíněného Docker FTP Deployer image tedy využije /bin/bash
protože je nainstalován a je v podmínce dříve. Pokud by ale přidán nebyl, použil by /bin/sh
.
const BashDetectShellScript = `if [ -x /usr/local/bin/bash ]; then exec /usr/local/bin/bash $@ elif [ -x /usr/bin/bash ]; then exec /usr/bin/bash $@ elif [ -x /bin/bash ]; then exec /bin/bash $@ elif [ -x /usr/local/bin/sh ]; then exec /usr/local/bin/sh $@ elif [ -x /usr/bin/sh ]; then exec /usr/bin/sh $@ elif [ -x /bin/sh ]; then exec /bin/sh $@ elif [ -x /busybox/sh ]; then exec /busybox/sh $@ else echo shell not found exit 1 fi `
// ...
func (b *BashShell) GetConfiguration(info common.ShellScriptInfo) (*common.ShellConfiguration, error) { // ... if info.Type == common.LoginShell { script.CmdLine += " -l" script.Arguments = []string{"-l"} script.DockerCommand = []string{"sh", "-c", strings.ReplaceAll(BashDetectShellScript, "$@", "-l")} } else { script.DockerCommand = []string{"sh", "-c", strings.ReplaceAll(BashDetectShellScript, "$@", "")} }
// ...
}
Zkušenosti s Gitlab CI pipeline můžete sdílet s ostatními v komentářích
K tomuto článku již není možné přidávat další komentáře