diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index cc93761e9604e..8b4f66c85761a 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -271,7 +271,11 @@ pub enum RunType { /// Workflows that run after a push to a PR branch PullRequest, /// Try run started with @bors try - TryJob { job_patterns: Option> }, + TryJob { + job_patterns: Option>, + /// Should the limit on the number of try jobs be ignored? + nolimit: bool, + }, /// Merge attempt workflow AutoJob, /// Fake job only used for sharing Github Actions cache. @@ -289,7 +293,7 @@ fn calculate_jobs( ) -> anyhow::Result> { let (jobs, prefix, base_env) = match run_type { RunType::PullRequest => (db.pr_jobs.clone(), "PR", &db.envs.pr_env), - RunType::TryJob { job_patterns } => { + RunType::TryJob { job_patterns, nolimit } => { let jobs = if let Some(patterns) = job_patterns { let mut jobs: Vec = vec![]; let mut unknown_patterns = vec![]; @@ -311,7 +315,7 @@ fn calculate_jobs( unknown_patterns.join(", ") )); } - if jobs.len() > MAX_TRY_JOBS_COUNT { + if jobs.len() > MAX_TRY_JOBS_COUNT && !nolimit { return Err(anyhow::anyhow!( "It is only possible to schedule up to {MAX_TRY_JOBS_COUNT} custom jobs, received {} custom jobs expanded from {} pattern(s)", jobs.len(), @@ -342,7 +346,7 @@ fn calculate_jobs( // built toolchain using `rustup-toolchain-install-master`), // we inject the `DIST_TRY_BUILD` environment variable to the jobs // to tell `opt-dist` to make the build faster by skipping certain steps. - if let RunType::TryJob { job_patterns } = run_type { + if let RunType::TryJob { job_patterns, nolimit: _ } = run_type { if job_patterns.is_none() { env.insert( "DIST_TRY_BUILD".to_string(), diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 8afda476ea68f..b8d8c18213948 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -30,6 +30,12 @@ const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); 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"); +#[derive(Default)] +struct TryJobMetadata { + job_patterns: Vec, + nolimit: bool, +} + struct GitHubContext { event_name: String, branch_ref: String, @@ -41,12 +47,16 @@ impl GitHubContext { match (self.event_name.as_str(), self.branch_ref.as_str()) { ("pull_request", _) => Some(RunType::PullRequest), ("push", "refs/heads/automation/bors/try-perf" | "refs/heads/try-perf") => { - Some(RunType::TryJob { job_patterns: None }) + Some(RunType::TryJob { job_patterns: None, nolimit: false }) } ("push", "refs/heads/automation/bors/try") => { - let patterns = self.get_try_job_patterns(); - let patterns = if !patterns.is_empty() { Some(patterns) } else { None }; - Some(RunType::TryJob { job_patterns: patterns }) + let metadata = self.get_try_job_metadata(); + let patterns = if !metadata.job_patterns.is_empty() { + Some(metadata.job_patterns) + } else { + None + }; + Some(RunType::TryJob { job_patterns: patterns, nolimit: metadata.nolimit }) } ("push", "refs/heads/automation/bors/auto") => Some(RunType::AutoJob), ("push", "refs/heads/main") => Some(RunType::MainJob), @@ -54,25 +64,46 @@ impl GitHubContext { } } - /// Tries to parse patterns of CI jobs that should be executed - /// from the commit message of the passed GitHub context + /// Tries to parse metadata about try jobs from the commit message. + /// + /// Currently, two things can be specified. + /// + /// # Try job patterns + /// The first is a set of patterns of CI jobs that should be executed. /// /// They can be specified in the form of /// try-job: /// or /// try-job: `` /// (to avoid GitHub rendering the glob patterns as Markdown) - fn get_try_job_patterns(&self) -> Vec { - if let Some(ref msg) = self.commit_message { - msg.lines() - .filter_map(|line| line.trim().strip_prefix("try-job: ")) - // Strip backticks if present - .map(|l| l.trim_matches('`')) - .map(|l| l.trim().to_string()) - .collect() - } else { - vec![] + /// + /// # No limit + /// The second is a marker that specifies that the limit on the maximum number of allowed try + /// jobs to execute should NOT be applied. + /// + /// try-nolimit + fn get_try_job_metadata(&self) -> TryJobMetadata { + let Some(commit_msg) = &self.commit_message else { + return TryJobMetadata::default(); + }; + + let mut nolimit = false; + let mut job_patterns = vec![]; + + for line in commit_msg.lines() { + let line = line.trim(); + if line.starts_with("try-nolimit") { + nolimit = true; + continue; + } + let Some(pattern) = line.strip_prefix("try-job: ") else { + continue; + }; + // Strip backticks if present + let pattern = pattern.trim_matches('`'); + job_patterns.push(pattern.trim().to_string()); } + TryJobMetadata { job_patterns, nolimit } } }