Summary: Ref T11034. Try to produce a roughly-one-sentence summary instead of a roughly-one-paragraph summary for the browse dialog.
Test Plan:
- Added unit tests, ran unit tests.
- Wrote a longer summary for a project, browsed to it, saw a shorter summary.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11034
Differential Revision: https://secure.phabricator.com/D16892
Summary: This code should go inside the field-locking loop. Otherwise, it only applies to the last field, and fatals if there are no fields.
Test Plan: Carefuller inspection.
Reviewers: chad
Reviewed By: chad
Subscribers: 20after4
Differential Revision: https://secure.phabricator.com/D16889
Summary:
Certain unusual queries, like `[-]`, could tokenize into a list which included the empty string.
This would then convert into a query for `... LIKE "%"` which just joins the entire table.
Instead: tokenize smarter; never return the empty token; add some test cases.
Test Plan: Ran unit tests. Queried for `[[blah blah]]`, saw a reasonable query come out the other end.
Reviewers: chad
Reviewed By: chad
Subscribers: 20after4
Differential Revision: https://secure.phabricator.com/D16888
Summary:
Ref T11887. This isn't a great fix but makes the method behave properly until I get around to a real fix.
In the longer term, I want to convert all of this pluggable Harbormaster/Drydock stuff (blueprints, artifacts, build plans) to use EditEngine + EditField instead of the weird mishmash of older/custom stuff it currently uses. However, this is a more involved project to execute and I'd like to be in that area of the codebase first so it gets adequate testing.
Until that happens, just put a reasonble-ish mechanism in place to let artifacts correct inbound types. This is the only artifact type and only parameter which needs casting.
Test Plan:
- Made a `curl` call to `harbormaster.createartifact` to create a URI artifact with `?...&ui.external=1`.
- Before patch: type error on `ui.external` not being a boolean.
- After patch: artifact created successfully.
Reviewers: chad
Reviewed By: chad
Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam
Maniphest Tasks: T11887
Differential Revision: https://secure.phabricator.com/D16887
Summary:
Ref T8510. Use "\n" as a delimiter between name sections. Specifically, project "AAA" with tag "zzz" should be a better match for query "AAA" than project "AAA BBB" is.
Make use of this delimiter slighlty more obvious in the UI.
Test Plan:
- Created projects "Phacility" and "Phacility Core Access".
- Typed "Phacility".
- Before patch: first hit is "Phacility Core Access".
- After patch: first hit is "Phacility".
- Viewed debugging output table, saw visual explanation of behavior.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T8510
Differential Revision: https://secure.phabricator.com/D16886
Summary:
Fixes T11785. Lightbox calls `JX.Stratcom.pass()` to let other handlers react, but should not. At least today, we never put, e.g., links inside a lightbox.
This code appears in the original commit so it was probably just copy/pasted from somewhere and I missed it in review.
(Or there's some edge case I'm not thinking of and we'll figure it out soon enough.)
Additionally, blacklist `/file/data/` from Quicksand naviagtion: Quicksand should never fetch these URIs.
Test Plan:
- Disabled `security.alternate-file-domain`.
- Enabled Quicksand ("Persistent Chat").
- Clicked an image thumbnail on a task.
- Repeated that until things flipped out a bit.
- After the patch: no issues.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11785
Differential Revision: https://secure.phabricator.com/D16884
Summary: Visually, I think these are much cleaner (with colors), and provide more workspace. I also don't really use the sidenav here and if I did, it would be to go back to the project homepage. I think this is overall better. If navigation page to project home is difficult or hard to find, we can maybe make a better header / crumbs bar to reduce that.
Test Plan: New project -> basic new board. Existing project -> color board. Desktop, Mobile, Fullscreen
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Differential Revision: https://secure.phabricator.com/D16882
Summary: Ref T11816. This could be a little cleaner, but we currently have two copies of the logic. Get them using the same code. Once that's actually working I can go make the code a little prettier.
Test Plan: Viewed Calendar month view tooltips, saw the same values as subheaders.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16880
Summary:
Ref T11816.
- Host gets weird behavior around defaulting to the viewer.
- Invitees get weird behavior around defaulting to the viewer.
- "All Day" is just sort of weird since start / end date aren't customizable.
- Recurring/Frequency are weird here and don't make much sense.
I can't immediately come up with reasons that any of these are particularly useful/valuable to default. More of them can be made editable after T10222 gets sorted out.
Test Plan: Edited edit engine custom forms for Calendar events, saw a more sensible list of customizable fields (e.g., policy stuff).
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16878
Summary: Uh, non-all-day-events said 1:30 - 2:29 PM, which is real silly.
Test Plan: Looked at a non-all-day-event.
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16874
Summary: Adds a headerimage and lets you set it on posts for added reverence. Is that a word?
Test Plan:
Add an image, see an image.
{F1923010}
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Differential Revision: https://secure.phabricator.com/D16873
Summary:
Fixes T11809. Ref
- Explicitly document the summary icon hints -- I don't think these are too hard to figure out (and maybe this stuff should just go in the tooltips) but we can start here.
- Use color + shape to distinguish between "cancelled" and "declined", not just color (for users with vision accessibility issues).
- Translate a "minute(s)" string into sensible English.
- Use RSVP status on the month view green circle thing.
Test Plan:
- Read docs.
- Looked at month view.
- Read reminder mail.
- Viewed month view mobile view.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16872
Summary:
Ref T11816. Since the dashboard got updated, Differential now interprets "Responsible Users: epriestley" to mean "epriestley, or any project or package epriestley is part of". You can query for just "epriestley" with "exact(epriestley)".
Give Calendar invites the same behavior: "epriestley" means "any event epriestley is invited to, or a project they are a member of is invited to". Individual invites can be queried with "exact(epriestley)".
This is a little bit copy-pastey but I want to wait for a third use case to clean it up since I think I'm going to have to do a bunch of generalization around "how does an individual PHID get turned into a bunch of PHIDs".
Test Plan: Queried for "Invited: dog", "invited: viewer", "invited; exact(dog)", etc.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16870
Summary: No view engine yet (adding header image next), but adds subtitle to display like PhameBlog
Test Plan: Add a subtitle, remove a subtitle.
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Differential Revision: https://secure.phabricator.com/D16871
Summary:
Ref T11816. Projects can be invited to an event, but the UI is currently fairly agnostic about them.
Instead, introduce the idea of "RSVPs", which are basically invites for you as an individual or for any group you're a part of. When we go to check if you're invited, we check for you individually first, then check for any groups you belong to if you haven't already accepted/declined.
On the calendar detail page:
- Show the quick "Join" / "Decline" buttons if any project you're a member of is invited.
- If you're invited, highlight any projects which you're a member of to make that more clear.
On other calendar views:
- If you're invited as part of a project, show the "multiple users" icon.
- If it's just you, continue showing the "add one user" icon.
Test Plan: Viewed month view, day view, detail view. Invited groups and individuals. Invited "Dog Project", accepted invite as user "Dog".
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16868
Summary:
Ref T11816. This logic was correct, we just did all the work and then mostly threw away the results. This worked correctly anyway in some timezones.
Instead, actually use `$min_date` and `$max_date`.
Test Plan: In "America/Toronto" with server in a more-western timezone, viewed a "Nov 11 - Nov 12" all-day event, saw those dates.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16867
Summary: Fixes T11867. This should really be on the `CredentialType` itself, but just punt that for now until the API endpoint gets updated. We'll need the actual code here anyway in some form.
Test Plan: {F1922728}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11867
Differential Revision: https://secure.phabricator.com/D16864
Summary: Fixes T11868. This is silly and does not make sense.
Test Plan: Edited a Phurl URL, verified mail only went to me, not to the object itself.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11868
Differential Revision: https://secure.phabricator.com/D16863
Summary:
Ref T9304. This adds a "GuidanceEngine" which can generate "Guidance".
In practice, this lets third-party code (rSERVICES) remove and replace instructions in the UI, which is basically only usefulf or us to tell users to go read the documentation in the Phacility cluster.
The next diff tailors the help on the "Auth Providers" and "Create New User" pages to say "PHACILITY PHACILITY PHACILITY PHACILITY".
Test Plan: Browed to "Auth Providers" and "Create New User" on instanced and non-instanced installs, saw appropriate guidance.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T9304
Differential Revision: https://secure.phabricator.com/D16861
Summary: Fixes T11866. This got converted wrong when doing the `/source/` stuff.
Test Plan: Browsed the root directory of a Subversion repository in Diffusion.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11866
Differential Revision: https://secure.phabricator.com/D16860
Summary: See D16851 - there's now a difference in their meaning, so don't unite them in the UI.
Test Plan: Load manage page of repos
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin
Differential Revision: https://secure.phabricator.com/D16858
Summary:
Fixes T11818. We don't discard output, so once we read more than 2GB of output we'll exceed the maximum size of a string in an internal buffer.
Instead, configure the future so output is discarded.
Test Plan: Added logging to `libphutil/`, saw internal buffer grow steadily before this change and stay constant at 0 after this change.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11818
Differential Revision: https://secure.phabricator.com/D16855
Summary: Fixes T4245. When a repository has a short name, use `/source/shortname/` as its primary URI.
Test Plan:
- Cloned Git repositories from shortnames via HTTP and SSH.
- Cloned Mercurial repositories from shortnames via HTTP and SSH.
- Cloned Subversion repositories from shortnames via SSH.
- Browsed Git, Mercurial and Subversion repositories.
- Added and removed short names to various repositories.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4245
Differential Revision: https://secure.phabricator.com/D16851
Summary: Ref T11816. This got dropped somewhere along the way, so the mobile month view no longer showed a green-colored hint if a day has events you're invited to.
Test Plan: Viewed Calendar month view on mobile, saw green circles for days with invited events.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16852
Summary: Depends on D16847. Ref T11044. This updates the remaining storage-related workflows from the CLI to accommodate multiple masters.
Test Plan:
- Configured multiple masters.
- Ran all `bin/storage` workflows.
- Ran `arc unit --everything`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11044
Differential Revision: https://secure.phabricator.com/D16848
Summary:
Depends on D16115. Ref T11044. In the brave new world of multiple masters, we need to check the schemata on each master when looking for missing storage patches, keys, schema changes, etc.
This realigns all the "check out what's up with that schema" calls to work for multiple hosts, and updates the web UI to include a "Server" column and allow you to browse per-server.
This doesn't update `bin/storage`, so it breaks things on its own (and unit tests probably won't pass). I'll update that in the next change.
Test Plan: Configured local environment in cluster mode with multiple masters, saw both hosts' status reported in web UI.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11044
Differential Revision: https://secure.phabricator.com/D16847
Summary:
Ref T11044. This moves toward partitioned application databases:
- You can define multiple masters.
- Convert all the easily-convertible code to become multi-master aware.
This doesn't convert most of `bin/storage` or "Config > Database (Stuff)" yet, as both are quite involved. They still work for now, but only operate on the first master instead of all masters.
Test Plan: Configured multiple masters, browsed around, ran `bin/storage` commands, ran `bin/storage --host ...`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11044
Differential Revision: https://secure.phabricator.com/D16115
Summary: I moved and then un-moved this incorrectly in D16846.
Test Plan: Looked at the old code, which worked better.
Reviewers: jacksongabbard, chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16849
Summary:
Ref T11085. To recreate the issue:
- From the web UI, click "Edit Revision".
- Write something like this as your "Summary" (i.e., put another field marker, like "Test Plan:", into the summary):
> This is a test of the
> Test Plan: field to see
> if it works.
- Save changes.
Later, when the summary is amended into a commit message, the parser will see two "Test Plan:" fields and fail to parse the message.
Instead, prevent users from making this edit.
Test Plan: {F1917640}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11085
Differential Revision: https://secure.phabricator.com/D16846
Summary:
Ref T11853. My CSS change for the more enormous policy dialog was a little too broad, and affected the "You shall not pass!" dialog too.
Narrow the scope of the CSS rules.
Also add a missing "." that I caught.
Test Plan:
- Looked at policy exception dialogs.
- Looked at policy explanation dialogs.
- Looked at the end of that sentence.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11853
Differential Revision: https://secure.phabricator.com/D16841
Summary:
Fixes T11853. To set this up:
- Create "Project A".
- Join "Project A".
- Create a subproject, "Project A Subproject 1".
- This causes Project A to become a parent project.
- This moves you to be a member of "Project A Subproject 1" instead of "Project A" directly.
- Create another subproject, "Project A Subproject 2".
- Do not join this subproject.
- Set the second subproject's policy to "Visible To: Members of Project A".
- Try to edit the second subproject.
Before this change, this fails:
- When querying projects, we sometime try to skip loading the viewer's membership in ancestor projects as a small optimization.
- Via `PhabricatorExtendedPolicyInterface`, we may then return the parent project to the policy filter for extended checks.
- The PolicyFilter has an optimization: if we're checking an object, and we already have that object, we can just use the object we already have. This is common and useful.
- However, in this case it causes us to reuse an incomplete object (an object without proper membership information). We fail a policy check which we should pass.
Instead, don't skip loading the viewer's membership in ancestor projects.
Test Plan:
- Did all that stuff above.
- Could edit the subproject.
- Ran `arc unit --everything`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11853
Differential Revision: https://secure.phabricator.com/D16840
Summary: Fixes T11839. Both are missing a parameter and one is a copy/paste slop.
Test Plan:
{F1913812}
{F1913813}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11839
Differential Revision: https://secure.phabricator.com/D16837
Summary:
Ref T8510. When users type "platypus" into a typeahead, they want "Platypus Playground" to be a higher-ranked match than "AAA Platypus", even though the latter is alphabetically first.
Specifically, the rule is: results which match the query as a prefix of the result text should rank above results which do not.
I believe we now always get this right on the client side. However, WMF has at least one case (described in T8510) where we do not get it right on the server side, and thus the user sees the wrong result.
The remaining issue is that if "platypus" matches more than 100 results, the result "Platypus Playground" may not appear in the result set at all, beacuse there are 100 copies of "AAA Platypus 1", "AAA Platypus 2", etc., first. So even though the client will apply the correct sort, it doesn't have the result the user wants and can't show it to them.
To fix this, split the server-side query into two phases:
- In the first phase, the "prefix" phase, we find results that **start with** "platypus".
- In the second phase, the "content" phase, we find results that contain "platypus" anywhere.
We skip the "prefix" phase if the user has not typed a query (for example, in the browse view).
Test Plan:
This is a lot of stuff, but the new ranking here puts projects which start with "w" at the top of the list. Lower down the list, you can see some projects which contain "w" but do not appear at the top (like "Serious Work").
{F1913931}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T8510
Differential Revision: https://secure.phabricator.com/D16838
Summary:
fixes T11792.
There's no good reason any more to have this option, so just drop it.
Test Plan: Load a file, toggle remaining "blame" button. Load search results page and an image too, which are serviced by the same controller.
Reviewers: chad, #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: Korvin
Maniphest Tasks: T11792
Differential Revision: https://secure.phabricator.com/D16833
Summary:
This has been replaced by `PolicyCodex` after D16830. Also:
- Rebuild Celerity map to fix grumpy unit test.
- Fix one issue on the policy exception workflow to accommodate the new code.
Test Plan:
- `arc unit --everything`
- Viewed policy explanations.
- Viewed policy errors.
Reviewers: chad
Reviewed By: chad
Subscribers: hach-que, PHID-OPKG-gm6ozazyms6q6i22gyam
Differential Revision: https://secure.phabricator.com/D16831
Summary:
Fixes T11836. See some prior discussion in T8376#120613.
The policy hint in headers in the UI is not exhaustive, and can not reasonably be exhaustive. For example, on a revision, it may say "All Users", but really mean "All users who can see the space this object is in and the repository it belongs to, plus the revision author and reviewers".
These rules are explained if you click (and, often, in the documentation), but "All Users" is still at least somewhat misleading.
I don't think there's any perfect solution here that balances the needs of both new and experienced users perfectly, but this change tries to do a bit better about avoiding cases where we say something very open (like "All Users") when the real policy is not very open.
Specifically, I've made these changes to the header:
- Spaces are now listed in the tag, so it will say `(S3 > All Users)` instead of `(All Users)`. They're already listed in the header, this just makes it more explicit that Spaces are a policy container and part of the view policy.
- Extended policy objects are now listed in the tag, so it will say `(S3 > rARC > All Users)` for a revision in the Arcanist repository which is also in Space 3.
- Objects can now provide a "Policy Codex", which is an object that represents a rulebook of more sophisticated policy descriptions. This codex can replace the tag with something else.
- Imported calendar events now say "Uses Import Policy" instead of, e.g., "All Users".
I've made these changes to the policy dialog:
- Split it into more visually separate sections.
- Added an explicit section for extended policies ("You must also have access to these other objects: ...").
- Broken the object policy rules into a "Special Rules" section (for rules like "you can only see a revision if you can see the repository it is part of") and an "Object Policy" section (for the actual object policy).
- Tried to make it a little more readable?
- The new policy dialogs are great to curl up with in front of a fire with a nice cup of cocoa.
I've made these changes to infrastructure:
- Implementing `PhabricatorPolicyInterface` no longer requires you to implement `describeAutomaticCapability()`.
- Instead, implement `PhabricatorPolicyCodexInterface` and return a `PhabricatorPolicyCodex` object.
- This "codex" is a policy rulebook which can set all the policy icons, labels, colors, rules, etc., to properly explain complex policies.
- Broadly, the old method was usually either not useful (most objects have no special rules) or not powerful enough (objects with special rules often need to do more in order to explain them).
Test Plan:
{F1912860}
{F1912861}
{F1912862}
{F1912863}
Reviewers: chad
Reviewed By: chad
Subscribers: avivey
Maniphest Tasks: T11836
Differential Revision: https://secure.phabricator.com/D16830
Summary: Redesign the action comment box for better use in two column, mobile, nuance.
Test Plan: Test in mobile / desktop / tablet, adding and removing actions. Actionless comment boxes, etc.
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: cspeckmim, Korvin
Differential Revision: https://secure.phabricator.com/D16811
Summary: Fixes T11834. Actually adding the step wasn't in the `if (...)` block. Also, typo fix.
Test Plan: Saw only one "Explore" on `/guides/`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11834
Differential Revision: https://secure.phabricator.com/D16828
Summary: Ref T5267. I missed these in the variable types conversion.
Test Plan: `arc unit --everything`
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T5267
Differential Revision: https://secure.phabricator.com/D16824
Summary:
Ref T5267. When extrating data from `pht()` calls, also extract the argument types and export them into the map so they can be used by consumers.
We recognize plurals (`phutil_count()`, `new PhutilNumber`) and genders (`phutil_person()`). We'll need to annotate the codebase for those, since they're currently runtime-only.
Test Plan:
Rebuilt extraction maps, got data like this (note "number" type annotation).
```
"Scaling pool \"%s\" up to %s daemon(s).": {
"uses": [
{
"file": "/daemon/PhutilDaemonOverseer.php",
"line": 378
}
],
"types": [
null,
"number"
]
},
```
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T5267
Differential Revision: https://secure.phabricator.com/D16823
Summary:
Ref T7643. When you do something like this:
- Edit a task description.
- Click "Show Details" on the resulting transaction.
- Get a prose diff dialog showing the change.
...now add some "Old" and "New" tabs. These are useful for:
- reverting to the old text by copy/pasting;
- reading just the new/old text if the diff is noisy;
- sometimes just nice to have?
(This looks a little rough but I didn't want to put a negative margin on tab groups inside dialogs? Not sure what the best fix here is.)
Test Plan: {F1909390}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T7643
Differential Revision: https://secure.phabricator.com/D16817
Summary:
Ref T11809. I missed this when adding a "Busy" status.
Also the other dot is orange? Just make them all orange for consistency.
Test Plan: Viewed `@username` of busy users (orange), away users (red).
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16819
Summary: Ref T7643. When we send mail about a change to a package description, allow it to say "CHANGES TO PACKAGE DESCRIPTION" instead of "EDIT DETAILS". Smooth!
Test Plan: {F1909417}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T7643
Differential Revision: https://secure.phabricator.com/D16818
Summary:
Ref T11801. These are pretty fiddly because users expect to see the end time for timed events ("10 AM - 11 AM" is ONE hour long) but not for all-day events ("Nov 2 - Nov 3" is TWO days long!)
We also want to store the thing the user actually entered so we don't lose data if they un-all-day the event later.
This may take a little more fiddling since it feels a little shaky, but I couldn't break this version immediately.
Test Plan: Imported a French holiday, got proper display in the UI.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11801
Differential Revision: https://secure.phabricator.com/D16815
Summary:
Ref T11801. This makes testing/debugging a little easier.
Also fix some inconsistencies with `importAuthorPHID` handling -- it should be the import's author PHID in all cases, so we update imported events properly.
Test Plan: Imported a French holiday with `bin/calendar reload ...`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11801
Differential Revision: https://secure.phabricator.com/D16814
Summary:
Ref T5267. Although translations with very few strings are already put into a "Limited Translations" group, this isn't necessarily clear and was empirically confusing to at least one user, who was surprised that selecting "Spanish" had no UI effect.
Instead, hide limited and test translations entirely unless the install is in developer mode.
Test Plan: In a non-developer-mode install, viewed translations menu. No longer saw translations with very few strings.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T5267
Differential Revision: https://secure.phabricator.com/D16807
Summary:
Fixes T4788. This change:
- converts the "Task Graph" into a "Related Objects" tabgroup.
- makes "Task Graph" the first tab in the group.
- moves "Mocks" to become a tab.
- adds a new "Mentions" tab, which shows inbound and outbound mentions.
Primary goal of "mocks" is to give us room for a pinboard/thumbnail view after the next Pholio iteration. Might make sense to make it the default tab (if present) at that point, too, since mocks are probably more important than related tasks when they're present.
Primary goal of "mentions" is to provide a bit of general support for various freeform relationships between tasks: if you want to treat tasks as "siblings" or "related" or "following" or whatever, you can at least find them all in one place. I don't plan to formalize any of these weird one-off relationships in the upstream, although it's vaguely possible that some far-future update might just let you define arbitrary custom relationships and then you can do whatever you want.
Test Plan: {F1906974}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4788
Differential Revision: https://secure.phabricator.com/D16806
Summary: Ref T11801. When a file is larger than 512KB, queue it for background import instead of trying to do it in the foreground, sinc we risk hitting `max_execution_time`.
Test Plan: {F1906943}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11801
Differential Revision: https://secure.phabricator.com/D16805
Summary:
Ref T11801. This issue led to the stack trace in T11801#199042.
It wasn't obvious that this was wrong because the recover-on-duplicate-key code made it work correctly.
Test Plan: Imported an event with external attendees with no warnings in the log.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11801
Differential Revision: https://secure.phabricator.com/D16804
Summary: Ref T11816. We're running this code on empty events which haven't been initialized and don't have a source attached -- just use a more explanatory check which doesn't need anything attached.
Test Plan: Edited default Calendar policies.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16803
Summary:
Ref T11816.
- Now that we can do something meaningful with them, bring back the yellow dots for "busy".
- Default to "busy" when attending events (we could make this "busy" for short events and "away" for long events or something).
- Let users pick how to display their attending status on the event page.
- Also show which event the user is attending since I had to mess with the cache code anyway. We can get rid of this again if it doesn't feel good.
Test Plan:
{F1904179}
{F1904180}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16802
Summary: Ref T11816. Depends on D16800. Show warnings generated by ICS import in the UI.
Test Plan: {F1904122}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11816
Differential Revision: https://secure.phabricator.com/D16801
Summary:
When Phortune merchant accounts are created via mechanisms other than the web UI (for example, by Phacility unit tests) this validation check may fail.
Transactions are validated even if no transactions of the given type are being applied, to allow the editor to raise errors like "Name is required!".
If there's no TYPE_INVOICEEMAIL transaction, we'll get called with empty `$xactions` and fail on `strlen($new_email)` because the variable is never defined.
As a secondary issue, if contactInfo, invoiceEmail or invoiceFooter are not provided the record will fail to insert (none of these are nullable).
Test Plan: Ran Phacility unit tests, got a clean result for new instance creation.
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16798
Summary:
Fixes T11812.
- Pull the logic for building the "Create Whatever" dropdown out.
- Use it to generate NUX buttons, too.
- Use the new logic in Paste and Maniphest.
Test Plan:
- Viewed Paste NUX, button worked.
- Viewed Maniphest NUX with multiple create forms, button worked.
Reviewers: chad, avivey
Reviewed By: avivey
Subscribers: avivey
Maniphest Tasks: T11812
Differential Revision: https://secure.phabricator.com/D16797
Summary:
Ref T11809.
- Allow users to remove the "Until" date from recurring events.
- When removing "Until", show a sensible string ("...set this event to repeat forever.")
- When users go through the "Make Recurring" workflow, don't require them to explicitly select "Recurring: Recurring" from the dropdown. This intent is clear from clicking "Make Recurring".
- When editing "All Future Events", don't literally apply date changes to them, since that doesn't make sense. We update the template, then reschedule any events which haven't been edited already. I think this is what users probably mean if they make this edit.
- When creating an event with a non-default icon, don't show "alice changed the icon from Default to Party.".
- Hide the "recurring mode" transaction, which had no string ("alice edited this Event.") and was redundant anyway.
- Also, add a little piece of developer text to make hunting these things down easier.
Test Plan: Edited various events, parents, children, made events recur, set until, unset until, viewed transactions, rescheduled parents, rescheduled children.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16796
Summary:
Ref T11809. Roughly documents most of the tricky/unintuitive stuff.
Also fixes a bug with "Make Recurring" with no "Until" date.
Test Plan: Read document.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16792
Summary:
Ref T11809. Currently, commenting on a recurring event hits the same "one or all?" dialog that other edits do.
For comments and edits submitted via the comment widget, we can safely assume that you mean "just this one", since it doesn't really make sense to try to bulk-edit an event from that UI.
Test Plan: Commented on a recurring event parent and an event in the series.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16795
Summary: Ref T11809. This makes the mail more consistent with Differential and Maniphest, which only include additional details in the first mail in the thread.
Test Plan:
- Created an event with a description.
- First mail included it.
- Followups did not.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16794
Summary:
Ref T11809. We show a red dot next to a username to indicate that the user is away (on vacation, in a meeting, etc).
It's not very obvious what this means unless you know that's what it is: when you click the username or view a hovercard, there's no visual hint about what the red dot means. It does say "Away", but there is a lot of information and it doesn't visually connect the two.
Connect the two visually by putting a red dot next to the "Away" bit, too.
Test Plan:
Here's my version of it, this feels OK to me but could maybe be more designed:
{F1893916}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16791
Summary:
Ref T11809. As we move toward unprototyping, this panel is probably more relevant/dynamic/interesting more often than the badges panel, I think?
Particularly, I want to make the red dots a little easier to understand, and I think putting this above the fold will help aid discovery (red dot -> click -> see red dot -> see "away until ..." -> see calendar -> "oh they're at a meeting"?).
This is entirely a product/subjective thing so I'm fine with not doing it or using a different order.
I think there's maybe even an argument for putting this above "Projects", but "Projects" feels more core to me, at least for now.
Test Plan: Viewed a user profile, saw "Calendar" above "Badges".
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16790
Summary: Ref T11808. This variable is wrong, and would sometimes cause events to set themsevles as their own parents. They would then fail to load, and disrupt cursor paging.
Test Plan:
- Reproduced T11808 locally by reloading test data 2+ times, creating events with themselves as their own parents.
- Appplied fix.
- Nuked data, reloaded, no more self-parents.
- Test datafile: {F1894017}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11808
Differential Revision: https://secure.phabricator.com/D16793
Summary: Ref T11809. These have been replaced with more flexible storage that accommodates a wider range of behaviors, including those in the ICS format and RRULEs.
Test Plan:
- Ran migration.
- Viewed, created, edited events.
- Grepped for all removed names/symbols.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16789
Summary:
Ref T11809. This came out of Facebook many years ago for computing the number of business days that revisions had been stale.
We removed the little staleness marker a few months ago and haven't seen complaints about it.
If we did holidays now it would make sense to integrate them more directly with Calendar as real events, but I have no plans to pursue this anytime soon. It's easy enough to add the federal holidays manually (~5 minutes of work per year?) if you want them, and they're commentable/editable and you can add local holidays if you're not in the US.
Test Plan:
- Ran `bin/storage upgrade -f`.
- Grepped for `CalendarHoliday`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11809
Differential Revision: https://secure.phabricator.com/D16788
Summary:
Fixes T11808. I couldn't reproduce the issue there locally so I'm just cheating a little bit until a better reproduction case shows up.
We don't need to do a full load here anyway, and testing for any row is more efficient.
Test Plan: Poked around imports without issues, but couldn't reproduce this problem locally.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11808
Differential Revision: https://secure.phabricator.com/D16787
Summary:
Fixes T11805. Depends on D16785. This generally tries to smooth out transactions:
- All-day stuff now says "Nov 3" instead of "Nov 3 12:00:00 AM".
- Fewer weird bugs / extra transactions.
- No more silly extra "yeah, you definitely set that event time" transaction on create.
Test Plan: Edited events; changed from all-day to not-all-day and back again, viewed transaction log.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11805
Differential Revision: https://secure.phabricator.com/D16786
Summary: Ref T7931. This is still quite rough, but should technically send vaguely-useful email as part of the standard trigger infrastructure.
Test Plan: Ran `bin/phd start`, created an event shortly, saw reminder email send in `bin/mail list-outbound`.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T7931
Differential Revision: https://secure.phabricator.com/D16784
Summary:
Ref T7931. I'm going to do this separate from existing infrastructure because:
- events start at different times for different users;
- I like the idea of being able to batch stuff (send one email about several upcoming events);
- triggering on ghost/recurring events is a real complicated mess.
This puts a skeleton in place that finds all the events we need to notify about and writes some silly example bodies to stdout, marking that we notified users so they don't get notified again.
Test Plan:
Ran `bin/calendar notify`, got a "great" notification in the command output.
{F1891625}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T7931
Differential Revision: https://secure.phabricator.com/D16783
Summary:
Fixes T11804. This probably isn't perfect but seems to work fairly reasonably and not be as much of a weird nonsense mess like the old behavior was.
When a user edits a recurring event, we ask them what they're trying to do. Then we more or less do that.
Test Plan:
- Edited an event in the middle of a series.
- Edited the first event in a series.
- Edited "just this" and "all future" events in various places in a series.
- Edited normal events.
- Cancelled various events.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11804
Differential Revision: https://secure.phabricator.com/D16782
Summary:
Ref T11804. This one is messy because we have to fork the //next// event, possibly creating it first.
Then we can edit the parent normally.
Test Plan: Cancelled the first event in a series, only that one cancelled.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11804
Differential Revision: https://secure.phabricator.com/D16781
Summary:
When you edit "X and all future events", X becomes the new parent of an event series.
Currently, it loses its relationship to its original parent. Instead, retain that relationship -- it's separate from the normal "parent", but we can use it to make the UI more clear or tweak behaviors later.
This mostly just keeps us from losing/destroying data that we might need/want later.
Test Plan:
- Ran migrations.
- Cancelled "X and all future events", saw sensible-appearing beahvior in the database for "seriesParentPHID".
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16780
Summary: Ref T11804. The field now reads the correct value directly and we don't need this wrapper.
Test Plan: Poked around Calendar without explosions.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11804
Differential Revision: https://secure.phabricator.com/D16779
Summary:
Ref T11804. This puts us on a path toward some kind of reasonable behavior here.
Currently, cancelling recurring events makes approximately zero sense ever in any situation.
Instead, give users the choice to cancel just the instance, or all future events. This is similar to Calendar.app. (Google Calendar has a third option, "All Events", which I may implement).
When the user picks something, basically do that.
The particulars of "do that" are messy. We have to split the series into two different series, stop the first series early, then edit the second series. Then we need to update any concrete events that are now part of the second series.
This code will get less junk in the next couple of diffs (I hope?) since I need to make it apply to edits, too, but this was a little easier to get started with.
Test Plan:
Cancelled an instance of an event; cancelled "All future events".
Both of them more or less worked in a reasonble way.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11804
Differential Revision: https://secure.phabricator.com/D16778
Summary:
In ICS, an event on "Nov 1" starts on "2016-11-01" and ends on "2016-11-02".
This is convenient for computers, but this isn't what users expect to enter in date controls. They expect to enter "nov 1" to "Nov 1" for a one-day, all-day event. This is consistent with other applications.
Store the value the user entered, but treat it as the first second of the next day when actually using it if the event is an all day event.
Test Plan:
Mucked around with multi-day all-day events, recurring all-day events, imports, etc. Couldn't catch any weird/unintuitive stuff anymore offhand.
(Previously, entering "Nov 1" to "Nov 2" created a one-day event, which was unclear.
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16777
Summary:
This feels a little cleaner:
- Clean up transaction log a bit.
- Use a checkbox instead of a two-option dropdown.
This is a little messy because the browser doesn't send anything if the user submits a form with an un-clicked checkbox.
We now send a dummy value ("Hey, there's definitely a checkbox in this form!") so the server can figure out what to do.
Test Plan:
- Edited all-dayness of an event.
- Viewed transaction log.
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16776
Summary:
Ref T11326. If you scheudle a monthly event on the 31st, the default behavior of RRULE means that it only occurs in months with 31 days.
This is actually how Google Calendar and Calendar.app both work: if you schedule a monthly event on the 31st, you get about six events per year.
This seems real confusing and bad to me?
Instead, if the user schedules a monthly event on the 29th, 30th or 31st, pretend they scheduled it on the "last day of the month" or "second-to-last day of the month" or similar, so they always get 12 events per year.
This could be slightly confusing too, but seems way less weird than not getting an event every month.
Test Plan: Scheduled events on the 31st of October, saw them occur in November too after the patch.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11326
Differential Revision: https://secure.phabricator.com/D16775
Summary:
Ref T11326. Currently, the "Create Event" form is pretty wordy. One particular culprit is the "recurring" controls, which are (presumably) rarely used and visually complex.
- Reflow the default form to hopefully feel a little better.
- Move recurrence stuff to a separate workflow.
Test Plan:
{F1891355}
{F1891356}
{F1891357}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11326
Differential Revision: https://secure.phabricator.com/D16774
Summary:
This adds the ability for Phabricator's OAuth server implementation to use HTTP basic auth for the client ID and secret and brings it in line with the OAuth 2.0 specification in this respect.
Fixes T11794
Test Plan: Fixes my use case. Shouldn't impact other use-cases.
Reviewers: #blessed_reviewers, epriestley
Reviewed By: #blessed_reviewers, epriestley
Subscribers: 0, Korvin
Maniphest Tasks: T11794
Differential Revision: https://secure.phabricator.com/D16763
Summary:
Ref T10747. In the in-email ICS event card that Gmail shows, it has a "Who" field which reads "Unknown Organizer*" if the URI for the organizer isn't email-address-like.
Previously, we used a URI like `https://phabricator.install.com/p/username`, which I think is OK as far as RFC 5545 is concerned, but Gmail doesn't like it.
Instead, use `PHID-USER-asdfa@phabricator.install.com`, which doesn't go anywhere, but makes Gmail happy. Users don't normally see this URI anyway.
Test Plan:
Got a readable "Who" in Gmail when importing an event exported from Calendar:
{F1890571}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16772
Summary: Ref T10747. This turns on the newer EditEngine behavior so we get a nice "X created this event." transaction, instead of an "X renamed this from <nothing> to Event Name."
Test Plan: Imported an event, saw a nice timeline.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16771
Summary: Ref T10747. The transaction version of this copies the "all day" flag over properly, but this non-transaction version needs to copy it explicitly.
Test Plan: Imported an all-day event, saw it come in as all-day.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16770
Summary: Makes a more complete PDF looking invoice form for printing in Phortune.
Test Plan: Make an invoice, click print view, print.
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Differential Revision: https://secure.phabricator.com/D16762
Summary: Ref T10747. If stuff has been deleted on the other calendar, delete it on ours.
Test Plan:
Imported with deletion, saw deletions:
{F1889689}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16768
Summary:
Ref T10747.
- Adds import documentation.
- Adds import/export docs to the help menu.
- Removes some weird/old/out-of-date information from the general user guide, which I'll rewrite later.
Test Plan: Read documentation somewhat thoroughly.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16766
Summary:
This fixes the permissions issue with D16750, which is actually not really a permissions issue, exactly.
This is the only place anywhere that we use a tokenizer field //and// give it a default value which is not the same as the object value (when creating a merchant, we default it to the viewer).
In other cases (like Maniphest) we avoid this because you can edit the form to have defaults, which would collide with whatever default we provide. Some disucssion in T10222.
Since we aren't going to let you edit these forms for the forseeable future, this behavior is reasonable here though.
However, it triggered a sort-of-bug related to conflict detection for these fields (see T4768). These fields actually have two values: a hidden "initial" value, and a visible edited value.
When you submit the form, we compute your edit by comparing the edited value to the initial value, then applying adds/removes, instead of just saying "set value equal to new value". This prevents issues when two people edit at the same time and both make changes to the field.
In this case, the initial value was being set to the display value, so the field would say "Value: [(alincoln x)]" but internally have that as the intitial value, too. When you submitted, it would see "you didn't change anything", and thus not add any members.
So the viewer wouldn't actually be added as a member, then the policy check would correctly fail.
Note that there are still some policy issues here (you can remove yourself from a Merchant and lock yourself out) but they fall into the realm of stuff discussed in D16677.
Test Plan: Created a merchant account with D16750 applied.
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16764
Summary: This is more consistent with the icon we use for documentation elsewhere.
Test Plan: Looked at the icon, had an easier time guessing it meant "documentation".
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16765
Summary: Converts PhortuneMerchant to EditEngine.
Test Plan: Edits existing merchants fine, same issue as Conpherence when making new ones with permissions.
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Differential Revision: https://secure.phabricator.com/D16750
Summary: Is a logo. For merchants.
Test Plan: Set a new logo, remove it. See on list.
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Maniphest Tasks: T7607
Differential Revision: https://secure.phabricator.com/D16751
Summary:
Ref T10747. When we import a ".ics" file, represent any attendees as simple external references.
For consistency with other areas of the product, I've avoided disclosing email addresses. We'll try to get a real name if we can.
(We store addresses and could expose or use them later, or do some kind of masking junk like "epr...ley@g...l.com" which is utterly impossible to figure out.)
Test Plan: {F1888367}
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16759
Summary:
Ref T11326. Currently:
- The month view and day view (ghosts) don't show that you're invited to a child event.
- The detail view copies the invite list, including attending status, but only //after// it shows the page for the first time.
Instead, for now, just do this:
- Ghosts/stubs use the parent invite list, but treat everyone as "invited".
- Materializing a stub just saves the list as-is (i.e., invited, not a copy of attending/declined/etc).
This behavior may need some refining eventually but is at least reasonable (not obviously bad/buggy).
Test Plan:
- Viewed month/day views, now shown as "invited".
- Viewed detail view, now invitee list shows up properly.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11326
Differential Revision: https://secure.phabricator.com/D16758
Summary:
A live instance hit the scenario described in the comment, where an out-of-date user was being selected as the actor.
Since they were no longer an account member, they could not see the payment method and autopay was failing.
Instead, select a relatively arbitrary user who is a current, valid, non-disabled member.
Test Plan: Ran subscriptions with `bin/worker execute ...`, saw it select a valid actor.
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16757
Summary:
Fixes T11638.
- Fix a regression: I broke this "round to the nearest hour" code a while ago while fiddling with datetimes.
- Improve a beahvior: from the day view, make the menu-bar "Create Event" button default to creating an event on the day you were viewing.
Test Plan: Created events from month and day views, got nice round numbers and proper day suggestions.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11638
Differential Revision: https://secure.phabricator.com/D16754
Summary: Fixes T11733. This fixes the issue by working around it, but it isn't useful to set these fields to a default value anyway.
Test Plan: Created a default Calendar form, set some other defaults, created an event, stuff no longer exploded.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11733
Differential Revision: https://secure.phabricator.com/D16753
Summary:
Ref T10747. For URI-based (and, in the future, Google-based) imports, we can automatically refresh them periodically.
(In the general case there's no way to get a push notification for an ICS file, so we just have to do this every-so-often.)
Test Plan:
- Set an ICS file to update hourly.
- Used `bin/trigger fire --id ...` to fire it artificially.
- Saw Calendar update.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16752
Summary: Part of making this look/feel/be more professional is having decent receipts for billing, including contact information (whatever we want to put in there). I'm not using this anywhere at the moment, but will.
Test Plan: Add Contact Info, see Contact Info. Also, why is Remarkup not rendering with line breaks? Seems to be a OneOff thing... anywho... bears!
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Maniphest Tasks: T7607
Differential Revision: https://secure.phabricator.com/D14125
Summary:
Ref T10747. RRULE events can repeat "UNTIL" a certain time, or a certain "COUNT" of times.
In the UI, we only support "UNTIL". Also support "COUNT".
Test Plan: Imported an event which repeats every other day, 5 times. Got 5 instances.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16749
Summary: Ref T10747. This makes development/debugging/testing easier and moves us closer to triggered imports (e.g., keep in sync with Google once per day).
Test Plan:
- Reloaded an event import.
- Edited an event in Google Calendar, reloaded, got updated event.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10747
Differential Revision: https://secure.phabricator.com/D16747
Summary:
Ref T11469. This isn't directly related, but has been on my radar for a while: building SSH keyfiles (particular for installs with a lot of keys, like ours) can be fairly slow.
At least one cluster instance is making multiple clone requests per second. While that should probably be rate limited separately, caching this should mitigate the impact of these requests.
This is pretty straightforward to cache since it's exactly the same every time, and only changes when users modify SSH keys (which is rare).
Test Plan:
- Ran `bin/auth-ssh`, saw authfile generate.
- Ran it again, saw it read from cache.
- Changed an SSH key.
- Ran it again, saw it regenerate.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T11469
Differential Revision: https://secure.phabricator.com/D16744