Skip to content

Commit 86a08dc

Browse files
authored
feat: automatically use token from gh cli (#18)
1 parent bb00d9a commit 86a08dc

File tree

5 files changed

+76
-49
lines changed

5 files changed

+76
-49
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ nixpkgs-track <PULL_REQUEST>
4141
Where `PULL_REQUEST` is either the numerical ID or the GitHub URL of the pull request to track. For example, both `370713` and `https://github.com/NixOS/nixpkgs/pull/370713` are valid references to [github.com/NixOS/nixpkgs/pull/370713](https://togithub.com/NixOS/nixpkgs/pull/370713).
4242

4343
> [!TIP]
44-
> Depending on usage, you may need to provide a GitHub API token to avoid rate-limiting. This can be done with the `--token` option or `GITHUB_TOKEN` environment variable if necessary.
44+
> Depending on usage (tracking multiple/many pull requests within a span of a few minutes), you may need to provide a GitHub API token to avoid rate-limiting on unauthenticated requests. nixpkgs-track automatically detects the `gh` command-line tool and attempts to retrieve a GitHub token using `gh auth token` when available. Otherwise, a token can be provided via the `GITHUB_TOKEN` environment variable or the `--token` option.
4545
4646
nixpkgs-track also supports saving a list of pull requests to check in the future.
4747

crates/nixpkgs-track/src/auth.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use std::process::Command;
2+
3+
use crate::cli::Cli;
4+
5+
pub fn get_github_token(args: &Cli) -> Option<String> {
6+
args.token.clone().or_else(|| {
7+
Command::new("gh")
8+
.args(["auth", "token"])
9+
.output()
10+
.ok()
11+
.filter(|output| output.status.success())
12+
.and_then(|output| String::from_utf8(output.stdout).ok())
13+
.map(|s| s.trim().to_string())
14+
})
15+
}

crates/nixpkgs-track/src/cli.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use clap::{Parser, Subcommand};
2+
3+
use crate::utils::parse_pull_request_id;
4+
5+
#[derive(Parser)]
6+
#[command(version, about, subcommand_negates_reqs = true)]
7+
pub struct Cli {
8+
/// Numerical ID of the pull request to check (e.g. 1234) or a GitHub URL to a pull request (e.g. https://github.com/nixos/nixpkgs/pull/1234).
9+
#[clap(required(true), value_parser = parse_pull_request_id)]
10+
pub pull_request: Option<u64>,
11+
12+
#[command(subcommand)]
13+
pub command: Option<Commands>,
14+
15+
/// GitHub token
16+
#[clap(long, short, env = "GITHUB_TOKEN")]
17+
pub token: Option<String>,
18+
}
19+
20+
#[derive(Subcommand)]
21+
pub enum Commands {
22+
/// Add pull request(s) to track list
23+
Add {
24+
#[clap(required(true), value_parser = parse_pull_request_id)]
25+
pull_requests: Vec<u64>,
26+
},
27+
/// Remove pull request(s) from track list
28+
Remove {
29+
#[clap(required_unless_present("all"), value_parser = parse_pull_request_id)]
30+
pull_requests: Vec<u64>,
31+
32+
#[clap(long, conflicts_with = "pull_requests")]
33+
all: bool,
34+
35+
#[clap(short, long, exclusive = true)]
36+
interactive: bool,
37+
},
38+
/// List tracked pull requests
39+
List {
40+
#[clap(long)]
41+
json: bool,
42+
},
43+
/// Check tracked pull requests
44+
Check {},
45+
}

crates/nixpkgs-track/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
pub mod auth;
2+
pub mod cli;
13
pub mod utils;

crates/nixpkgs-track/src/main.rs

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::fmt::Write;
22
use std::fs;
33
use std::sync::Arc;
44

5-
use clap::{Parser, Subcommand};
65
use dialoguer::MultiSelect;
76
use miette::{Context, IntoDiagnostic};
87
use regex::Regex;
@@ -11,54 +10,18 @@ use serde::{Deserialize, Serialize};
1110
use chrono::Utc;
1211
use yansi::hyperlink::HyperlinkExt;
1312

14-
use nixpkgs_track::utils::{format_seconds_to_time_ago, parse_pull_request_id};
13+
use clap::Parser;
14+
15+
use nixpkgs_track::{
16+
auth::get_github_token,
17+
cli::{Cli, Commands},
18+
utils::format_seconds_to_time_ago,
19+
};
1520
use nixpkgs_track_lib::{branch_contains_commit, fetch_nixpkgs_pull_request, NixpkgsTrackError};
1621

1722
static ROLLING_BRANCHES: [&str; 6] = ["staging", "staging-next", "master", "nixpkgs-unstable", "nixos-unstable-small", "nixos-unstable"];
1823
static STABLE_BRANCHES_TEMPLATE: [&str; 6] = ["staging-XX.XX", "staging-next-XX.XX", "release-XX.XX", "nixpkgs-XX.XX-darwin", "nixos-XX.XX-small", "nixos-XX.XX"];
1924

20-
#[derive(Parser)]
21-
#[command(version, about, subcommand_negates_reqs = true)]
22-
struct Cli {
23-
/// Numerical ID of the pull request to check (e.g. 1234) or a GitHub URL to a pull request (e.g. https://github.com/nixos/nixpkgs/pull/1234).
24-
#[clap(required(true), value_parser = parse_pull_request_id)]
25-
pull_request: Option<u64>,
26-
27-
#[command(subcommand)]
28-
command: Option<Commands>,
29-
30-
/// GitHub token
31-
#[clap(long, short, env = "GITHUB_TOKEN")]
32-
token: Option<String>,
33-
}
34-
35-
#[derive(Subcommand)]
36-
enum Commands {
37-
/// Add pull request(s) to track list
38-
Add {
39-
#[clap(required(true), value_parser = parse_pull_request_id)]
40-
pull_requests: Vec<u64>,
41-
},
42-
/// Remove pull request(s) from track list
43-
Remove {
44-
#[clap(required_unless_present("all"), value_parser = parse_pull_request_id)]
45-
pull_requests: Vec<u64>,
46-
47-
#[clap(long, conflicts_with = "pull_requests")]
48-
all: bool,
49-
50-
#[clap(short, long, exclusive = true)]
51-
interactive: bool,
52-
},
53-
/// List tracked pull requests
54-
List {
55-
#[clap(long)]
56-
json: bool,
57-
},
58-
/// Check tracked pull requests
59-
Check {},
60-
}
61-
6225
async fn check(client: Arc<reqwest::Client>, pull_request: u64, token: Option<&str>) -> miette::Result<String, CheckError> {
6326
let mut output = String::new();
6427

@@ -186,6 +149,8 @@ async fn main() -> miette::Result<()> {
186149
Cache::new()
187150
};
188151

152+
let token = get_github_token(&args);
153+
189154
match args.command {
190155
Some(Commands::Add { pull_requests }) => {
191156
cache_data
@@ -196,7 +161,7 @@ async fn main() -> miette::Result<()> {
196161
}
197162
Some(Commands::Remove { pull_requests, all, interactive }) => {
198163
if interactive {
199-
let pull_requests = fetch_cached_pull_requests(&cache_data.pull_requests, args.token).await?;
164+
let pull_requests = fetch_cached_pull_requests(&cache_data.pull_requests, token).await?;
200165

201166
let selection = MultiSelect::new()
202167
.with_prompt("Select pull requests to remove")
@@ -230,7 +195,7 @@ async fn main() -> miette::Result<()> {
230195
}
231196
}
232197
Some(Commands::List { json }) => {
233-
let pull_requests = fetch_cached_pull_requests(&cache_data.pull_requests, args.token).await?;
198+
let pull_requests = fetch_cached_pull_requests(&cache_data.pull_requests, token).await?;
234199

235200
println!(
236201
"{}",
@@ -257,7 +222,7 @@ async fn main() -> miette::Result<()> {
257222

258223
for pull_request in cache_data.pull_requests.iter().copied() {
259224
let client = client.clone();
260-
let token = args.token.clone();
225+
let token = token.clone();
261226

262227
set.spawn(async move { check(client, pull_request, token.as_deref()).await });
263228
}
@@ -269,7 +234,7 @@ async fn main() -> miette::Result<()> {
269234
.collect();
270235
print!("{}", results?.join("\n"));
271236
}
272-
None => print!("{}", check(Arc::new(reqwest::Client::new()), args.pull_request.expect("is present"), args.token.as_deref()).await?),
237+
None => print!("{}", check(Arc::new(reqwest::Client::new()), args.pull_request.expect("is present"), token.as_deref()).await?),
273238
}
274239

275240
fs::write(

0 commit comments

Comments
 (0)