diff --git a/skills/ci-container-build/SKILL.md b/skills/ci-container-build/SKILL.md index 4e9c659..e19f598 100644 --- a/skills/ci-container-build/SKILL.md +++ b/skills/ci-container-build/SKILL.md @@ -32,6 +32,31 @@ 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 @@ -123,27 +148,44 @@ tag: latest ### Dockerfile -Dockerfile yhdistää tarvitut työkalut yhteen konttiin. Molemmat tavat kelpaavat: +Dockerfile yhdistää tarvitut työkalut yhteen konttiin. +**Kaikki riippuvuudet ladataan build-vaiheessa — kontti on täysin itseriittoinen.** ```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__ # Ei koskaan git:iä — kloonaus kuuluu pipelinelle +RUN apk add --no-cache __PAKETIT__ -# Tapa B: curl-lataus (normaali Dockerfilessa) +# Tapa B: Build-vaiheen curl-lataus 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` on selkeämpi kun binääri -tulee suoraan GitHub Releasesista tai vastaavasta. +`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. ## Mitä EI kannata tehdä - Älä lisää `workflow_call`-triggariä — CI-konttia ei koskaan buildata automaattisesti - Älä poista `.`-prefiksiä olemassaolevista tiedostoista — ne kuuluvat monorepo-nimeämiskonventioon - Älä sisällytä CI-konttiin mitään sovelluskoodia — vain työkalut -- Ä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 +- Ä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ä diff --git a/skills/consumer-pipelines/REFERENCE.md b/skills/consumer-pipelines/REFERENCE.md index 64d93c1..58ae7ce 100644 --- a/skills/consumer-pipelines/REFERENCE.md +++ b/skills/consumer-pipelines/REFERENCE.md @@ -2,6 +2,93 @@ 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 diff --git a/skills/consumer-pipelines/SKILL.md b/skills/consumer-pipelines/SKILL.md index 31a042a..542fc0c 100644 --- a/skills/consumer-pipelines/SKILL.md +++ b/skills/consumer-pipelines/SKILL.md @@ -82,7 +82,36 @@ 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 CI-kontin ajaminen jobissa +### 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 | 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 Ainoa sallittu tapa on `container:`-direktiivi. `docker run` komennolla kontin käynnistäminen stepin sisällä on anti-pattern. @@ -91,7 +120,8 @@ 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. +joka vaatii sekä `nodejs` että `git`. Varmista että CI-kontin Dockerfilessä on +molemmat — muuten checkout ei toimi ja pipeline failaa. ## 5. Raporttitasot @@ -243,15 +273,14 @@ helm-build-push: # chart_path: '.' # oletus, vaihda jos Chart.yaml on alihakemistossa ``` -**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. +**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). -- 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 +**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. **Yksittäisten Helm-UI-linkkien raportointi:** `HELM_UI_URL` on tarkoitettu yleiselle registry UI:lle — provider muodostaa linkin