#ifndef LIBREPOMGR_BUILD_ACTION_H #define LIBREPOMGR_BUILD_ACTION_H #include "./buildactionfwd.h" #include "./buildactionmeta.h" #include "./subprocessfwd.h" #include "../webapi/routes.h" #include "../globallock.h" #include "../logcontext.h" #include "../../libpkg/data/config.h" #include "../../libpkg/data/lockable.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class BuildActionsTests; namespace LibRepoMgr { struct ServiceSetup; namespace WebAPI { struct Params; class Session; } // namespace WebAPI struct InternalBuildAction; using AssociatedLocks = std::vector>; struct LIBREPOMGR_EXPORT PackageBuildData : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::string existingVersion; std::vector> existingPackages; std::string sourceDirectory; std::string originalSourceDirectory; std::optional sourceInfo; std::vector packages; std::vector warnings; std::string error; std::size_t specifiedIndex = std::numeric_limits::max(); bool hasSource = false; }; struct LIBREPOMGR_EXPORT BuildPreparation : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::unordered_map buildData; std::vector>> dbConfig, stagingDbConfig; std::string targetDb, targetArch, stagingDb; std::vector> batches; std::vector cyclicLeftovers; std::vector warnings; std::string error; bool manuallyOrdered = false; }; enum class PackageStagingNeeded { Undetermined, Yes, No, }; struct LIBREPOMGR_EXPORT PackageBuildProgress : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { bool hasBeenAnyProgressMade() const; void resetProgress(); void resetChrootSettings(); CppUtilities::DateTime started; CppUtilities::DateTime finished; std::string buildDirectory; std::string chrootDirectory; std::string chrootUser; std::vector makechrootpkgFlags; std::vector makepkgFlags; std::string packageExtension; std::vector warnings; std::string error; std::string updatedVersion; PackageStagingNeeded stagingNeeded = PackageStagingNeeded::Undetermined; bool skipChrootUpgrade = false; bool skipChrootCleanup = false; bool keepPreviousSourceTree = false; bool checksumsUpdated = false; bool hasSources = false; bool addedToRepo = false; }; struct LIBREPOMGR_EXPORT RebuildInfo : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::vector provides; std::vector libprovides; void replace(const LibPkg::DependencySet &deps, const std::unordered_set &libs); void add(const LibPkg::DependencySet &deps, const std::unordered_set &libs); }; using RebuildInfoByPackage = std::unordered_map; using RebuildInfoByDatabase = std::unordered_map; struct LIBREPOMGR_EXPORT BuildProgress : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::unordered_map progressByPackage; std::string targetDbFilePath; std::string targetRepoPath; std::string stagingDbFilePath; std::string stagingRepoPath; RebuildInfoByPackage producedProvides, removedProvides; RebuildInfoByDatabase rebuildList; }; struct LIBREPOMGR_EXPORT PackageMovementResult : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::vector> failedPackages; std::vector processedPackages; std::string errorMessage; }; struct LIBREPOMGR_EXPORT RepositoryProblem : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::variant desc; std::string pkg; bool critical = true; }; struct LIBREPOMGR_EXPORT BuildActionMessages : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::vector notes; std::vector warnings; std::vector errors; }; class BuildProcessSession; struct ServiceSetup; struct LIBREPOMGR_EXPORT BuildActionBase : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { using IdType = BuildActionIdType; static constexpr IdType invalidId = std::numeric_limits::max(); explicit BuildActionBase(IdType id = invalidId); bool isScheduled() const; bool isExecuting() const; bool isDone() const; bool hasSucceeded() const; IdType id; BuildActionType type = BuildActionType::Invalid; std::string taskName; std::string templateName; BuildActionStatus status = BuildActionStatus::Created; BuildActionResult result = BuildActionResult::None; CppUtilities::DateTime created = CppUtilities::DateTime::gmtNow(); CppUtilities::DateTime started; CppUtilities::DateTime finished; std::vector startAfter; std::string directory; std::vector sourceDbs, destinationDbs; std::vector packageNames; BuildActionFlagType flags = noBuildActionFlags; std::unordered_map settings; }; inline BuildActionBase::BuildActionBase(IdType id) : id(id) { } struct LIBREPOMGR_EXPORT BuildAction : public BuildActionBase, public std::enable_shared_from_this, public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { friend InternalBuildAction; friend ServiceSetup; friend BuildProcessSession; friend BuildActionsTests; friend void WebAPI::Routes::postBuildAction(const WebAPI::Params ¶ms, WebAPI::ResponseHandler &&handler); friend void WebAPI::Routes::postBuildActionsFromTask(const WebAPI::Params ¶ms, WebAPI::ResponseHandler &&handler, const std::string &taskName, const std::string &directory, const std::vector &startAfterIds, bool startImmediately); friend void WebAPI::Routes::deleteBuildActions(const WebAPI::Params ¶ms, WebAPI::ResponseHandler &&handler); friend void WebAPI::Routes::postCloneBuildActions(const WebAPI::Params ¶ms, WebAPI::ResponseHandler &&handler); public: explicit BuildAction(IdType id = invalidId, ServiceSetup *setup = nullptr) noexcept; BuildAction &operator=(BuildAction &&other); ~BuildAction(); static bool haveSucceeded(const std::vector> &buildActions); bool isAborted() const; const std::atomic_bool &aborted() const; LibPkg::StorageID start(ServiceSetup &setup); void assignStartAfter(const std::vector> &startsAfterBuildActions); void abort(); void appendOutput(std::string_view output); void appendOutput(std::string &&output); template void appendOutput(Args &&...args); template void appendOutput(CppUtilities::EscapeCodes::Phrases phrase, Args &&...args); LogContext &log(); void setStopHandler(std::function &&stopHandler); void setConcludeHandler(std::function &&concludeHandler); std::shared_ptr findBuildProcess(const std::string &filePath); std::shared_ptr makeBuildProcess( std::string &&displayName, std::string &&logFilePath, ProcessHandler &&handler, AssociatedLocks &&locks = AssociatedLocks()); void terminateOngoingBuildProcesses(); void streamFile(const WebAPI::Params ¶ms, const std::string &filePath, boost::beast::string_view fileMimeType, boost::beast::string_view contentDisposition = boost::beast::string_view()); ServiceSetup *setup(); using ReflectiveRapidJSON::JsonSerializable::fromJson; using ReflectiveRapidJSON::JsonSerializable::toJson; using ReflectiveRapidJSON::JsonSerializable::toJsonDocument; using ReflectiveRapidJSON::BinarySerializable::toBinary; using ReflectiveRapidJSON::BinarySerializable::restoreFromBinary; using ReflectiveRapidJSON::BinarySerializable::fromBinary; protected: private: template void post(); template void post(Callback &&codeToRun); LibPkg::StorageID conclude(BuildActionResult result); public: std::vector logfiles; std::vector artefacts; std::variant, LibPkg::LicenseResult, LibPkg::PackageUpdates, BuildPreparation, BuildProgress, PackageMovementResult, std::unordered_map>, BuildActionMessages> resultData; private: LogContext m_log; ServiceSetup *m_setup = nullptr; std::atomic_bool m_aborted = false; std::function m_stopHandler; std::function m_concludeHandler; std::mutex m_processesMutex; std::unordered_map> m_ongoingProcesses; std::mutex m_outputSessionMutex; std::shared_ptr m_outputSession; std::unique_ptr m_internalBuildAction; }; inline bool BuildActionBase::isScheduled() const { return status == BuildActionStatus::Created || status == BuildActionStatus::AwaitingConfirmation; } inline bool BuildActionBase::isExecuting() const { return status == BuildActionStatus::Enqueued || status == BuildActionStatus::Running; } inline bool BuildActionBase::isDone() const { return status == BuildActionStatus::Finished; } inline bool BuildActionBase::hasSucceeded() const { return isDone() && result == BuildActionResult::Success; } inline bool BuildAction::isAborted() const { return m_aborted.load(); } inline const std::atomic_bool &BuildAction::aborted() const { return m_aborted; } inline LogContext &BuildAction::log() { return m_log; } inline void BuildAction::setStopHandler(std::function &&stopHandler) { m_stopHandler = std::move(stopHandler); } inline void BuildAction::setConcludeHandler(std::function &&concludeHandler) { m_concludeHandler = std::move(concludeHandler); } inline std::shared_ptr BuildAction::findBuildProcess(const std::string &filePath) { const auto i = m_ongoingProcesses.find(filePath); return i != m_ongoingProcesses.cend() ? i->second : nullptr; } inline ServiceSetup *BuildAction::setup() { return m_setup; } /*! * \brief Appends the specified arguments to the build action's log but *not* to the overall service log. */ template inline void BuildAction::appendOutput(Args &&...args) { appendOutput(CppUtilities::argsToString(std::forward(args)...)); } /*! * \brief Append output (overload needed to prevent endless recursion). */ inline void BuildAction::appendOutput(std::string &&output) { appendOutput(std::string_view(output)); } /*! * \brief Appends the specified arguments to the build action's log and to the overall service log. */ template inline void BuildAction::appendOutput(CppUtilities::EscapeCodes::Phrases phrase, Args &&...args) { appendOutput(std::move(CppUtilities::argsToString(CppUtilities::EscapeCodes::formattedPhraseString(phrase), std::forward(args)...))); } } // namespace LibRepoMgr #endif // LIBREPOMGR_BUILD_ACTION_H // avoid making LogContext available without also defining overloads for operator() which would possibly lead to linker errors #include "../logging.h"