Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
ci: verify that codebuild jobs use ghcr.io
  • Loading branch information
marcoieni committed May 28, 2025
commit bf52d1a8037c15ea67c21d857cb9ae6e2829931b
66 changes: 66 additions & 0 deletions src/ci/citool/src/jobs/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::path::Path;

use super::Job;
use crate::jobs::{JobDatabase, load_job_db};
use crate::{DOCKER_DIRECTORY, JOBS_YML_PATH, utils};

#[test]
fn lookup_job_pattern() {
Expand Down Expand Up @@ -62,3 +66,65 @@ fn check_pattern(db: &JobDatabase, pattern: &str, expected: &[&str]) {

assert_eq!(jobs, expected);
}

/// Validate that CodeBuild jobs use Docker images from ghcr.io registry.
/// This is needed because otherwise from CodeBuild we get rate limited by Docker Hub.
fn validate_codebuild_image(job: &Job) -> anyhow::Result<()> {
let is_job_on_codebuild = job.codebuild.unwrap_or(false);
if !is_job_on_codebuild {
// Jobs in GitHub Actions don't get rate limited by Docker Hub.
return Ok(());
}

let image_name = job.image();
// we hardcode host-x86_64 here, because in codebuild we only run jobs for this architecture.
let dockerfile_path =
Path::new(DOCKER_DIRECTORY).join("host-x86_64").join(&image_name).join("Dockerfile");

if !dockerfile_path.exists() {
return Err(anyhow::anyhow!(
"Dockerfile not found for CodeBuild job '{}' at path: {}",
job.name,
dockerfile_path.display()
));
}

let dockerfile_content = utils::read_to_string(&dockerfile_path)?;

// Check if all FROM statement uses ghcr.io registry
let has_ghcr_from = dockerfile_content
.lines()
.filter(|line| line.trim_start().to_lowercase().starts_with("from "))
.all(|line| line.contains("ghcr.io"));

if !has_ghcr_from {
return Err(anyhow::anyhow!(
"CodeBuild job '{}' must use ghcr.io registry in its Dockerfile FROM statement. \
Dockerfile path: {dockerfile_path:?}",
job.name,
));
}

Ok(())
}

#[test]
fn validate_jobs() {
let db = {
let default_jobs_file = Path::new(JOBS_YML_PATH);
let db_str = utils::read_to_string(default_jobs_file).unwrap();
load_job_db(&db_str).expect("Failed to load job database")
};

let all_jobs =
db.pr_jobs.iter().chain(db.try_jobs.iter()).chain(db.auto_jobs.iter()).collect::<Vec<_>>();

let errors: Vec<anyhow::Error> =
all_jobs.into_iter().filter_map(|job| validate_codebuild_image(job).err()).collect();

if !errors.is_empty() {
let error_messages =
errors.into_iter().map(|e| format!("- {e}")).collect::<Vec<_>>().join("\n");
panic!("Job validation failed:\n{error_messages}");
}
}
2 changes: 1 addition & 1 deletion src/ci/citool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::test_dashboard::generate_test_dashboard;
use crate::utils::{load_env_var, output_details};

const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
pub const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml");

struct GitHubContext {
Expand Down
Loading