]> git.ipfire.org Git - pakfire.git/commitdiff
buildservice: Implement uploading builds
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 20 Oct 2023 10:46:12 +0000 (10:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 20 Oct 2023 10:46:12 +0000 (10:46 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/cli/lib/client-build.c [new file with mode: 0644]
src/cli/lib/client-build.h [new file with mode: 0644]
src/cli/pakfire-client.c
src/libpakfire/buildservice.c
src/libpakfire/include/pakfire/buildservice.h

index 85e9e5fc968b903ac926d586f3ba2360ddd62645..ea33933e01121140848ac9f8313fec18ea655308 100644 (file)
@@ -465,6 +465,8 @@ libcli_la_SOURCES = \
        src/cli/lib/check.h \
        src/cli/lib/clean.c \
        src/cli/lib/clean.h \
+       src/cli/lib/client-build.c \
+       src/cli/lib/client-build.h \
        src/cli/lib/color.c \
        src/cli/lib/color.h \
        src/cli/lib/command.c \
diff --git a/src/cli/lib/client-build.c b/src/cli/lib/client-build.c
new file mode 100644 (file)
index 0000000..914d747
--- /dev/null
@@ -0,0 +1,156 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2023 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <argp.h>
+
+#include "client-build.h"
+#include "command.h"
+
+#include <pakfire/ctx.h>
+#include <pakfire/buildservice.h>
+
+static const char* args_doc = "[OPTIONS...] MAKEFILES...";
+
+static const char* doc = "Build packages remotely";
+
+#define MAX_ARCHES     8
+#define MAX_UPLOADS   32
+#define MAX_PACKAGES  32
+#define MAX_MAKEFILES 32
+
+struct config {
+       const char* repo;
+       int flags;
+
+       const char* arches[MAX_ARCHES];
+       unsigned int num_arches;
+
+       // Packages
+       char* packages[MAX_PACKAGES];
+       unsigned int num_packages;
+
+       // Uploads
+       char* uploads[MAX_UPLOADS];
+       unsigned int num_uploads;
+};
+
+enum {
+       OPT_ARCH          = 1,
+       OPT_DISABLE_TESTS = 2,
+       OPT_REPO          = 3,
+};
+
+static struct argp_option options[] = {
+       { "arch",          OPT_ARCH,          "ARCH", 0, "Build for this architecture",   0 },
+       { "disable-tests", OPT_DISABLE_TESTS,   NULL, 0, "Do not run tests",              0 },
+       { "repo",          OPT_REPO,          "REPO", 0, "Build against this repository", 0 },
+       { NULL },
+};
+
+static error_t parse(int key, char* arg, struct argp_state* state, void* data) {
+       struct config* config = data;
+
+       switch (key) {
+               case OPT_ARCH:
+                       if (config->num_arches >= MAX_ARCHES)
+                               return -ENOBUFS;
+
+                       config->arches[config->num_arches++] = arg;
+                       break;
+
+               case OPT_DISABLE_TESTS:
+                       config->flags |= PAKFIRE_BUILD_DISABLE_TESTS;
+                       break;
+
+               case OPT_REPO:
+                       config->repo = arg;
+                       break;
+
+               case ARGP_KEY_ARG:
+                       if (config->num_packages >= MAX_PACKAGES)
+                               return -ENOBUFS;
+
+                       config->packages[config->num_packages++] = arg;
+                       break;
+
+               default:
+                       return ARGP_ERR_UNKNOWN;
+       }
+
+       return 0;
+}
+
+int cli_client_build(void* data, int argc, char* argv[]) {
+       struct pakfire_buildservice* service = NULL;
+       struct config config = {};
+       char* upload = NULL;
+       int r;
+
+       struct pakfire_ctx* ctx = data;
+
+       // Parse the command line
+       r = cli_parse(options, NULL, args_doc, doc, parse, argc, argv, &config);
+       if (r)
+               goto ERROR;
+
+       // Connect to the build service
+       r = pakfire_buildservice_create(&service, ctx);
+       if (r)
+               goto ERROR;
+
+       // Upload all packages
+       for (unsigned int i = 0; i < config.num_packages; i++) {
+               r = pakfire_buildservice_upload(service, config.packages[i], NULL, &upload);
+               if (r)
+                       goto ERROR;
+
+               // Store the upload ID
+               config.uploads[config.num_uploads++] = upload;
+       }
+
+       // No uploads
+       if (!config.num_uploads)
+               goto ERROR;
+
+       // Build all the things
+       for (unsigned int i = 0; i < config.num_uploads; i++) {
+               r = pakfire_buildservice_build(service, config.uploads[i], config.repo,
+                       config.arches, config.flags);
+               if (r)
+                       goto ERROR;
+
+               // Free the upload
+               free(config.uploads[i]);
+               config.uploads[i] = NULL;
+       }
+
+ERROR:
+       // Delete & free all uploads that could not be processed
+       for (unsigned int i = 0; i < config.num_uploads; i++) {
+               if (config.uploads[i]) {
+                       pakfire_buildservice_delete_upload(service, config.uploads[i]);
+                       free(config.uploads[i]);
+               }
+       }
+       if (service)
+               pakfire_buildservice_unref(service);
+
+       return r;
+}
diff --git a/src/cli/lib/client-build.h b/src/cli/lib/client-build.h
new file mode 100644 (file)
index 0000000..13b7ca7
--- /dev/null
@@ -0,0 +1,26 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2023 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PAKFIRE_CLI_CLIENT_BUILD_H
+#define PAKFIRE_CLI_CLIENT_BUILD_H
+
+int cli_client_build(void* data, int argc, char* argv[]);
+
+#endif /* PAKFIRE_CLI_CLIENT_BUILD_H */
index c39c643e1916ca98a9ae58254d58b8af5403b27f..cfe91d4738fa0d49beca5741c0079ae6fc05e763 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <pakfire/ctx.h>
 
+#include "lib/client-build.h"
 #include "lib/command.h"
 #include "lib/progressbar.h"
 #include "lib/upload.h"
@@ -30,7 +31,8 @@
 const char* argp_program_version = PACKAGE_VERSION;
 
 static const struct command commands[] = {
-       { "upload", cli_upload, -1, -1, 0 },
+       { "build",  cli_client_build, 1, -1, 0 },
+       { "upload", cli_upload,      -1, -1, 0 },
        { NULL },
 };
 
index 42cace9120f09717018cd284ab13dabbe8db17d1..a0c5d8ff1f3fb090f9c6ec2a759b33c60f89a5b0 100644 (file)
@@ -297,6 +297,80 @@ ERROR:
        return r;
 }
 
+// Build
+
+int pakfire_buildservice_build(struct pakfire_buildservice* service, const char* upload,
+               const char* repo, const char** arches, int flags) {
+       struct pakfire_transfer* transfer = NULL;
+       struct json_object* response = NULL;
+       char* buffer = NULL;
+       size_t length = 0;
+       int r;
+
+       // Create a new transfer
+       r = pakfire_buildservice_create_transfer(&transfer, service, "/api/v1/builds");
+       if (r)
+               goto ERROR;
+
+       // Enable authentication
+       r = pakfire_downloader_transfer_auth(transfer);
+       if (r)
+               goto ERROR;
+
+       // Add the upload parameter
+       r = pakfire_downloader_transfer_add_param(transfer, "upload", "%s", upload);
+       if (r)
+               goto ERROR;
+
+       // Add the repo parameter
+       r = pakfire_downloader_transfer_add_param(transfer, "repo", "%s", repo);
+       if (r)
+               goto ERROR;
+
+       // Add any arches
+       if (arches) {
+               for (const char** arch = arches; *arch; arch++) {
+                       r = pakfire_downloader_transfer_add_param(transfer, "arch", "%s", *arch);
+                       if (r)
+                               goto ERROR;
+               }
+       }
+
+       // Disable tests?
+       if (flags & PAKFIRE_BUILD_DISABLE_TESTS) {
+               r = pakfire_downloader_transfer_add_param(transfer, "disable_test_builds", "%s", "yes");
+               if (r)
+                       goto ERROR;
+       }
+
+       // Write the response to the buffer
+       r = pakfire_downloader_transfer_set_output_buffer(transfer, &buffer, &length);
+       if (r)
+               goto ERROR;
+
+       // Run the transfer
+       r = pakfire_downloader_transfer_run(transfer, PAKFIRE_TRANSFER_NO_PROGRESS);
+       if (r)
+               goto ERROR;
+
+       // Parse the response
+       r = pakfire_buildservice_parse_response(service, transfer, buffer, length, &response);
+       if (r) {
+               CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
+               goto ERROR;
+       }
+
+ERROR:
+       if (transfer)
+               pakfire_downloader_transfer_unref(transfer);
+       if (response)
+               json_object_put(response);
+       if (buffer)
+               free(buffer);
+
+       return r;
+}
+
 // Uploads
 
 static int pakfire_buildservice_create_upload(struct pakfire_buildservice* service,
index 17b3c8a3b209fc6487de39be151d6c5331e23f29..b134877ea71ad3a0d1827cc1469939b20c605737 100644 (file)
@@ -32,6 +32,15 @@ int pakfire_buildservice_create(struct pakfire_buildservice** service, struct pa
 struct pakfire_buildservice* pakfire_buildservice_ref(struct pakfire_buildservice* service);
 struct pakfire_buildservice* pakfire_buildservice_unref(struct pakfire_buildservice* service);
 
+// Builds
+
+typedef enum pakfire_buildservice_build_flags {
+       PAKFIRE_BUILD_DISABLE_TESTS = (1 << 0),
+} pakfire_buildservice_build_flags_t;
+
+int pakfire_buildservice_build(struct pakfire_buildservice* service, const char* upload,
+       const char* repo, const char** arches, int flags);
+
 // Uploads
 
 int pakfire_buildservice_upload(struct pakfire_buildservice* service,