summaryrefslogtreecommitdiffstats
path: root/src/commands/build.rs
AgeCommit message (Collapse)Author
2021-11-19Update Copyright string to 2020-2022Matthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-09-16Add passing of data for condition-checkMatthias Beyer
This patch extends the interface for building the package DAG with a parameter for the data that is required to check conditions for conditional dependencies. A "DTO" type is added for this data. The actual condition-checking is not implemented in this patch. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-08-12Fix clippy: Remove needless borrowsMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-07-27Merge branch 'optional-dag-loading-progress'Matthias Beyer
2021-07-21Sort importsMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-06-18Make progress bar for loading DAG optionalMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-05-11Add module-level docsMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-05-11Refactor: Replace manual string-formatting with LogItem::display() callMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-05-11Refactor: Use moving iterator for ParsedLogMatthias Beyer
This patch replaces the ParsedLog::iter() function with ParsedLog::into_iter(), to use a moving iteration rather than a iteration by reference, because iterating by reference is not necessary at all. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-05-11Refactor: Implement FromStrMatthias Beyer
Instead of having a function `&str -> Result<Self>` on the type, implement the `std::str::FromStr` trait to be more rusty here. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-04-12Shuffle endpoint configurationsMatthias Beyer
As the comment in the code explains, we're always loading the endpoints from the same file and feed it to the scheduler the same way. Because of that, we always schedule to the first endpoint until it is full and then to the second. To have a bit more spreading over the endpoints, shuffle the configurations before connecting, so this way the scheduler does not always (each time butido is called) use the same endpoint as first endpoint. This is not a perfect solution, but a simple and working one. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-04-08Print submit details before starting buildsMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-03-11Merge branch 'misc'Matthias Beyer
2021-03-11Endpoint configuration as MapMatthias Beyer
This patch rewrites the endpoint configuration format to be a map. The problem here is, that a list of endpoints cannot easily be used with layered configuration, where a part of the configuration lives in the XDG config home of the user and the rest lives in the repository. With this patch, the endpoints are configured with a map instead of an array, which makes it less complicated to overwrite. The name of an endpoint is now the key in the map. A type `EndpointName` was introduced to take advantage of strong typing. Thus, the patch touches a bit more code to adapt to the new type in use. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-03-11Fix: Make error message more readable for humansMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-03-04Remove counting of package filesMatthias Beyer
This removes the counting of package files and using that value to set the length of the progress bar. This was just overhead and because of the duration of the bars to be visible (very short) simply not necessary. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-03-04Do not pass progress bars by value, but by referenceMatthias Beyer
Because passing by value is simply not necessary here. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-03-01Add feature to pass git author and git commit information to containerMatthias Beyer
This patch implements the feature to be able to pass author and commit hash information from the repository to the container. This can be used to set packager or package description commit hash inside the build container, if desired. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-03-01Refactor: Open git repository in command::build()Matthias Beyer
This commit refactors the git2::Repository::open() call to be in the command::build() implementation, so we do not open the repository multiple times. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-25Multiple release storesMatthias Beyer
This patch adds the ability to have more than one release store. With this patch, a user can (has to) configure release store names in the configuration file, and can then specify one of the configured names to release the artifacts to. This way, different release "channels" can be served, for example a stable channel and a rolling release channel (although "channel" is not in our wording). The code was adapted to be able to fetch releases from multiple release directories, in the crate::db::find_artifact implementation, so that re-using artifacts works across all release directories. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-22Fix: Re-use submit UUID if staging directory is overwrittenMatthias Beyer
This patch changes the behaviour if the staging directory is re-used. If the staging directory is re-used, we take the submit UUID from there instead of generating a new one. This way, database entries are added to the already existing submit instead of added to a new one, but the artifacts are put into the staging store of the reused one. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-22Remove printlnMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-15Add logging which repository search mechanism is usedMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-08Colorize log output for better discoverabilityMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-08Remove `Artifact` typeMatthias Beyer
This patch follows-up on the shrinking of the `Artifact` type and removes it entirely. The type is not needed. Only the `ArtifactPath` type is needed, which is a thin wrapper around `PathBuf`, ensuring that the path is relative to the store root. The `Artifact` type used `pom` to parse the name and version of the package from the `ArtifactPath` object it contained, which resulted in the restriction that the path must always be <name>-<version>... Which should not be a requirement and actually caused issues with a package named "foo-bar" (as an example). Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-02-06Rewrite package organizational structure using DAGMatthias Beyer
This patch reimplements the package orchestration functionality to rely on a DAG rather than a tree. A / \ B E / \ \ C D F Before this change, the structure the packages were organized in for a build was a tree. That did work reasonable well for initial development of butido, because this is a simple case and the implementation is rather simple, too. But, packages and their dependencies are not always organized in a tree. Most of the time, they are organized in a DAG: .-> C -, / \ D > A \ / `-> B -´ This is a real-world example: A could be a common crypto-library that I do not want to name here. B and C could be libraries that use the said crypto-library and D could be a program that use B and C. Because said crypto-library builds rather long, building it twice and throwing one result away is a no-go. A DAG as organizational structure makes that issue go away entirely. Also, we can later implement checks whether the DAG contains multiple versions of the same library, if that is undesireable. The change itself is rather big, frankly because it is a non-trivial change the replace the whole data structure and its handling in the orchestrator code. First of all, we introduce the "daggy" library, which provides the DAG implementation on top of the popular "petgraph" library. The package `Tree` datastructure was replaced by a package `Dag` datastructure. This type implements the heavy-lifting that is needed to load a package and all its dependencies from the `Repository` object. The `JobTree` was also reimplemented, but as `daggy::Dag` provides a convenient `map()` function, its implementation which transforms the package `Dag` into a job `Dag` is rather trivial. `crate::job::Dag` then provides the convenience `iter()` function to iterate over all elements in the DAG and providing a `JobDefinition` object for each node. The topology in which we traverse the DAG is not an issue, as we need to create tasks for all `JobDefinition`s anyways, so we do not care about traversal topology at all. The `crate::package::Package` type got an `Hash` implementation, which is necessary to keep track of the mappings while reading the DAG from the repository. The implementation does not create the edges between the nodes in the DAG right when inserting, but afterwards. To keep track of the `daggy::NodeIndex`es, it keeps a mapping Package -> NodeIndex in a Hashmap. Thus, `Package` must implement `std::hash::Hash` Signed-off-by: Matthias Beyer <mail@beyermatthias.de> Tested-by: Matthias Beyer <mail@beyermatthias.de> squash! Reimplement as DAG
2021-02-05Remove "tree" from submitMatthias Beyer
This removes the "tree" column from the "submits" table. This is because we do not store the build-tree in the database anymore. We don't actually need this feature and we can always re-build the tree from an old commit in the repository. Thus, this is not required anymore. Also, it is less easy to do as soon as the internal implementation changes from a "tree" structure to a "DAG" structure. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-30Update tokio: 0.2 -> 1.0, shipliftMatthias Beyer
Because tokio 1.0 does not ship with the Stream trait, this patch also introduces tokio_stream as new dependency. For more information, look here: https://docs.rs/tokio/1.0.3/tokio/stream/index.html Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Let the JobHandle::run() return a Vec<Artifact>Matthias Beyer
Before that change, it returned the dbmodels::Artifact objects, for which we needed to fetch the filestore::Artifact again. This change removes that restriction (improving runtime, of course). Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-21Reimplement: Orchestrator::run()Matthias Beyer
This patch reimplements the running of the computed jobs. The old implementation was structured as follows: 1. Compute a Tree of dependencies for the requested package 2. Make sets of this tree (see below) 3. For each set 3.1. Run set in parallel by submitting each job in the set to the scheduler 3.2. collect outputs and errors 3.3. Record outputs and return errors (if any) The complexity here was the computing of the JobSets but also the running of each job in a set in parallel. The code was non-trivial to understand. But that's not even the biggest concern with this approch. Consider the following tree of jobs: A / \ B E / \ \ C D F / \ G H \ I Each node here represents a package, the edges represent dependencies on the lower-hanging package. This tree would result in 5 sets of jobs: [ [ I ] [ G, H ] [ C, D, F ] [ B, E ] [ A ] ] because each "layer" in the tree would be run in parallel. It can be easily seen, that in the tree from above, the jobs for [ I, G, D, C ] can be run in parallel easily, because they do not have dependencies. The reimplementation also has another (crucial) benefit: The implementation does not depend on a structure of artifact path names anymore. Before, the artifacts needed to have a name as follows: <name of the package>-<version of the package>.<something> which was extremely restrictive. With the changes from this patch, the implementation does not depend on such a format anymore. Instead: Dependencies are associated with a job, by the output of jobs run for dependent packages. That means that, considering the above tree of packages: deps_of(B) = outputs_of(job_for(C)) + outputs_of(job_for(D)) in text: The dependencies of package B are the outputs of the job run for package C plus the outputs of the job run for package D. With that change in place, the outputs of a job run for a package can yield arbitrary file names and as long as the build script for the package can process them, everything is fine. The new algorithm, that solves that issue, is rather simple: 1. Hold a list of errors 2. Hold a list of artifacts that were built 3. Hold a list of jobs that were run 4. Iterate over all jobs, filtered by - If the job appears in the "already run jobs" list, ignore it - If a job has dependencies (on outputs of other jobs) that do not appear in the "already run jobs", ignore it (for now) 5. Run these jobs, and for each job: 5.1. Take the job UUID and put it in the "already run jobs" list. 5.2. Take the result of the job, 5.2.1. if it is an error, put it in the "list of errors" 5.2.2. if it is ok, put the artifact in the "list of artifacts" 6. if the list of errors is not empty, goto 9 7. if all jobs are in the "already run jobs" list, goto 9 8. goto 4 9. return all artifacts and all errors Because this approach is fundamentally different than the previous approach, a lot of things had to be rewritten: - The `JobSet` type was complete removed - There is a new type `crate::job:Tree` that gets built from the `crate::package::Tree` It is a mapping of a UUID (the job UUID) to a `JobDefinition`. The `JobDefinition` type is - A Job - A list of UUIDs of other jobs, where this job depends on the outputs It is therefore a mapping of `Job -> outputs(jobs_of(dependencies)` The `crate::job::Tree` type is now responsible for building a `Job` object for each `crate::package::Package` object from the `crate::package::Tree` object. Because the `crate::package::Tree` object contains all required packages for the complete built, the implementation of `crate::job::Tree::build_tree()` does not check sanity. It is assumed that the input tree to the function contains all mappings. Despite the name `crate::job::Tree` ("Tree"), the actual structure stored in the type is not a real tree. - The `MergedStores::get_artifact_by_path()` function was adapted because in the previous implementation, it used `StagingStore::load_from_path()`, which tried to load the file from the filesystem and put it into the internal map, which failed if it was already there. The adaption checks if the artifact already exists in the internal map and returns that object instead. (For the release store accordingly) - The interface of the `RunnableJob::build_from_job()` function was adapted, as this function does not need to access the `MergedStores` object anymore to load dependency-Artifacts from the filesystem. Instead, these Artifacts are passed to the function now. - The Orchestrator code - Got a type alias `JobResult` which represents the result of a job run wich is either - A number of artifacts (for optimization reasons with their associated database artifact entry) - or an error with the job uuid that failed (again, for optimization reasons) - Got an implementation of the algorithm described above - Got a new implementation of run_job(), which - Fetches the pathes of dependency-artifacts from the database by using the job uuids from the JobDefinition object - Creates the RunnableJob object for that - Schedules the RunnableJob object in the scheduler - For each output artifact (database object representing it) - get the filesystem Artifact object for it Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-20Move the cleanness check to the "build" command implementationMatthias Beyer
All other subcommands should be able to run on an unclean repository, but the build command should not. Thus, move this function call from main() to the build() implementation. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Fix: Missing variable name for interpolationMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-18Run `cargo fmt`Matthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-18Add comments on subcommand implementationsMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-15Fix clippy: this `if` statement can be collapsedMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: this `else { if .. }` block can be collapsedMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Allow too many arguments for crate::commands::build()Matthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: `.map().collect()` can be replaced with `.try_for_each()`Matthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: useless use of `format!`Matthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: `.map().collect()` can be replaced with `.try_for_each()`Matthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: you should consider adding a `Default` implementation for ↵Matthias Beyer
`package::tree::Tree` Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-14Move splitting of CLI env k-v-string to utility moduleMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-13Add LICENSE file and license headersMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-04Add an prefix when logging error messagesMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2020-12-15Fix: Only print phase name if error came from scriptMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2020-12-15Fix: Overflowing subtractionMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2020-12-15Fix: Only print message if there are in fact artifacts createdMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2020-12-14Report phase in which a job errored, if it erroredMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2020-12-11Rename for consistency: deny_images -> denied_imagesMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2020-12-11Add allowlist featureMatthias Beyer
This patch adds the "allowlist" feature for packages. A package can have a list of allowed images to be built on - butido will not execute the submit if one package is not allowed on the image passed to butido. This is the opposite of the denylist, of course. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>