glacier.rs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //! Allows team members to directly create a glacier PR with the code provided.
  2. use crate::{
  3. config::GlacierConfig,
  4. github::Event,
  5. handlers::{Context, Handler},
  6. };
  7. use futures::future::{BoxFuture, FutureExt};
  8. use parser::command::glacier::GlacierCommand;
  9. use parser::command::{Command, Input};
  10. use octocrab::params::repos::Reference;
  11. use octocrab::models::Object;
  12. pub(super) struct GlacierHandler;
  13. impl Handler for GlacierHandler {
  14. type Input = GlacierCommand;
  15. type Config = GlacierConfig;
  16. fn parse_input(
  17. &self,
  18. ctx: &Context,
  19. event: &Event,
  20. _: Option<&GlacierConfig>,
  21. ) -> Result<Option<Self::Input>, String> {
  22. let body = if let Some(b) = event.comment_body() {
  23. b
  24. } else {
  25. // not interested in other events
  26. return Ok(None);
  27. };
  28. let mut input = Input::new(&body, &ctx.username);
  29. match input.parse_command() {
  30. Command::Glacier(Ok(command)) => Ok(Some(command)),
  31. Command::Glacier(Err(err)) => {
  32. return Err(format!(
  33. "Parsing glacier command in [comment]({}) failed: {}",
  34. event.html_url().expect("has html url"),
  35. err
  36. ));
  37. }
  38. _ => Ok(None),
  39. }
  40. }
  41. fn handle_input<'a>(
  42. &self,
  43. ctx: &'a Context,
  44. _config: &'a GlacierConfig,
  45. event: &'a Event,
  46. cmd: GlacierCommand,
  47. ) -> BoxFuture<'a, anyhow::Result<()>> {
  48. handle_input(ctx, event, cmd).boxed()
  49. }
  50. }
  51. async fn handle_input(ctx: &Context, event: &Event, cmd: GlacierCommand) -> anyhow::Result<()> {
  52. let is_team_member = event.user().is_team_member(&ctx.github).await.unwrap_or(false);
  53. if !is_team_member {
  54. return Ok(())
  55. };
  56. let response = ctx.github.raw().get(&cmd.source).send().await?;
  57. let body = response.text().await?;
  58. let number = event.issue().unwrap().number;
  59. let user = event.user();
  60. let octocrab = &ctx.octocrab;
  61. let fork = octocrab.repos("rustbot", "glacier");
  62. let base = octocrab.repos("rust-lang", "glacier");
  63. let master = base.get_ref(&Reference::Branch("master".to_string())).await?.object;
  64. let master = if let Object::Commit { sha, ..} = master {
  65. sha
  66. } else {
  67. log::error!("invalid commit sha - master {:?}", master);
  68. unreachable!()
  69. };
  70. fork.create_ref(&Reference::Branch(format!("triagebot-ice-{}", number)), master).await?;
  71. fork.create_file(format!("ices/{}.rs", number), format!("Add ICE reproduction for issue #{}.", number), body)
  72. .branch(format!("triagebot-ice-{}", number))
  73. .send()
  74. .await?;
  75. octocrab.pulls("rust-lang", "glacier")
  76. .create(format!("ICE - {}", number), format!("rustbot:triagebot-ice-{}", number), "master")
  77. .body(format!("Automatically created by @{} in issue #{}", user.login, number),)
  78. .send()
  79. .await?;
  80. Ok(())
  81. }