Bundle mission-control into Triple-C instead of cloning from GitHub
All checks were successful
Build App / compute-version (push) Successful in 2s
Build App / build-macos (push) Successful in 2m47s
Build Container / build-container (push) Successful in 9m0s
Build App / build-linux (push) Successful in 4m41s
Build App / build-windows (push) Successful in 5m33s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 10s

The mission-control (Flight Control) project is being closed upstream.
This embeds the project files directly in the repo under container/mission-control/,
bakes them into the Docker image at /opt/mission-control, and copies them into place
at container startup instead of git cloning from GitHub.

Also adds missing osc52-clipboard, audio-shim, and triple-c-sso-refresh to the
programmatic Docker build context in image.rs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 09:09:15 -07:00
parent 57a7cee544
commit 2dffef0767
43 changed files with 7212 additions and 37 deletions

View File

@@ -1957,6 +1957,25 @@ dependencies = [
"png 0.18.1",
]
[[package]]
name = "include_dir"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd"
dependencies = [
"include_dir_macros",
]
[[package]]
name = "include_dir_macros"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -4927,6 +4946,7 @@ dependencies = [
"fern",
"futures-util",
"iana-time-zone",
"include_dir",
"keyring",
"local-ip-address",
"log",

View File

@@ -28,6 +28,7 @@ dirs = "6"
log = "0.4"
fern = { version = "0.7", features = ["date-based"] }
tar = "0.4"
include_dir = "0.7"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
iana-time-zone = "0.1"
sha2 = "0.10"

View File

@@ -80,7 +80,7 @@ When working on any project that has a `.flightops/` directory, follow the Fligh
const MISSION_CONTROL_PROJECT_INSTRUCTIONS: &str = r#"## Flight Operations
This project uses [Flight Control](https://github.com/msieurthenardier/mission-control) for structured development.
This project uses **Flight Control** (bundled with Triple-C) for structured development.
**Before any mission/flight/leg work, read these files in order:**
1. `.flightops/README.md` — What the flightops directory contains

View File

@@ -1,6 +1,7 @@
use bollard::image::{BuildImageOptions, CreateImageOptions, ListImagesOptions};
use bollard::models::ImageSummary;
use futures_util::StreamExt;
use include_dir::{include_dir, Dir};
use std::collections::HashMap;
use std::io::Write;
@@ -11,6 +12,11 @@ const DOCKERFILE: &str = include_str!("../../../../container/Dockerfile");
const ENTRYPOINT: &str = include_str!("../../../../container/entrypoint.sh");
const SCHEDULER: &str = include_str!("../../../../container/triple-c-scheduler");
const TASK_RUNNER: &str = include_str!("../../../../container/triple-c-task-runner");
const OSC52_CLIPBOARD: &str = include_str!("../../../../container/osc52-clipboard");
const AUDIO_SHIM: &str = include_str!("../../../../container/audio-shim");
const SSO_REFRESH: &str = include_str!("../../../../container/triple-c-sso-refresh");
static MISSION_CONTROL_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/../../container/mission-control");
pub async fn image_exists(image_name: &str) -> Result<bool, String> {
let docker = get_docker()?;
@@ -150,38 +156,48 @@ where
Ok(())
}
fn append_file_to_archive(
archive: &mut tar::Builder<&mut Vec<u8>>,
path: &str,
content: &[u8],
mode: u32,
) -> Result<(), std::io::Error> {
let mut header = tar::Header::new_gnu();
header.set_size(content.len() as u64);
header.set_mode(mode);
header.set_cksum();
archive.append_data(&mut header, path, content)
}
fn append_embedded_dir(
archive: &mut tar::Builder<&mut Vec<u8>>,
dir: &Dir,
prefix: &str,
) -> Result<(), std::io::Error> {
for file in dir.files() {
let path = format!("{}/{}", prefix, file.path().display());
append_file_to_archive(archive, &path, file.contents(), 0o644)?;
}
for subdir in dir.dirs() {
append_embedded_dir(archive, subdir, prefix)?;
}
Ok(())
}
fn create_build_context() -> Result<Vec<u8>, std::io::Error> {
let mut buf = Vec::new();
{
let mut archive = tar::Builder::new(&mut buf);
let dockerfile_bytes = DOCKERFILE.as_bytes();
let mut header = tar::Header::new_gnu();
header.set_size(dockerfile_bytes.len() as u64);
header.set_mode(0o644);
header.set_cksum();
archive.append_data(&mut header, "Dockerfile", dockerfile_bytes)?;
append_file_to_archive(&mut archive, "Dockerfile", DOCKERFILE.as_bytes(), 0o644)?;
append_file_to_archive(&mut archive, "entrypoint.sh", ENTRYPOINT.as_bytes(), 0o755)?;
append_file_to_archive(&mut archive, "triple-c-scheduler", SCHEDULER.as_bytes(), 0o755)?;
append_file_to_archive(&mut archive, "triple-c-task-runner", TASK_RUNNER.as_bytes(), 0o755)?;
append_file_to_archive(&mut archive, "osc52-clipboard", OSC52_CLIPBOARD.as_bytes(), 0o755)?;
append_file_to_archive(&mut archive, "audio-shim", AUDIO_SHIM.as_bytes(), 0o755)?;
append_file_to_archive(&mut archive, "triple-c-sso-refresh", SSO_REFRESH.as_bytes(), 0o755)?;
let entrypoint_bytes = ENTRYPOINT.as_bytes();
let mut header = tar::Header::new_gnu();
header.set_size(entrypoint_bytes.len() as u64);
header.set_mode(0o755);
header.set_cksum();
archive.append_data(&mut header, "entrypoint.sh", entrypoint_bytes)?;
let scheduler_bytes = SCHEDULER.as_bytes();
let mut header = tar::Header::new_gnu();
header.set_size(scheduler_bytes.len() as u64);
header.set_mode(0o755);
header.set_cksum();
archive.append_data(&mut header, "triple-c-scheduler", scheduler_bytes)?;
let task_runner_bytes = TASK_RUNNER.as_bytes();
let mut header = tar::Header::new_gnu();
header.set_size(task_runner_bytes.len() as u64);
header.set_mode(0o755);
header.set_cksum();
archive.append_data(&mut header, "triple-c-task-runner", task_runner_bytes)?;
append_embedded_dir(&mut archive, &MISSION_CONTROL_DIR, "mission-control")?;
archive.finish()?;
}