-
Notifications
You must be signed in to change notification settings - Fork 21
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
feat(Config): Introduce new config resolution #70
Conversation
7d94871
to
d1be3c6
Compare
bc3b25f
to
c22141a
Compare
Codecov Report
@@ Coverage Diff @@
## master #70 +/- ##
==========================================
+ Coverage 80.83% 89.17% +8.33%
==========================================
Files 8 8
Lines 167 194 +27
==========================================
+ Hits 135 173 +38
+ Misses 32 21 -11
Continue to review full report at Codecov.
|
let globalConfigPath; | ||
|
||
before(async () => { | ||
await fs.promises.mkdir('local'); |
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 reason for that construct being present in multiple tests is the fact that we're mocking both homedir
and cwd
to a temporary directory, which means that both local and global config has the same location in these scenarios. I'd love to hear feedback on how to potentially improve that in the scope of these tests
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 think you've taken very good approach, I cannot think of anything better 👍
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.
Looks really good! It's great to see so extensive testing (after all it's a very sensitive functionality)
I have just few comments. Let me know
config.js
Outdated
config.meta.updated_at = Math.round(Date.now() / 1000); | ||
// write to .serverlessrc file | ||
return storeConfig(config); | ||
return storeConfig(config, configPath, { updated: true }); |
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 think in all cases we should return same value as getConfig
would return (in light of that I would strip returning any value from storeConfig
)
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 think we can skip returning anything from storeConfig
👍 The question here is - should we return anything from storeConfig
then? I was thinking about true
/false
for indicating if save was successful or not or maybe we should just throw any potential errors?
config.js
Outdated
try { | ||
writeFileAtomic.sync(serverlessrcPath, JSON.stringify(config, null, 2)); | ||
if (options.updated) { |
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.
Why do we need that option, can't we store it unconditionally?
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 wanted to keep previous behavior when on default global config creation updated_at
was not populated but I'm fine with updating it unconditionally. What do you think?
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 would update it unconditionally. I think there's no valid reason to be conditional here.
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.
updated 👍
config.js
Outdated
if (!config.userId) { | ||
return null; | ||
} | ||
const user = get(['users', config.userId, 'dashboard'], config); |
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.
As we already resolved config, probably more optimal would be to resort o _.get(config, path)
here (?)
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.
definitely, I totally missed that when moving functionality from platform-sdk
test/config.js
Outdated
|
||
it('should have CONFIG_FILE_NAME', () => { | ||
const configFilename = config.CONFIG_FILE_NAME; | ||
expect(configFilename).to.exist; // eslint-disable-line |
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 think we don't need this eslint disable comment (I know it's like that in master, but I guess we can clean this now)
let clock; | ||
|
||
before(() => { | ||
clock = sinon.useFakeTimers(Date.now()); |
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.
Why those tests needed to be updated?
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've tried to clarify that on lines 27-28. Essentially, it turned out that after refactoring, new config resolution is faster than rc
and this test started to fail from time to time. After inspection, it was caused by the fact that some of the notifications were emitted almost at the exact same time, which caused them to have the same lastShown
value. That in turn resulted in the functionality selecting the next notification to be emitted to be resolved incorrectly (I've observed situations where CODE0A
was selected instead of CODE0C
because they had the same lastShown
date.
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 see, good point, but in such case I'd rather introduce await wait(1)
between calls (with a comment that it ensures distinct ms timestamps)
At least (but maybe it's just my bias) interfering with JS clock feels quite invasive to me. I'd rely on it, as a last resort (where e.g. we need simulate longer periods of times, or precisely reproduce some time sequences)
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 think wait(1)
here makes sense and is definitely enough 👍 I might be heavily biased myself due to my background in Python, where mocking time is much more common practice. I've changed to the suggested approach 👍
test/config.js
Outdated
before(() => { | ||
clock = sinon.useFakeTimers(now); | ||
}); | ||
|
||
after(() => { | ||
clock.restore(); | ||
}); |
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 take, it's to test, the updated_at
, but isn't it overkill? Can't we simply do setTimeout(.., 10)
and confirm that updated_at
was updated (?) If it appears as needed, maybe it'll be nicer to mock timers only for tests where we test that functionality and not whole test file (?)
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 agree, it might be a bit of an overkill here. I'll adjust it 👍
let globalConfigPath; | ||
|
||
before(async () => { | ||
await fs.promises.mkdir('local'); |
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 think you've taken very good approach, I cannot think of anything better 👍
c8f2be1
to
0f86d99
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.
Looks great @pgrzesik ! I've posted just a few minor suggestions
config.js
Outdated
config.meta = config.meta || {}; | ||
config.meta.updated_at = Math.round(Date.now() / 1000); |
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 would remove those two from try
. Technically this clause is dedicated to catch write error and nothing else.
To be fully bulletproof also config stringification is best if outside of try/catch clause (if it crashes it feels as programmer error on our side, which I would expose unconditionally)
config.js
Outdated
config.meta.updated_at = Math.round(Date.now() / 1000); | ||
// write to .serverlessrc file | ||
return storeConfig(config); | ||
return storeConfig(config, configPath); |
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.
As now storeConfig
doesn't return anything, I think we need to return result of getConfig
here
config.js
Outdated
if (key && typeof key === 'string') { | ||
config = _.omit(config, [key]); | ||
} else if (key && Array.isArray(key)) { | ||
config = _.omit(config, key); | ||
} | ||
// write to .serverlessrc file | ||
return storeConfig(config); | ||
return storeConfig(config, configPath); |
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.
Same here
BREAKING CHANGE: Removed `getGlobalConfig`, removed support for all `rc`-discoverable files, update not always modify only global config
0f86d99
to
668e7d9
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.
Great job! 👍
Notifications tests had to be adjusted because they became nondeterministic - in some cases, the
lastShown
date for two notifications was the same and not the one that was expected was returned.It introduces the following breaking changes:
getGlobalConfig
from APIrc
-discoverable filesCloses: #69