|
2 | 2 | mod tests;
|
3 | 3 |
|
4 | 4 | use std::collections::BTreeMap;
|
| 5 | +use std::path::Path; |
5 | 6 |
|
6 | 7 | use anyhow::Context as _;
|
7 | 8 | use serde_yaml::Value;
|
8 | 9 |
|
9 |
| -use crate::GitHubContext; |
10 |
| -use crate::utils::load_env_var; |
| 10 | +use crate::utils::{self, load_env_var}; |
| 11 | +use crate::{DOCKER_DIRECTORY, GitHubContext}; |
11 | 12 |
|
12 | 13 | /// Representation of a job loaded from the `src/ci/github-actions/jobs.yml` file.
|
13 | 14 | #[derive(serde::Deserialize, Debug, Clone)]
|
@@ -46,6 +47,47 @@ impl Job {
|
46 | 47 | fn is_linux(&self) -> bool {
|
47 | 48 | self.os.contains("ubuntu")
|
48 | 49 | }
|
| 50 | + |
| 51 | + /// Validate that CodeBuild jobs use Docker images from ghcr.io registry. |
| 52 | + /// This is needed because otherwise from CodeBuild we get rate limited by Docker Hub. |
| 53 | + fn validate_codebuild_image(&self) -> anyhow::Result<()> { |
| 54 | + let is_job_on_codebuild = self.codebuild.unwrap_or(false); |
| 55 | + if !is_job_on_codebuild { |
| 56 | + // Jobs in GitHub Actions don't get rate limited by Docker Hub. |
| 57 | + return Ok(()); |
| 58 | + } |
| 59 | + |
| 60 | + let image_name = self.image(); |
| 61 | + // we hardcode host-x86_64 here, because in codebuild we only run jobs for this architecture. |
| 62 | + let dockerfile_path = |
| 63 | + Path::new(DOCKER_DIRECTORY).join("host-x86_64").join(&image_name).join("Dockerfile"); |
| 64 | + |
| 65 | + if !dockerfile_path.exists() { |
| 66 | + return Err(anyhow::anyhow!( |
| 67 | + "Dockerfile not found for CodeBuild job '{}' at path: {}", |
| 68 | + self.name, |
| 69 | + dockerfile_path.display() |
| 70 | + )); |
| 71 | + } |
| 72 | + |
| 73 | + let dockerfile_content = utils::read_to_string(&dockerfile_path)?; |
| 74 | + |
| 75 | + // Check if all FROM statement uses ghcr.io registry |
| 76 | + let has_ghcr_from = dockerfile_content |
| 77 | + .lines() |
| 78 | + .filter(|line| line.trim_start().to_lowercase().starts_with("from ")) |
| 79 | + .all(|line| line.contains("ghcr.io")); |
| 80 | + |
| 81 | + if !has_ghcr_from { |
| 82 | + return Err(anyhow::anyhow!( |
| 83 | + "CodeBuild job '{}' must use ghcr.io registry in its Dockerfile FROM statement. \ |
| 84 | + Dockerfile path: {dockerfile_path:?}", |
| 85 | + self.name, |
| 86 | + )); |
| 87 | + } |
| 88 | + |
| 89 | + Ok(()) |
| 90 | + } |
49 | 91 | }
|
50 | 92 |
|
51 | 93 | #[derive(serde::Deserialize, Debug)]
|
@@ -214,6 +256,10 @@ fn calculate_jobs(
|
214 | 256 | let jobs = substitute_github_vars(jobs.clone())
|
215 | 257 | .context("Failed to substitute GitHub context variables in jobs")?;
|
216 | 258 | let jobs = skip_jobs(jobs, channel);
|
| 259 | + for j in &jobs { |
| 260 | + j.validate_codebuild_image() |
| 261 | + .context(format!("Failed to validate CodeBuild job '{}'", j.name))?; |
| 262 | + } |
217 | 263 | let jobs = jobs
|
218 | 264 | .into_iter()
|
219 | 265 | .map(|job| {
|
|
0 commit comments