Skip to content

Commit b99da91

Browse files
committed
Check if commit is from bors
1 parent f5143ed commit b99da91

File tree

3 files changed

+84
-34
lines changed

3 files changed

+84
-34
lines changed

Diff for: src/git.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,29 @@ use git2::build::RepoBuilder;
1313
use git2::{Commit as Git2Commit, Repository};
1414
use log::debug;
1515

16-
use crate::Commit;
16+
use crate::{Author, Commit, GitDate, BORS_AUTHOR};
1717

1818
impl Commit {
1919
// Takes &mut because libgit2 internally caches summaries
2020
fn from_git2_commit(commit: &mut Git2Commit<'_>) -> Self {
21+
let committer = commit.committer();
2122
Commit {
2223
sha: commit.id().to_string(),
23-
date: Utc
24-
.timestamp_opt(commit.time().seconds(), 0)
25-
.unwrap()
26-
.date_naive(),
24+
date: time_to_date(&commit.time()),
2725
summary: String::from_utf8_lossy(commit.summary_bytes().unwrap()).to_string(),
26+
committer: Author {
27+
name: committer.name().unwrap_or("").to_string(),
28+
email: committer.email().unwrap_or("").to_string(),
29+
date: time_to_date(&committer.when()),
30+
},
2831
}
2932
}
3033
}
3134

35+
fn time_to_date(time: &git2::Time) -> GitDate {
36+
Utc.timestamp_opt(time.seconds(), 0).unwrap().date_naive()
37+
}
38+
3239
struct RustcRepo {
3340
repository: Repository,
3441
origin_remote: String,
@@ -145,8 +152,12 @@ pub fn get_commits_between(first_commit: &str, last_commit: &str) -> anyhow::Res
145152
// two commits are merge commits made by bors
146153
let assert_by_bors = |c: &Git2Commit<'_>| -> anyhow::Result<()> {
147154
match c.author().name() {
148-
Some("bors") => Ok(()),
149-
Some(author) => bail!("Expected author {} to be bors for {}.\n Make sure specified commits are on the master branch!", author, c.id()),
155+
Some(author) if author == BORS_AUTHOR => Ok(()),
156+
Some(author) => bail!(
157+
"Expected author {author} to be {BORS_AUTHOR} for {}.\n \
158+
Make sure specified commits are on the master branch!",
159+
c.id()
160+
),
150161
None => bail!("No author for {}", c.id()),
151162
}
152163
};
@@ -167,7 +178,7 @@ pub fn get_commits_between(first_commit: &str, last_commit: &str) -> anyhow::Res
167178
res.push(Commit::from_git2_commit(&mut current));
168179
match current.parents().next() {
169180
Some(c) => {
170-
if c.author().name() != Some("bors") {
181+
if c.author().name() != Some(BORS_AUTHOR) {
171182
debug!(
172183
"{:?} has non-bors author: {:?}, skipping",
173184
c.id(),

Diff for: src/github.rs

+36-22
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use reqwest::header::{HeaderMap, HeaderValue, InvalidHeaderValue, AUTHORIZATION,
33
use reqwest::{self, blocking::Client, blocking::Response};
44
use serde::{Deserialize, Serialize};
55

6-
use crate::{parse_to_naive_date, Commit, GitDate};
6+
use crate::{parse_to_naive_date, Author, Commit, GitDate, BORS_AUTHOR};
77

88
#[derive(Serialize, Deserialize, Debug)]
99
struct GithubCommitComparison {
@@ -16,8 +16,8 @@ struct GithubCommitElem {
1616
}
1717
#[derive(Serialize, Deserialize, Debug)]
1818
struct GithubCommit {
19-
author: GithubAuthor,
20-
committer: GithubAuthor,
19+
author: Option<GithubAuthor>,
20+
committer: Option<GithubAuthor>,
2121
message: String,
2222
}
2323
#[derive(Serialize, Deserialize, Debug)]
@@ -38,19 +38,33 @@ pub(crate) struct GithubComment {
3838

3939
impl GithubCommitElem {
4040
fn date(&self) -> anyhow::Result<GitDate> {
41-
let (date_str, _) =
42-
self.commit.committer.date.split_once('T').context(
43-
"commit date should folllow the ISO 8061 format, eg: 2022-05-04T09:55:51Z",
44-
)?;
41+
let (date_str, _) = self
42+
.commit
43+
.committer
44+
.as_ref()
45+
.ok_or_else(|| anyhow::anyhow!("commit should have committer"))?
46+
.date
47+
.split_once('T')
48+
.context("commit date should folllow the ISO 8061 format, eg: 2022-05-04T09:55:51Z")?;
4549
Ok(parse_to_naive_date(date_str)?)
4650
}
4751

4852
fn git_commit(self) -> anyhow::Result<Commit> {
4953
let date = self.date()?;
54+
let committer = self
55+
.commit
56+
.committer
57+
.ok_or_else(|| anyhow::anyhow!("commit should have committer"))?;
58+
let committer = Author {
59+
name: committer.name,
60+
email: committer.email,
61+
date,
62+
};
5063
Ok(Commit {
5164
sha: self.sha,
5265
date,
5366
summary: self.commit.message,
67+
committer,
5468
})
5569
}
5670
}
@@ -123,13 +137,11 @@ impl CommitsQuery<'_> {
123137
let mut commits = Vec::new();
124138

125139
// focus on Pull Request merges, all authored and committed by bors.
126-
let author = "bors";
127-
128140
let client = Client::builder().default_headers(headers()?).build()?;
129141
for page in 1.. {
130142
let url = CommitsUrl {
131143
page,
132-
author,
144+
author: BORS_AUTHOR,
133145
since: self.since_date,
134146
sha: self.most_recent_sha,
135147
}
@@ -138,21 +150,17 @@ impl CommitsQuery<'_> {
138150
let response: Response = client.get(&url).send()?;
139151

140152
let action = parse_paged_elems(response, |elem: GithubCommitElem| {
141-
let date = elem.date()?;
142-
let sha = elem.sha.clone();
143-
let summary = elem.commit.message;
144-
let commit = Commit { sha, date, summary };
145-
commits.push(commit);
146-
147-
Ok(if elem.sha == self.earliest_sha {
153+
let found_last = elem.sha == self.earliest_sha;
154+
if found_last {
148155
eprintln!(
149156
"ending github query because we found starting sha: {}",
150157
elem.sha
151158
);
152-
Loop::Break
153-
} else {
154-
Loop::Next
155-
})
159+
}
160+
let commit = elem.git_commit()?;
161+
commits.push(commit);
162+
163+
Ok(if found_last { Loop::Break } else { Loop::Next })
156164
})?;
157165

158166
if let Loop::Break = action {
@@ -254,9 +262,15 @@ mod tests {
254262
#[test]
255263
fn test_github() {
256264
let c = get_commit("25674202bb7415e0c0ecd07856749cfb7f591be6").unwrap();
265+
let committer = Author {
266+
name: String::from("bors"),
267+
email: String::from("[email protected]"),
268+
date: GitDate::from_ymd_opt(2022, 5, 4).unwrap(),
269+
};
257270
let expected_c = Commit { sha: "25674202bb7415e0c0ecd07856749cfb7f591be6".to_string(),
258271
date: parse_to_naive_date("2022-05-04").unwrap(),
259-
summary: "Auto merge of #96695 - JohnTitor:rollup-oo4fc1h, r=JohnTitor\n\nRollup of 6 pull requests\n\nSuccessful merges:\n\n - #96597 (openbsd: unbreak build on native platform)\n - #96662 (Fix typo in lint levels doc)\n - #96668 (Fix flaky rustdoc-ui test because it did not replace time result)\n - #96679 (Quick fix for #96223.)\n - #96684 (Update `ProjectionElem::Downcast` documentation)\n - #96686 (Add some TAIT-related tests)\n\nFailed merges:\n\nr? `@ghost`\n`@rustbot` modify labels: rollup".to_string()
272+
summary: "Auto merge of #96695 - JohnTitor:rollup-oo4fc1h, r=JohnTitor\n\nRollup of 6 pull requests\n\nSuccessful merges:\n\n - #96597 (openbsd: unbreak build on native platform)\n - #96662 (Fix typo in lint levels doc)\n - #96668 (Fix flaky rustdoc-ui test because it did not replace time result)\n - #96679 (Quick fix for #96223.)\n - #96684 (Update `ProjectionElem::Downcast` documentation)\n - #96686 (Add some TAIT-related tests)\n\nFailed merges:\n\nr? `@ghost`\n`@rustbot` modify labels: rollup".to_string(),
273+
committer,
260274
};
261275
assert_eq!(c, expected_c)
262276
}

Diff for: src/main.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,21 @@ use crate::toolchains::{
3636
ToolchainSpec, NIGHTLY_SERVER, YYYY_MM_DD,
3737
};
3838

39+
const BORS_AUTHOR: &str = "bors";
40+
3941
#[derive(Debug, Clone, PartialEq)]
4042
pub struct Commit {
4143
pub sha: String,
4244
pub date: GitDate,
4345
pub summary: String,
46+
pub committer: Author,
47+
}
48+
49+
#[derive(Debug, Clone, PartialEq)]
50+
pub struct Author {
51+
pub name: String,
52+
pub email: String,
53+
pub date: GitDate,
4454
}
4555

4656
/// The first commit which build artifacts are made available through the CI for
@@ -1086,10 +1096,25 @@ impl Config {
10861096

10871097
fn bisect_ci_via(&self, start_sha: &str, end_ref: &str) -> anyhow::Result<BisectionResult> {
10881098
let access = self.args.access.repo();
1089-
let end_sha = access.commit(end_ref)?.sha;
1090-
let commits = access.commits(start_sha, &end_sha)?;
1099+
let start = access.commit(start_sha)?;
1100+
let end = access.commit(end_ref)?;
1101+
let assert_by_bors = |c: &Commit| -> anyhow::Result<()> {
1102+
if c.committer.name != BORS_AUTHOR {
1103+
bail!(
1104+
"Expected author {} to be {BORS_AUTHOR} for {}.\n \
1105+
Make sure specified commits are on the master branch \
1106+
and refer to a bors merge commit!",
1107+
c.committer.name,
1108+
c.sha
1109+
);
1110+
}
1111+
Ok(())
1112+
};
1113+
assert_by_bors(&start)?;
1114+
assert_by_bors(&end)?;
1115+
let commits = access.commits(start_sha, &end.sha)?;
10911116

1092-
assert_eq!(commits.last().expect("at least one commit").sha, end_sha);
1117+
assert_eq!(commits.last().expect("at least one commit").sha, end.sha);
10931118

10941119
commits.iter().zip(commits.iter().skip(1)).all(|(a, b)| {
10951120
let sorted_by_date = a.date <= b.date;
@@ -1111,7 +1136,7 @@ impl Config {
11111136
)
11121137
}
11131138

1114-
self.bisect_ci_in_commits(start_sha, &end_sha, commits)
1139+
self.bisect_ci_in_commits(start_sha, &end.sha, commits)
11151140
}
11161141

11171142
fn bisect_ci_in_commits(

0 commit comments

Comments
 (0)