summaryrefslogtreecommitdiffstats
path: root/src
AgeCommit message (Collapse)Author
2021-01-25Merge branch 'more-parallelism' into masterMatthias Beyer
2021-01-25Outsource receiving, ensure we received it allMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Make progress bar message format uniformMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
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-25Reimplement Orchestrator::run()Matthias Beyer
This reimplements the Orchestrator::run() function _again_. Commit 889649ac16367fe671ce61363bb6ce82531e5a6b was the basis for this work, improving the baseline so we can take a step further in this commit. The approach before the change from 889649ac16367fe671ce61363bb6ce82531e5a6b had one flaw. In the following scenario: A / \ B E / \ \ C D F The nodes C, D and F are selected and then run. After they all succeeded, the next iteration is checked, and yields that B and E can be built. But if F takes extremely long, B and E both have to wait until it is ready (because that's how the implementation works), although B can be built as soon as C and D are ready. This patch changes the implementation to the following: 1. For each job, there is a task. 2. The task has a channel where it receives results from its dependencides. In above example, B would receive the results of the job runs for C and D, and E would receive the result from the job run of F. 3. The task also has a sender where it can send its resulting artifacts to a parent task. The task _also_ sends the results of its childs. This way we propagate the built artifacts up to the root node. All these tasks are started concurrently. The "root" task sends the result to the orchestrator. The task itself is responsible for sending the job to the scheduler and processing the result. If the job errored, the task sends that to its parent. If a child errored, the task aborts its own error and propagates that error. What does not yet work in this commit: * Artifacts that were built before the error occoured are not reported yet. * The staging/release stores may contain artifacts that can be re-used. They are completely ignored by now. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net> Tested-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-25Do not deny missing docs, we havent written em yetMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Do not deny missing copy impls, we have to manyMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Do not deny missing debug impls, we have to manyMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Do not deny unused results, we have too manyMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Remove unnecessary qualificationMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-25Fix: Use rand as _ to make lint happyMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-25Deny more things, sort denylistMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-25Reimplement hash verification using streamingMatthias Beyer
This patch re-implements hashing using streams and buffered readers instead of reading a full file to RAM before hashing it. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-25Implement sha256/sha512 supportMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-25Fix: Filter each entry, strip prefixMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-25Refactor: Move package name regex building to helper functionMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-21Fix clippy: Remove noop drop() callMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-21Fix clippy: Do not clone() copy typeMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-21Remove trailing whitespaceMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-21Remove RunnableJob::package_environment()Matthias Beyer
This functionality is not required anymore, as we put the whole package definition in the job script interpolation anyways. Signed-off-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-21Add derive(Debug) for FillArtifactPathDisplayMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-21Add MergedStores::get_artifact_by_path()Matthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-21Add FullArtifactPath::exists()Matthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-21impl From<Artifact> for JobResourceMatthias Beyer
Signed-off-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-20Fix: Check the repository diff to workdir as wellMatthias Beyer
This patch fixes the repository cleanness check, because the Repository::state() is RepositoryState::Clean even if there are changed files in the worktree. We want to fail if there's something uncommitted/unclean, so we have to check the diff here as well. Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Collect environment variables into comma-seperated listMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Make database types Eq, PartialEqMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Merge branch 'verification-colored'Matthias Beyer
2021-01-19Add some color in the hash verification routineMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Fix: Hash verification not asyncMatthias Beyer
Because we continuously get blocking filesystem operations when the implementation of the verification is async, simply remove the asyncness here now. This does not decrease performance (yet), because the function is called concurrently with other calls anyways. It blocks the tokio worker thread tho, thus maximum parallelism might be = number of cores. :-( Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Fix: Linenumbers should start with 1Matthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Fix: Do not add newlines when interpolating script helpersMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-19Fix: Remove license header from (generated) schema.rs fileMatthias Beyer
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-19Fix clippy: calling `as_bytes()` on a string literalMatthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-18Merge branch 'rustfmt'Matthias Beyer
Merge formatting, but do not enforce it because that'd be a too high hurdle for possible contributors.
2021-01-18Post-format clippy cleanupMatthias Beyer
This patch cleans some rustfmt code that was formatted, but where clippy had something to complain: a scope was unnecessary here, so remove it. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-18Merge branch 'package-meta-information'Matthias Beyer
2021-01-18Run `cargo fmt`Matthias Beyer
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-18Add a "meta" field for the Package structMatthias Beyer
This field may be used by the packager to define meta information on a package and later use that meta-information in their packaging scripts. For example: meta.description = "A simple package" and later use that to write a RPM spec file: echo "Description: {{this.meta.description}}" >> specfile Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
2021-01-18Add doc on configuration codeMatthias 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-18Fix clippy: Remove redundant clone() callsMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-18Fix: Add missing field initializationMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: single-character string constant used as patternMatthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2021-01-15Fix clippy: this `.into_iter()` call is equivalent to `.iter()` and will not ↵Matthias Beyer
consume the `Vec` 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-15Fix clippy: using `writeln!(outlock, "")`Matthias Beyer
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>