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
Diagnose command: Add GitHub OAuth token expiration date information #11688
Conversation
cabf237
to
4121c50
Compare
I like the approach to show additional information of the personal access token if available and gave these changes a try, then played with some more changes of my preference which I'd like to share. As passing the header value as-is into the users terminal is a no-go in my book, parsing the expiration date is mandatory. This allows to normalize the timezone to UTC which has the benefit to hide some details of the token and furthermore, present it more informative: The screenshot shows a fine-grained access token which expires in 27 minutes. The text is lowercase and the outer parenthesis has been removed, to make it more plain and when there are no colors it allows to keep the focus on the OK of the message.
Next to fine-grained personal access tokens, there are classic ones and then Github's REST API has the scopes in the response headers (
This allows to show the scopes of a classic token, which allows a user to reflect usage with the expiration as a by-catch for running
Or if a classic token has scopes, the number of scopes show up:
Per my current implementation, relative times are relative to the timestamp of the composer diagnose command ( For the expiration display I started with the following:
This has grown quite a bit, but I could not find a good middle-ground, e.g. a more safe handling of the header value already requires to parse it for the date and time data, therefore it requires testing, then setting up a unit test etc. and then you find yourself experimenting already with the output format. I need to run a couple more tests and can then push my branch so that there is some code to see, the implementation is based on the changes here, but instead of asking for a header in the response object, it describes the whole response object in a seam (which was put under test). |
I like the idea of displaying a relative time. Perhaps we can show the absolute timestamp when increased verbosity is requested ( For another project where I show a relative time, I calculate how many months, weeks, days, hours, minutes (in turn) and display the first one which rounds to more than one (ie, 1.5 or above), then it would display that number with its word. I only display one unit (so only "3 hours" and not "3 hours and 15 minutes"). Eg, 100 days --> 3 months; 50 days --> 2 months; 40 days --> 6 weeks; 37 days --> 5 weeks; 50 hours --> 2 days; 32.5 hours --> 32 hours. I wonder if this approach would be suitable here. I wonder what the benefit of extra precision would be for end users. See also the suggestion above about showing the real timestamp with "verbose." I think omitting/hiding the expiration time (when the number of days remaining is very large) seems confusing. It may lead people to believe that the token does not expire, rather than suggesting they may like to check back in (for example) a month if the token expires in "5 weeks." (Yes, it wouldn't say "never expires" and would effectively be the same as without this feature / the current behaviour.) I was going to enquire about what this looks like when the token has already expired, but I've tested this locally now. I'm including a screen-shot of this so others can see that this case is already handled outside of the scope of this pull request.
|
Thank you @fredden and @ktomk for the excellent feedback!
I will push with these two changes taken care of. However, I can't say I'm 100% in with the idea of relative times, and would still prefer to show the exact timestamp after validating it:
|
Sounds like good improvements to me overall. I have not read all the details sorry too many walls of text here, but I'll let you two hash it out and trust a good solution will come out of it :D |
4121c50
to
9571e9a
Compare
Thank you @Seldaek. I updated the PR with some of the suggestions above (which indeed went pretty extensively I agree :) ). The summary of changes are that:
Thank you. |
Thanks a lot @fredden and @Ayesh, you mentioned the Law of Triviality, and rightly so, this is
Headers:
Rule of thumb: If there is the scopes header, it's a classic token. More notes and references are buried in the commit message and code (tests are the docs). That just for the moment. And @fredden, you can find a second interval style active based on your feedback if you're interested (feel free to use my repo for commenting, even prolonging), thanks for the inspiration and feedback also for both of you. Token types / Composer support tableInformation only, there is no need to inspect the actual token. This is just note-taking for the patterns I've seen to document the work:
More: GitHub's token formats |
9571e9a
to
46dd29a
Compare
Thank you @ktomk - your experiment work looks quite extensive and thorough! Because this PR was added to the 2.7 milestone, do you think you could open a new PR with the token-info improvements? I'm sure GitLab also has something similar on your end that we could incorporate. I look forward to your new PR, and kindly @-mention me when you do so. |
@Ayesh I like your thinking, however for only the token-info improvements, it should be a three/five/seven liner. Don't get blinded by the experiment that ships with some bulk (first implementation that is). Let me scratch it, it is basically this part: $scopeHeader = $this->getHeader(self::GH_OAUTH_SCOPES_HEADER);
if (null !== $scopeHeader) {
$numberOfScopes = count(Preg::split('~,[ \x09]*~', $scopeHeader, 128, PREG_SPLIT_NO_EMPTY));
if (0 === $numberOfScopes) {
$buffer = 'classic (no scopes) ';
} else {
$buffer = sprintf('classic (%d scope%s) ', $numberOfScopes, 1 === $numberOfScopes ? '' : 's');
}
} With the tiny detail that |
And for the relative time: I like it, but that one has the most complexity and while I have now played and tested with it, this must not ship right now. It's always good to leave something for the next iteration. |
Thanks again for your comments and the code review. I still would like to keep this particular PR quite minimal, and also to not display the scope information. The way composer uses GitHub API, I don't think the scope information matters all that much, and the reason why I wanted to submit this PR is because it's been about a year since GH added fine-grained, so there are actual PATs that are expiring these days. I didn't want to deal with the |
Let me just comment this: If you see
I can understand your reasoning, from where I come from is that this added code should be silent as it's otherwise throwing while it adds additional information (it's not the main part of this diagnose check). For this implementation it could be done by switching to The problem with unintended exceptions is that this brings the composer invocation down. That means, it will degrade non-interactive use. As you commented earlier: "Given that composer diagnose is likely called on systems that do not function properly, ...". If you say you don't want to put the token info in, I'd say it's a bit sad, but it's ok to do that as expiration is the feature. Potentially throwing code for expiration info we would otherwise silently drop, not ok as this renders the safe-guard the parsing is here moot. It still requires formatting of the parsed value or otherwise escaping of the header value. |
d748c32
to
bcbb7e0
Compare
Fair, what @ktomk mentioned about not breaking workflows with date formats and new potential exceptions. I really try not to use |
Hey @Ayesh sorry this kinda got lost.. but would you say it's ready now? If so I'll try to review it tomorrow. |
GitHub's new fine-grained tokens have a cumpulsory expiration date, and their classic tokens also support an expiration date. https://github.blog/changelog/2021-07-26-expiration-options-for-personal-access-tokens/ This improves the `composer diagnose` command to display the expiration date and time if it is provided by the response headers (via `GitHub-Authentication-Token-Expiration`). The `DateTime::createFromFormat` call is used to validate the expected date format. It accounts for all the possible issued with the datetime extension by catching `\Throwable` exceptions. This can be fine-tuned in the future by narrowing the catched scopes to `\ValueError`, or the new granualar [exceptions in PHP >= 8.3](https://php.watch/versions/8.3/datetime-exceptions)
bcbb7e0
to
cd2d68f
Compare
Hi @Seldaek - thank you for coming back to this. The PR is ready :) I also rebased it from the current |
… not need to marry a date format here
Thanks! |
GitHub's new fine-grained tokens have a cumpulsory expiration date, and their classic tokens also support an expiration date.
https://github.blog/changelog/2021-07-26-expiration-options-for-personal-access-tokens/
This improves the
composer diagnose
command to display the expiration date and time if it is provided by the response headers (viaGitHub-Authentication-Token-Expiration
).