From 340620300ef023e823c022c247459630a72e7817 Mon Sep 17 00:00:00 2001
From: STEVAN Antoine <antoine.stevan@isae-supaero.fr>
Date: Tue, 8 Apr 2025 14:31:15 +0000
Subject: [PATCH] build the pipelines image from Dockerfile
 (dragoon/komodo!205)

This adds a Dockerfile to build an image for the pipelines, once and for all, until we decide to bump the Rust toolchain.

## changelog
- add `.gitlab-ci.dockerfile` which
  - uses `rust:latest` as a base (it appears using `alpine:latest` is both bigger and slower :shrug:)
  - installs basic system dependencies
  - uses `rust-toolchain.toml` to install the toolchain of the project
  - installs `cargo-script`
- use [`gitlab-registry.isae-supaero.fr/dragoon/komodo:bcb0e6b`](https://gitlab.isae-supaero.fr/dragoon/komodo/container_registry/42) in the GitLab pipelines and [`ghcr.io/dragoon-rs/dragoon/komodo:bcb0e6b`](https://github.com/orgs/dragoon-rs/packages/container/dragoon%2Fkomodo/388672772?tag=bcb0e6b5f73420762f6208700a43291e0066c2c3) in the GitHub pipelines and remove the "manual" dependency installation
- add `./make.rs container`, `./make.rs container --login` and `./make.rs container --push`
  - uses `nob.rs@7ea6be8` to capture output of commands with `+` syntax
  - get the current Git SHA as the tag of the image
- instructions have been added to the `README.md` for later reference

## mirror
| id                                                                             | head_sha                                                                                                                           | status    | conclusion | run_started_at        |
| ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | --------- | ---------- | --------------------- |
| [`14262324842`](https://github.com/dragoon-rs/komodo/actions/runs/14262324842) | [`c93d9c87928964aa20f347c1302757a06d2da628`](https://github.com/dragoon-rs/komodo/commit/c93d9c87928964aa20f347c1302757a06d2da628) | completed | success    | `2025-04-04T11:28:30` |
| [`14262372440`](https://github.com/dragoon-rs/komodo/actions/runs/14262372440) | [`f905e57633f5e3dc7b1c38faa463daf54fb674bb`](https://github.com/dragoon-rs/komodo/commit/f905e57633f5e3dc7b1c38faa463daf54fb674bb) | completed | cancelled  | `2025-04-04T11:31:12` |
| [`14262477396`](https://github.com/dragoon-rs/komodo/actions/runs/14262477396) | [`21b26efd988b2d8d7159d24cae37341135cfb1b9`](https://github.com/dragoon-rs/komodo/commit/21b26efd988b2d8d7159d24cae37341135cfb1b9) | completed | success    | `2025-04-04T11:36:59` |
| [`14263257396`](https://github.com/dragoon-rs/komodo/actions/runs/14263257396) | [`5bdca8cdb96e6ac2c25035513721485bcb08645d`](https://github.com/dragoon-rs/komodo/commit/5bdca8cdb96e6ac2c25035513721485bcb08645d) | completed | success    | `2025-04-04T12:22:10` |
| [`14263314072`](https://github.com/dragoon-rs/komodo/actions/runs/14263314072) | [`bcb0e6b5f73420762f6208700a43291e0066c2c3`](https://github.com/dragoon-rs/komodo/commit/bcb0e6b5f73420762f6208700a43291e0066c2c3) | completed | success    | `2025-04-04T12:25:27` |
| [`14263368772`](https://github.com/dragoon-rs/komodo/actions/runs/14263368772) | [`ddd4a2a9c1c28f4502814065de6aeca00b8b7a2f`](https://github.com/dragoon-rs/komodo/commit/ddd4a2a9c1c28f4502814065de6aeca00b8b7a2f) | completed | success    | `2025-04-04T12:28:30` |
| [`14263575177`](https://github.com/dragoon-rs/komodo/actions/runs/14263575177) | [`f9400e619a066294714024174dacd4a0501a369c`](https://github.com/dragoon-rs/komodo/commit/f9400e619a066294714024174dacd4a0501a369c) | completed | success    | `2025-04-04T12:40:44` |



## speed
the performance appears to be around
- ~ 1min 35sec on GitLab (see
    [8331](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8331),
    [8332](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8332),
    [8333](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8333),
    [8334](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8334),
    [8335](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8335),
    [8336](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8336),
    [8337](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8337),
    [8338](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8338),
    [8339](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8339),
    [8340](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8340),
    [8341](https://gitlab.isae-supaero.fr/dragoon/komodo/-/pipelines/8341),
    all after b82e8950fa98f365970fac857b9daad865f21562)
- ~ 4min on GitHub (see
    [14263257396](https://github.com/dragoon-rs/komodo/actions/runs/14263257396),
    [14263314072](https://github.com/dragoon-rs/komodo/actions/runs/14263314072),
    [14263368772](https://github.com/dragoon-rs/komodo/actions/runs/14263368772),
    [14263575177](https://github.com/dragoon-rs/komodo/actions/runs/14263575177),
    all after [5bdca8c](https://github.com/dragoon-rs/komodo/commit/5bdca8cdb96e6ac2c25035513721485bcb08645d))
---
 .env.dockerfile          | 14 ++++++++++++
 .github/workflows/ci.yml | 17 ++++----------
 .gitlab-ci.yml           | 13 ++---------
 README.md                | 21 +++++++++++++++++
 make.rs                  | 49 +++++++++++++++++++++++++++++++++++++---
 rust-toolchain.toml      |  1 -
 6 files changed, 87 insertions(+), 28 deletions(-)
 create mode 100644 .env.dockerfile

diff --git a/.env.dockerfile b/.env.dockerfile
new file mode 100644
index 00000000..791a1cc0
--- /dev/null
+++ b/.env.dockerfile
@@ -0,0 +1,14 @@
+FROM rust:latest
+
+# Suppress prompts during package installation
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt update --yes && apt upgrade --yes
+RUN apt install --yes protobuf-compiler
+
+COPY rust-toolchain.toml /
+RUN rustup show && cargo --version
+
+RUN cargo install cargo-script
+
+RUN apt clean && rm -rf /var/lib/apt/lists/*
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 89dd078b..ef20985f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,32 +5,23 @@ on: [push, pull_request, workflow_dispatch]
 jobs:
   fmt:
     runs-on: ubuntu-latest
+    container:
+      image: "ghcr.io/dragoon-rs/dragoon/komodo:bcb0e6b5f73420762f6208700a43291e0066c2c3"
     if: "!contains(github.event.head_commit.message, 'draft:') && !contains(github.event.head_commit.message, 'no-ci:')"
     steps:
       - uses: actions/checkout@v3
-      - name: Set up Rust
-        uses: actions-rs/toolchain@v1
-        with:
-          toolchain: stable
-      - name: Install dependencies
-        run: |
-          cargo install cargo-script
       - name: Run fmt check
         run: |
           ./make.rs fmt --check
 
   test:
     runs-on: ubuntu-latest
+    container:
+      image: "ghcr.io/dragoon-rs/dragoon/komodo:bcb0e6b5f73420762f6208700a43291e0066c2c3"
     needs: fmt
     if: "!contains(github.event.head_commit.message, 'draft:') && !contains(github.event.head_commit.message, 'no-ci:')"
     steps:
       - uses: actions/checkout@v3
-      - name: Install dependencies
-        run: |
-          sudo apt update --yes
-          sudo apt upgrade --yes
-          sudo apt install protobuf-compiler --yes
-          cargo install cargo-script
       - name: Show configuration
         run: |
           ./make.rs version
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d44462d5..fe3fff7b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,4 @@
-# WARNING: update `rust-toolchain.toml` as well
-image: "rust:1.78"
+image: "gitlab-registry.isae-supaero.fr/dragoon/komodo:bcb0e6b5f73420762f6208700a43291e0066c2c3"
 
 stages:
   - fmt
@@ -16,8 +15,6 @@ workflow:
 
 fmt:
   stage: fmt
-  before_script:
-    - cargo install cargo-script
   script:
     - ./make.rs fmt --check
 
@@ -25,14 +22,8 @@ test:
   stage: test
   needs:
     - fmt
-  before_script:
-    - apt update --yes
-    - apt upgrade --yes
-    - apt install protobuf-compiler --yes
-    - cargo install cargo-script
-    - ./make.rs version
-
   script:
+    - ./make.rs version
     - ./make.rs check
     - ./make.rs clippy
     - ./make.rs test
diff --git a/README.md b/README.md
index 2f9badd5..eff6db1d 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,26 @@ see [`benchmarks/`](benchmarks/README.md)
 
 the results can be found in [`dragoon/komodo-benchmark-results`](https://gitlab.isae-supaero.fr/dragoon/komodo-benchmark-results).
 
+## development
+
+Komodo uses a Docker image as the base of the GitLab pipelines.
+
+That means that there is nothing to build apart from the source code of Komodo itself when running jobs.
+
+When the development environment needs to change, e.g. when the version of Rust is bumped in
+[`rust-toolchain.toml`](./rust-toolchain.toml), one shall run the following commands to push the new
+Docker image to the [_container registry_][gitlab.isae-supaero.fr:dragoon/komodo@containers].
+
+```shell
+./make.rs container --login
+```
+```shell
+./make.rs container
+```
+```shell
+./make.rs container --push
+```
+
 ## contributors
 
 Because the code for this project has been originally extracted from
@@ -35,3 +55,4 @@ note that the following people have contributed to this code base:
 - @j.detchart
 
 [pcs-fec-id]: https://gitlab.isae-supaero.fr/dragoon/pcs-fec-id
+[gitlab.isae-supaero.fr:dragoon/komodo@containers]: https://gitlab.isae-supaero.fr/dragoon/komodo/container_registry/42
diff --git a/make.rs b/make.rs
index 6fa31a67..4a3cf762 100755
--- a/make.rs
+++ b/make.rs
@@ -6,13 +6,18 @@
 //! edition = "2021"
 //!
 //! [dependencies]
-//! nob = { git = "https://gitlab.isae-supaero.fr/a.stevan/nob.rs", rev = "e4b03cdd4f1ba9daf3095930911b12fb28b6a248" }
+//! nob = { git = "https://gitlab.isae-supaero.fr/a.stevan/nob.rs", rev = "7ea6be855cf5600558440def6e59a83f78b8b543" }
 //! clap = { version = "4.5.17", features = ["derive"] }
 //! ```
 extern crate clap;
 
 use clap::{Parser, Subcommand};
 
+const REGISTRY: &str = "gitlab-registry.isae-supaero.fr";
+const MIRROR_REGISTRY: &str = "ghcr.io/dragoon-rs";
+const IMAGE: &str = "dragoon/komodo";
+const DOCKERFILE: &str = ".env.dockerfile";
+
 #[derive(Parser)]
 #[command(version, about, long_about = None)]
 struct Cli {
@@ -55,6 +60,15 @@ enum Commands {
         #[arg(short, long)]
         features: bool,
     },
+    /// Builds the container.
+    Container {
+        /// Log into the registry instead of building.
+        #[arg(short, long)]
+        login: bool,
+        /// Push to the registry instead of building.
+        #[arg(short, long)]
+        push: bool,
+    },
 }
 
 #[rustfmt::skip]
@@ -85,7 +99,7 @@ fn main() {
                 "--",
                 "-D",
                 "warnings"
-            )
+            );
         }
         Some(Commands::Test { verbose, examples }) => {
             let mut cmd = vec!["cargo", "test"];
@@ -117,7 +131,36 @@ fn main() {
             if *private { cmd.push("--document-private-items") }
             if *features { cmd.push("--all-features") }
             nob::run_cmd_as_vec_and_fail!(cmd ; "RUSTDOCFLAGS" => "--html-in-header katex.html");
-        },
+        }
+        Some(Commands::Container { login, push }) => {
+            let res = nob::run_cmd_and_fail!(@+"git", "rev-parse", "HEAD");
+            let sha = String::from_utf8(res.stdout).expect("Invalid UTF-8 string");
+            let image = format!("{}/{}:{}", REGISTRY, IMAGE, sha.trim());
+            let mirror_image = format!("{}/{}:{}", MIRROR_REGISTRY, IMAGE, sha.trim());
+
+            if *login {
+                nob::run_cmd_and_fail!("docker", "login", REGISTRY);
+                nob::run_cmd_and_fail!("docker", "login", MIRROR_REGISTRY);
+            } else if *push {
+                nob::run_cmd_and_fail!("docker", "push", &image);
+                nob::run_cmd_and_fail!("docker", "push", &mirror_image);
+            } else {
+                nob::run_cmd_and_fail!(
+                    "docker",
+                    "build",
+                    "-t", &image,
+                    ".",
+                    "--file", DOCKERFILE
+                );
+                nob::run_cmd_and_fail!(
+                    "docker",
+                    "build",
+                    "-t", &mirror_image,
+                    ".",
+                    "--file", DOCKERFILE
+                );
+            }
+        }
         None => {}
     }
 }
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index f8eeac88..2c00fd6a 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,5 +1,4 @@
 [toolchain]
 profile = "minimal"
-# WARNING: update `.gitlab-ci.yml` as well
 channel = "1.78"
 components = ["rustfmt", "clippy", "rust-analyzer"]
-- 
GitLab