1
+ use anyhow:: bail;
2
+
1
3
use crate :: {
2
4
github:: { Event , IssuesAction , IssuesEvent } ,
3
5
handlers:: Context ,
@@ -10,6 +12,10 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
10
12
return Ok ( ( ) ) ;
11
13
} ;
12
14
15
+ if !e. issue . is_pr ( ) {
16
+ return Ok ( ( ) ) ;
17
+ }
18
+
13
19
let repo = e. issue . repository ( ) ;
14
20
let prefix = match ( & * repo. organization , & * repo. repository ) {
15
21
( "rust-lang" , "rfcs" ) => "text/" ,
@@ -25,32 +31,69 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
25
31
}
26
32
27
33
async fn add_rendered_link ( ctx : & Context , e : & IssuesEvent , prefix : & str ) -> anyhow:: Result < ( ) > {
28
- if e. action == IssuesAction :: Opened {
34
+ if e. action == IssuesAction :: Opened
35
+ || e. action == IssuesAction :: Closed
36
+ || e. action == IssuesAction :: Reopened
37
+ {
29
38
let files = e. issue . files ( & ctx. github ) . await ?;
30
39
31
40
if let Some ( file) = files. iter ( ) . find ( |f| f. filename . starts_with ( prefix) ) {
32
- if !e. issue . body . contains ( "[Rendered]" ) {
33
- // This URL should be stable while the PR is open, even if the
34
- // user pushes new commits.
35
- //
36
- // It will go away if the user deletes their branch, or if
37
- // they reset it (such as if they created a PR from master).
38
- // That should usually only happen after the PR is closed.
39
- // During the closing process, the closer should update the
40
- // Rendered link to the new location (which we should
41
- // automate!).
42
- let head = e. issue . head . as_ref ( ) . unwrap ( ) ;
43
- let url = format ! (
44
- "https://github.com/{}/blob/{}/{}" ,
45
- head. repo. full_name, head. git_ref, file. filename
46
- ) ;
47
- e. issue
48
- . edit_body (
49
- & ctx. github ,
50
- & format ! ( "{}\n \n [Rendered]({})" , e. issue. body, url) ,
51
- )
52
- . await ?;
53
- }
41
+ let head = e. issue . head . as_ref ( ) . unwrap ( ) ;
42
+ let base = e. issue . base . as_ref ( ) . unwrap ( ) ;
43
+
44
+ // This URL should be stable while the PR is open, even if the
45
+ // user pushes new commits.
46
+ //
47
+ // It will go away if the user deletes their branch, or if
48
+ // they reset it (such as if they created a PR from master).
49
+ // That should usually only happen after the PR is closed
50
+ // a which point we switch to a SHA-based url.
51
+ //
52
+ // If the PR is merged we use a URL that points to the actual
53
+ // repository, as to be resilient to branch deletion, as well
54
+ // be in sync with current "master" branch.
55
+ //
56
+ // For a PR "octocat:master" <- "Bob:patch-1", we generate,
57
+ // - if merged: `https://github.com/octocat/REPO/blob/master/FILEPATH`
58
+ // - if open: `https://github.com/Bob/REPO/blob/patch-1/FILEPATH`
59
+ // - if closed: `https://github.com/octocat/REPO/blob/SHA/FILEPATH`
60
+ let rendered_link = format ! (
61
+ "[Rendered](https://github.com/{}/blob/{}/{})" ,
62
+ if e. issue. merged || e. action == IssuesAction :: Closed {
63
+ & e. repository. full_name
64
+ } else {
65
+ & head. repo. full_name
66
+ } ,
67
+ if e. issue. merged {
68
+ & base. git_ref
69
+ } else if e. action == IssuesAction :: Closed {
70
+ & head. sha
71
+ } else {
72
+ & head. git_ref
73
+ } ,
74
+ file. filename
75
+ ) ;
76
+
77
+ let new_body = if !e. issue . body . contains ( "[Rendered]" ) {
78
+ // add rendered link to the end of the body
79
+ format ! ( "{}\n \n {rendered_link}" , e. issue. body)
80
+ } else if let Some ( start_pos) = e. issue . body . find ( "[Rendered](" ) {
81
+ let Some ( end_offset) = & e. issue . body [ start_pos..] . find ( ')' ) else {
82
+ bail ! ( "no `)` after `[Rendered]` found" )
83
+ } ;
84
+
85
+ // replace the current rendered link with the new one
86
+ e. issue . body . replace (
87
+ & e. issue . body [ start_pos..=( start_pos + end_offset) ] ,
88
+ & rendered_link,
89
+ )
90
+ } else {
91
+ bail ! (
92
+ "found `[Rendered]` but not it's associated link, can't replace it, bailing out"
93
+ )
94
+ } ;
95
+
96
+ e. issue . edit_body ( & ctx. github , & new_body) . await ?;
54
97
}
55
98
}
56
99
0 commit comments