Job tokens that open issues and pull requests (A1)

16cf1ed · Gabriel Morell · 2026-10-22 20:53

54 files +690 -53
Message
{commit_body(@commit)}

Files changed

modified cli/README.md
+2 −0
@@ -56,6 +56,8 @@ gg ci dispatch WORKFLOW [--ref REF] [-f NAME=VALUE …] [--watch]
56 56
57 57 gg issues list [--state open|closed|all] [--search TEXT]
58 58 gg issue show N [--no-comments]
59 +gg issue create --title TEXT [--body TEXT | --body-file PATH] [--label LABEL …]
60 + open one; prints the number and URL
59 61 gg issue comment N --body TEXT (or --body-file PATH, or piped stdin)
60 62 gg issue close|reopen N
61 63
modified cli/src/api/mod.rs
+18 −0
@@ -353,6 +353,24 @@ impl Client {
353 353 .await
354 354 }
355 355
356 + pub async fn create_issue(
357 + &self,
358 + repo: &RepoRef,
359 + title: &str,
360 + body: Option<&str>,
361 + labels: &[String],
362 + ) -> Result<Res<IssueResponse>> {
363 + let mut payload = json!({ "title": title });
364 + if let Some(text) = body {
365 + payload["body"] = json!(text);
366 + }
367 + if !labels.is_empty() {
368 + payload["labels"] = json!(labels);
369 + }
370 + self.post(&["repos", &repo.owner, &repo.name, "issues"], Some(payload))
371 + .await
372 + }
373 +
356 374 pub async fn comment_on_issue(
357 375 &self,
358 376 repo: &RepoRef,
modified cli/src/api/models.rs
+5 −0
@@ -478,6 +478,11 @@ pub struct IssuesResponse {
478 478 pub issues: Vec<Issue>,
479 479 }
480 480
481 +#[derive(Debug, Clone, Deserialize)]
482 +pub struct IssueResponse {
483 + pub issue: Issue,
484 +}
485 +
481 486 #[derive(Debug, Clone, Deserialize)]
482 487 pub struct IssueDetailResponse {
483 488 pub issue: Issue,
modified cli/src/cli.rs
+16 −0
@@ -319,6 +319,22 @@ pub enum IssueCommand {
319 319 no_comments: bool,
320 320 },
321 321
322 + /// Open an issue. Prints its number and URL.
323 + Create {
324 + /// The issue's title.
325 + #[arg(long)]
326 + title: String,
327 +
328 + #[command(flatten)]
329 + body: OptionalBodyArgs,
330 +
331 + /// A label to apply, by name. Repeat for more; applied if you
332 + /// have triage access, and refused if the repository has no such
333 + /// label.
334 + #[arg(long = "label", value_name = "LABEL")]
335 + labels: Vec<String>,
336 + },
337 +
322 338 /// Add a comment.
323 339 Comment {
324 340 number: i64,
modified cli/src/commands/issue.rs
+30 −0
@@ -121,6 +121,36 @@ pub async fn run(ctx: &Ctx, command: &IssueCommand) -> Result<()> {
121 121 Ok(())
122 122 }
123 123
124 + IssueCommand::Create {
125 + title,
126 + body,
127 + labels,
128 + } => {
129 + let text = read_body(body.body.as_deref(), body.body_file.as_deref(), false)?;
130 + let res = ctx
131 + .api
132 + .create_issue(
133 + &repo,
134 + title,
135 + text.as_deref().map(str::trim).filter(|t| !t.is_empty()),
136 + labels,
137 + )
138 + .await?;
139 + if ctx.emitted(&res.raw)? {
140 + return Ok(());
141 + }
142 + println!(
143 + "Opened issue #{}: {}",
144 + res.issue.number,
145 + res.issue.title.as_deref().unwrap_or("(untitled)")
146 + );
147 + println!(
148 + "{}",
149 + ctx.repo_web_url(&repo, &format!("/issues/{}", res.issue.number))
150 + );
151 + Ok(())
152 + }
153 +
124 154 IssueCommand::Comment { number, body } => {
125 155 let text = read_body(body.body.as_deref(), body.body_file.as_deref(), true)?
126 156 .expect("required body");
modified docs/plans/dependency-security.md
+7 −3

Click to load diff…

modified lib/git_gud/accounts.ex
+46 −0

Click to load diff…

modified lib/git_gud/accounts/user.ex
+7 −0

Click to load diff…

modified lib/git_gud/federation/publishing.ex
+3 −0

Click to load diff…

modified lib/git_gud/issues.ex
+14 −5

Click to load diff…

modified lib/git_gud/issues/issue.ex
+2 −0

Click to load diff…

modified lib/git_gud/pull_requests.ex
+22 −6

Click to load diff…

modified lib/git_gud/pull_requests/pull_request.ex
+2 −0

Click to load diff…

modified lib/git_gud/workflows/permissions.ex
+18 −7

Click to load diff…

modified lib/git_gud_web/controllers/api/mobile/auth.ex
+48 −3

Click to load diff…

modified lib/git_gud_web/controllers/api/mobile/helpers.ex
+15 −0

Click to load diff…

modified lib/git_gud_web/controllers/api/mobile/issue_controller.ex
+67 −2

Click to load diff…

modified lib/git_gud_web/controllers/api/mobile/pull_request_controller.ex
+20 −7

Click to load diff…

modified lib/git_gud_web/live/issue_live/show.ex
+10 −1

Click to load diff…

modified lib/git_gud_web/live/pr_live/show.ex
+9 −0

Click to load diff…

modified lib/git_gud_web/router.ex
+1 −0

Click to load diff…

added priv/repo/migrations/20261022203804_add_bot_accounts_and_job_authorship.exs
+20 −0

Click to load diff…

modified test/git_gud/workflows/permissions_test.exs
+29 −19

Click to load diff…

added test/git_gud_web/controllers/api/mobile/mobile_job_token_test.exs
+279 −0

Click to load diff…

Parents: f821e9e