rename web/ to admin/, along with the web-named build and cli identifiers

This commit is contained in:
2026-08-16 00:17:58 +02:00
parent 5b3d1cd65c
commit 1e97c80f6b
136 changed files with 196 additions and 196 deletions
+39 -39
View File
@@ -32,7 +32,7 @@ pub fn build(b: *std.Build) void {
// Milestone-17 ruling 5. The embedded golden carries no source-tree path,
// so regeneration names the destination explicitly:
// zig build test -Dintegration \
// -Dcontract-samples-out="$PWD/web/src/lib/contractSamples.gen.ts"
// -Dcontract-samples-out="$PWD/admin/src/lib/contractSamples.gen.ts"
const contract_samples_out = b.option(
[]const u8,
"contract-samples-out",
@@ -44,34 +44,34 @@ pub fn build(b: *std.Build) void {
const version_option = b.option([]const u8, "version-string", "Version reported by `nxdns version` (required by `dist`)");
const version_string = version_option orelse "0.1.0-dev";
const git_commit = b.option([]const u8, "git-commit", "Git commit reported by `nxdns version`") orelse "unknown";
const web_dist = b.option(
const admin_dist = b.option(
[]const u8,
"web-dist",
"admin-dist",
"Built web UI directory to embed (default: the placeholder page). " ++
"Only the exact value `web/dist` gets the freshness check; " ++
"Only the exact value `admin/dist` gets the freshness check; " ++
"the placeholder and any other path skip it.",
) orelse "web/dist-placeholder";
) orelse "admin/dist-placeholder";
// `b.path` panics on absolute paths, and a CI artifact directory is one.
const web_dist_path: std.Build.LazyPath = if (std.fs.path.isAbsolute(web_dist))
.{ .cwd_relative = web_dist }
const admin_dist_path: std.Build.LazyPath = if (std.fs.path.isAbsolute(admin_dist))
.{ .cwd_relative = admin_dist }
else
b.path(web_dist);
b.path(admin_dist);
// A stale `web/dist` shipped a crashing settings page once (milestone-15
// A stale `admin/dist` shipped a crashing settings page once (milestone-15
// ruling 5). The stamp is checked only for the real dist tree: the
// placeholder has no sources to be stale against, and an explicit path is a
// CI artifact that was built elsewhere.
const web_dist_check: ?*std.Build.Step = if (std.mem.eql(u8, web_dist, "web/dist")) check: {
const admin_dist_check: ?*std.Build.Step = if (std.mem.eql(u8, admin_dist, "admin/dist")) check: {
const run_check = b.addSystemCommand(&.{"node"});
// The script path goes through `b.path` so it resolves against the
// build root: `zig build` run from any other directory would not find
// a cwd-relative one.
run_check.addFileArg(b.path("web/scripts/stamp-dist.mjs"));
run_check.addFileArg(b.path("admin/scripts/stamp-dist.mjs"));
run_check.addArg("--check");
break :check &run_check.step;
} else null;
const web_assets = webAssetsIndex(b, web_dist_path, web_dist_check);
const admin_assets = adminAssetsIndex(b, admin_dist_path, admin_dist_check);
const options = b.addOptions();
options.addOption(bool, "integration", integration);
@@ -81,7 +81,7 @@ pub fn build(b: *std.Build) void {
options.addOption([]const u8, "zig_version_string", builtin.zig_version_string);
options.addOption([]const u8, "contract_samples_out", contract_samples_out);
const exe = addExecutable(b, target, optimize, options, web_assets);
const exe = addExecutable(b, target, optimize, options, admin_assets);
b.installArtifact(exe);
const run = b.addRunArtifact(exe);
@@ -125,7 +125,7 @@ pub fn build(b: *std.Build) void {
// the reference is the 0.16.0 source lines above. See AGENTS.md.
const licenses_files = licensesFilesRoot(b);
const tests = addTestSuite(b, target, optimize, options, web_assets, licenses_files);
const tests = addTestSuite(b, target, optimize, options, admin_assets, licenses_files);
const test_step = b.step("test", "Run the test suite");
test_step.dependOn(&b.addRunArtifact(tests).step);
@@ -220,7 +220,7 @@ pub fn build(b: *std.Build) void {
const aarch64_target = b.resolveTargetQuery(
std.Target.Query.parse(.{ .arch_os_abi = aarch64_triple }) catch unreachable,
);
const aarch64_tests = addTestSuite(b, aarch64_target, optimize, options, web_assets, licenses_files);
const aarch64_tests = addTestSuite(b, aarch64_target, optimize, options, admin_assets, licenses_files);
aarch64_tests.linkage = .static;
const aarch64_run = b.addRunArtifact(aarch64_tests);
aarch64_run.skip_foreign_checks = true;
@@ -269,11 +269,11 @@ pub fn build(b: *std.Build) void {
});
test_step.dependOn(&b.addRunArtifact(container_check_tests).step);
addDist(b, options, web_assets, .{
addDist(b, options, admin_assets, .{
.version = version_option,
.version_string = version_string,
.git_commit = git_commit,
.web_dist = web_dist,
.admin_dist = admin_dist,
});
}
@@ -281,10 +281,10 @@ pub fn build(b: *std.Build) void {
const max_binary_bytes = 15_728_640;
const max_asset_free_binary_bytes = 10_485_760;
/// The default of `-Dweb-dist`. A release built without the flag would ship the
/// The default of `-Dadmin-dist`. A release built without the flag would ship the
/// placeholder admin page, so `dist` refuses it (milestone-14 ruling 4). There
/// is deliberately no override.
const placeholder_web_dist = "web/dist-placeholder";
const placeholder_admin_dist = "admin/dist-placeholder";
/// Repository files that go into the tarball verbatim. `nxdns.conf` is
/// `sysusers.conf` under the name it is installed with, so nothing renames a
@@ -306,7 +306,7 @@ const DistOptions = struct {
version: ?[]const u8,
version_string: []const u8,
git_commit: []const u8,
web_dist: []const u8,
admin_dist: []const u8,
};
/// `dist` builds everything releasable; `verify-dist` asserts the result.
@@ -316,7 +316,7 @@ const DistOptions = struct {
fn addDist(
b: *std.Build,
options: *std.Build.Step.Options,
web_assets: std.Build.LazyPath,
admin_assets: std.Build.LazyPath,
dist_options: DistOptions,
) void {
const dist_step = b.step("dist", "Build the release tarballs, checksums and staged payloads");
@@ -363,7 +363,7 @@ fn addDist(
// directory (milestone-14 ruling 5). Not the placeholder: ruling 4 makes
// that unbuildable, and re-admitting it for one size check through a back
// door would defeat the point of the refusal.
const empty_web_assets = webAssetsIndex(b, b.addWriteFiles().getDirectory(), null);
const empty_admin_assets = adminAssetsIndex(b, b.addWriteFiles().getDirectory(), null);
for (cross_targets) |triple| {
const query = std.Target.Query.parse(.{ .arch_os_abi = triple }) catch |err| {
@@ -376,7 +376,7 @@ fn addDist(
// not change shape because a flag was forgotten. `.strip` is
// `std.Build.Module.strip`, which emits `-fstrip` (Module.zig:545), so
// no objcopy and no binutils-aarch64-linux-gnu on the runner.
const exe = addExecutable(b, target, .ReleaseSafe, options, web_assets);
const exe = addExecutable(b, target, .ReleaseSafe, options, admin_assets);
exe.linkage = .static;
exe.root_module.strip = true;
@@ -449,7 +449,7 @@ fn addDist(
sums_run.addArg(b.fmt("{s}.tar.gz", .{name}));
sums_run.addFileArg(tarball);
const asset_free_exe = addExecutable(b, target, .ReleaseSafe, options, empty_web_assets);
const asset_free_exe = addExecutable(b, target, .ReleaseSafe, options, empty_admin_assets);
asset_free_exe.linkage = .static;
asset_free_exe.root_module.strip = true;
@@ -477,10 +477,10 @@ fn distPreflight(b: *std.Build, dist_options: DistOptions) ?[]const u8 {
"(the release tag without its leading `v`); it has no default here.") catch @panic("OOM");
}
if (std.mem.eql(u8, b.pathFromRoot(dist_options.web_dist), b.pathFromRoot(placeholder_web_dist))) {
problems.append(b.allocator, "-Dweb-dist resolves to " ++ placeholder_web_dist ++
if (std.mem.eql(u8, b.pathFromRoot(dist_options.admin_dist), b.pathFromRoot(placeholder_admin_dist))) {
problems.append(b.allocator, "-Dadmin-dist resolves to " ++ placeholder_admin_dist ++
", which a release must never ship. Build the real admin UI " ++
"(cd web && npm ci && npm run build) and pass -Dweb-dist=web/dist.") catch @panic("OOM");
"(cd admin && npm ci && npm run build) and pass -Dadmin-dist=admin/dist.") catch @panic("OOM");
}
for ([_][]const u8{
@@ -576,7 +576,7 @@ fn addTestSuite(
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
options: *std.Build.Step.Options,
web_assets: std.Build.LazyPath,
admin_assets: std.Build.LazyPath,
licenses_files: std.Build.LazyPath,
) *std.Build.Step.Compile {
const tests = b.addTest(.{
@@ -601,9 +601,9 @@ fn addTestSuite(
// An anonymous-import root must be Zig, so the committed TypeScript golden
// is reached through a one-decl wrapper beside it.
tests.root_module.addAnonymousImport("contract_samples", .{
.root_source_file = b.path("web/src/lib/contract_samples.zig"),
.root_source_file = b.path("admin/src/lib/contract_samples.zig"),
});
tests.root_module.addAnonymousImport("web_assets", .{ .root_source_file = web_assets });
tests.root_module.addAnonymousImport("admin_assets", .{ .root_source_file = admin_assets });
tests.root_module.addAnonymousImport("licenses_files", .{ .root_source_file = licenses_files });
return tests;
}
@@ -614,7 +614,7 @@ fn addTestSuite(
///
/// A module cannot embed anything above its own root directory, so the trees
/// are merged into one WriteFiles directory: `licenses/` at the root, plus
/// copies of `build.zig.zon`, `web/package-lock.json` and the image Dockerfile
/// copies of `build.zig.zon`, `admin/package-lock.json` and the image Dockerfile
/// beside it. The module root is the copy of `licenses/licenses.zig`, which is
/// why that file's `@embedFile` paths name files that do not sit beside it in
/// the repository.
@@ -622,7 +622,7 @@ fn licensesFilesRoot(b: *std.Build) std.Build.LazyPath {
const stage = b.addWriteFiles();
_ = stage.addCopyDirectory(b.path("licenses"), ".", .{});
_ = stage.addCopyFile(b.path("build.zig.zon"), "build.zig.zon");
_ = stage.addCopyFile(b.path("web/package-lock.json"), "package-lock.json");
_ = stage.addCopyFile(b.path("admin/package-lock.json"), "package-lock.json");
_ = stage.addCopyFile(b.path(dockerfile_path), "Dockerfile");
return stage.getDirectory().path(b, "licenses.zig");
}
@@ -679,7 +679,7 @@ fn addExecutable(
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
options: *std.Build.Step.Options,
web_assets: std.Build.LazyPath,
admin_assets: std.Build.LazyPath,
) *std.Build.Step.Compile {
const exe = b.addExecutable(.{
.name = "nxdns",
@@ -691,7 +691,7 @@ fn addExecutable(
}),
});
exe.root_module.addOptions("build_options", options);
exe.root_module.addAnonymousImport("web_assets", .{ .root_source_file = web_assets });
exe.root_module.addAnonymousImport("admin_assets", .{ .root_source_file = admin_assets });
exe.root_module.linkLibrary(sqliteLibrary(b, target, optimize));
exe.root_module.linkLibrary(mbedtlsLibrary(b, target, optimize));
exe.root_module.addCSourceFile(.{ .file = b.path("src/platform/mbedtls_shim.c") });
@@ -702,13 +702,13 @@ fn addExecutable(
/// The embedded web UI (milestone-8 ruling 24): the dist directory plus the
/// generated `assets.zig` index and build-time gzip siblings, merged into one
/// WriteFiles directory so every `@embedFile` path resolves inside the module
/// root. Returns the index file, the root of the `web_assets` module.
/// root. Returns the index file, the root of the `admin_assets` module.
///
/// The dist is staged through its own WriteFiles step before it reaches the
/// tool because a Run step hashes only the resolved path string of a directory
/// argument, not its contents; the staged copy lives at a content-hashed path,
/// so editing an asset re-runs the tool instead of replaying a stale cache.
fn webAssetsIndex(
fn adminAssetsIndex(
b: *std.Build,
dist: std.Build.LazyPath,
freshness_check: ?*std.Build.Step,
@@ -718,9 +718,9 @@ fn webAssetsIndex(
const staged = stage.addCopyDirectory(dist, ".", .{});
const tool = b.addExecutable(.{
.name = "gen_web_assets",
.name = "gen_admin_assets",
.root_module = b.createModule(.{
.root_source_file = b.path("tools/gen_web_assets.zig"),
.root_source_file = b.path("tools/gen_admin_assets.zig"),
.target = b.graph.host,
.optimize = .ReleaseSafe,
}),
@@ -728,7 +728,7 @@ fn webAssetsIndex(
const run = b.addRunArtifact(tool);
run.addDirectoryArg(staged);
const generated = run.addOutputDirectoryArg("web_assets");
const generated = run.addOutputDirectoryArg("admin_assets");
const merged = b.addWriteFiles();
_ = merged.addCopyDirectory(staged, ".", .{});