Agents move along on private repositories too
The lifecycle, acceptance checks, reviews and the files a pull request changes all read the repository as the pull request's author. Authors are stored without their memberships, so on a private repository the repository looked missing and nothing moved: no review, no revision, no checks, no overlaps. They now read it as the author with membership of the repository's workspace.
4 files+29−60/4 viewed
| 110 | 110 | }; | |
| 111 | 111 | ||
| 112 | 112 | // The author can read both the repository and the pull request's source. | |
| 113 | − | let viewer = Some(pull.author.clone()); | |
| 113 | + | let viewer = self.author_viewer(&pull).await?; | |
| 114 | 114 | let repo: Outcome<Repo> = g1t_kit::call( | |
| 115 | 115 | &self.repos, | |
| 116 | 116 | "get_by_id", |
| 116 | 116 | .await | |
| 117 | 117 | } | |
| 118 | 118 | ||
| 119 | + | /// A pull request's author as a viewer who can read its repository and | |
| 120 | + | /// source. Stored authors carry no memberships, so a private repository | |
| 121 | + | /// would otherwise look missing to them. | |
| 122 | + | pub(crate) async fn author_viewer(&self, pull: &Pull) -> Result<Viewer> { | |
| 123 | + | let path: Option<RepoPath> = g1t_kit::call( | |
| 124 | + | &self.repos, | |
| 125 | + | "path_by_id", | |
| 126 | + | &g1t_contracts::repos::PathByIdArgs { id: pull.repo_id.clone() }, | |
| 127 | + | ) | |
| 128 | + | .await?; | |
| 129 | + | let mut author = pull.author.clone(); | |
| 130 | + | if let Some(path) = path | |
| 131 | + | && !author.is_member(&path.namespace.to_lowercase()) | |
| 132 | + | { | |
| 133 | + | author.workspaces.push(g1t_contracts::Membership { | |
| 134 | + | slug: path.namespace.to_lowercase(), | |
| 135 | + | role: g1t_contracts::Role::Member, | |
| 136 | + | }); | |
| 137 | + | } | |
| 138 | + | Ok(Some(author)) | |
| 139 | + | } | |
| 140 | + | ||
| 119 | 141 | /// Publishes an event caused by `actor`, or by g1t itself. | |
| 120 | 142 | async fn publish_as<T: Serialize>( | |
| 121 | 143 | &self, |
| 739 | 739 | if pull.status != PullStatus::Open { | |
| 740 | 740 | return Ok(Advance::None); | |
| 741 | 741 | } | |
| 742 | − | // Its author can read both the repository and the fork. | |
| 743 | − | let viewer: Viewer = Some(pull.author.clone()); | |
| 742 | + | // As a member: a private repository would look missing otherwise, | |
| 743 | + | // and the pull request would never move. | |
| 744 | + | let viewer: Viewer = self.author_viewer(&pull).await?; | |
| 744 | 745 | let repo: Outcome<Repo> = g1t_kit::call( | |
| 745 | 746 | &self.repos, | |
| 746 | 747 | "get_by_id", | |
| 1052 | 1053 | "get_by_id", | |
| 1053 | 1054 | &GetByIdArgs { | |
| 1054 | 1055 | id: pull.repo_id.clone(), | |
| 1055 | − | viewer: Some(pull.author.clone()), | |
| 1056 | + | viewer: self.author_viewer(&pull).await?, | |
| 1056 | 1057 | }, | |
| 1057 | 1058 | ) | |
| 1058 | 1059 | .await?; |
| 63 | 63 | /// every one of them each time. | |
| 64 | 64 | pub(crate) async fn refresh_files(&self, pull: &Pull) -> Result<Vec<ChangedFile>> { | |
| 65 | 65 | // Its author can read both the repository and the pull request's source. | |
| 66 | − | let viewer = Some(pull.author.clone()); | |
| 66 | + | let viewer = self.author_viewer(pull).await?; | |
| 67 | 67 | let compared: Outcome<Comparison> = | |
| 68 | 68 | g1t_kit::call(&self.repos, "compare", &pull.comparison(&viewer)).await?; | |
| 69 | 69 | let files: Vec<ChangedFile> = match compared { | |
| 180 | 180 | "A pull request can be reviewed once it is ready for review.", | |
| 181 | 181 | )); | |
| 182 | 182 | } | |
| 183 | − | let viewer = Some(pull.author.clone()); | |
| 183 | + | let viewer = self.author_viewer(&pull).await?; | |
| 184 | 184 | let repo: Outcome<Repo> = g1t_kit::call( | |
| 185 | 185 | &self.repos, | |
| 186 | 186 | "get_by_id", |