v0.27.1
This commit is contained in:
1 parent
3a2eb4fe79
commit
e0194fbaff
63 files changed
+1553
-379
No files matched your search
+66
-17
@@ -24,7 +24,7 @@ def read_docker_agent_source() -> str:
|
||||
|
||||
preflight(root)
|
||||
manifest = tomllib.loads((root / "Cargo.toml").read_text())
|
||||
assert manifest["package"]["version"] == "0.27.0"
|
||||
assert manifest["package"]["version"] == "0.27.1"
|
||||
assert manifest["dependencies"]["quinn"]["version"] == "0.11.12"
|
||||
h3dep = manifest["dependencies"]["h3"]
|
||||
assert h3dep["package"] == "hpx-h3" and h3dep["version"] == "=2.5.19" and "quinn" in h3dep["features"]
|
||||
@@ -32,14 +32,14 @@ assert "h3-quinn" not in manifest["dependencies"]
|
||||
lock_path = root / "Cargo.lock"
|
||||
if lock_path.exists():
|
||||
lock = lock_path.read_text()
|
||||
assert 'name = "rust-proxy"\nversion = "0.27.0"' in lock
|
||||
assert 'name = "rust-proxy"\nversion = "0.27.1"' in lock
|
||||
assert 'name = "systemstat"' in lock and 'name = "metrics-process"' in lock and 'name = "sysinfo"' in lock, "Cargo.lock must be resolver-generated after adding cross-platform statistics libraries"
|
||||
for release_doc, marker in {
|
||||
"README.md": "# RustProxy 0.27.0",
|
||||
"CHANGELOG.md": "## 0.27.0",
|
||||
"ROADMAP.md": "## 0.27.0",
|
||||
"AGENTS.md": "Current source version: 0.27.0.",
|
||||
"docs/TEST_REPORT.md": "# Verification report - RustProxy 0.27.0",
|
||||
"README.md": "# RustProxy 0.27.1",
|
||||
"CHANGELOG.md": "## 0.27.1",
|
||||
"ROADMAP.md": "## 0.27.1",
|
||||
"AGENTS.md": "Current source version: 0.27.1.",
|
||||
"docs/TEST_REPORT.md": "# Verification report - RustProxy 0.27.1",
|
||||
}.items():
|
||||
assert marker in (root / release_doc).read_text(), f"stale release identity in {release_doc}"
|
||||
assert tomllib.loads((root / "rust-toolchain.toml").read_text())["toolchain"]["channel"] == "stable"
|
||||
@@ -113,8 +113,12 @@ for marker in [
|
||||
'MODE=update',
|
||||
'bash update.sh',
|
||||
'--prefix "$PREFIX"',
|
||||
'python3-venv',
|
||||
'python3-pip',
|
||||
'certbot',
|
||||
'python3-certbot-dns-rfc2136',
|
||||
'python3-certbot-dns-cloudflare',
|
||||
'python3-certbot-dns-ovh',
|
||||
]:
|
||||
assert marker in bootstrap, marker
|
||||
assert 'curl ' not in bootstrap, 'Debian bootstrap must use wget instead of curl'
|
||||
@@ -136,12 +140,13 @@ assert "USER rustproxy:rustproxy" in dockerfile
|
||||
assert 'VOLUME ["/var/lib/rustproxy"]' in dockerfile
|
||||
assert "COPY . ." in dockerfile
|
||||
for marker in [
|
||||
"python3 -m venv /opt/rustproxy-certbot",
|
||||
"certbot==5.8.0",
|
||||
"certbot-dns-cloudflare==5.8.0",
|
||||
"certbot-dns-ovh==5.8.0",
|
||||
"certbot-dns-rfc2136==5.8.0",
|
||||
"PATH=/opt/rustproxy-certbot/bin:",
|
||||
"python3-venv",
|
||||
"python3-pip",
|
||||
"certbot",
|
||||
"python3-certbot-dns-cloudflare",
|
||||
"python3-certbot-dns-ovh",
|
||||
"python3-certbot-dns-rfc2136",
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
]:
|
||||
assert marker in dockerfile, marker
|
||||
assert "data" in (root / ".dockerignore").read_text().splitlines()
|
||||
@@ -157,6 +162,21 @@ for selector in ["config-history-month", "config-history-day", "config-history-c
|
||||
assert ".vhost-chart-line" in css and ".host-chip-editor" in css
|
||||
assert 'class="vhost-dialog logging-format-dialog"' in html
|
||||
assert 'data-panel="streams"' in html and 'id="panel-streams"' in html
|
||||
for marker in ['id="vhost-sort"', 'id="vhost-sort-direction"', 'id="docker-vhost-sort"', 'id="docker-vhost-sort-direction"', 'id="redirect-sort"', 'id="redirect-sort-direction"', 'id="notfound-sort"', 'id="notfound-sort-direction"', 'id="stream-sort"', 'id="stream-sort-direction"']:
|
||||
assert marker in html, marker
|
||||
preferences_source = (root / "src/admin/preferences.rs").read_text(encoding="utf-8")
|
||||
for marker in ['vhost_list_sort', 'docker_vhost_sort', 'redirect_list_sort', 'notfound_list_sort', 'stream_list_sort', 'VHOST_LIST_SORT_COLUMNS', 'DOCKER_VHOST_SORT_COLUMNS', 'REDIRECT_LIST_SORT_COLUMNS', 'NOTFOUND_LIST_SORT_COLUMNS', 'STREAM_LIST_SORT_COLUMNS']:
|
||||
assert marker in preferences_source, marker
|
||||
for source_name, markers in {
|
||||
"src/admin/web/vhosts/render.js": ["vhost_list_sort", "vhost_list_descending"],
|
||||
"src/admin/web/docker.js": ["docker_vhost_sort", "docker_vhost_descending", "sortServiceRows"],
|
||||
"src/admin/web/redirects.js": ["redirect_list_sort", "redirect_list_descending"],
|
||||
"src/admin/web/host404.js": ["notfound_list_sort", "notfound_list_descending"],
|
||||
"src/admin/web/streams.js": ["stream_list_sort", "stream_list_descending"],
|
||||
}.items():
|
||||
source_text = (root / source_name).read_text(encoding="utf-8")
|
||||
for marker in markers:
|
||||
assert marker in source_text, (source_name, marker)
|
||||
assert 'data-panel="docker-vhosts"' in html and 'id="panel-docker-vhosts"' in html
|
||||
assert 'id="settings-tab-docker-agents"' in html and 'id="settings-page-docker-agents"' in html
|
||||
assert '/assets/docker.js' in html and 'cache-live-toggle' in html
|
||||
@@ -267,7 +287,7 @@ assert 'Opt-in health decisions based on ordinary user traffic. Defaults to disa
|
||||
assert '"force_ssl"' in openapi and '"forward_client_ip"' in openapi
|
||||
assert '"backend_header"' in openapi and '"backend_timing_header"' in openapi
|
||||
assert '"StreamMetrics"' in openapi and '"streams"' in openapi
|
||||
for marker in ['"version": "0.27.0"', '"/api/traffic"', '"capture_user_agent"', '"capture_country"', '"hot_auto_trim_enabled"', '"hot_auto_trim_after_seconds"', '"hot_auto_trim_target_percent"', '"/api/config/{section}"', '"ConfigSectionUpdate"', '"cold_on_idle"', '"cold_on_age"', '"cold_max_hot_seconds"', '"cold_on_lru"', '"cold_on_shutdown"', '"cold_gc_interval_seconds"', '"cold_gc_max_delete"', '"collapse_enabled"', '"collapse_wait_timeout_ms"', '"collapse_timeout_fallback"', '"stale_if_error_timeout"', '"stale_if_error_connection"', '"stale_if_error_dns"', '"stale_if_error_tls"', '"stale_if_error_statuses"', '"proactive_refresh_enabled"', '"proactive_refresh_before_expiry_seconds"', '"proactive_refresh_percent"', '"proactive_refresh_max_inflight"', '"TransformSettings"', '"TransformOverrides"', '"/api/cache/cold/cleanup"', '"/api/cache/invalidate"', '"/api/cache/bans"', '"/api/cache/bans/{id}"', '"CacheInvalidationRequest"', '"CacheInvalidationResponse"', '"ColdCleanupJob"', '"match_type"', '"regex_insensitive"', '"rewrite"', '"response"', '"covered_hosts"', '"default": true']:
|
||||
for marker in ['"version": "0.27.1"', '"/api/traffic"', '"capture_user_agent"', '"capture_country"', '"hot_auto_trim_enabled"', '"hot_auto_trim_after_seconds"', '"hot_auto_trim_target_percent"', '"/api/config/{section}"', '"ConfigSectionUpdate"', '"cold_on_idle"', '"cold_on_age"', '"cold_max_hot_seconds"', '"cold_on_lru"', '"cold_on_shutdown"', '"cold_gc_interval_seconds"', '"cold_gc_max_delete"', '"collapse_enabled"', '"collapse_wait_timeout_ms"', '"collapse_timeout_fallback"', '"stale_if_error_timeout"', '"stale_if_error_connection"', '"stale_if_error_dns"', '"stale_if_error_tls"', '"stale_if_error_statuses"', '"proactive_refresh_enabled"', '"proactive_refresh_before_expiry_seconds"', '"proactive_refresh_percent"', '"proactive_refresh_max_inflight"', '"TransformSettings"', '"TransformOverrides"', '"/api/cache/cold/cleanup"', '"/api/cache/invalidate"', '"/api/cache/bans"', '"/api/cache/bans/{id}"', '"CacheInvalidationRequest"', '"CacheInvalidationResponse"', '"ColdCleanupJob"', '"match_type"', '"regex_insensitive"', '"rewrite"', '"response"', '"covered_hosts"', '"default": true']:
|
||||
assert marker in openapi, marker
|
||||
for marker in ['"NotFoundHost"', '"not_found_hosts"', '"PrometheusSettings"', '"allow_trusted_network_without_token"', '"include_docker_vhosts"', '"include_streams"', '"include_logging"']:
|
||||
assert marker in openapi, marker
|
||||
@@ -537,6 +557,15 @@ for marker in ['function selectTab(name, focus = false, persist = true)', 'log_d
|
||||
for marker in ['resetIssueFormJob = value.job?.id || null', 'value.status === "ready"', 'resetIssueForm(); resetIssueFormJob = null', 'value.status === "failed"']:
|
||||
assert marker in acme_js, marker
|
||||
assert 'render(value.job); resetIssueForm();' not in acme_js, "ACME form must not reset before issuance actually succeeds"
|
||||
for marker in ['id="acme-runtime-card"', 'id="acme-runtime-message"', 'id="acme-runtime-state"', 'id="acme-runtime-path"']:
|
||||
assert marker in html, marker
|
||||
for marker in ['function renderRuntime(value)', 'runtimeAvailable', 'certificateRuntimeUnavailable', 'acme.runtime_checking']:
|
||||
assert marker in acme_js, marker
|
||||
assert 'rust-proxy --data-dir ./data admin setup-token' in html
|
||||
assert 'rust-proxy --data-dir /var/lib/rustproxy admin setup-token' in html
|
||||
login_html_source = (root / "src/admin/web/login.html").read_text(encoding="utf-8")
|
||||
assert 'rust-proxy --data-dir ./data admin setup-token' in login_html_source
|
||||
assert 'rust-proxy --data-dir /var/lib/rustproxy admin setup-token' in login_html_source
|
||||
login_js = (root / "src/admin/web/login.js").read_text()
|
||||
assert 'const panelPaths = new Set' in login_js and 'panelPaths.has(location.pathname)' in login_js
|
||||
assert '"/404-hosts"' in login_js
|
||||
@@ -558,6 +587,20 @@ h2_settings_controls = integrations_js.split('function http2SettingsControls', 1
|
||||
assert 'listener-h2' not in h2_settings_controls, 'HTTP/2 enablement belongs to the listener editor, not the tuning page'
|
||||
h3_settings_controls = integrations_js.split('function http3SettingsControls', 1)[1].split('function addRow', 1)[0]
|
||||
assert 'h3Enable' not in h3_settings_controls, 'HTTP/3 enablement belongs to the listener editor, not the tuning page'
|
||||
for marker in ['https://git.linuxiarz.pl/gru/RustProxy', 'https://rustproxy.linuxiarz.pl/', 'id="about-python-runtime"', 'id="runtime-python"', 'id="acme-runtime-components"']:
|
||||
assert marker in html, marker
|
||||
for language in ['langs/en_US.json', 'langs/pl_pl.json']:
|
||||
language_text = (root / language).read_text(encoding='utf-8')
|
||||
assert './dev.sh tls deploy' not in language_text
|
||||
assert '/opt/rustproxy/current/rust-proxy --data-dir /var/lib/rustproxy tls deploy' in language_text
|
||||
startup_source = rust_source(root, 'src/main/admin_runtime.rs')
|
||||
for marker in ['https://git.linuxiarz.pl/gru/RustProxy', 'https://rustproxy.linuxiarz.pl/', 'join("acme-python")', 'certificate_runtime']:
|
||||
assert marker in startup_source, marker
|
||||
for document in ['docs/RENEWAL.md', 'docs/INSTALL.md', 'docs/API.md']:
|
||||
document_text = (root / document).read_text(encoding='utf-8')
|
||||
assert './dev.sh tls deploy' not in document_text
|
||||
assert '/opt/rustproxy/current/rust-proxy --data-dir /var/lib/rustproxy tls deploy' in document_text
|
||||
assert '"certificate_runtime": state.acme.runtime_view()' in rust_source(root, 'src/admin/status.rs')
|
||||
assert 'data-i18n="processDiagnostics">Process<' in html
|
||||
for marker in ['function setOptionalMetric', 'setOptionalMetric("process-rss-anon"', 'setOptionalMetric("system-swap"', 'closest(".mini-live-chart").hidden']:
|
||||
assert marker in app_js, marker
|
||||
@@ -565,6 +608,11 @@ for marker in ['/api/certificate-api', 'certificate-api-form', 'certificate-api-
|
||||
assert marker in settings_js or marker in html, marker
|
||||
db_source = rust_source(root, "src/db.rs")
|
||||
acme_source = rust_source(root, "src/acme.rs")
|
||||
acme_runtime_source = (root / "src/acme/runtime_env.rs").read_text(encoding="utf-8")
|
||||
assert 'runtime_setup_once' in acme_source
|
||||
assert 'include!("acme/runtime_env.rs")' in (root / "src/acme.rs").read_text(encoding="utf-8")
|
||||
for marker in ['CERTBOT_PACKAGES', 'certbot==5.8.0', 'certbot-dns-cloudflare==5.8.0', 'certbot-dns-ovh==5.8.0', 'certbot-dns-rfc2136==5.8.0', 'join("acme-python")', 'virtualenv>=20,<21', 'system_has_pip', 'distro_certbot_available', 'acme.runtime_python_missing', 'acme.runtime_pip_missing']:
|
||||
assert marker in acme_runtime_source, marker
|
||||
main_source = rust_source(root, "src/main.rs")
|
||||
logging_source = rust_source(root, "src/logging.rs")
|
||||
secret_store_source = rust_source(root, "src/secret_store.rs")
|
||||
@@ -636,6 +684,7 @@ assert 'load_renewal_observations' not in acme_source and 'renewals.json' not in
|
||||
for marker in ['pub kind: &\'static str', 'pub log_directory: String', 'pub(crate) fn certbot_log_directory', 'kind: "issue"', '"renewal-dry-run"']:
|
||||
assert marker in acme_source, marker
|
||||
assert '"log_directories":log_directories' in admin and 'crate::acme::certbot_log_directory' in admin
|
||||
assert '"runtime":state.acme.runtime_view()' in admin
|
||||
assert 'let cert_dir = Some(directory.clone());' in main_source, 'certificate directory must remain available after ValidationPolicy construction'
|
||||
assert 'accept-remote-admin-risk' in main_source and 'hide = true' in main_source
|
||||
for marker in [
|
||||
@@ -767,7 +816,7 @@ assert any(variable.get('name') == 'traffic_vhost' for variable in grafana['temp
|
||||
assert any(panel.get('title') == 'Traffic analytics and Web Server' for panel in grafana['panels'])
|
||||
assert any(panel.get('title') == 'Traffic capture state' for panel in grafana['panels'])
|
||||
assert any(panel.get('title') == 'Top configured routes' for panel in grafana['panels'])
|
||||
# 0.27.0 compression/protocol/dashboard UX regressions.
|
||||
# 0.27.1 compression/protocol/dashboard UX regressions.
|
||||
compression_source = rust_source(root, "src/compression.rs")
|
||||
metrics_source = rust_source(root, "src/metrics.rs")
|
||||
admin_source = rust_source(root, "src/admin/mod.rs")
|
||||
@@ -1324,7 +1373,7 @@ assert '"error_log" => {' not in admin_0241 and 'request("/api/config/error_log"
|
||||
assert '"error_log"' in openapi and 'logging, error_log, forwarding' not in openapi
|
||||
assert 'logging_section_persists_error_log_settings_atomically' in admin_0241 and 'error_log_is_not_a_standalone_configuration_section' in admin_0241
|
||||
assert 'location.pathname === "/logging"' in settings_js_0241
|
||||
assert '"RuntimeInformation"' in openapi and '"version": "0.27.0"' in openapi
|
||||
assert '"RuntimeInformation"' in openapi and '"version": "0.27.1"' in openapi
|
||||
|
||||
# 0.24.1 compiler and hostname-cardinality regressions.
|
||||
tls_0241 = rust_source(root, "src/tls.rs")
|
||||
@@ -1369,5 +1418,5 @@ for schema_name in ["RedirectHost", "NotFoundHost"]:
|
||||
node = openapi_0241["components"]["schemas"][schema_name]["properties"]["frontend"]["properties"]["hosts"]
|
||||
assert "maxItems" not in node, schema_name
|
||||
|
||||
print("PASS: 0.27.0 manifest/package, shared system-statistics/runtime metadata, Settings logging, retained H2, external-packaging/Grafana/Prometheus/404-host/custom-location/path/cache/dashboard/Nagios UI/source contracts, stopped legacy-renewal removal, session/admin/transport contracts, deterministic package source and embedded SQLite schema-v8 migrations.")
|
||||
print("PASS: 0.27.1 manifest/package, shared system-statistics/runtime metadata, Settings logging, retained H2, external-packaging/Grafana/Prometheus/404-host/custom-location/path/cache/dashboard/Nagios UI/source contracts, stopped legacy-renewal removal, session/admin/transport contracts, deterministic package source and embedded SQLite schema-v8 migrations.")
|
||||
print("NOT VERIFIED: Rust parsing, types, compilation, linking or runtime behavior. Run ./dev.sh test.")
|
||||
Reference in new issue
Block a user