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

☂ Umbrella: Install development dependencies when missing #976

Closed
2 tasks done
molant opened this issue Feb 14, 2020 · 3 comments
Closed
2 tasks done

☂ Umbrella: Install development dependencies when missing #976

molant opened this issue Feb 14, 2020 · 3 comments

Comments

@molant
Copy link
Contributor

molant commented Feb 14, 2020

Describe the Feature

Getting an environment ready for React Native development can take some time and is error prone. Developers have also problems setting up all the Android environment and emulators and on Windows it's even worse with the mixed messages about Hyper-V and HAXM.

After talking with a few RN developers from different projects and companies, it seems like the average to get a new machine up and running is between 1/2-1 day 😓

doctor is great to help with this, and I think we can take it even further by automatically installing and configuring the required dependencies if missing.

Tasks

Possible Implementations

My tests were mainly on Windows because I believe it's going to be the most complicated platform. My goal is to not require admin privileges so the developer doesn't see the UAC prompt. I think it's doable.

The list of dependencies from the docs are:

Node 10+

Script runs on node so not a lot to check other than the version via process.version for completeness?

Python 2

We can use the same approach as windows-build-tools.
The installation on Windows should be under %LOCALAPPDATA%/python2

JDK

Version 8 or later is recommended in the docs. I'd rather use a later one as the installation without admin privileges will be a lot easier.

  • Download link: https://javadl.oracle.com/webapps/download/GetFile/${JAVA_VERSION}-b${BUILD}/${ID}/windows-i586/jdk-${JDK_VERSION}-windows-x64.exe (need to add some extra stuff in that URL...)
  • Command: "${jdkInstaller}" /s INSTALLDIR="${targetDir}" ADDLOCAL="ToolsFeature,SourceFeature";

Android packages

My initial tests where without Android Studio and going directly with the Android SDK Tools (https://dl.google.com/android/repository/sdk-tools-windows-4333796.zip). It looks like a lot of developers still need AS for native debugging and other scenarios so I think we should start with it and then maybe add an option to only download the SDK tools.

The biggest problem here was that user needs to accept licenses when using the CLI or nothing gets downloaded/installed. I ended up doing the following to auto-accept:

const installDependency = (command) => {
    return new Promise((done, error) => {
        const child = exec(command, { maxBuffer: 1024 * 500 });

        child.stdout.on('data', (data) => {
            if (data.includes('(y/N):')) {
                console.log(`Accepting License for ${command}`);
                child.stdin.write('y\n');
            }
        });

        child.stderr.on('data', (data) => {
            console.error(data);
        });

        child.on('close', done);
        child.on('error', error);
    });
};

Hyper-V vs HAXM vs WHPX

I know there's a command to know if Hyper-V is active or not. I'll check with other teams in Microsoft (Xamarin?) to know exactly what the best configuration is for running the Android emulators.

Setting and updating environment variables

The approaches that worked for me are:

// https://superuser.com/a/601034
// Set
const command = `setx ${variable} "${value}"`;

// Update
const command = `for /f "skip=2 tokens=3*" %a in ('reg query HKCU\\Environment /v ${variable}') do @if [%b]==[] ( @setx ${variable} "${value};%~a" ) else ( @setx ${variable} "${value};%~a %~b" )
    `;

And execute it via require('child_process').exec

This will only modify the user ones, which was one of my goals.

Open questions

  • What happens if the user is running WSL(2) on Windows?
  • Other platforms (macOS) should be supported as well. What would be the best way (homebrew?)
  • Some actions can take a while (JDK, Android Studio, their installation). Will be good to have a progress bar when possible (downloads) so the user does not think the process is hung (happened to me a couple times 😅)

For reference, my testing project is in here.

Hope this is enough to get the conversation started and identify any other issues or conflicts!

@thymikee
Copy link
Member

Thanks for the thorough proposal! I think we could definitely make it a part of doctor. Furthermore, we could detect some specific issues and advise people to run doctor to help resolve them.

@molant molant changed the title Install development dependencies when missing ☂ Umbrella: Install development dependencies when missing Feb 15, 2020
@molant
Copy link
Contributor Author

molant commented Feb 21, 2020

I'm starting to look at this in more depth and here is my current proposal.

I've look at the current code and there's a tools/install.ts that defaults to hombrew for macOS. Even though Windows has chocolatey, it's not installed by default and as widely use. I think I prefer to stick to my plan of "manual" download and install. What I'm thinking is that instead of trying to abstract everything under install in the runAutomaticFix, each healthcheck should know how to get solved on each platform. An quick example could be:

export default {
  label: 'Python',
  getDiagnostics: async ({Languages}) => ({
    // ...
  }),
  runAutomaticFix: async ({loader}) => {
    switch(process.platform) {
       case 'win32': await windowsInstall(urlToDownload, command, label, loader); break;
       case 'darwin': await brewInstall({pkg, label, loader}); break;
       default: logManualInstallation(...); break;
    },
  },
} as HealthCheckInterface;

Another option (that I think I prefer) would be to have specific actions per platform and a default one in case it is not supported. That way we remove the switch (that will be repeated in all healthchecks). It will be the responsibility of whoever is calling runAutomaticFix to decide which one to run.

export default {
  label: 'Python',
  getDiagnostics: async ({Languages}) => ({
   // ...
  }),
  win32AutomaticFix: async () => { },
  darwinAutomaticFix: async () => { },
  runAutomaticFix: async () => { /* fallback scenario */ },  
} as HealthCheckInterface;

One of the pros of the latest approach is that it should be easy to look at a file and know what platform doesn't have an automatic fix.

  • Create a downloader.ts tool under cli/src/tools that will download any given URL to the OS tmp folder (and returning that path) using got (has progress events but it's 1.21MB) or node-fetch (no progress events and 153kB). I see you are using ora so I'm not sure about how to add a real progress bar. Maybe having the spinner and saying it might take a while is enough?

  • I don't think it makes a lot of sense to add a windowsInstall.ts. Each package will be installed differently (.msi, .exe, .zip, different commands, some require fake "user input", etc.). I'm planning on using execa just so there's less boilerplate. Not too big and should make the code more readable.

  • Create a updateWindowsEnvVariables.ts (or similar) under tools to update/create the user env variables.

  • envinfo can tell the installed Python and Java versions so I'll just expand cli/src/info/info.ts to request that information (and make whatever changes are needed).

For the testing strategy I'm thinking about using some mocks and look at:

  • Checking environment variables before/after
  • Look at output paths

Let me know what you think and if everything looks fine I'll start working on the Python healthcheck and make a draft PR to start looking at the changes!

@github-actions
Copy link

There hasn't been any activity on this issue in the past 3 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 7 days.

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

No branches or pull requests

2 participants