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(branchlab/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 files — main.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="."
fi5. 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}"
fi8. 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
| Element | Opis |
|---|---|
technology/golang/main.yml | Pełny CI+CD dla Go: inputs (go_version, app_name, environment) |
common/helpers/lab-ca.sh.yml | Helper do instalacji Lab Root CA |
common/helpers/executors.sh.yml | CA instalowany automatycznie w before_script |
common/artifacts/common.yml | unit-test artifact: coverage.out |
GITLAB_RELEASE_TOKEN | CI 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
| Pipeline | Status | Opis |
|---|---|---|
| #265–274 | ❌ | Iteracje naprawiania — dependency, build, coverage |
| #284 | ✅ CI | Pierwszy pełny sukces — wszystkie 9 jobów green |
| #285 | ❌ CD | glab --pattern nieznana flaga |
| #287 | ✅ CI | Drugi pełny sukces |
| #288 | ❌ CD | BINARY=app zamiast kunegunda-api |
| #290 | ⏳ | Test końcowy po wszystkich poprawkach |
