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

[NoQA] Fix the internal QA PR section losing its state #9946

Merged
merged 12 commits into from
Jul 19, 2022

Conversation

mountiny
Copy link
Contributor

@mountiny mountiny commented Jul 16, 2022

Details

The internal QA section of the Staging deploy issue loses its state when the issue is regenerated when new deploy blocker is found or we CP some PR to Staging.

Not ideal.

This PR aims to fix this situation by passing a list of URLs of the InternalQA PRs which were checked off already to the function which generates the new issue body.

I have left comments in the PR to explain how this is fixing the problem and also why the integration test hasn't caught this issue previously.

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/198446

Tests

Automated tests cover this change.

Manual tests:

  1. This PR will have InternalQA label
  2. Once merged and deployed to staging, it should appear in the latest Staging QA issue
  3. Check the PR off in the list signaling that it has been resolved
  4. Create another PR with a dummy change at some markdown file for example
  5. Add CP Staging and InternalQA labels and merge it
  6. Once it is deployed to production it should show up in the InternalQA section too and this PR should preserve its QA state (ie QA done, resolved)
  • Verify that no errors appear in the JS console

PR Review Checklist

Contributor (PR Author) Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

PR Reviewer Checklist

The Contributor+ will copy/paste it into a new comment and complete it after the author checklist is completed

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

QA Steps

Check the Tests section.

  • Verify that no errors appear in the JS console

Screenshots

N/A

@mountiny mountiny added the InternalQA This pull request required internal QA label Jul 16, 2022
@mountiny mountiny requested a review from a team as a code owner July 16, 2022 17:09
@mountiny mountiny self-assigned this Jul 16, 2022
@melvin-bot melvin-bot bot requested review from neil-marcellini and removed request for a team July 16, 2022 17:09
Comment on lines +125 to +129
// Get the internalQA PR list, preserving the previous state of `isResolved`
const internalQAPRList = _.sortBy(
currentStagingDeployCashData.internalQAPRList,
'number',
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We are first getting the list of the InternalQA PRs from the previous issue body.

return GithubUtils.generateStagingDeployCashBody(
newTag,
_.pluck(PRList, 'url'),
_.pluck(_.where(PRList, {isVerified: true}), 'url'),
_.pluck(_.where(PRList, {isAccessible: true}), 'url'),
_.pluck(deployBlockers, 'url'),
_.pluck(_.where(deployBlockers, {isResolved: true}), 'url'),
_.pluck(_.where(internalQAPRList, {isResolved: true}), 'url'),
didVersionChange ? false : currentStagingDeployCashData.isTimingDashboardChecked,
didVersionChange ? false : currentStagingDeployCashData.isFirebaseChecked,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

And then passing as a parameter an array of URLs of only those PRs which are resolved (the checkbox has been ticked)

Comment on lines -280 to +284
issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `;
issueBody += `\r\n${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

And finally check if the URL is in the resolvedInternalQAPRs array as the verifiedOrNoQAPRs does not include the necessary InternalQA PRs with isResolved field, hence it was always false and it have reset the checkbox to unchecked state.

@@ -533,7 +534,7 @@ describe('GithubUtils', () => {
));

test('Test some verified internalQA PRs', () => (
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [internalQAPRList[0]])
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [], [], [], [], [internalQAPRList[0]])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to pass this new argument containing the resolved/verified InternalQA PR to the function in the test to make sure that the checkbox state has been preserved.

Copy link
Contributor Author

@mountiny mountiny Jul 17, 2022

Choose a reason for hiding this comment

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

The reason this test has been passing before (although this feature clearly does not work) is that we have not been simulating the actual flow as it happens in reality. We have passed in the checked-off internalQA PR as a third argument, which then made it to the verifiedOrNoQAPRs array which then worked, however, normally, the internalQA PR would never make it to the third argument so it always resetted the checkboxes 😢

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, makes sense 👍

@mountiny mountiny changed the title [WIP] Fix the internal QA PR section losing its state Fix the internal QA PR section losing its state Jul 17, 2022
@mountiny
Copy link
Contributor Author

This should be ready for a review, thank you very much for having a look. I will kindly ask @roryabraham and @yuwenmemon for reviews as you have worked on this before.

roryabraham
roryabraham previously approved these changes Jul 18, 2022
Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

This looks good. Mind if we test on the next checklist? Don't want to introduce potential breaking changes or distractions when we seem close to deploying the current (massive) checklist to production.

@@ -533,7 +534,7 @@ describe('GithubUtils', () => {
));

test('Test some verified internalQA PRs', () => (
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [internalQAPRList[0]])
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [], [], [], [], [internalQAPRList[0]])
Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, makes sense 👍

Copy link
Contributor

@neil-marcellini neil-marcellini left a comment

Choose a reason for hiding this comment

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

Due to my current limited knowledge about GH actions, I asked a few questions and I'll leave it to others to approve.

issueBody += '\r\n\r\n\r\n**Internal QA:**';
_.each(internalQAPRMap, (assignees, URL) => {
const assigneeMentions = _.reduce(assignees, (memo, assignee) => `${memo} @${assignee}`, '');
issueBody += `\r\n${_.contains(verifiedOrNoQAPRs, URL) ? '- [x]' : '- [ ]'} `;
issueBody += `\r\n${_.contains(resolvedInternalQAPRs, URL) ? '- [x]' : '- [ ]'} `;
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 so much code duplication for creating the internal QA PR list and getStagingDeployCashData in these Github actions? I'm very new to Github actions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Check out the documentation here

@mountiny

This comment was marked as outdated.

@mountiny

This comment was marked as outdated.

Comment on lines +352 to +356
// The format of this map is following:
// {
// 'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ],
// 'https://github.com/Expensify/App/pull/9642': [ 'mountiny', 'kidroca' ]
// }
Copy link
Contributor Author

@mountiny mountiny Jul 19, 2022

Choose a reason for hiding this comment

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

Added this comment to explain what the format of the map will be as it is not immediately clear imho, which then probably lead to the bug.

@mountiny
Copy link
Contributor Author

@roryabraham @neil-marcellini Updated this PR with a fix to the additional bug, which I thought for some reason was gone haha. Left comments explaining the changes and why it was failing.

@mountiny mountiny changed the title Fix the internal QA PR section losing its state [WIP] Fix the internal QA PR section losing its state Jul 19, 2022
@mountiny mountiny changed the title [WIP] Fix the internal QA PR section losing its state Fix the internal QA PR section losing its state Jul 19, 2022
Comment on lines -146 to +147
const internalQAPRList = this.getStagingDeployCashInternalQA(issue);
return _.sortBy(_.union(PRList, internalQAPRList), 'number');
return _.sortBy(PRList, 'number');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, this is what was causing the internalQA PRs to be added to the normal PR list as well as the internal QA section. It is not necessary to be added here since the PRs are already fetched and then filtered somewhere else. This should fix that bug.

@mountiny
Copy link
Contributor Author

And yes, we can test it, but it on this checklist!

Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

This LGTM, but also I feel like maybe this code has hit a critical mass of complexity where we need to do some refactoring. If you want we can do the refactoring separately. I'll leave that up to you.

@mountiny
Copy link
Contributor Author

Going to merge and test this using a Test deploy blocker!

2 bugs to test, they have the same testing steps:

  1. Merge this PR and wait a bit to make sure the workflows from this will be used
  2. Make sure the current checklist does not contain the internalQA amongst the normal PRs (which is a big now)
  3. If it does, manually remove it
  4. Check off the internalQA PR which is currently listed in the internal QA section if it is not already (remember to put it back to the original state once testing it done)
  5. Create a test issue and assign a DeployBlocker label to it
  6. This will trigger the workflow to update the checklist with the new deploy blocker

InternalQA is present in the list of other PRs too

  • We already have one internalQA PR in the current locked checklist
  • Currently, when the checklist is updated, the internalQA PR will be added to the list of normal PRs which is a bug
  • Make sure that the internalQA PR is not added to the list of normal PRs

Preserving the checked state of the internalQA PR

  • The internalQA Pr should be checked off as verified before a new deploy blocker is created
  • Once the checklist is updated with the new deploy blocker, make sure the PR is still marked as verified

That is it 🎉 happy testing!

@mountiny mountiny removed the InternalQA This pull request required internal QA label Jul 19, 2022
@mountiny mountiny changed the title Fix the internal QA PR section losing its state [NoQA] Fix the internal QA PR section losing its state Jul 19, 2022
@mountiny
Copy link
Contributor Author

Given we will QA it now, internalQA is not correct for this PR, removing and will report here how the testing went!

@mountiny mountiny merged commit 728a0f4 into main Jul 19, 2022
@mountiny mountiny deleted the vit-fixInternalQASection branch July 19, 2022 17:36
@melvin-bot melvin-bot bot added the Emergency label Jul 19, 2022
@melvin-bot
Copy link

melvin-bot bot commented Jul 19, 2022

@mountiny looks like this was merged without passing tests. Please add a note explaining why this was done and remove the Emergency label if this is not an emergency.

@mountiny
Copy link
Contributor Author

Not an emergency. Tests were passing.

@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@mountiny
Copy link
Contributor Author

First part worked: InternalQA is present in the list of other PRs too

Second part did not 😡 Preserving the checked state of the internalQA PR

Looking into the logs

@mountiny
Copy link
Contributor Author

Oh, found the problem, from the logs:

Filtering out the following automated pull requests: [ 'https://github.com/Expensify/App/pull/9997' ]
Found the following Internal QA PRs: {
  'https://github.com/Expensify/App/pull/9641': [ 'PauloGasparSv', 'kidroca' ]
}
Found the following NO QA PRs: [
  'https://github.com/Expensify/App/pull/9913',
  'https://github.com/Expensify/App/pull/9890'
]
Found the following verified Internal QA PRs: [
  'https://github.com/Expensify/App/pull/9641 - @PauloGasparSv @kidroca'
]
Successfully updated StagingDeployCash! 🎉 https://github.com/Expensify/App/issues/9970

You can see the Found the following verified Internal QA PRs are not just URLs, which is wrong. I am putting up a PR to fix it!

@mountiny
Copy link
Contributor Author

The follow up PR fixed it! #10007 🎉

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by @mountiny in version: 1.1.86-0 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@OSBotify
Copy link
Contributor

OSBotify commented Aug 1, 2022

🚀 Deployed to production by @yuwenmemon in version: 1.1.86-5 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

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.

4 participants