Public Access
Initial implementation: aptly container image, Compose stacks, Helm chart, and Gitea Actions pipelines
Provides a self-contained, containerized aptly (Debian repo manager) stack with independently releasable image and Helm chart versions. - images/: aptly-server (aptly built from source, cross-compiled) and aptly-deb-builder (nfpm + dpkg-buildpackage) container images - rootfs/: shared aptly-init/aptly-reconcile/aptly-push/aptly-pack scripts consumed identically by Compose and the Helm chart, driven by one declarative state.yaml contract - compose/: test (ephemeral, open) and production docker-compose stacks with an nginx read/auth sidecar - charts/aptly/: aptly-native Helm chart covering every security posture from fully open to authenticated read+write, Ingress and Gateway API support (usable in parallel for migration scenarios), metrics, and declarative repo/mirror/publish reconciliation via a Helm hook - .gitea/workflows/: CI (lint, template, kubeconform, E2E smoke test) plus separately tagged image (image/v*) and chart (chart/v*) releases, weekly rebuilds, and a preflight workflow validating the runner's Docker/Helm-OCI capabilities - pubkeys/: RSA chart-signing key for Helm --sign / Artifact Hub's signKey annotation (Helm can't verify Ed25519 keys) - docs/, README.md, charts/aptly/README.md: usage, security, and versioning documentation
This commit is contained in:
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
# tests/smoke-test.sh — the actual merge gate for this repo. Proves the
|
||||
# whole promise of the project end to end, not just that things compile:
|
||||
#
|
||||
# pack -> push -> publish -> `apt-get update && apt-get install` -> content
|
||||
#
|
||||
# against the real docker-compose.test.yaml stack (aptly-init -> aptly ->
|
||||
# nginx sidecar), using the same rootfs scripts and images CI ships. Nothing
|
||||
# here is mocked. Run from the repo root: ./tests/smoke-test.sh
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
log() { printf '\033[1;34m[smoke]\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m[smoke] ERROR:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
COMPOSE_FILE="compose/docker-compose.test.yaml"
|
||||
PROJECT="aptly-smoke-$$"
|
||||
FIXTURE_DIR="tests/fixtures/demo-package"
|
||||
WORK_DIR="$(mktemp -d)"
|
||||
|
||||
cleanup() {
|
||||
log "cleaning up (project: ${PROJECT})"
|
||||
docker compose -p "$PROJECT" -f "$COMPOSE_FILE" down -v --remove-orphans >/dev/null 2>&1 || true
|
||||
rm -rf "$WORK_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
log "building images and starting the test stack"
|
||||
# Not --wait: it treats the `reconcile` one-shot service's expected exit(0)
|
||||
# as a failure and aborts. Poll nginx's own healthcheck instead.
|
||||
docker compose -p "$PROJECT" -f "$COMPOSE_FILE" up -d --build
|
||||
|
||||
network="${PROJECT}_default"
|
||||
|
||||
log "waiting for nginx to report healthy"
|
||||
deadline=$(( $(date +%s) + 120 ))
|
||||
until docker compose -p "$PROJECT" -f "$COMPOSE_FILE" ps nginx --format '{{.Health}}' 2>/dev/null | grep -q healthy; do
|
||||
(( $(date +%s) < deadline )) || die "nginx did not become healthy within 120s"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
log "building the deb-builder image"
|
||||
docker build -q -f images/aptly-deb-builder/Dockerfile -t "aptly-deb-builder:${PROJECT}" . >/dev/null
|
||||
|
||||
log "packaging the demo .deb with aptly-pack (nfpm path)"
|
||||
mkdir -p "${WORK_DIR}/dist"
|
||||
docker run --rm \
|
||||
-v "${ROOT_DIR}/${FIXTURE_DIR}:/work:ro" \
|
||||
-v "${WORK_DIR}/dist:/work-out" \
|
||||
-w /tmp/pkg \
|
||||
--entrypoint /bin/sh \
|
||||
"aptly-deb-builder:${PROJECT}" \
|
||||
-c "cp -r /work/. /tmp/pkg && aptly-pack --output-dir /work-out"
|
||||
|
||||
deb_file="$(find "${WORK_DIR}/dist" -name '*.deb' | head -1)"
|
||||
[[ -n "$deb_file" ]] || die "aptly-pack produced no .deb"
|
||||
log "built: $(basename "$deb_file")"
|
||||
|
||||
log "pushing the package into the (unsigned, open) test repo via aptly-push"
|
||||
# Reuses the already-built `reconcile` service's image/network via `compose
|
||||
# run` instead of guessing compose's image-naming convention.
|
||||
docker compose -p "$PROJECT" -f "$COMPOSE_FILE" run --rm --no-deps \
|
||||
-e "APTLY_URL=http://aptly:8080" \
|
||||
-v "${WORK_DIR}/dist:/dist:ro" \
|
||||
--entrypoint /usr/local/bin/aptly-push \
|
||||
reconcile \
|
||||
--repo demo --distribution stable --no-sign "/dist/$(basename "$deb_file")"
|
||||
|
||||
log "verifying via a real apt-get against the published repo (through nginx)"
|
||||
docker run --rm --network "$network" debian:trixie-slim bash -euxc "
|
||||
echo 'deb [trusted=yes] http://nginx:8080/ stable main' > /etc/apt/sources.list.d/smoke.list
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends demo-package
|
||||
test \"\$(cat /usr/share/demo-package/hello.txt)\" = 'hello from aptly-containerized'
|
||||
"
|
||||
|
||||
log "reconcile idempotency: re-running against unchanged state must not fail"
|
||||
docker compose -p "$PROJECT" -f "$COMPOSE_FILE" run --rm reconcile
|
||||
|
||||
log "PASS — build -> push -> publish -> apt-get chain verified end to end"
|
||||
Reference in New Issue
Block a user