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
12 changes: 8 additions & 4 deletions src/ci/citool/src/jobs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<String>> },
TryJob {
job_patterns: Option<Vec<String>>,
/// 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.
Expand All @@ -289,7 +293,7 @@ fn calculate_jobs(
) -> anyhow::Result<Vec<GithubActionsJob>> {
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<Job> = vec![];
let mut unknown_patterns = vec![];
Expand All @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
63 changes: 47 additions & 16 deletions src/ci/citool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
nolimit: bool,
}

struct GitHubContext {
event_name: String,
branch_ref: String,
Expand All @@ -41,38 +47,63 @@ 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),
_ => None,
}
}

/// 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: <job-pattern>
/// or
/// try-job: `<job-pattern>`
/// (to avoid GitHub rendering the glob patterns as Markdown)
fn get_try_job_patterns(&self) -> Vec<String> {
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 }
}
}

Expand Down
Loading