-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add error handling, general refinement to --skip-invitation
flag
#1006
Changes from 27 commits
9ce116f
2763058
7f3bd6d
07cf29b
3cfe13e
81368d6
93f2918
4a7aa73
ccec1ea
f015a2f
36c83ba
0c220ef
c939758
cfca6c6
ec80960
40dd323
018e348
48d433d
9dfd63e
7e92a61
73538a2
e4238bc
8f8c4d4
fc0ae94
1d91a17
55af699
5ba7b60
7d55454
bf2c4eb
9a971d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
- Add additional error handling to `reclaim-mannequin` process | ||
- Removed ability to use `gh gei` to migrate from ADO -> GH. You must use `gh ado2gh` to do this now. This was long since obsolete, but was still available via hidden args - which have now been removed. | ||
- Add `bbs2gh inventory-report` command to write data available for migrations in CSV form |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,61 +3,61 @@ namespace OctoshiftCLI.Services | |
{ | ||
public class ConfirmationService | ||
{ | ||
# region Variables | ||
|
||
private readonly Action<string> _writeToConsoleOut; | ||
private readonly Action<string, ConsoleColor> _writeToConsoleOut; | ||
private readonly Func<ConsoleKey> _readConsoleKey; | ||
private readonly Action<int> _cancelCommand; | ||
|
||
#endregion | ||
|
||
#region Constructors | ||
public ConfirmationService() | ||
{ | ||
_writeToConsoleOut = msg => Console.WriteLine(msg); | ||
_writeToConsoleOut = (msg, outputColor) => | ||
{ | ||
Console.ForegroundColor = outputColor; | ||
Console.WriteLine(msg); | ||
}; | ||
_readConsoleKey = ReadKey; | ||
_cancelCommand = code => Environment.Exit(code); | ||
} | ||
|
||
// Constructor designed to allow for testing console methods | ||
public ConfirmationService(Action<string> writeToConsoleOut, Func<ConsoleKey> readConsoleKey) | ||
public ConfirmationService(Action<string, ConsoleColor> writeToConsoleOut, Func<ConsoleKey> readConsoleKey, Action<int> cancelCommand) | ||
{ | ||
_writeToConsoleOut = writeToConsoleOut; | ||
_readConsoleKey = readConsoleKey; | ||
_cancelCommand = cancelCommand; | ||
} | ||
|
||
#endregion | ||
|
||
#region Functions | ||
public bool AskForConfirmation(string confirmationPrompt, string cancellationErrorMessage = "") | ||
public virtual bool AskForConfirmation(string confirmationPrompt, string cancellationErrorMessage = "") | ||
{ | ||
ConsoleKey response; | ||
do | ||
{ | ||
_writeToConsoleOut(confirmationPrompt); | ||
_writeToConsoleOut(confirmationPrompt, ConsoleColor.Yellow); | ||
Console.ForegroundColor = ConsoleColor.White; | ||
response = _readConsoleKey(); | ||
if (response != ConsoleKey.Enter) | ||
{ | ||
_writeToConsoleOut(""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this to write a blank line to the output? If so, perhaps we also want to have _writeToConsoleOut = (msg = "", outputColor = ConsoleColor.White) => This way, for empty (white) lines, we can simply do: _writeToConsoleOut(); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the other default value comment... I think it would be a great once this is implemented though! "This doesn't seem to be a c# feature (yet): https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/lambda-method-group-defaults#relevant-background Unless we want to use preview but I don't think it's worth using an unsupported feature." |
||
_writeToConsoleOut("", ConsoleColor.White); | ||
} | ||
|
||
} while (response is not ConsoleKey.Y and not ConsoleKey.N); | ||
|
||
if (response == ConsoleKey.Y) | ||
{ | ||
_writeToConsoleOut("Confirmation Recorded. Proceeding..."); | ||
_writeToConsoleOut("Confirmation Recorded. Proceeding...", ConsoleColor.White); | ||
return true; | ||
} | ||
else | ||
{ | ||
_writeToConsoleOut("Canceling Command..."); | ||
throw new OctoshiftCliException($"Command Cancelled. {cancellationErrorMessage}"); | ||
_writeToConsoleOut($"Command Cancelled. {cancellationErrorMessage}", ConsoleColor.White); | ||
_cancelCommand(0); | ||
} | ||
return false; | ||
} | ||
|
||
private ConsoleKey ReadKey() | ||
{ | ||
return Console.ReadKey(false).Key; | ||
} | ||
#endregion | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,6 +104,48 @@ public virtual async Task RemoveTeamMember(string org, string teamSlug, string m | |
await _retryPolicy.Retry(() => _client.DeleteAsync(url)); | ||
} | ||
|
||
public virtual async Task<string> GetLoginName() | ||
{ | ||
var url = $"{_apiUrl}/graphql"; | ||
|
||
var payload = new | ||
{ | ||
query = "query{viewer{login}}" | ||
}; | ||
|
||
try | ||
{ | ||
return await _retryPolicy.Retry(async () => | ||
{ | ||
var data = await _client.PostGraphQLAsync(url, payload); | ||
|
||
return (string)data["data"]["viewer"]["login"]; | ||
}); | ||
} | ||
catch (Exception ex) | ||
{ | ||
throw new OctoshiftCliException($"Failed to lookup the login for current user", ex); | ||
} | ||
Comment on lines
+125
to
+128
Check notice Code scanning / CodeQL Generic catch clause
Generic catch clause.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with this CodeQL warning, here. What does a failure look like? Would there be a permission error, for example? Keep in mind that GraphQL will return a 200 on failures related to the response, so we'll want to inspect the GraphQL We're using Additionally, another thing we should be careful of is reporting the correct exceptions to the user. With this block, every exception will turn into a generic It's probably better to handle most expected cases, like permissions errors being raised via GraphQL and some network-related errors, then go ahead and let the edge cases slip through as unhandled exceptions (in this scope). Then we'll get all the weird stuff displayed in the console and in the logs, even if they aren't following the happiest path of exception handling 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @synthead The OctoshiftCliException is set up so that we can pass the exception ("ex") as an This is the pattern used on a few other functions within this class. If we want to get more specific with errors here, should this and other functions be cleaned up as part of a separate PR? 🤷♀️ As for "what does a failure" look like here; honestly, I don't think there really will be anything outside of a network error; I set up the catch to be cautious. Since we're just getting the user's login and that is associated with the PAT they are using, I don't think we should run into a permissions issue or anything else particularly funky. |
||
} | ||
|
||
public virtual async Task<string> GetOrgMembershipForUser(string org, string member) | ||
{ | ||
var url = $"{_apiUrl}/orgs/{org}/memberships/{member}"; | ||
|
||
try | ||
{ | ||
var response = await _client.GetAsync(url); | ||
|
||
var data = JObject.Parse(response); | ||
|
||
return (string)data["role"]; | ||
} | ||
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound) // Not a member | ||
{ | ||
return null; | ||
} | ||
} | ||
|
||
public virtual async Task<bool> DoesRepoExist(string org, string repo) | ||
{ | ||
var url = $"{_apiUrl}/repos/{org.EscapeDataString()}/{repo.EscapeDataString()}"; | ||
|
@@ -729,7 +771,7 @@ ... on User { | |
return data.ToObject<CreateAttributionInvitationResult>(); | ||
} | ||
|
||
public virtual async Task<ReattributeMannequinToUserResult> ReclaimMannequinsSkipInvitation(string orgId, string mannequinId, string targetUserId) | ||
public virtual async Task<ReattributeMannequinToUserResult> ReclaimMannequinSkipInvitation(string orgId, string mannequinId, string targetUserId) | ||
{ | ||
var url = $"{_apiUrl}/graphql"; | ||
var mutation = "mutation($orgId: ID!,$sourceId: ID!,$targetId: ID!)"; | ||
|
@@ -758,10 +800,18 @@ ... on User { | |
variables = new { orgId, sourceId = mannequinId, targetId = targetUserId } | ||
}; | ||
|
||
var response = await _client.PostAsync(url, payload); | ||
var data = JObject.Parse(response); | ||
|
||
return data.ToObject<ReattributeMannequinToUserResult>(); | ||
try | ||
{ | ||
return await _retryPolicy.Retry(async () => | ||
{ | ||
var data = await _client.PostGraphQLAsync(url, payload); | ||
return data.ToObject<ReattributeMannequinToUserResult>(); | ||
}); | ||
} | ||
catch (OctoshiftCliException ex) when (ex.Message.Contains("Field 'reattributeMannequinToUser' doesn't exist on type 'Mutation'")) | ||
{ | ||
throw new OctoshiftCliException($"Reclaiming mannequins with the--skip - invitation flag is not enabled for your GitHub organization.For more details, contact GitHub Support.", ex); | ||
} | ||
} | ||
|
||
public virtual async Task<IEnumerable<GithubSecretScanningAlert>> GetSecretScanningAlertsForRepository(string org, string repo) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we made
outputColor
default toConsoleColor.White
? That way, we only need to specify a color if we want to use something other than the default (impliedConsoleColor.White
).Something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be a c# feature (yet): https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/lambda-method-group-defaults#relevant-background
Unless we want to use
preview
but I don't think it's worth using an unsupported feature.