Skip to content

Commit 744d644

Browse files
Merge pull request #1702 from ehuss/docs-update-trigger
Add ability to trigger docs-update via Zulip
2 parents bb3950e + 5d7e473 commit 744d644

File tree

4 files changed

+197
-235
lines changed

4 files changed

+197
-235
lines changed

src/actions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ impl<'a> Action for Step<'a> {
112112
// These are unused for query.
113113
default_branch: "master".to_string(),
114114
fork: false,
115+
parent: None,
115116
};
116117

117118
for QueryMap { name, kind, query } in queries {

src/github.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ pub struct Repository {
987987
pub default_branch: String,
988988
#[serde(default)]
989989
pub fork: bool,
990+
pub parent: Option<Box<Repository>>,
990991
}
991992

992993
#[derive(Copy, Clone)]
@@ -1485,16 +1486,66 @@ impl Repository {
14851486
}
14861487

14871488
/// Synchronize a branch (in a forked repository) by pulling in its upstream contents.
1489+
///
1490+
/// **Warning**: This will to a force update if there are conflicts.
14881491
pub async fn merge_upstream(&self, client: &GithubClient, branch: &str) -> anyhow::Result<()> {
14891492
let url = format!("{}/merge-upstream", self.url());
1490-
client
1493+
let merge_error = match client
14911494
.send_req(client.post(&url).json(&serde_json::json!({
14921495
"branch": branch,
14931496
})))
14941497
.await
1498+
{
1499+
Ok(_) => return Ok(()),
1500+
Err(e) => {
1501+
if e.downcast_ref::<reqwest::Error>().map_or(false, |e| {
1502+
matches!(
1503+
e.status(),
1504+
Some(StatusCode::UNPROCESSABLE_ENTITY | StatusCode::CONFLICT)
1505+
)
1506+
}) {
1507+
e
1508+
} else {
1509+
return Err(e);
1510+
}
1511+
}
1512+
};
1513+
// 409 is a clear error that there is a merge conflict.
1514+
// However, I don't understand how/why 422 might happen. The docs don't really say.
1515+
// The gh cli falls back to trying to force a sync, so let's try that.
1516+
log::info!(
1517+
"{} failed to merge upstream branch {branch}, trying force sync: {merge_error:?}",
1518+
self.full_name
1519+
);
1520+
let parent = self.parent.as_ref().ok_or_else(|| {
1521+
anyhow::anyhow!(
1522+
"{} failed to merge upstream branch {branch}, \
1523+
force sync could not determine parent",
1524+
self.full_name
1525+
)
1526+
})?;
1527+
// Note: I'm not sure how to handle the case where the branch name
1528+
// differs to the upstream. For example, if I create a branch off
1529+
// master in my fork, somehow GitHub knows that my branch should push
1530+
// to upstream/master (not upstream/my-branch-name). I can't find a
1531+
// way to find that branch name. Perhaps GitHub assumes it is the
1532+
// default branch if there is no matching branch name?
1533+
let branch_ref = format!("heads/{branch}");
1534+
let latest_parent_commit = parent
1535+
.get_reference(client, &branch_ref)
1536+
.await
1537+
.with_context(|| {
1538+
format!(
1539+
"failed to get head branch {branch} when merging upstream to {}",
1540+
self.full_name
1541+
)
1542+
})?;
1543+
let sha = latest_parent_commit.object.sha;
1544+
self.update_reference(client, &branch_ref, &sha)
1545+
.await
14951546
.with_context(|| {
14961547
format!(
1497-
"{} failed to merge upstream branch {branch}",
1548+
"failed to force update {branch} to {sha} for {}",
14981549
self.full_name
14991550
)
15001551
})?;

src/handlers/docs_update.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! A scheduled job to post a PR to update the documentation on rust-lang/rust.
22
33
use crate::db::jobs::JobSchedule;
4-
use crate::github::{self, GitTreeEntry, GithubClient, Repository};
4+
use crate::github::{self, GitTreeEntry, GithubClient, Issue, Repository};
55
use anyhow::Context;
66
use anyhow::Result;
77
use cron::Schedule;
@@ -56,10 +56,13 @@ pub async fn handle_job() -> Result<()> {
5656
}
5757

5858
tracing::trace!("starting docs-update");
59-
docs_update().await.context("failed to process docs update")
59+
docs_update()
60+
.await
61+
.context("failed to process docs update")?;
62+
Ok(())
6063
}
6164

62-
async fn docs_update() -> Result<()> {
65+
pub async fn docs_update() -> Result<Option<Issue>> {
6366
let gh = GithubClient::new_with_default_token(Client::new());
6467
let work_repo = gh.repository(WORK_REPO).await?;
6568
work_repo
@@ -69,12 +72,11 @@ async fn docs_update() -> Result<()> {
6972
let updates = get_submodule_updates(&gh, &work_repo).await?;
7073
if updates.is_empty() {
7174
tracing::trace!("no updates this week?");
72-
return Ok(());
75+
return Ok(None);
7376
}
7477

7578
create_commit(&gh, &work_repo, &updates).await?;
76-
create_pr(&gh, &updates).await?;
77-
Ok(())
79+
Ok(Some(create_pr(&gh, &updates).await?))
7880
}
7981

8082
struct Update {
@@ -184,7 +186,7 @@ async fn create_commit(
184186
Ok(())
185187
}
186188

187-
async fn create_pr(gh: &GithubClient, updates: &[Update]) -> Result<()> {
189+
async fn create_pr(gh: &GithubClient, updates: &[Update]) -> Result<Issue> {
188190
let dest_repo = gh.repository(DEST_REPO).await?;
189191
let mut body = String::new();
190192
for update in updates {
@@ -197,5 +199,5 @@ async fn create_pr(gh: &GithubClient, updates: &[Update]) -> Result<()> {
197199
.new_pr(gh, TITLE, &head, &dest_repo.default_branch, &body)
198200
.await?;
199201
tracing::debug!("created PR {}", pr.html_url);
200-
Ok(())
202+
Ok(pr)
201203
}

0 commit comments

Comments
 (0)