From: Michael Tremer Date: Fri, 20 Oct 2023 10:46:12 +0000 (+0000) Subject: buildservice: Implement uploading builds X-Git-Tag: 0.9.30~1426 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27629aaf6d0aee560abc82115fbc2f3c3adb0b87;p=pakfire.git buildservice: Implement uploading builds Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 85e9e5fc9..ea33933e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 index 000000000..914d74710 --- /dev/null +++ b/src/cli/lib/client-build.c @@ -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 . # +# # +#############################################################################*/ + +#include + +#include "client-build.h" +#include "command.h" + +#include +#include + +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 index 000000000..13b7ca777 --- /dev/null +++ b/src/cli/lib/client-build.h @@ -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 . # +# # +#############################################################################*/ + +#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 */ diff --git a/src/cli/pakfire-client.c b/src/cli/pakfire-client.c index c39c643e1..cfe91d473 100644 --- a/src/cli/pakfire-client.c +++ b/src/cli/pakfire-client.c @@ -23,6 +23,7 @@ #include +#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 }, }; diff --git a/src/libpakfire/buildservice.c b/src/libpakfire/buildservice.c index 42cace912..a0c5d8ff1 100644 --- a/src/libpakfire/buildservice.c +++ b/src/libpakfire/buildservice.c @@ -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, diff --git a/src/libpakfire/include/pakfire/buildservice.h b/src/libpakfire/include/pakfire/buildservice.h index 17b3c8a3b..b134877ea 100644 --- a/src/libpakfire/include/pakfire/buildservice.h +++ b/src/libpakfire/include/pakfire/buildservice.h @@ -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,