Sesja: Golang CI/CD pipeline — 2026-03-08

Data: 2026-03-08 (popołudnie, ~14:26–18:00 UTC) Uczestnicy: Orwil 🐹, Aleksander Agenci pomocnicy: Stefan 🔍 (inspektor), Klaudynka 🤖 (implementacja)


Cel sesji

Zbudowanie pełnego pipeline CI/CD dla projektu Golang (platform/biz/kunegunda/api) z następującymi założeniami:

  • CI — przy commicie do main: buduj, testuj, pakuj binarki, publikuj do Package Registry, twórz tag i GitLab Release
  • CD — przy tagu git: pobierz artefakt z Package Registry i deployuj
  • Pipeline realizowany przez centralny szablon platform/arch/cicd/pipeline (branch lab/experiment-tag)

Problemy napotkane i rozwiązania

1. Błąd wersji Go — go 1.22 vs go 1.23

Problem: Runner używał golang:1.22 ale go.mod wymagał >= 1.23 (zależność gin-contrib/sse@v1.1.0).
Rozwiązanie: Zmiana go_version: '1.22''1.23' w .gitlab-ci.yml projektu.

2. go mod failuje — brak GONOSUMCHECK

Problem: go mod download i go mod verify failowały w prywatnej sieci bez dostępu do sum DB.
Rozwiązanie: Dodanie GONOSUMCHECK=*, GONOSUMDB=*, GOPRIVATE=* do dependency.sh.

3. go mod tidy wymagane po zmianie wersji

Problem: go vet ./... i go build ./... failowały z go: updates to go.mod needed; to update it: go mod tidy.
Rozwiązanie: Dodanie go mod tidy jako pierwszego kroku w dependency.sh. Dodanie GOFLAGS=-mod=mod do build.sh i unit-test.sh.

4. no Go files — main package w podkatalogu

Problem: go build . failowało z no Go filesmain.go jest w cmd/api/, nie w rocie.
Rozwiązanie: Auto-detect w package.sh:

if [ -d "cmd/${BINARY}" ]; then MAIN_PKG="./cmd/${BINARY}"
elif [ -d "cmd/api" ]; then MAIN_PKG="./cmd/api"
else MAIN_PKG="."
fi

5. SSL/TLS — Lab Root CA

Problem: Kontenery nie ufały self-signed certyfikatom *.internal.
Rozwiązanie: Wbudowanie instalacji CA (https://ca.internal:9000/roots.pem) bezpośrednio w before_script_executor.sh — działa automatycznie dla każdego joba bez modyfikacji skryptów technologicznych.

6. coverage.out nie przekazywane między jobami

Problem: coverage-report failował z cover: open coverage.out: no such file — artifact nie był zdefiniowany dla unit-test.
Rozwiązanie: Zmiana unit-test: {}unit-test: {paths: [coverage.out], expire_in: 1 day} w common/artifacts/common.yml.

7. Błędne wersjonowanie przez git describe

Problem: prepare.sh używał git describe --tags → zwracał stary tag v1.1.0 zamiast auto-wersji.
Rozwiązanie: Zmiana logiki na:

if [ -n "${CI_COMMIT_TAG}" ]; then VERSION="${CI_COMMIT_TAG#v}"
else VERSION="0.1.${CI_PIPELINE_IID}"
fi

8. publish:release vs release-notes — podział odpowiedzialności

Problem: Początkowo publish:release tworzył git tag (przez glab tag create) — sprzeczność z rolą joba.
Decyzja architektoniczna:

  • publish:release → TYLKO upload binarki do Generic Package Registry (curl PUT)
  • release-notes → git tag (przez GitLab API) + GitLab Release z linkiem do pakietu

9. release-notes — brak glab + JOB_TOKEN bez uprawnień do tagów

Problem: Job nie instalował glab CLI. CI_JOB_TOKEN nie ma uprawnień do tworzenia tagów przez API.
Rozwiązanie: Zmiana na GitLab REST API z GITLAB_RELEASE_TOKEN (personal access token dodany jako zmienna CI).

10. YAML multiline string — Build: ... parsowane jako klucz

Problem: NOTES="Release ${TAG} Build: ..."Build: bez indentacji w YAML block scalar powodowało błąd parsowania.
Rozwiązanie: NOTES=$(printf 'Release %s\nBuild: %s...' ...) — printf w jednej linii.

11. glab release download --pattern — nieznana flaga

Problem: Glab 1.46.1 nie ma flagi --pattern dla release download.
Rozwiązanie: Podmiana na curl z Generic Package Registry:

curl -k -f -H "JOB-TOKEN: ${CI_JOB_TOKEN}" \
  "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${BINARY}/${VERSION}/${FILENAME}" \
  -o "${DEPLOY_DIR}/${FILENAME}"

12. APP_NAME=app w CD pipeline — nadpisanie przez cd/variables

Problem: common/cd/variables/common.yml miało APP_NAME: app które nadpisywało globalną zmienną z inputs (kunegunda-api).
Rozwiązanie: Usunięcie APP_NAME z cd/variables/common.yml — deploy job dziedziczy globalną zmienną.


Architektura CI/CD — stan końcowy

.gitlab-ci.yml (kunegunda/api)
  ↓ include technology/golang/main.yml
    ↓ include common/process.yml (CI jobs)
    ↓ include common/cd/ (deploy job)

Trigger: commit do main
  → PROCES_TYPE=CI
  → prepare → dependency → build → unit-test → coverage-report
  → sonarqube → package → publish:release → release-notes
  → release-notes tworzy tag v0.1.{IID}
  → tag triggeruje nowy pipeline CD

Trigger: tag v*.*.*
  → PROCES_TYPE=CD
  → deploy (pobiera z Package Registry, wdraża)

Nowe elementy infrastruktury

ElementOpis
technology/golang/main.ymlPełny CI+CD dla Go: inputs (go_version, app_name, environment)
common/helpers/lab-ca.sh.ymlHelper do instalacji Lab Root CA
common/helpers/executors.sh.ymlCA instalowany automatycznie w before_script
common/artifacts/common.ymlunit-test artifact: coverage.out
GITLAB_RELEASE_TOKENCI variable w projekcie 3 z PAT do tworzenia tagów

Rola Stefana — przeprojektowanie

Stefan 🔍 zmienił rolę: z monitora pipeline na inspektora/analityka:

  • Przed: Stefan próbował monitorować pipeline w pętli (subagenty nie mogą niezawodnie trzymać pętli)
  • Po: Stefan analizuje zakończone pipeline — dostaje job IDs, pobiera logi, porównuje z wzorcem, raportuje odchylenia

Orwil monitoruje pipeline przez exec + process poll. Gdy pipeline skończy → zleca Stefanowi analizę.


Wyniki

PipelineStatusOpis
#265–274Iteracje naprawiania — dependency, build, coverage
#284✅ CIPierwszy pełny sukces — wszystkie 9 jobów green
#285❌ CDglab --pattern nieznana flaga
#287✅ CIDrugi pełny sukces
#288❌ CDBINARY=app zamiast kunegunda-api
#290Test końcowy po wszystkich poprawkach