# Хражевник — OCI-образ из scratch.
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Multi-stage: node:22-alpine собирает Vue-SPA, golang:1.26-alpine
# собирает статический бинарник (CGO_ENABLED=0, -trimpath) со встроенным
# через //go:embed бандлом, scratch наследует только бинарник и бандл
# доверенных CA (для HTTPS к upstream-репозиториям). PID 1 — сам бинарник,
# non-root 65534, ReadOnlyRootfs возлагается на quadlet
# (deploy/quadlet/khrazhevnik.container). Сборка — make image.
#
# VERSION: передаётся через --build-arg в CI (тег/SHA); при локальной
# сборке без аргумента — фолбэк на git describe, иначе "dev".

# web: Vue-SPA (vue-tsc + vite build). vite.config.ts задаёт
# outDir '../internal/core/web/assets' — при WORKDIR=/web resolves в
# /internal/core/web/assets (тот же конфиг, что локально; без переопределения
# через CLI, к-рое npm не пробрасывает сквозь script с &&). package*.json
# отдельным слоем — кеш npm между правками исходников Vue. web/node_modules
# в контекст не попадает (.gitignore в чистом checkout) — COPY web/ не затирает
# результат npm ci.
FROM node:22-alpine AS web
WORKDIR /web
# Корень step-ca ДО npm: node верит только своему вшитому хранилищу CA
# (системный бандл alpine игнорирует) — без NODE_EXTRA_CA_CERTS npm ci
# на https://nora... упадёт с self-signed certificate. В git файл не
# коммитится: его кладёт builder (шаг в build.yml / цель в Makefile)
# непосредственно перед сборкой.
COPY deploy/certs/step-ca-root.pem /etc/step-ca-root.pem
# npm — через Nora-прокси (как npm-шаг в build.yml): без ENV npm ci
# идёт на registry.npmjs.org напрямую — дыра в герметичности сборки
# образа.
ENV NODE_EXTRA_CA_CERTS=/etc/step-ca-root.pem \
    npm_config_registry=https://nora.panelka.yadr01.internal/npm/
COPY web/package.json web/package-lock.json ./
RUN npm ci
COPY web/ ./
RUN npm run build

FROM golang:1.26-alpine AS build
# Корень step-ca до apk (chicken-and-egg: без него TLS к инстансу не
# поднимется). apk читает /etc/ssl/certs/ca-certificates.crt, НЕ
# /etc/apk/certificates-bundle (CI-факт 2026-09-06: аппенд в bundle
# доверия не дал). Порядок канонический: аппенд для бустрапа, копия в
# /usr/local/share/ca-certificates (иначе update-ca-certificates корень
# выкинет), apk add ca-certificates с дефолтных реп (публичный TLS),
# перегенерация бандла с корнем — и только потом sed repositories:
# git ставится уже через Хражевник.
COPY deploy/certs/step-ca-root.pem /usr/local/share/ca-certificates/step-ca-root.crt
RUN cat /usr/local/share/ca-certificates/step-ca-root.crt >> /etc/ssl/certs/ca-certificates.crt \
    && apk add --no-cache ca-certificates \
    && update-ca-certificates \
    && sed -i 's#https://dl-cdn.alpinelinux.org/alpine#https://khrazhevnik.panelka.yadr01.internal/apk/alpine#g' /etc/apk/repositories \
    && apk add --no-cache git
# ca-certificates: scratch-образу нужен бандл доверенных CA, иначе
# HTTPS-запросы к upstream-зеркалам упадут с x509. git — фолбэк версии
# через git describe при локальной сборке без --build-arg VERSION.
ARG VERSION=
# Go-модули — через Nora-прокси (как GOPROXY в build.yml): без явного
# ENV go build ходит на дефолтный proxy.golang.org — дыра в
# герметичности сборки образа.
ENV GOPROXY="https://nora.panelka.yadr01.internal/go,direct" \
    GOSUMDB=off \
    GOPRIVATE="git.yadr00.internal/*"
WORKDIR /src
COPY . .
# Встроенный SPA-бандл из web-stage: //go:embed (internal/core/web/spa.go)
# требует assets/index.html на момент go build. В build-context (git checkout)
# assets/ не лежит (gitignore) — берём собранный бандл из web-stage.
COPY --from=web /internal/core/web/assets ./internal/core/web/assets
# -X main.Version: линкер Go 1.26 для package main принимает только
# "main.Version", не полный importpath (полный путь молча не apply'ится;
# проверено локально, см. .forgejo/workflows/build.yml).
RUN set -e; \
    v="${VERSION}"; \
    if [ -z "$v" ]; then v="$(git describe --tags --always 2>/dev/null || echo dev)"; fi; \
    CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.Version=$v" \
        -o /out/khrazhevnik ./cmd/khrazhevnik

FROM scratch
LABEL org.opencontainers.image.title="khrazhevnik" \
      org.opencontainers.image.description="Кеш-прокси и зеркало linux-репозиториев" \
      org.opencontainers.image.licenses="AGPL-3.0-or-later" \
      org.opencontainers.image.terminal="false"
COPY --from=build /out/khrazhevnik /khrazhevnik
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
USER 65534:65534
EXPOSE 29202 30202
VOLUME ["/var/lib/khrazhevnik"]
ENTRYPOINT ["/khrazhevnik"]
