-
Notifications
You must be signed in to change notification settings - Fork 220
Add directory
key to package.json repository
#1233
Conversation
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.
There are a few outstanding discrepancies causing the tests for some packages to fail. I'm looking for feedback from reviewers on how to address them.
Once they've been addressed, I'll update the tests, remove the FIXME
comments, and address any other linting errors.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the expected main', () => { | ||
if(packageName === 'graphql-persisted') return; // FIXME: Address this in graphql-persisted |
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.
The graphql-persisted
package does not specify an entry for main
.
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.
Yah, a main
doesn't really make sense to me here. The package has two equally-important consumers (koa, apollo), so there isn't a good default import source.
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.
Would it not still make sense to have a main
index.js
that consists of something like
export {apollo} from './apollo';
export {apollo} from './koa';
This would make it conform to the expected main entry point, while still offering the option to import the desired consumer directly. As a side benefit, it would also allow the types
entry to be consistent.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the expected types', () => { | ||
if(packageName === 'graphql-persisted') return; // FIXME |
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.
The graphql-persisted
package fails to specify types
.
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.
Similar to the main
conversation for this package, this seems fine to me. Consumers will directly import:
@shopify/graphql-persisted/apollo
, which ships with apollo typedefs@shopify/graphql-persisted/koa
, which ships with koa typedefs
directory
key to package.json repository
b88f11d
to
44d5e8f
Compare
44d5e8f
to
c95189b
Compare
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.
👍 A lot of bikeshedding from me about removing some cognitive load from test expectations, but everything looks sound to me. Thank you 💟
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the expected main', () => { | ||
if(packageName === 'graphql-persisted') return; // FIXME: Address this in graphql-persisted |
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.
Yah, a main
doesn't really make sense to me here. The package has two equally-important consumers (koa, apollo), so there isn't a good default import source.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the expected types', () => { | ||
if(packageName === 'graphql-persisted') return; // FIXME |
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.
Similar to the main
conversation for this package, this seems fine to me. Consumers will directly import:
@shopify/graphql-persisted/apollo
, which ships with apollo typedefs@shopify/graphql-persisted/koa
, which ships with koa typedefs
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the MIT license', () => { | ||
expect(packageJSON.license).toBe(packageJSONTemplate.license); |
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.
expect(packageJSON.license).toBe(packageJSONTemplate.license); | |
expect(packageJSON.license).toBe('MIT'); |
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.
I had originally hardcoded things like this in this file, but then I started adding tests for the template as well. I realized that it made more sense to treat the template as the expected values, and ensure each package conforms to it.
If we hard code MIT
here, it means that if we change the template down the road, the change will only be detected by the test suite after generating a new package and seeing it fail the suite. By coupling to the template, changing the license there would cause every package's license test to fail, which is likely what we want, since we'd probably want to update their licenses as well.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies Quilt deep-link homepage', () => { | ||
const expectedHomepage = compile(packageJSONTemplate.homepage); |
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.
I know it's guaranteeing less, but I'd be happy enough with:
expect(packageJSON.homepage).toEndWith(`/${basename(packageJSONTemplatePath)}/README.md`)
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.
I'm not sure what loosening this would gain us. I think the compile
version is clearer, since it matches what is used in the other tests, and couples to the template as authoritative.
test/consistent-package-json.test.ts
Outdated
it('specifies a repository deep-linking into the Quilt monorepo', () => { | ||
const expectedRepository = { | ||
...packageJSONTemplate.repository, | ||
directory: compile(packageJSONTemplate.repository.directory), |
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.
Again, simplifying this to check for packages/${basename(packageJsonPath)}
seems fine.
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.
Thanks for the review @GoodForOneFare! I've responded to a number of the comments.
Something that came up in a couple comments was the use of the compile
helper, and the suggestion to decouple from the template. I feel that the template code and package specifications should match. Updating the template should probably require updating the packages to match. Decoupling from the template means packages can diverge, leading to inconsistencies, even if small.
That said, I agree that in some cases the use of compile
is a little confusing. I considered deep-compiling the entire template for each package. This would allow usage like
expect(packageJSON.foo).toBe(expectedPackageJSON.foo);
I opted not to, as it would mean having to deeply compile the entire template for each package. If that's clearer though, I could switch it over to that.
It does occur to me that I could replace {{name}}
in the raw JSON before parsing it, which would be simpler than deeply replacing {{name}}
in the parsed object.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies Quilt deep-link homepage', () => { | ||
const expectedHomepage = compile(packageJSONTemplate.homepage); |
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.
I'm not sure what loosening this would gain us. I think the compile
version is clearer, since it matches what is used in the other tests, and couples to the template as authoritative.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the MIT license', () => { | ||
expect(packageJSON.license).toBe(packageJSONTemplate.license); |
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.
I had originally hardcoded things like this in this file, but then I started adding tests for the template as well. I realized that it made more sense to treat the template as the expected values, and ensure each package conforms to it.
If we hard code MIT
here, it means that if we change the template down the road, the change will only be detected by the test suite after generating a new package and seeing it fail the suite. By coupling to the template, changing the license there would cause every package's license test to fail, which is likely what we want, since we'd probably want to update their licenses as well.
test/consistent-package-json.test.ts
Outdated
}); | ||
|
||
it('specifies the expected main', () => { | ||
if(packageName === 'graphql-persisted') return; // FIXME: Address this in graphql-persisted |
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.
Would it not still make sense to have a main
index.js
that consists of something like
export {apollo} from './apollo';
export {apollo} from './koa';
This would make it conform to the expected main entry point, while still offering the option to import the desired consumer directly. As a side benefit, it would also allow the types
entry to be consistent.
test/consistent-package-json.test.ts
Outdated
expect(packageJSON.types).toBe(packageJSONTemplate.types); | ||
}); | ||
|
||
it('specifies a version', () => { |
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.
Fair. Should it be this file's responsibility to catch it before it gets to the publish stage though?
@GoodForOneFare, I've added a commit in which I switch to pre-compiling the expected template for each package, instead of using |
I've addressed all exceptional packages and lint errors:
@GoodForOneFare, should these changes have accompanying changelog entries? Should they be in a separate PR, or are they fine here? |
test/consistent-package-json.test.ts
Outdated
expect(packageJSON.types).toBe(packageJSONTemplate.types); | ||
}); | ||
|
||
it('specifies a version', () => { |
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.
It's a moot point because IMO this test will never catch anything 🤷🏻♂️ If someone doesn't use the generator:
- Other 💩 will fail (like the sideEffects check) and they'll end up using the generator / copy+pasting from elsewhere
- Worst case, they'll use
yarn init
, which also includes a version
I don't want to delay shipping the PR because of this, but I'd strongly prefer that tests for the sake of completion don't make it into the codebase.
RE changelog entries, I guess they have to be part of this PR. Otherwise, any merge gap between this and a changelog PR will result in someone else having to release everything. |
eb24a36
to
b85e704
Compare
@GoodForOneFare, I've done the following:
While I had originally agreed with your point on consolidating the tests into one test per key for all packages, I have switched it back to my original one test per key per package. I feel strongly that this is a better developer experience. You brought up two main points:
Based on that, I think the benefits of granular failures far outweigh the cost. |
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.
👍 You're a champ, @sambostock! Very much necessary, and very much appreciated 🙏
The existing test file did not match the testRegex, so it was not running. Changing the extension to .test.ts allows it to match the regex, and generating separate tests for each package allows for more granular failures.
b85e704
to
ee4541b
Compare
Description
TL;DR
#1224 should have made this change instead:
"name": "@shopify/{{name}}", "repository": { "type": "git", "url": "git+https://github.com/Shopify/quilt.git", + "directory": "packages/{{name}}", },
Details
This follows up on #1224, which updated the repository fields, in an effort to improve support for tools such as Dependabot to deep-link into the repo:
While these links do work, they still did not improve integration with Dependabot.
After speaking to Dependabot support, and being referred to React's
package.json
repository
entry, it looks like specifying the additionaldirectory
key is the answer:This makes that change, fixes some other small inconsistencies, and adds tests along the way.
Type of change
Checklist