refaktorointia
CI Feature / Validate CI config (push) Successful in 20s
ci-cucumber Cucumber tests OK
CI Feature / Cucumber tests (push) Successful in 1m5s
ci-build Build complete
CI Feature / Report Index (push) Successful in 18s
CI Feature / Load gitea-env.conf to pipeline env (push) Successful in 11s
ci-validate CI config valid
ci-bats Bats tests OK
CI Feature / Bats tests (push) Successful in 1m42s
CI Feature / Validate CI config (push) Successful in 20s
ci-cucumber Cucumber tests OK
CI Feature / Cucumber tests (push) Successful in 1m5s
ci-build Build complete
CI Feature / Report Index (push) Successful in 18s
CI Feature / Load gitea-env.conf to pipeline env (push) Successful in 11s
ci-validate CI config valid
ci-bats Bats tests OK
CI Feature / Bats tests (push) Successful in 1m42s
This commit is contained in:
@@ -8,10 +8,13 @@ on:
|
|||||||
secrets:
|
secrets:
|
||||||
GITEA_TOKEN:
|
GITEA_TOKEN:
|
||||||
required: true
|
required: true
|
||||||
|
GIT_PAGES_PUBLISH_TOKEN:
|
||||||
|
required: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }}
|
GITEA_API_URL: ${{ fromJson(inputs.env_json).GITEA_API_URL }}
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
GIT_PAGES_PUBLISH_TOKEN: ${{ secrets.GIT_PAGES_PUBLISH_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validate:
|
validate:
|
||||||
@@ -30,12 +33,10 @@ jobs:
|
|||||||
id: validate
|
id: validate
|
||||||
run: bash .ci/scripts/ci-validate.sh
|
run: bash .ci/scripts/ci-validate.sh
|
||||||
|
|
||||||
- name: Report status
|
- name: Report status SUCCESS
|
||||||
if: always()
|
if: success()
|
||||||
run: |
|
run: bash .ci/scripts/report-status.sh success "CI config valid" ci-validate
|
||||||
if [ "${{ steps.validate.outcome }}" = "success" ]; then
|
|
||||||
bash .ci/scripts/report-status.sh success "CI config valid" ci-validate
|
- name: Report status FAILURE
|
||||||
else
|
if: failure()
|
||||||
bash .ci/scripts/report-status.sh failure "CI validation FAILED" ci-validate
|
run: bash .ci/scripts/report-status.sh failure "CI validation FAILED" ci-validate
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report status
|
- name: Report status
|
||||||
if: always()
|
if: always()
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ "${CUCUMBER_EXIT}" = "0" ]; then
|
if [ "${CUCUMBER_EXIT}" = "0" ]; then
|
||||||
if [ -f "reports/${GITHUB_SHA:0:8}/cucumber/index.html" ]; then
|
if [ -f "reports/${GITHUB_SHA:0:8}/cucumber/index.html" ]; then
|
||||||
|
|||||||
@@ -30,12 +30,10 @@ jobs:
|
|||||||
id: report-index
|
id: report-index
|
||||||
run: bash .ci/.gitea/scripts/generate-report-index.sh
|
run: bash .ci/.gitea/scripts/generate-report-index.sh
|
||||||
|
|
||||||
- name: Report status
|
- name: Report status SUCCESS
|
||||||
if: always()
|
if: success()
|
||||||
run: |
|
run: bash .ci/scripts/report-status.sh success "Build complete" ci-build
|
||||||
if [ "${{ steps.report-index.outcome }}" = "success" ]; then
|
|
||||||
bash .ci/scripts/report-status.sh success "Build complete" ci-build
|
- name: Report status FAILURE
|
||||||
else
|
if: failure()
|
||||||
bash .ci/scripts/report-status.sh failure "Build FAILED" ci-build
|
run: bash .ci/scripts/report-status.sh failure "Build FAILED" ci-build
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# 7. Statusraportoinnin pattern
|
||||||
|
|
||||||
|
## Päätös
|
||||||
|
|
||||||
|
Jokaisen jobin on raportoitava lopputulos commit-statukseen. Käytössä on kaksi
|
||||||
|
patternia, jotka eroavat toisistaan vain raporttien julkaisun osalta.
|
||||||
|
|
||||||
|
### Tool-jobit (validate, build, push, tag, check-version, report-index)
|
||||||
|
|
||||||
|
```
|
||||||
|
PENDING → työvaihe → SUCCESS (if: success) / FAILURE (if: failure)
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Set Gitea status to PENDING
|
||||||
|
run: bash .ci/scripts/report-status.sh pending "Validating..." ci-validate
|
||||||
|
|
||||||
|
- name: Do work
|
||||||
|
run: some-command
|
||||||
|
|
||||||
|
- name: Report status SUCCESS
|
||||||
|
if: success()
|
||||||
|
run: bash .ci/scripts/report-status.sh success "OK" ci-validate
|
||||||
|
|
||||||
|
- name: Report status FAILURE
|
||||||
|
if: failure()
|
||||||
|
run: bash .ci/scripts/report-status.sh failure "FAILED" ci-validate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test-jobit (bats, cucumber)
|
||||||
|
|
||||||
|
```
|
||||||
|
PENDING → testit → publish (always) → status (always, exit-koodin mukaan)
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Set Gitea status to PENDING
|
||||||
|
run: bash .ci/scripts/report-status.sh pending "Running tests..." ci-tests
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
run-tests
|
||||||
|
EXIT=$?
|
||||||
|
echo "EXIT=${EXIT}" >> "${GITHUB_ENV}"
|
||||||
|
exit ${EXIT}
|
||||||
|
|
||||||
|
- name: Publish reports
|
||||||
|
if: always()
|
||||||
|
run: bash .ci/scripts/publish-git-pages.sh suite
|
||||||
|
|
||||||
|
- name: Report status
|
||||||
|
if: always()
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [ "${EXIT}" = "0" ]; then
|
||||||
|
bash .ci/scripts/report-status.sh success "Tests OK" ci-tests suite
|
||||||
|
else
|
||||||
|
bash .ci/scripts/report-status.sh failure "Tests FAILED" ci-tests suite
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Periaatteet
|
||||||
|
|
||||||
|
1. Ennen varsinaista työvaihetta asetetaan status `pending` — näin commit-näkymässä
|
||||||
|
näkyy heti, että jobi on käynnissä.
|
||||||
|
2. `run`-komennon on nostettava virhe ylös — oli kyse tool-callista (docker,
|
||||||
|
curl, bash) tai testien ajamisessa tapahtuneesta testivirheestä.
|
||||||
|
3. Tool-jobit käyttävät `if: success()` ja `if: failure()` — jobin sisäinen
|
||||||
|
tila ratkaisee suoraan kumman steppi ajetaan.
|
||||||
|
4. Test-jobit käyttävät `if: always()` publish- ja status-stepeissä — raportti
|
||||||
|
julkaistaan ja status asetetaan aina, riippumatta testin lopputuloksesta.
|
||||||
|
5. Testiraportit julkaistaan myös virhetilanteessa, mikäli ne ovat syntyneet.
|
||||||
|
6. Status-linkki ohjaa testiraporttiin (suite-parametri) jos raportti on
|
||||||
|
olemassa, muuten Gitea Actions -logiin.
|
||||||
|
|
||||||
|
## Tausta
|
||||||
|
|
||||||
|
Aiemmassa `quality-gate.yml`:ssä käytettiin `if: always()` + sisäistä if/elseä
|
||||||
|
myös tool-jobeissa (`steps.<id>.outcome`-tarkistus). Tämä on tarpeetonta
|
||||||
|
kompleksisuutta työvaiheille, jotka eivät tuota erillistä raporttia — jobin oma
|
||||||
|
tila (`success`/`failure`) on riittävä ehto.
|
||||||
|
|
||||||
|
Test-jobit tarvitsevat `if: always()`:n koska raportti on julkaistava ja status
|
||||||
|
asetettava silloinkin kun testit epäonnistuvat. Status-viestin URL osoittaa
|
||||||
|
suoraan raporttiin git-pagesissa, mikä on kriittinen feature virheenjäljityksessä.
|
||||||
|
|
||||||
|
Pipeline-status jokaiselle vaiheelle on välttämätön, koska Gitean branch
|
||||||
|
protection -säännöt käyttävät commit-statusta merge-estona. Jokainen
|
||||||
|
`ci-*`-konteksti voi toimia vaadittuna statuksena PR:n sulkemiselle — jos
|
||||||
|
yksikin status on `failure`, merge estyy. Tämä korvaa Jenkinsin
|
||||||
|
`disableConcurrentBuilds()`- ja build gate -logiikan Gitea-natiivilla
|
||||||
|
mekanismilla.
|
||||||
|
|
||||||
|
Status-näkymä toimii myös master-haaran terveyden monitorina: Git UI:sta
|
||||||
|
näkee suoraan yhdellä silmäyksellä onko uusin commit vihreä. Ei tarvitse
|
||||||
|
avata CI-järjestelmän dashboardia.
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
1. Exit-koodi on ainoa totuus. `0` = onnistui, kaikki muut = epäonnistui.
|
||||||
|
2. Exit-koodia ei saa syödä. Pipe (`|`) viimeisenä komentona `tee`:hen syö
|
||||||
|
exit-koodin — `docker run … | tee file` palauttaa aina 0.
|
||||||
|
3. Data transfer -pipet ovat sallittuja (`tar c . | docker run … tar x`),
|
||||||
|
koska niiden exit-koodilla ei ole semanttista merkitystä.
|
||||||
|
4. Testien tai työkalujen ajaminen ei saa päättyä pipeen.
|
||||||
|
5. `set -o pipefail` ei ole riittävä suojaus — PIPESTATUS resetoituu herkästi.
|
||||||
|
|
||||||
|
## Sallitut patternit
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 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}`.
|
||||||
Reference in New Issue
Block a user