2.3 KiB
8. Exit code — ainoa onnistumisen mittari
Päätös
Jokaisen run-stepin on nostettava virheellinen exit-koodi ylös sellaisenaan.
Exit-koodia ei saa "syödä" missään tilanteessa. Onnistumisen ja epäonnistumisen
päättely tapahtuu ainoastaan exit-koodin perusteella — ei tiedostojen
olemassaolon, stdout-tulosteen tai minkään muun heuristiikan perusteella.
Periaatteet
- Exit-koodi on ainoa totuus.
0= onnistui, kaikki muut = epäonnistui. - Exit-koodia ei saa syödä. Pipe (
|) viimeisenä komentonatee:hen syö exit-koodin —docker run … | tee filepalauttaa aina 0. - Data transfer -pipet ovat sallittuja (
tar c . | docker run … tar x), koska niiden exit-koodilla ei ole semanttista merkitystä. - Testien tai työkalujen ajaminen ei saa päättyä pipeen.
set -o pipefailei ole riittävä suojaus — PIPESTATUS resetoituu herkästi.
Sallitut patternit
# Oikein: suora ajo, exit koodi $?:iin
- name: Do work
run: |
some-command
EXIT=$?
echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
exit ${EXIT}
# Oikein: stdout talteen ilman pipeä
- name: Do work
run: |
some-command > results.txt 2>&1
EXIT=$?
echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
exit ${EXIT}
# Oikein: docker run ilman pipeä
- name: Run in container
run: |
docker run --rm image command > output.txt 2>&1
EXIT=$?
exit ${EXIT}
Kielletyt patternit
# Väärin: pipe syö exit-koodin
- run: docker run … | tee results.txt
# Väärin: pipe syö exit-koodin
- run: tar … | docker … | tee file
# Väärin: onnistumisen päättely tiedoston olemassaolosta
- run: |
some-command || true
[ -f success.txt ] && exit 0 || exit 1
Tausta
Gitea Actionsissa run-stepin tila määräytyy viimeisen komennon exit-koodista.
Pipe (|) asettaa $?:ksi viimeisen komennon tuloksen — jos viimeinen komento
on tee, tulos on aina 0 riippumatta siitä mitä aiemmat komennot palauttivat.
Tämä on aiheuttanut tuotannossa tilanteita, joissa testit feilasivat mutta jobi
näytti vihreää, koska tee söi exit-koodin. Virhe havaittiin vasta kun raportteja
alettiin lukea manuaalisesti — commit-status valehteli.
Ratkaisu on yksiselitteinen: exit-koodi talteen $?-muuttujaan ennen kuin mikään
muu komento ehtii muuttaa sitä, ja stepin viimeinen komento on aina exit ${EXIT}.