11use std:: time:: Duration ;
22
3- use crate :: { api_client:: CodSpeedAPIClient , config:: CodSpeedConfig , prelude:: * } ;
3+ use crate :: api_client:: { CodSpeedAPIClient , GetRepositoryVars } ;
4+ use crate :: cli:: run:: helpers:: { find_repository_root, parse_repository_from_remote, ParsedRepository } ;
5+ use crate :: config:: CodSpeedConfig ;
6+ use crate :: prelude:: * ;
47use clap:: { Args , Subcommand } ;
58use console:: style;
9+ use git2:: Repository ;
610use tokio:: time:: { Instant , sleep} ;
711
12+ use super :: status:: { check_mark, cross_mark} ;
13+
814#[ derive( Debug , Args ) ]
915pub struct AuthArgs {
1016 #[ command( subcommand) ]
@@ -15,6 +21,8 @@ pub struct AuthArgs {
1521enum AuthCommands {
1622 /// Login to CodSpeed
1723 Login ,
24+ /// Show the authentication status
25+ Status ,
1826}
1927
2028pub async fn run (
@@ -24,6 +32,7 @@ pub async fn run(
2432) -> Result < ( ) > {
2533 match args. command {
2634 AuthCommands :: Login => login ( api_client, config_name) . await ?,
35+ AuthCommands :: Status => status ( api_client) . await ?,
2736 }
2837 Ok ( ( ) )
2938}
@@ -80,3 +89,86 @@ async fn login(api_client: &CodSpeedAPIClient, config_name: Option<&str>) -> Res
8089
8190 Ok ( ( ) )
8291}
92+
93+ /// Detect the repository from the git remote of the current directory
94+ fn detect_repository ( ) -> Option < ParsedRepository > {
95+ let current_dir = std:: env:: current_dir ( ) . ok ( ) ?;
96+ let root_path = find_repository_root ( & current_dir) ?;
97+ let git_repository = Repository :: open ( & root_path) . ok ( ) ?;
98+ let remote = git_repository. find_remote ( "origin" ) . ok ( ) ?;
99+ let url = remote. url ( ) ?;
100+ parse_repository_from_remote ( url) . ok ( )
101+ }
102+
103+ fn provider_label ( provider : & crate :: run_environment:: RepositoryProvider ) -> & ' static str {
104+ match provider {
105+ crate :: run_environment:: RepositoryProvider :: GitHub => "GitHub" ,
106+ crate :: run_environment:: RepositoryProvider :: GitLab => "GitLab" ,
107+ crate :: run_environment:: RepositoryProvider :: Project => "Project" ,
108+ }
109+ }
110+
111+ pub async fn status ( api_client : & CodSpeedAPIClient ) -> Result < ( ) > {
112+ let config = CodSpeedConfig :: load_with_override ( None , None ) ?;
113+ let has_token = config. auth . token . is_some ( ) ;
114+ let detected_repo = detect_repository ( ) ;
115+
116+ // 1. Check token validity
117+ let token_valid = has_token && api_client. is_token_valid ( ) . await ;
118+
119+ info ! ( "{}" , style( "Authentication" ) . bold( ) ) ;
120+ if token_valid {
121+ info ! ( " {} Logged in" , check_mark( ) ) ;
122+ } else if has_token {
123+ info ! (
124+ " {} Token expired (run {} to re-authenticate)" ,
125+ cross_mark( ) ,
126+ style( "codspeed auth login" ) . cyan( )
127+ ) ;
128+ } else {
129+ info ! (
130+ " {} Not logged in (run {} to authenticate)" ,
131+ cross_mark( ) ,
132+ style( "codspeed auth login" ) . cyan( )
133+ ) ;
134+ }
135+ info ! ( "" ) ;
136+
137+ // 2. If token is valid and we detected a repo, check repository existence
138+ info ! ( "{}" , style( "Repository" ) . bold( ) ) ;
139+ match detected_repo {
140+ Some ( parsed) => {
141+ let label = provider_label ( & parsed. provider ) ;
142+ if token_valid {
143+ let repo_exists = api_client
144+ . get_repository ( GetRepositoryVars {
145+ owner : parsed. owner . clone ( ) ,
146+ name : parsed. name . clone ( ) ,
147+ provider : parsed. provider . clone ( ) ,
148+ } )
149+ . await
150+ . ok ( )
151+ . flatten ( )
152+ . is_some ( ) ;
153+ if repo_exists {
154+ info ! ( " {} {}/{} ({})" , check_mark( ) , parsed. owner, parsed. name, label) ;
155+ } else {
156+ info ! (
157+ " {} {}/{} ({}, not found on CodSpeed)" ,
158+ cross_mark( ) ,
159+ parsed. owner,
160+ parsed. name,
161+ label
162+ ) ;
163+ }
164+ } else {
165+ info ! ( " {}/{} ({})" , parsed. owner, parsed. name, label) ;
166+ }
167+ }
168+ None => {
169+ info ! ( " Not inside a git repository" ) ;
170+ }
171+ }
172+
173+ Ok ( ( ) )
174+ }
0 commit comments