Răsfoiți Sursa

feat: deploy --system/--spm passthrough with per-system base images

spry deploy gains --system fedora|debian|ubuntu|alpine|gentoo, a
shorthand expanding to the matching :latest base image plus --spm
(dnf/apt/apt/apk/emerge), mutually exclusive with --spm and --base; with
none of the three the fedora-equivalent default applies (only --spm dnf
is passed, so usm's own base constant keeps deciding the image).
MANIFEST declares the gcc and g-ir-compiler toolchain build deps the
in-container build needs on distros that do not pull them transitively.
clanker 1 săptămână în urmă
părinte
comite
27a31cbcf5
4 a modificat fișierele cu 126 adăugiri și 8 ștergeri
  1. 2 0
      MANIFEST.usm
  2. 15 3
      README.md
  3. 94 1
      tools/spry/Deploy.vala
  4. 15 4
      tools/spry/spry.vala

+ 2 - 0
MANIFEST.usm

@@ -31,6 +31,8 @@
       "bin:valac",
       "bin:meson",
       "bin:ninja",
+      "bin:gcc",
+      "bin:g-ir-compiler",
       "bin:python3",
       "pc:glib-2.0.pc",
       "pc:gobject-2.0.pc",

+ 15 - 3
README.md

@@ -200,12 +200,24 @@ Web-Stack, then the image is saved as `<app>-<version>.image.tar.xz`
 (`podman load -i` to import).
 
 ```
-spry deploy [--exec CMD] [--base IMAGE] [--repository FILE]...
-            [--installer-url URL] [--no-build] [--usm FILE]
+spry deploy [--exec CMD] ([--system SYSTEM] | [--spm SPM] [--base IMAGE])
+            [--repository FILE]... [--installer-url URL] [--no-build]
+            [--usm FILE]
 ```
 
 - `--exec CMD` (default `<app> 8080`) — the container entrypoint.
-- `--base IMAGE` (default usm's `fedora:43`) — the base image.
+- `--system SYSTEM` — target system: `fedora`, `debian`, `ubuntu`,
+  `alpine` or `gentoo`. Expands to the system's `:latest` base image plus
+  its SPM (`dnf`, `apt`, `apt`, `apk`, `emerge` respectively) and is
+  therefore **mutually exclusive with `--spm` and an explicit `--base`** —
+  combined invocations fail with an error naming the conflict.
+- `--spm SPM` — the system package manager wired into the image
+  (`dnf|apt|apk|emerge|none`), passed through to `usm manifest deploy`.
+- `--base IMAGE` — the base image (default usm's `fedora:43`).
+- When none of `--system`/`--spm`/`--base` is given, spry deploys the
+  fedora equivalent — `--spm dnf` with **no** `--base`, so usm's own
+  fedora base constant keeps deciding the image and default deploys are
+  unchanged from before the flags existed.
 - `--repository FILE` (repeatable) — resolve from exactly these `.usmr`
   repositories instead of the machine's configured set; a local Web-Stack
   repository is the usual choice while the canonical one is unavailable.

+ 94 - 1
tools/spry/Deploy.vala

@@ -14,17 +14,106 @@ namespace Spry.Cli {
      * (scaffolded by `spry new`) drive its build and install. Flags pass
      * through to `usm manifest deploy` verbatim; `--exec` defaults to
      * `<app> 8080` so the container serves on the documented port.
+     * `--system`/`--spm` map to usm's `--base`/`--spm` (see
+     * {@link Deploy.resolve_system}).
      */
     public class Deploy : GLib.Object {
 
+        /** `--system fedora` base image ({@link Deploy.resolve_system}). */
+        public const string SYSTEM_FEDORA_BASE = "registry.fedoraproject.org/fedora:latest";
+
+        /** `--system debian` base image ({@link Deploy.resolve_system}). */
+        public const string SYSTEM_DEBIAN_BASE = "docker.io/library/debian:latest";
+
+        /** `--system ubuntu` base image ({@link Deploy.resolve_system}). */
+        public const string SYSTEM_UBUNTU_BASE = "docker.io/library/ubuntu:latest";
+
+        /** `--system alpine` base image ({@link Deploy.resolve_system}). */
+        public const string SYSTEM_ALPINE_BASE = "docker.io/library/alpine:latest";
+
+        /** `--system gentoo` base image ({@link Deploy.resolve_system}). */
+        public const string SYSTEM_GENTOO_BASE = "docker.io/gentoo/stage3:latest";
+
+        /**
+         * Resolves `--system`/`--spm`/`--base` into the base image and SPM
+         * handed to `usm manifest deploy`.
+         *
+         * `--system` is mutually exclusive with `--spm` and an explicit
+         * `--base` (it expands to both); a combined invocation is reported
+         * as an error listing the conflicting flags. When none of the three
+         * is given, spry keeps today's behaviour via the fedora-equivalent
+         * default: only `--spm dnf` is set and NO base image, so usm's own
+         * fedora base constant keeps deciding the image and its identity
+         * is unchanged.
+         *
+         * @param system the `--system` value or null
+         * @param base_image null, or the explicitly passed `--base` value;
+         *   set to the expanded base image on success
+         * @param spm null, or the explicitly passed `--spm` value; set to
+         *   the expanded SPM name on success
+         * @return false (after printing the problem) on conflicting or
+         *   unknown flags, true otherwise
+         */
+        public static bool resolve_system(string? system, ref string? base_image, ref string? spm) {
+            if (system != null) {
+                var conflicts = new string[0];
+                if (spm != null) {
+                    conflicts += "--spm";
+                }
+                if (base_image != null) {
+                    conflicts += "--base";
+                }
+                if (conflicts.length > 0) {
+                    stderr.printf("Error: --system %s cannot be combined with %s — --system already expands to a base image and an SPM. Pass either --system, or --spm/--base directly.\n",
+                        system, string.joinv("/", conflicts));
+                    return false;
+                }
+                switch (system) {
+                    case "fedora":
+                        base_image = SYSTEM_FEDORA_BASE;
+                        spm = "dnf";
+                        return true;
+                    case "debian":
+                        base_image = SYSTEM_DEBIAN_BASE;
+                        spm = "apt";
+                        return true;
+                    case "ubuntu":
+                        base_image = SYSTEM_UBUNTU_BASE;
+                        spm = "apt";
+                        return true;
+                    case "alpine":
+                        base_image = SYSTEM_ALPINE_BASE;
+                        spm = "apk";
+                        return true;
+                    case "gentoo":
+                        base_image = SYSTEM_GENTOO_BASE;
+                        spm = "emerge";
+                        return true;
+                    default:
+                        stderr.printf("Error: '%s' is not a valid --system value (expected fedora, debian, ubuntu, alpine or gentoo).\n", system);
+                        return false;
+                }
+            }
+            if (base_image == null && spm == null) {
+                // The fedora-equivalent default deliberately passes no
+                // --base: usm's own fedora base constant keeps deciding
+                // the image, so default deploys stay byte-identical
+                spm = "dnf";
+            }
+            return true;
+        }
+
         /**
          * Runs `usm manifest deploy` in {@link app_dir} with the collected
          * flags. The USM binary is resolved from `--usm` or PATH; a missing
          * binary is reported with install guidance rather than a raw spawn
          * error. Returns the delegate process's exit status.
+         *
+         * @param spm the `--spm` value resolved by {@link resolve_system},
+         *   or null to let usm default (repo-only resolution)
          */
         public static int run(string app_dir, string app_name, string? usm_path,
-                string? exec_command, string? base_image, string[] repositories,
+                string? exec_command, string? base_image, string? spm, string[] repositories,
                 string? installer_url, bool no_build, bool verbose = false) throws Error {
             var usm = usm_path != null ? (!)usm_path : Environment.find_program_in_path("usm");
             if (usm == null) {
@@ -38,6 +127,10 @@ namespace Spry.Cli {
                 argv += "--base";
                 argv += base_image;
             }
+            if (spm != null) {
+                argv += "--spm";
+                argv += spm;
+            }
             foreach (var repository in repositories) {
                 argv += "--repository";
                 argv += repository;

+ 15 - 4
tools/spry/spry.vala

@@ -24,6 +24,8 @@ namespace Spry.Cli {
         private static string? usm = null;
         private static string? deploy_exec = null;
         private static string? deploy_base = null;
+        private static string? deploy_spm = null;
+        private static string? deploy_system = null;
         [CCode (array_length = false, null_terminated = true)]
         private static string[] deploy_repositories = null;
         private static string? deploy_installer_url = null;
@@ -57,6 +59,8 @@ namespace Spry.Cli {
         private const OptionEntry[] deploy_options = {
             { "usm", '\0', 0, OptionArg.FILENAME, ref usm, "usm binary to delegate to (default: search PATH)", "FILE" },
             { "exec", '\0', 0, OptionArg.STRING, ref deploy_exec, "Container command (default: \"<app> 8080\")", "CMD" },
+            { "system", '\0', 0, OptionArg.STRING, ref deploy_system, "Target system: fedora, debian, ubuntu, alpine or gentoo — expands to --base + --spm, so it cannot be combined with either (default: the fedora equivalent, i.e. --spm dnf on usm's fedora base)", "SYSTEM" },
+            { "spm", '\0', 0, OptionArg.STRING, ref deploy_spm, "System package manager wired into the image: dnf, apt, apk, emerge or none (default: dnf via the fedora-equivalent default)", "SPM" },
             { "base", '\0', 0, OptionArg.STRING, ref deploy_base, "Base image (default: usm's fedora:43)", "IMAGE" },
             { "repository", '\0', 0, OptionArg.STRING_ARRAY, ref deploy_repositories, "USM repository (.usmr) to resolve from; repeatable (default: the machine's configured repositories)", "FILE" },
             { "installer-url", '\0', 0, OptionArg.STRING, ref deploy_installer_url, "USM installer source override (file://… for local testing)", "URL" },
@@ -144,9 +148,11 @@ namespace Spry.Cli {
                 "  add register                     Add the registration page\n" +
                 "  add user-management              Add the admin user-management page\n" +
                 "  keys [--out FILE]                Generate/merge static keys into web-config.json\n" +
-                "  deploy [--exec CMD] [--base I]   Build the USM container image (usm manifest\n" +
-                "                                   deploy; --repository/--installer-url/\n" +
-                "                                   --no-build pass through)\n" +
+                "  deploy [--exec CMD]              Build the USM container image (usm manifest\n" +
+                "          [--system SYSTEM]|       deploy; --repository/--installer-url/\n" +
+                "          [--spm SPM] [--base I]    --no-build pass through; default --spm dnf\n" +
+                "          [--repository FILE]...    on usm's fedora base; --system expands to\n" +
+                "                                   --base + --spm and excludes both)\n" +
                 "  dev [--port N] [--fresh]         Build, run and watch: rebuild + restart on save\n" +
                 "\n" +
                 "Options:\n" +
@@ -412,7 +418,12 @@ namespace Spry.Cli {
             extract_repositories(args, out repositories, out remaining);
             parse(remaining, "- build the USM container image via usm manifest deploy", deploy_options);
             var app = require_app();
-            return Deploy.run(app.dir, app.name, usm, deploy_exec, deploy_base,
+            string? base_image = deploy_base;
+            string? spm = deploy_spm;
+            if (!Deploy.resolve_system(deploy_system, ref base_image, ref spm)) {
+                return 1;
+            }
+            return Deploy.run(app.dir, app.name, usm, deploy_exec, base_image, spm,
                 repositories, deploy_installer_url, deploy_no_build, deploy_verbose);
         }