Skip to content
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

Loading unpacked extensions #1508

Merged
merged 9 commits into from
Jan 7, 2019
Merged

Loading unpacked extensions #1508

merged 9 commits into from
Jan 7, 2019

Conversation

lguychard
Copy link
Contributor

@lguychard lguychard commented Dec 19, 2018

closes #489

This PR adds the ability to load locally served Sourcegraph extensions. Review by commit.

The URL to an unpacked extension can be set using the debug palette:

image

In the browser extension, the unpacked extension url is stored in chrome.storage.local. This is done to avoid reading & fetching a URL from localStorage that may have been set by other scripts.

In the webapp, the value is read from localStorage.

By using localStorage/chrome.storage.local rather than settings, and only allowing one unpacked extension, we avoid usage of this feature to circumvent the "private extensions registry is a premium feature" restriction.

TODO:

  • styling
  • tests

@lguychard lguychard requested a review from sqs December 19, 2018 18:51
lguychard added a commit to sourcegraph/create-extension that referenced this pull request Dec 19, 2018
This exposes the package.json when running `yarn serve`, which allows [loading unpacked extensions](sourcegraph/sourcegraph#1508)
Copy link
Member

@sqs sqs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High-level idea lgtm. Haven’t reviewed code.

@lguychard lguychard changed the title WIP Loading unpacked extensions Loading unpacked extensions Jan 2, 2019
@codecov-io
Copy link

codecov-io commented Jan 2, 2019

Codecov Report

Merging #1508 into master will increase coverage by 0.02%.
The diff coverage is 87.5%.

Impacted Files Coverage Δ
shared/src/api/client/services.ts 100% <ø> (ø) ⬆️
shared/src/api/integration-test/testHelpers.ts 91.42% <100%> (ø) ⬆️
shared/src/api/client/services.test.ts 62.5% <100%> (ø) ⬆️
.../src/api/client/services/extensionsService.test.ts 88.23% <86.66%> (-2.68%) ⬇️
...hared/src/api/client/services/extensionsService.ts 69.73% <86.95%> (+4.73%) ⬆️

@lguychard
Copy link
Contributor Author

This is now ready for review

shared/src/api/client/services/extensionsService.test.ts Outdated Show resolved Hide resolved
)
),
cold('-a--|', { a: '' }),
() => of(null)
).activeExtensions
)
).toBe('-a-b-|', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there an expected break in time? (the - between a and b)

Copy link
Member

@sqs sqs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High-level looks great. I added several comments about docs, impl, etc.

Also, you should add docs to doc/extensions/authoring/publishing.md about this new sideloading feature. Here is what I would recommend (feel free to add/change, just wanted to help out): documentation diff with TODOs. (One other awesome thing about this new feature is that it lets us remove a lot of complexity around the WIP extension creation/publishing process.)

shared/src/platform/context.ts Outdated Show resolved Hide resolved
shared/src/extensions/controller.ts Outdated Show resolved Hide resolved
shared/src/extensions/ExtensionStatus.tsx Outdated Show resolved Hide resolved
type="text"
id="extension-status__unpackedurl"
className="form-control"
onChange={this.onUnpackedURLChange}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will using onChange instead of waiting for blur or submit cause a lot of weird error messages if you are typing the URL in character-by-character? I think so, and that will probably confuse people. My guess is that the amount of effort now on your part required to avoid that confusion is worth it. (You could use a window.prompt(...) to avoid complicating the code here to handle the not-yet-committed state.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with window.prompt. Here's the new experience:

image
image

id="extension-status__unpackedurl"
className="form-control"
onChange={this.onUnpackedURLChange}
placeholder="URL"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
placeholder="URL"
placeholder="URL to extension's package.json"

And then modify the fetchUnpackedExtension code above slightly to treat the user's input URL as the package.json URL instead of appending as in ${baseUrl}/package.json.

This resolves the user's confusion "What URL do I put in there?" and makes it clear they need to make the package.json HTTP-accessible too (not just the extension JS file).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end, I decided against making this the URL to the package.json, and made it explicit that the user should enter the URL to the Parcel dev server. I also made this explicit in the publishing docs.

The extension creator will be updated to make sure the package.json is HTTP-accessible when running npm run serve.

Since parcel can only serve from dist/, our code assumes that the package.json is served from inside of dist/ (through a symlink, as set up by the extension creator), and that the relative path to the bundle should be fixed accordingly. I'd rather hide that complexity from the user.

shared/src/api/client/services/extensionsService.test.ts Outdated Show resolved Hide resolved
shared/src/api/client/services/extensionsService.ts Outdated Show resolved Hide resolved
client/browser/src/browser/ExtensionStorageSubject.ts Outdated Show resolved Hide resolved
shared/src/platform/context.ts Show resolved Hide resolved
sqs added a commit that referenced this pull request Jan 3, 2019
Excluding WIP extensions from result sets added a lot of complexity to the code (API parameters) and the UI. It is sufficient to just sort them last. There will be fewer WIP extensions present anyway after #1508 is merged.
sqs added a commit that referenced this pull request Jan 4, 2019
Excluding WIP extensions from result sets added a lot of complexity to the code (API parameters) and the UI. It is sufficient to just sort them last. There will be fewer WIP extensions present anyway after #1508 is merged.
sqs added a commit that referenced this pull request Jan 4, 2019
* remove extension title, use extension ID instead

The extension title (the package.json extension manifest's `title` property) was redundant and added complexity:

- It made it difficult to see the publisher of an extension on the extension registry, which is important for finding the right or trusted extension to use.
- It was fairly redundant with the extension ID (`my-extension` vs `My extension`).
- The presence of a title meant that the descriptions were longer and had boilerplate content (such as "This is a Sourcegraph extension that..."). Now that there is no title and it won't feel duplicative, descriptions can be shorter and more to-the-point. This, in turn, means that we can show the description on a single line in the extension registry list page, which reduces visual variance among extensions (some of which had multi-line descriptions, some of which had one-line descriptions).

The only feature that required the use of the title was marking an extension as WIP. You can now do that by setting the extension manifest `wip` property to true. For backcompat, titles with `WIP:` and `[WIP]` prefixes still indicate WIP extensions.

* show "Categories" dropdown next to extension registry search query input

This lets users easily filter extensions by category.

* add "Include WIP extensions" option to extension registry list page

This removes the GraphQL includeWIP query parameter because it is no longer necessary. API clients can now express the same thing by including `#wip` in the query. It was only ever used by the immediate web app, never any other clients, so it is safe to remove.

* add "Show enabled/disabled extensions" to the extension registry list page

This lets users see only enabled extensions, or only disabled extensions.

* remove include/exclude WIP, only sort WIP last

Excluding WIP extensions from result sets added a lot of complexity to the code (API parameters) and the UI. It is sufficient to just sort them last. There will be fewer WIP extensions present anyway after #1508 is merged.

* make category:"Other" also match extensions w/manifest with no category
@lguychard lguychard merged commit 0fc289a into master Jan 7, 2019
@lguychard lguychard deleted the unpacked-extensions branch January 14, 2019 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support adding extensions locally for dev
5 participants