-
Notifications
You must be signed in to change notification settings - Fork 44
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: ci awareness to disable terminal prompting within commands #449
Conversation
@@ -37,6 +37,8 @@ jest.mock('../../src/lib/prompts'); | |||
describe('rdme versions*', () => { | |||
beforeAll(() => nock.disableNetConnect()); | |||
|
|||
beforeEach(() => jest.resetModules()); |
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.
Because we're mocking out process.env.CIRCLECI
to test the ci-info package if we don't reset modules here then that package will get loaded within our src/lib/enquirer.js
wrapper without the env variable, and cached -- so when the test that does need it, and does mock that environment variable out, the cached module doesn't see it.
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 feel like it might make more sense to do this in a global beforeEach
call at some point
mockRequest.done(); | ||
}); | ||
|
||
it.todo('should prompt a version list if no `--fork` argument is supplied'); |
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.
Not having something like promptHandler.createVersionPrompt.mockResolvedValue
to mock Enquirer responses with this new setup is annoying but as it is I'm comfortable with the tradeoff we're making with this work and not having to have tests for Enquirer being able to prompt us for questions.
though i'm sure i'l regret this a year from 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.
lmaoo yeah I like that we can mock and reuse responses with that promptHandler
, but we have a lot of different patterns in that file that are pretty confusing so I think we should revisit that at some point
{ | ||
type: 'select', | ||
name: 'fork', | ||
message: 'Which version would you like to fork from?', |
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.
Having these questions duped in some commands sucks but I'm comfortable with the tradeoff of having duped questions in two commands than having to maintain a question generation library.
src/lib/enquirer.js
Outdated
`We've detected you're running within a ${ | ||
ci.name | ||
} environment, please supply the following required arguments for your command instead of relying on our terminal prompt system: ${chalk.yellow( | ||
missingArgs.join(',') |
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 do not like this sentence I've written; please suggest something better.
|
||
describe('ci environments', () => { | ||
beforeEach(() => { | ||
process.env.CIRCLECI = 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.
Purposefully testing it with CIRCLECI
here instead of GITHUB_ACTIONS
because I know that GITHUB_ACTIONS
will always be present in our CI and I don't want to delete that from the workflow runner.
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.
good thinking!
.basicAuth({ user: key }) | ||
.reply(200, [{ version }, { version }]) | ||
.post('/api/v1/version') | ||
.post('/api/v1/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.
We weren't fully testing out the expected API payload. Wish there were a way for us to configure Nock to require this...
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 have one general question about the default export from the enquirer
handler (and a few minor comments/suggestions). Big fan of this pattern overall 👏🏽
@@ -37,6 +37,8 @@ jest.mock('../../src/lib/prompts'); | |||
describe('rdme versions*', () => { | |||
beforeAll(() => nock.disableNetConnect()); | |||
|
|||
beforeEach(() => jest.resetModules()); |
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 feel like it might make more sense to do this in a global beforeEach
call at some point
mockRequest.done(); | ||
}); | ||
|
||
it.todo('should prompt a version list if no `--fork` argument is supplied'); |
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.
lmaoo yeah I like that we can mock and reuse responses with that promptHandler
, but we have a lot of different patterns in that file that are pretty confusing so I think we should revisit that at some point
|
||
describe('ci environments', () => { | ||
beforeEach(() => { | ||
process.env.CIRCLECI = 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.
good thinking!
__tests__/cmds/versions.test.js
Outdated
.reply(200, [{ version }, { version }]); | ||
|
||
await expect(createVersion.run({ key, version })).rejects.toThrow( | ||
/We've detected you're running within a (.*) environment, please supply the following required arguments for your command instead of relying on our terminal prompt system: fork/ |
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.
Any reason why we can't just test for an exact match 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.
Because even though I'm setting CIRCLECI
to the environment, GITHUB_ACTIONS
is also present and ci-info
picks that up first so this message says "We've detected you're running within a Github Actions environment" in CI and "within a CircleCI environment" locally.
src/lib/enquirer.js
Outdated
return enquirer.prompt(questions).catch(err => { | ||
// If the Enquirer promise was rejected without an error then the user killed an open prompt so | ||
// we should abide by their wishes and bail out. | ||
if (!err) process.exit(0); |
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 feel like we could return a 1
here since it's technically not a success, right? Not sure what the best practices are 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.
Exit code 1
generally means that that app executed with errors but since in this case I'm killing the prompt myself it's not really an error. Jest also returns the same 0
exit code when you exit out of an open --watch
.
Exiting Jest before it's able to load any tests:
Exiting an open --watch
process:
src/lib/enquirer.js
Outdated
// Purposefully loading `ci-info` here so we can adequately test it. | ||
const ci = require('ci-info'); // eslint-disable-line global-require | ||
if (!ci.isCI) { | ||
// If we aren't in a CI environment then we shouldn't look for unanswered questions. | ||
return prompt(list); | ||
} |
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.
This is really clean 🤩
{ | ||
type: 'confirm', | ||
name: 'main', | ||
message: 'Would you like to make this version the main version for this project?', |
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.
@kanadgupta Thoughts on slightly reworking this? The double "version" in there reads off.
message: 'Would you like to make this version the main version for this project?', | |
message: 'Would you like to make this the main version for this project?', |
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.
Agreed! Nice find
After talking through this this morning I'm deciding to close this work out. We have a lot of problems with our existing prompt system (difficult to work with, difficult to test, not every question is mapped to an argument) that while this work aimed to solve it solved it in a backwards way. Instead of rejecting CI execution of these commands that likely will never be executed from a CI environment anyways, we should instead focus on cleaning up these individual commands instead. |
🧰 Changes
With our new workflow in #437 there's a new issue that will likely crop up for some folks is that if you don't supply all of the required arguments for a command in a CI environment, our enquirer setup will prompt the terminal for input -- something that will never be answered in a CI environment.
For this we're introducing some new awareness to our commands that ask the user for input to not do that if it's within a CI environment and instead throw an error telling them that they're missing arguments.
I'm also making some other adjustments to a couple commands to clean up their argument structure:
versions:create
--main
and--beta
are now booleans--isPublic
has been renamed to just--public
and it's also been made into a boolean.versions:update
--main
and--beta
are now booleans--isPublic
has been renamed to just--public
and it's also been made into a boolean.🧬 QA & Testing
If with all the changes I made tests are still passing, 👍
You can also test this behavior out locally by prefixing
GITHUB_ACTIONS=true
to a./bin/rdme
call: