Compare commits
1 Commits
0.2.19
..
bfd0428a78
| Author | SHA1 | Date | |
|---|---|---|---|
| bfd0428a78 |
@@ -8,7 +8,7 @@ on:
|
||||
cucumber-node-image:
|
||||
required: false
|
||||
type: string
|
||||
default: gitea.app.keskikuja.site/niko/ci-cucumber:with-python
|
||||
default: gitea.app.keskikuja.site/niko/ci-cucumber:latest
|
||||
secrets:
|
||||
GITEA_TOKEN:
|
||||
required: true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM node:22
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install -y -qq --no-install-recommends lsof jq python3 && \
|
||||
apt-get install -y -qq --no-install-recommends lsof jq && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
npm install -g @cucumber/cucumber
|
||||
|
||||
@@ -32,31 +32,6 @@ Kun kontti on pushattu registryyn, se on muiden pipeline-jobien käytettävissä
|
||||
`latest`-tägillä — rebuild = käyttöönotto. Mitään versioviittauksia ei tarvitse
|
||||
päivittää.
|
||||
|
||||
## Offline-periaate (DoD)
|
||||
|
||||
CI-kontin **Definition of Done**:
|
||||
|
||||
> Kontti ei lataa mitään pipeline-vaiheessa (`workflow run` -stepit) eikä kontin
|
||||
> runtime-prosessissa (`container:` / `docker run`). Kaikki riippuvuudet
|
||||
> (kielikohtaiset paketit, työkalut, binäärit) on joko:
|
||||
> - Pre-cachattu kontin **build-vaiheessa** Dockerfilessä, TAI
|
||||
> - Kopioitu multi-stage buildilla toisesta imagesta (`COPY --from`)
|
||||
>
|
||||
> Ainoa sallittu lataushetki on `docker build`. Sen jälkeen kontti toimii
|
||||
> ilman verkkoyhteyttä.
|
||||
|
||||
**Miksi:** Toistettavuus, air gap -yhteensopivuus, nopeus. Pipeline ei saa
|
||||
epäonnistua sen takia että ulkoinen registry on alhaalla tai että `go mod download`
|
||||
joutuu latamaan 100 modulia jokaisella testiajolla.
|
||||
|
||||
**Kielikohtaiset pre-cachet:** Jos kontissa ajetaan kielikohtaista testiä
|
||||
(Go, Java, Node, Python, ...), kaikki kielikohtaiset riippuvuudet on
|
||||
pre-cachattava Dockerfilessä build-vaiheessa:
|
||||
- Go: `COPY go.mod go.sum ./` → `RUN go mod download`
|
||||
- Java/Maven: `COPY pom.xml ./` → `RUN mvn dependency:go-offline`
|
||||
- Node: `COPY package.json package-lock.json ./` → `RUN npm ci --omit=dev`
|
||||
- Python: `COPY requirements.txt ./` → `RUN pip wheel --wheel-dir=/wheels -r requirements.txt` → `COPY --from` käyttöön
|
||||
|
||||
## Nimeäminen
|
||||
|
||||
CI-kontin build-workflow noudattaa samaa nimeämiskonventiota kuin muutkin
|
||||
@@ -148,80 +123,27 @@ tag: latest
|
||||
|
||||
### Dockerfile
|
||||
|
||||
Dockerfile yhdistää tarvitut työkalut yhteen konttiin.
|
||||
**Kaikki riippuvuudet ladataan build-vaiheessa — kontti on täysin itseriittoinen.**
|
||||
Dockerfile yhdistää tarvitut työkalut yhteen konttiin. Molemmat tavat kelpaavat:
|
||||
|
||||
```dockerfile
|
||||
# Tapa A: COPY --from toisesta imagesta
|
||||
FROM __BASE_IMAGE__:__VERSION__
|
||||
COPY --from=__SOURCE_IMAGE__:__VERSION__ /path/to/binary /usr/local/bin/
|
||||
RUN apk add --no-cache __PAKETIT__
|
||||
RUN apk add --no-cache __PAKETIT__ # Ei koskaan git:iä — kloonaus kuuluu pipelinelle
|
||||
|
||||
# Tapa B: Build-vaiheen curl-lataus
|
||||
# Tapa B: curl-lataus (normaali Dockerfilessa)
|
||||
FROM __BASE_IMAGE__:__VERSION__
|
||||
RUN apk add --no-cache curl __PAKETIT__ && \
|
||||
curl -fsSL __URL__/__BINARY__.tar.gz | tar xz -C /usr/local/bin && \
|
||||
apk del curl
|
||||
|
||||
# Tapa C: Multi-stage + kielikohtainen pre-cache
|
||||
FROM __BASE_IMAGE__:__VERSION__ AS deps
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
FROM deps AS build
|
||||
COPY . .
|
||||
RUN go test -c -o /tmp/test.bin ./...
|
||||
|
||||
FROM __BASE_IMAGE__:__VERSION__
|
||||
COPY --from=deps /go/pkg/mod /go/pkg/mod
|
||||
COPY --from=build /tmp/test.bin /usr/local/bin/test
|
||||
```
|
||||
|
||||
`COPY --from` on kevyempi (ei curl-asennusta). `curl` (Tapa B) on sallittu
|
||||
vain build-vaiheessa — `apk del curl` poistaa työkalun ennen runtimea.
|
||||
Tapa C pre-cacheaa kielikohtaiset riippuvuudet ja tuottaa täysin
|
||||
offline-runtime-kontin.
|
||||
|
||||
## Testaus ennen julkaisua
|
||||
|
||||
Konttia ei saa pushata registryyn ennen kuin se on validoitu.
|
||||
|
||||
### 1. Aja testit kontin sisällä
|
||||
|
||||
Testit on ajettava **kontin sisällä**, ei suoraan lokaalilla koneella.
|
||||
|
||||
```bash
|
||||
# OIKEIN — kontin sisällä
|
||||
docker build -t ci-tyokalu:test .
|
||||
docker run --rm -v "$(pwd):/repo" -w /repo ci-tyokalu:test bash -c 'bats tests/'
|
||||
|
||||
# VÄÄRIN — lokaalit binäärit vs kontti
|
||||
bats tests/ # eri bash/työkalut kuin kontissa
|
||||
bashcov -- bats tests/ # eri ruby-versio kuin kontissa
|
||||
```
|
||||
|
||||
Lokaali ympäristö (macOS, eri kirjastoversiot) poikkeaa aina kontista.
|
||||
Testi voi mennä läpi lokaalissa mutta failata CI:ssä, tai päinvastoin.
|
||||
|
||||
### 2. Fragile-testien seulonta (10x ajo)
|
||||
|
||||
Aja koko testipaketti **10 kertaa peräkkäin** kontin sisällä ennen pushausta:
|
||||
|
||||
```bash
|
||||
for i in $(seq 1 10); do
|
||||
echo "=== RUN $i ==="
|
||||
docker run --rm -v "$(pwd):/repo" -w /repo ci-tyokalu:test \
|
||||
bash -c 'bats tests/' || exit 1
|
||||
done
|
||||
```
|
||||
|
||||
Jos yksikin ajo failaa, kontissa on fragile testi — korjaa ennen pushausta.
|
||||
Fragile testit syövät devaukseen käytettyä aikaa turhilla uusinta-ajoilla.
|
||||
`COPY --from` on kevyempi (ei curl-asennusta). `curl` on selkeämpi kun binääri
|
||||
tulee suoraan GitHub Releasesista tai vastaavasta.
|
||||
|
||||
## Mitä EI kannata tehdä
|
||||
|
||||
- Älä lisää `workflow_call`-triggariä — CI-konttia ei koskaan buildata automaattisesti
|
||||
- Älä poista `<komponentti>.`-prefiksiä olemassaolevista tiedostoista — ne kuuluvat monorepo-nimeämiskonventioon
|
||||
- Älä sisällytä CI-konttiin mitään sovelluskoodia — vain työkalut
|
||||
- Älä koskaan lataa mitään pipeline- tai runtime-vaiheessa — kaikki lataukset kuuluvat `docker build` -vaiheeseen (Offline-periaate)
|
||||
- Älä jätä kielikohtaisia riippuvuuksia pre-cachaamatta — `go mod download`, `npm install`, `mvn dependency:go-offline` jne. ajetaan Dockerfilessä, ei pipelinessä
|
||||
- Älä koskaan asenna `git`:iä CI-konttiin — repon kloonaus ja checkout ovat Gitea Actionsin natiiveja operaatioita, eivät kontin vastuulla. Git paisuttaa konttia turhaan ja luo harhan että kontti hallitsee repoa
|
||||
|
||||
@@ -2,93 +2,6 @@
|
||||
|
||||
Mallipohjat, esimerkit ja konfiguraatiot. Katso säännöt `SKILL.md`:stä.
|
||||
|
||||
## Pre-cache-esimerkit (Offline Container)
|
||||
|
||||
Alla Dockerfile-esimerkit kielikohtaisista pre-cacheista. Kaikki ajetaan
|
||||
build-vaiheessa — kontti on täysin itseriittoinen eikä lataa mitään
|
||||
pipeline- tai runtime-vaiheessa.
|
||||
|
||||
### Go
|
||||
|
||||
```dockerfile
|
||||
FROM golang:1.24-alpine AS deps
|
||||
WORKDIR /build
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
FROM deps AS test-build
|
||||
COPY . .
|
||||
RUN go test -c -o /tmp/test.bin ./...
|
||||
|
||||
FROM alpine:3.21
|
||||
RUN apk add --no-cache git nodejs
|
||||
COPY --from=deps /go/pkg/mod /go/pkg/mod
|
||||
COPY --from=test-build /tmp/test.bin /usr/local/bin/test
|
||||
```
|
||||
|
||||
### Node.js
|
||||
|
||||
```dockerfile
|
||||
FROM node:22-alpine AS deps
|
||||
WORKDIR /build
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --omit=dev
|
||||
|
||||
FROM node:22-alpine
|
||||
RUN apk add --no-cache git
|
||||
COPY --from=deps /build/node_modules /app/node_modules
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
```
|
||||
|
||||
### Java / Maven
|
||||
|
||||
```dockerfile
|
||||
FROM maven:3.9-eclipse-temurin-21 AS deps
|
||||
WORKDIR /build
|
||||
COPY pom.xml ./
|
||||
RUN mvn dependency:go-offline -B
|
||||
|
||||
FROM maven:3.9-eclipse-temurin-21 AS build
|
||||
COPY --from=deps /root/.m2 /root/.m2
|
||||
COPY . .
|
||||
RUN mvn package -B -DskipTests
|
||||
|
||||
FROM eclipse-temurin:21-jre
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=build /build/target/*.jar /app/app.jar
|
||||
WORKDIR /app
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.12-alpine AS deps
|
||||
WORKDIR /build
|
||||
COPY requirements.txt ./
|
||||
RUN pip wheel --wheel-dir=/wheels -r requirements.txt
|
||||
|
||||
FROM python:3.12-alpine
|
||||
RUN apk add --no-cache git
|
||||
COPY --from=deps /build/wheels /wheels
|
||||
COPY --from=deps /build/requirements.txt /
|
||||
RUN pip install --no-index --find-links=/wheels -r /requirements.txt && rm -rf /wheels
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
```
|
||||
|
||||
### Helm + Node.js (korvaa helm-build-push.yml:n runtime-apk)
|
||||
|
||||
```dockerfile
|
||||
FROM alpine/helm:3.16.0 AS helm-bin
|
||||
FROM node:22-alpine
|
||||
RUN apk add --no-cache git
|
||||
COPY --from=helm-bin /usr/bin/helm /usr/local/bin/helm
|
||||
```
|
||||
|
||||
Tämä kontti korvaa `helm-build-push.yml`:n `alpine/helm:3.19.0`-image-riippuvuuden
|
||||
ja poistaa tarpeen asentaa node.js runtime-vaiheessa.
|
||||
|
||||
## Reititin — täydellinen esimerkki
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -82,36 +82,7 @@ koko stepin ensimmäisellä failaavalla komennolla, ja loput jäävät ajamatta.
|
||||
|
||||
CI-kontin build-workflow'n template: `skills/ci-container-build/SKILL.md`.
|
||||
|
||||
### 4.1 Offline Container -vaatimus (DoD)
|
||||
|
||||
CI-kontin (ja kaikkien pipeline-konttien) on oltava täysin itseriittoisia:
|
||||
|
||||
> Kontti ei lataa mitään pipeline-vaiheessa (`workflow run` -stepit) eikä
|
||||
> kontin runtime-prosessissa (`container:` / `docker run`). Kaikki
|
||||
> riippuvuudet pre-cachataan `docker build` -vaiheessa.
|
||||
> Ainoa sallittu lataushetki on `docker build`.
|
||||
|
||||
**Esimerkkejä rikkomuksista:**
|
||||
- `apk add`, `apt-get install`, `npm install`, `go mod download`, `pip install`
|
||||
pipeline-stepissä
|
||||
- `curl <url> | tar xz` runtime-vaiheessa
|
||||
- Node.js-konttikuva ilman nodea (joudutaan asentamaan lennossa)
|
||||
|
||||
### 4.2 Kielikohtainen pre-cache
|
||||
|
||||
Kun kontissa testataan kielikohtaista koodia, kaikki riippuvuudet on
|
||||
pre-cachattava Dockerfilessä, ei pipeline-stepissä:
|
||||
|
||||
| Kieli | Pre-cache Dockerfilessä |
|
||||
|---|---|
|
||||
| Go | `COPY go.mod go.sum ./` → `RUN go mod download` |
|
||||
| Java/Maven | `COPY pom.xml ./` → `RUN mvn dependency:go-offline` |
|
||||
| Node | `COPY package.json package-lock.json ./` → `RUN npm ci --omit=dev` |
|
||||
| Python | `COPY requirements.txt ./` → `RUN pip install -r requirements.txt` |
|
||||
|
||||
Katso tarkat Dockerfile-esimerkit `REFERENCE.md`:stä.
|
||||
|
||||
### 4.3 CI-kontin ajaminen jobissa
|
||||
### 4.1 CI-kontin ajaminen jobissa
|
||||
|
||||
Ainoa sallittu tapa on `container:`-direktiivi. `docker run` komennolla kontin
|
||||
käynnistäminen stepin sisällä on anti-pattern.
|
||||
@@ -120,8 +91,7 @@ Katso CI-kontin template `REFERENCE.md`:stä.
|
||||
|
||||
**Huomio `actions/checkout@v4`:stä:** `container:`-direktiivillä kaikki stepit
|
||||
ajetaan kontin *sisällä* — myös `actions/checkout@v4`. Se on JavaScript-action
|
||||
joka vaatii sekä `nodejs` että `git`. Varmista että CI-kontin Dockerfilessä on
|
||||
molemmat — muuten checkout ei toimi ja pipeline failaa.
|
||||
joka vaatii sekä `nodejs` että `git`. Varmista että CI-kontin Dockerfilessä on molemmat.
|
||||
|
||||
## 5. Raporttitasot
|
||||
|
||||
@@ -273,14 +243,15 @@ helm-build-push:
|
||||
# chart_path: '.' # oletus, vaihda jos Chart.yaml on alihakemistossa
|
||||
```
|
||||
|
||||
**Vanhentunut käytäntö:** Nykyinen `helm-build-push.yml` asentaa node.js:n
|
||||
lennossa `apk add --no-cache nodejs` ennen checkouttia — tämä rikkoo
|
||||
Offline Container -vaatimusta (4.1).
|
||||
**Node.js-kompromissi:** `actions/checkout@v4` on JavaScript-action.
|
||||
Kontissa `alpine/helm` ei ole node.js:ää, joten se asennetaan lennossa
|
||||
`apk add --no-cache nodejs` ennen checkouttia.
|
||||
|
||||
**Korjaustoimenpide:** Rakenna custom CI-kontti `ci-container-build`-skillillä
|
||||
jossa on helm + nodejs + git (katso pre-cache-esimerkit `REFERENCE.md`:stä),
|
||||
päivitä workflow'n `container: image:` osoittamaan omaan konttiin, ja poista
|
||||
runtime-apk.
|
||||
- Vaatii internet-yhteyden
|
||||
- Ei toimi air gap -ympäristössä
|
||||
- Korvaa tarvittaessa custom-kontilla (helm + nodejs):
|
||||
rakenna `ci-container-build`-skillillä ja päivitä workflow'n
|
||||
`container: image:` osoittamaan omaan konttiin
|
||||
|
||||
**Yksittäisten Helm-UI-linkkien raportointi:** `HELM_UI_URL` on
|
||||
tarkoitettu yleiselle registry UI:lle — provider muodostaa linkin
|
||||
|
||||
Binary file not shown.
@@ -12,10 +12,8 @@ MOCK_CONFIG_FILE=""
|
||||
_kill_port() {
|
||||
local pids
|
||||
pids=$(lsof -ti ":$MOCK_PORT" 2>/dev/null) || true
|
||||
if [ -n "$pids" ]; then
|
||||
kill -9 $pids 2>/dev/null || true
|
||||
sleep 0.5
|
||||
fi
|
||||
[ -n "$pids" ] && kill -9 $pids 2>/dev/null || true
|
||||
sleep 0.5
|
||||
}
|
||||
|
||||
_wait_port_free() {
|
||||
@@ -28,7 +26,7 @@ _wait_port_free() {
|
||||
|
||||
_wait_port_ready() {
|
||||
local i=0
|
||||
while ! lsof -ti ":$MOCK_PORT" >/dev/null 2>&1 && [ $i -lt 30 ]; do
|
||||
while ! lsof -ti ":$MOCK_PORT" >/dev/null 2>&1 && [ $i -lt 5 ]; do
|
||||
sleep 0.2
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user