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

Add auto-update on hide workflow for Electron on Mac #1318

Merged
merged 6 commits into from
Mar 2, 2021
Merged

Add auto-update on hide workflow for Electron on Mac #1318

merged 6 commits into from
Mar 2, 2021

Conversation

nbhargava
Copy link
Contributor

@nbhargava nbhargava commented Jan 24, 2021

Details

This change allows the Electron app to auto-update when it has finished downloading the update and it is backgrounded.

Fixed Issues

Fixes #1011.

Tests

  1. Install and run MinIO locally.
  2. Point the publish spec in electron.config.js at the local server.
  3. Publish a new version with the build number set very high (i.e. 1.0.1-999).
  4. Build a new version for local development with a lower build number (i.e. 1.0.1-374). It is important that this is notarized, so you must use npm run desktop-build. This build should also have the publish spec pointed at MinIO.
  5. Run the app.
  6. Verify the app version is 1.0.1-374.
  7. Once the new update has been downloaded, either hide or close the window.
  8. The app may reboot a few times.
  9. Foreground the app and verify that the app version is 1.0.1-999.

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

Web

N/A

Mobile Web

N/A

Desktop

Video of the experience: https://www.dropbox.com/s/17jhevgcax2xz6x/Screen%20Recording%202021-02-24%20at%2010.13.15%20PM.mov?dl=0

Update modal:
image

iOS

N/A

Android

N/A

@nbhargava nbhargava requested a review from a team as a code owner January 24, 2021 21:56
@github-actions
Copy link
Contributor

github-actions bot commented Jan 24, 2021

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@botify botify requested review from timszot and removed request for a team January 24, 2021 21:56
@nbhargava
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

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.

Haven't tested this yet, but just had a few comments to start. Overall looks very good!

Also, since this requires and external tool to test, I think it's probably worth including some documentation in the README explaining how to test the desktop auto-updater.

src/libs/checkForUpdates.js Outdated Show resolved Hide resolved
desktop/main.js Outdated Show resolved Hide resolved
desktop/main.js Outdated Show resolved Hide resolved
desktop/main.js Outdated Show resolved Hide resolved
@nbhargava
Copy link
Contributor Author

Just pinging this again!

README.md Outdated Show resolved Hide resolved
@roryabraham
Copy link
Contributor

I ran into this issue notarizing the desktop app:

Package Summary:
 
1 package(s) were not uploaded because they had problems:
	/var/folders/0l/2cyzv7b14fx8rs5w8xpvvbyc0000gn/T/9185A388-AB1B-4C7A-9092-E8BF05A0CA7F/com.expensifyreactnative.chat.itmsp - Error Messages:
		The username rory@seahorsevineyards.com is not a member of the provider . Contact your team admin for assistance. (1296)
2021-02-01 09:16:22.785 altool[10536:83496] *** Error: Unable to notarize app.
2021-02-01 09:16:22.785 altool[10536:83496] *** Error: code 1296 (The username rory@seahorsevineyards.com is not a member of the provider . Contact your team admin for assistance. (1296))

Did you encounter this issue? Do you know what the problem is/how to resolve the error?

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.

While I was not completely successful in testing this yet, I did have some suggestions for documentation improvements. I know it's not the best format (sorry), but hopefully you can apply the suggestions from this diff to your PR: autoUpdaterDocsImprovements.txt

@nbhargava
Copy link
Contributor Author

I haven't seen that error before so I'm not 100% sure how to resolve it. My best guess is that you have local certificates installed that are for a member of some team/organization and that your personal account, rory@seahorsevineyards.com, is not allowed access to that. If that's the case, my guess would be that switching to your corporate account should let you upload properly.

This issue I found online seems roughly related: https://developer.apple.com/forums/thread/119445

@nbhargava
Copy link
Contributor Author

^ real quick on the above: I only tested from a paid developer account, so I'm not sure if that's also a requirement.

@roryabraham
Copy link
Contributor

Thanks for finding a way to test this and making those documentation updates, but it seems that the only way we can test this is to use a personal paid developer account (we don't want to use our production credentials). So could you please:

  1. Move all the great documentation you have here to a separate README in the desktop directory (there should be no diff on the README in the root).
  2. Make a note in the documentation that in order to test with a notarized build you'll need to have a paid apple developer account.
  3. Post a screen recording of the auto-update happening so we can see that it works for you in real time and not just screenshots?

Thanks!

@nbhargava
Copy link
Contributor Author

Updated the README as described and below is a video cast of the experience: https://www.dropbox.com/s/un6xgb4gepibmm6/Screen%20Recording%202021-02-02%20at%206.26.57%20PM.mov?dl=0

The flickering on the screen you see right before we re-load it is Big Sur's "verification" of the binary. It is sometimes slow and sometimes this fast.

roryabraham
roryabraham previously approved these changes Feb 3, 2021
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.

Excellent work!

@roryabraham
Copy link
Contributor

Hi @nbhargava, do you think it would be possible to have the auto-update happen in the middle of the night (even if the laptop is sleeping), rather than when the app is backgrounded?

@nbhargava
Copy link
Contributor Author

Shouldn't be too difficult. What counts as middle of the night? 11pm-3am local time?

Also do you want it to be both middle of the night AND backgrounded or just middle of the night?

@nbhargava
Copy link
Contributor Author

Oh sorry, missed the part about the laptop sleeping. If the laptop is sleeping I don't know how we'd be able to resume control to initiate the update. Not sure if that changes things.

@roryabraham
Copy link
Contributor

Hi @nbhargava, after chatting about this internally a bit, we've decided on a change of plans.

Long-term, I think we're going to create a separate issue to investigate remote-hosting the JS bundle so that electron can auto-update its JS without having to close and reopen at all (like the Slack desktop client).

For this PR, could you please update it so that instead of closing and restarting the app when it's hidden, instead we just provide a custom notification to autoUpdater.checkForUpdatesAndNotify that includes an Update Now button. If the Update Now button in the notification is clicked, then it should close the app, install the update, and restart it (no need to immediately hide the app on relaunch).

Thanks!

@nbhargava
Copy link
Contributor Author

I'll take a swing at this and see what I can do. The part that may be tricky is handling the fact that the "install" part of quitAndInstall doesn't seem to always fire reliably.

@nbhargava
Copy link
Contributor Author

@roryabraham -- I've uploaded a new version with the requested changes. Here is a screen recording: https://www.dropbox.com/s/n8a04piq2nijhnv/Screen%20Recording%202021-02-06%20at%201.56.26%20PM.mov?dl=0

@roryabraham
Copy link
Contributor

roryabraham commented Feb 9, 2021

Hi @nbhargava, we'd really prefer if the notification and modal maintain a look-and-feel that's consistent with the rest of our application. So that means instead of using Electron's dialog.showMessageBoxSync:

  1. Please use a browser notification to inform the user that there's an update available and to provide a button to trigger the update. We have a LocalNotification module which ideally could be extended to have a showUpdateNotification function.
  2. Please use a react-native-modal component to display the confirmation dialog. We have a Modal module you can use to start.

The modules I linked above use the ES6 module system, so if you want to use them (which would be ideal), you may have to refactor our Electron configuration to enable the importation of ES6 modules into desktop/main.js. Do you think that's something you'd be up to? I noticed that the Electron v12 beta uses Node 14, and therefore should offer interoperability between CJS and ES6 modules without the use of an external package such as ESM. There is some more info in this GH issue.

@roryabraham
Copy link
Contributor

Also, for the record @nbhargava has completed the task we initially gave him, and my previous comment constitutes a change in the scope-of-work. Do we have other examples for what we do when we increase the scope-of-work after the fact? cc @michaelhaxhiu @laurenreidexpensify @puneetlath – have you guys encountered this situation yet?

@puneetlath
Copy link
Contributor

I think in that case let's just increase the scope of the Upwork job/pay by the same scale as the increase in scope.

@michaelhaxhiu
Copy link
Contributor

+1 to that @puneetlath. Let's provide a bonus for the additional scope if it's agreeable for @nbhargava !

@nbhargava
Copy link
Contributor Author

At the time, I was trying to import LocalNotification, but as you mention, it's much cleaner to just use Electron's IPC to get this done.

FWIW, in the future, the esm strategy does work quite well if you do need to end up importing ES6 modules in the future.

@nbhargava
Copy link
Contributor Author

This new diff has the updates that pop open a modal when the download is available and then triggers the download when the user interacts with the popover. Below is a video of the interaction:

https://www.dropbox.com/s/6oa7p4qtnms58yr/Screen%20Recording%202021-02-21%20at%204.19.05%20PM.mov?dl=0

@roryabraham
Copy link
Contributor

roryabraham commented Feb 22, 2021

@nbhargava The video you've provided looks great to me! @AndrewGable, what do you think?

However, I noticed your code has several lint and test failures, so could you please work on resolving those before I dive into a thorough review?

@nbhargava
Copy link
Contributor Author

Yup, I realized yesterday that there are some rebase issues due to refactors that happened while I was developing.

Will update later today and re-ping the thread once those are fixed.

@AndrewGable
Copy link
Contributor

Looks great to me, cc @Expensify/design to make sure this is the UI element we'd like.

@shawnborton
Copy link
Contributor

Are the screenshots on the original comment correct? From my understanding of reading through this, it seems like there should be some kind of Update button but I wasn't seeing one in the screenshots. It also looks like the video link you provided was deleted.

@AndrewGable
Copy link
Contributor

I believe this is the latest video

@shawnborton
Copy link
Contributor

Got it, @nbhargava can you update the original comment with both the video as well as static screenshots that clearly show the update flow?

In terms of the UI, I think it's great and is the best thing we can do right now before we have some kind of in-app notification/growl/toast component created. We can address that as a separate problem/solution when we start to develop the need for it.

@nbhargava
Copy link
Contributor Author

Updated the original comment with the video & a static screenshot of the modal and fixed all the rebase issues

Not sure how to re-run the iOS tests, but from the log output: This is an error with npm itself, so I'm not too sure that I'm newly causing this error?

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.

Overall code looks good, just a few minor changes. I re-ran the iOS tests and they passed, so you're good there.

Also, I noticed that the UpdateAppModal module has an index.native.js and index.website.js that are identical. We just fixed a webpack bug yesterday so that you shouldn't need to do that anymore. Just put your desktop-specific code in index.desktop.js and the default in index.js and it should work.

desktop/main.js Outdated Show resolved Hide resolved
src/components/UpdateAppModal/BaseUpdateAppModal.js Outdated Show resolved Hide resolved
src/components/UpdateAppModal/BaseUpdateAppModal.js Outdated Show resolved Hide resolved
src/components/UpdateAppModal/BaseUpdateAppModal.js Outdated Show resolved Hide resolved
src/components/UpdateAppModal/BaseUpdateAppModal.js Outdated Show resolved Hide resolved
src/setup/index.desktop.js Outdated Show resolved Hide resolved
>
Update App
</Text>
</TouchableOpacity>
Copy link
Contributor

@roryabraham roryabraham Feb 24, 2021

Choose a reason for hiding this comment

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

NAB, but might be nice to have a "Maybe later" cancel button too.

Fix double-add

Lint fixes

Add more documentation

Update docs

Move README to desktop/

Show modal prompting user to restart

Use modal to initiate download of update
@nbhargava
Copy link
Contributor Author

Updated with your feedback and added a new video/screenshot to the top.


// Version string for the app to update to.
// eslint-disable-next-line react/no-unused-prop-types
version: PropTypes.string,
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry I missed it in the last review, but if this prop is unused then we should just get rid of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, actually I see why you did this. NAB but what I would've done is:

  1. Create a new file called src/components/UpdateAppModal/UpdateAppModalPropTypes
  2. Export the props types and default props you have in here as named exports like export {propTypes, defaultProps} from that file
  3. In UpdateAppModal/index.js and UpdateAppModal/desktop.index.js, use the prop types from step 2, unaltered. Then just pass the one prop that's needed in BaseUpdateAppModalonSumbit
  4. In BaseUpdateAppModal, set the propTypes to _.omit(propTypes, 'version'). Same for default props.

import BaseUpdateAppModal from './BaseUpdateAppModal';

const UpdateAppModal = (props) => {
const onSubmit = () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

From our style guide...

When you have an event handler, do not prefix it with "on" or "handle". The method should be named for what it does, not what it handles.

So I would just rename this to updateApp

@roryabraham
Copy link
Contributor

@nbhargava Any update here?

@nbhargava
Copy link
Contributor Author

Sorry, forgot to push! The video is working for me, even in an incognito window. Are you still having issues with it?

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.

LGTM and great work 👍

@roryabraham roryabraham merged commit ab1f1e4 into Expensify:master Mar 2, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Mar 2, 2021
@marcaaron
Copy link
Contributor

propTypes warnings were not fixed :( we should just make them errors

@roryabraham
Copy link
Contributor

propTypes warnings were not fixed

Idk why I didn't think about this some more (should have held on merging), but it seems like a false warning to me. The prop types were imported from another file then altered, but should actually include onSubmit.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Automatically update the Expensify.cash desktop app when a new version is released on mac
8 participants