Compare commits
3 Commits
feat/expec
...
chore/runn
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dd6eb5c21 | |||
| c32e6105d0 | |||
| c51cd84159 |
@ -9,13 +9,18 @@
|
||||
let
|
||||
# MAX_TESTS (plan §4.2/§4.3 resource safety): max CI builds the exec runner runs at once. Drone
|
||||
# queues the rest in its native pending-build queue (no custom queue). THE concurrency cap that
|
||||
# bounds how many test apps can be live at once — kept LOW (1) on this single 28GiB node since
|
||||
# recipes are heavy (immich/matrix large volumes). With capacity=1 there is never a concurrent
|
||||
# in-flight run, so the run-start janitor can safely reap *any* orphan (a SIGKILL'd build runs no
|
||||
# teardown) and the "at most MAX_TESTS apps live" bound holds exactly. Raise to 2 only if the node
|
||||
# is shown to handle two light recipes at once (then the janitor MUST stay age-based to avoid
|
||||
# reaping a concurrent run — see DECISIONS.md "Resource safety").
|
||||
maxTests = "1";
|
||||
# bounds how many test apps can be live at once.
|
||||
#
|
||||
# Raised to 2 (operator request 2026-06-09) so two recipes can be tested in parallel (e.g. immich
|
||||
# and plausible under active development at once). Verified safe on the current node (Hetzner cpx22,
|
||||
# ~7.6 GiB / 4 vCPU — NOTE: smaller than the original 28 GiB this was written for): a full immich CI
|
||||
# stack measured ~1 GiB (server+ML+pg+redis) with multiple GiB free, so two concurrent recipes fit.
|
||||
# The concurrency PRECONDITION holds: the run-start janitor is age-based (default 2h) + run-app-name
|
||||
# scoped, so it never reaps a concurrent in-flight run (harness.lifecycle.janitor). TRADE-OFF: with
|
||||
# capacity>1 a SIGKILL'd build (no teardown) leaves an orphan the run-start sweep can't reap
|
||||
# immediately (it might be a live run) — bounded instead by the 2h janitor + the /upgrade-all
|
||||
# start/end reap + sweep-orphans. Revert to "1" if OOM / disk-I/O contention is observed under load.
|
||||
maxTests = "2";
|
||||
in
|
||||
{
|
||||
# Drone ships under the Polyform Small Business license (nixpkgs marks it unfree);
|
||||
|
||||
@ -3,10 +3,49 @@
|
||||
# no secrets — just static files behind traefik + the wildcard TLS (same pattern as dashboard.nix,
|
||||
# but a plain nginx:alpine since there's nothing to render server-side). Content is updated by writing
|
||||
# files into /var/lib/cc-ci-reports; nginx serves them live (no redeploy needed).
|
||||
#
|
||||
# It ALSO serves a same-origin realtime PR-status proxy at /pr/<recipe>/<n>: the report's STATUS
|
||||
# column fetches it client-side to show each PR's live state (open vs. ✓). Same-origin means no
|
||||
# dependency on the Gitea CORS allow-list; the recipe mirrors are public so no token is needed. The
|
||||
# proxy is pinned to recipe-maintainers + a safe recipe-name charset and is read-only (GET/HEAD).
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
reportsDir = "/var/lib/cc-ci-reports";
|
||||
|
||||
# Custom nginx server: static report files + the /pr/<recipe>/<n> → Gitea-API proxy. Replaces the
|
||||
# stock /etc/nginx/conf.d/default.conf (which the image's nginx.conf includes inside http{}).
|
||||
nginxConf = pkgs.writeText "cc-ci-reports-default.conf" ''
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Realtime PR-status proxy for the Recipe Report STATUS column.
|
||||
# GET /pr/<recipe>/<n> -> the PUBLIC Gitea PR JSON ({state, merged, ...}). Same-origin from
|
||||
# the browser's view, so no CORS dependency; unauthenticated, since the recipe mirrors are
|
||||
# public. The repo owner is hard-pinned to recipe-maintainers and the recipe name to a
|
||||
# slashless charset, so the proxied path can only ever address recipe-maintainers/<name>/pulls
|
||||
# (it cannot be coerced to another org or path). Only safe read methods are allowed.
|
||||
location ~ ^/pr/([a-z0-9._-]+)/([0-9]+)$ {
|
||||
limit_except GET HEAD { deny all; }
|
||||
resolver 127.0.0.11 ipv6=off valid=30s; # docker embedded DNS (forwards external names)
|
||||
proxy_ssl_server_name on;
|
||||
proxy_set_header Host git.autonomic.zone;
|
||||
proxy_set_header Accept "application/json";
|
||||
proxy_pass https://git.autonomic.zone/api/v1/repos/recipe-maintainers/$1/pulls/$2;
|
||||
proxy_intercept_errors off;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_read_timeout 10s;
|
||||
add_header Cache-Control "no-store" always; # always fetch live state, never cache in the browser
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
stack = pkgs.writeText "cc-ci-reports-stack.yml" ''
|
||||
version: "3.8"
|
||||
services:
|
||||
@ -17,6 +56,10 @@ let
|
||||
source: ${reportsDir}
|
||||
target: /usr/share/nginx/html
|
||||
read_only: true
|
||||
- type: bind
|
||||
source: ${nginxConf}
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
networks:
|
||||
- proxy
|
||||
deploy:
|
||||
|
||||
Reference in New Issue
Block a user