Skip to content

ci: verify that codebuild jobs use ghcr.io #141643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 29, 2025
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
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