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

admin install linux #5

Draft
wants to merge 74 commits into
base: nagilson-admin-install
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
005f6ee
Introduce linux code patterns
nagilson May 18, 2023
ba19214
refactor most of the global sdk code to allow linux to be separated i…
nagilson May 23, 2023
4a5e04b
Fix some bugs so the code can get closer to running
nagilson May 24, 2023
1735ada
Remove failure test because I couldn't get the test runner to not sho…
nagilson May 30, 2023
b80a075
Port the documentation change stating how to test only a subset of fe…
nagilson May 30, 2023
0f07e17
rename listSDKS and listRuntimes to listNewestSDKs and listNewestRunt…
nagilson May 31, 2023
9ec2149
update tests to check for the newly added support phase
nagilson May 31, 2023
cfa6b32
Describe how to breakpoint the app
nagilson May 31, 2023
2a1cb21
update exported apis to have list newest sdks or runtimes
nagilson May 31, 2023
97f20d0
Update gitignore to ignore .d.ts and .js.map and .js files as they ca…
nagilson May 31, 2023
dbf4f81
rename commands to listNewestDotnets -> this is because the command l…
nagilson May 31, 2023
8dfb8fd
Merge branch 'nagilson-list-sdks' of https://github.com/nagilson/vsco…
nagilson May 31, 2023
42624f4
Fix a typo in sample command registration
nagilson May 31, 2023
2e57ddc
Remove unneeded change in license
nagilson May 31, 2023
a9834cb
Merge branch 'nagilson-list-sdks' of https://github.com/nagilson/vsco…
nagilson May 31, 2023
80989e6
Rename list newest sdks to newest dotnets that did not save in the la…
nagilson May 31, 2023
0a9c97d
Remove misleading information from a docstring
nagilson May 31, 2023
4f30e1d
remove trailing whitespace for lint
nagilson May 31, 2023
cc22387
Merge branch 'nagilson-list-sdks' of https://github.com/nagilson/vsco…
nagilson May 31, 2023
19ced1a
change listNewestDotnets to listVersions
nagilson Jun 5, 2023
541e652
add a sample function for the runtime extension as well as the sdk ex…
nagilson Jun 5, 2023
ef7a840
respond to all feedback except for the versioning file duplication
nagilson Jun 5, 2023
fba7914
respond to all pr feedback
nagilson Jun 5, 2023
b4e01de
remove the api from the runtime extension so its only in the sdk exte…
nagilson Jun 5, 2023
66c1f22
Dont check if not equal null and just check the item
nagilson Jun 5, 2023
575e4e4
fix lint issues
nagilson Jun 5, 2023
2360346
added not implemented code to interface to build
nagilson Jun 5, 2023
7677214
Merge branch 'nagilson-admin-install-linux' of https://github.com/nag…
nagilson Jun 5, 2023
724933f
remove unneeded includes
nagilson Jun 6, 2023
49b6c7d
clean up unneeded code for version resolver
nagilson Jun 6, 2023
9cdd7f9
remove the releases class as we can replace it with the external faci…
nagilson Jun 6, 2023
6fff95b
add sample command for the recommendedVersion command
nagilson Jun 6, 2023
df82241
respond to lint
nagilson Jun 6, 2023
e84dfbb
fix bad auto-generated imports
nagilson Jun 7, 2023
5d917d4
make a test more comprehensive
nagilson Jun 7, 2023
efcba6b
Merge pull request #791 from nagilson/nagilson-list-sdks
nagilson Jun 7, 2023
fc30ae9
Merge remote-tracking branch 'upstream/main' into nagilson-admin-inst…
nagilson Jun 7, 2023
5f9207e
finish merging with the changes to listVersions api
nagilson Jun 7, 2023
f777259
Remove ignored files
nagilson Jun 7, 2023
cb86525
Revert "Remove ignored files"
nagilson Jun 7, 2023
5aeea5e
Remove files that should be ignored
nagilson Jun 7, 2023
3dbed2d
bump vscode to support activation event removal and temporarily comme…
nagilson Jun 7, 2023
0f73e30
Use a simple type for distro instead of an enum
nagilson Jun 13, 2023
4d5f8e2
add back the support status enum because it separates the logic out f…
nagilson Jun 13, 2023
a144d7c
Move to linux line endings
Jun 13, 2023
f06f27a
Get distro detection to work
Jun 13, 2023
e70ddc4
Add logic to detect conflicting Linux SDKs for global installs and ad…
Jun 14, 2023
2a8d4cf
Break up the install verification into smaller functions. Next, check…
Jun 14, 2023
2649db1
use promise instead of void
nagilson Jun 15, 2023
568a953
Add distro-data and json parsing code, fix sudo parsing code (needs t…
nagilson Jun 15, 2023
a3dc8c5
Add WSL detection for running sudo or not, wrap the sudo lib to make …
nagilson Jun 19, 2023
054aa64
Fix some basic bugs with command parsing logic.
nagilson Jun 20, 2023
d277088
Bug fixes for global install, fix ubuntu json versions, add space in …
nagilson Jun 20, 2023
5606419
Force error on WSL because we cant run sudo through exec sync without…
nagilson Jun 20, 2023
63599b8
Move Command Execution to a separate class for mocking
nagilson Jun 20, 2023
b1f98d1
Add tests for every ubuntu command and add list runtimes command (not…
nagilson Jun 20, 2023
6e2c3ce
ALL Linux Distro Tests pass!
nagilson Jun 20, 2023
015cbba
Add tests for the version resolver and fix version bugs. Rename Linux…
nagilson Jun 22, 2023
80dd621
fix a bug with the version resolver where itd not find bad patch vers…
nagilson Jun 22, 2023
10dab4e
Add outlines for further tests for the InstallerResolver and the Linu…
nagilson Jun 26, 2023
8b4e207
Add a mock distro provider for testing the linux version resolver
nagilson Jun 27, 2023
370f3f6
Remove colons from the distrosupport file as they were not supposed t…
nagilson Jun 27, 2023
09f21ce
Example
sfoslund Oct 14, 2022
3429290
Bump vscode versions so that vsce package succeeds on the sample exte…
nagilson Jun 28, 2023
9f67837
Make all of the linux version resolver tests pass
nagilson Jun 28, 2023
d2c8d34
Prevent Running Sample Extension as a .VSIX
nagilson Jun 28, 2023
f2dd236
Implement tests for Global Installer Resolver. Rename classes to be s…
nagilson Jul 12, 2023
6228bd0
Add documentation we had internally to the repository.
nagilson Jul 12, 2023
624b2d1
Fix Windows Registry Check and Add Tests For It
nagilson Jul 13, 2023
b041e1c
Pass all windows and mac installer tests and fix exposed bugs
nagilson Jul 13, 2023
047bcc8
Fix the PATH Logic for Global Installs and E2E Test.
nagilson Jul 13, 2023
babf6a9
Add a document describing the global installs
nagilson Jul 14, 2023
a849b2e
Add images to the global install change document
nagilson Jul 14, 2023
ae4fe99
Fix Installer Status Code Handling + Partial Installs
nagilson Jul 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ project.lock.json
*.ncrunchsolution
*.*sdf
*.ipch
*.js
*.d.ts
*.js.map
.build/
.vs/
launchSettings.json
Expand Down
16 changes: 11 additions & 5 deletions Documentation/contributing-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ You can contribute to .NET Core with issues and PRs. Simply filing issues for pr

We use and recommend the following workflow:

1. Create an issue for your work.
1. Create an issue for your work.
- You can skip this step for trivial changes.
- Reuse an existing issue on the topic, if there is one.
- Use [CODE_OWNERS.TXT](../CODE_OWNERS.txt) to find relevant maintainers and @ mention them to ask for feedback on your issue.
- Get agreement from the team and the community that your proposed change is a good one.
- If your change adds a new API, follow the [API Review Process](https://github.com/dotnet/corefx/blob/main/Documentation/project-docs/api-review-process.md) (but replace CoreFX with this repo).
- If your change adds a new API, follow the [API Review Process](https://github.com/dotnet/corefx/blob/main/Documentation/project-docs/api-review-process.md) (but replace CoreFX with this repo).
- Clearly state that you are going to take on implementing it, if that's the case. You can request that the issue be assigned to you. Note: The issue filer and the implementer don't have to be the same person.
2. Create a personal fork of the repository on GitHub (if you don't already have one).
3. Create a branch off of main (`git checkout -b mybranch`).
- Name the branch so that it clearly communicates your intentions, such as issue-123 or githubhandle-issue.
3. Create a branch off of main (`git checkout -b mybranch`).
- Name the branch so that it clearly communicates your intentions, such as issue-123 or githubhandle-issue.
- Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork.
4. Make and commit your changes.
- Please follow our [Commit Messages](contributing.md#commit-messages) guidance.
5. Add new tests corresponding to your change, if applicable.
If you are having difficulty debugging changes, note that you can add breakpoints into the tests for the library, runtime, or SDK by opening their corresponding workspace folder and launching the debug tab for their tests in VS Code. If you want to breakpoint the code, you'll need to breakpoint the test in typescript, but then every reload add breakpoints to the JS code generated from the typescript code if you want to debug code outside of the tests thesmelves that the tests run.
6. Build the repository with your changes.
- Make sure that the builds are clean.
- Make sure that the tests are all passing, including your new tests.
Expand All @@ -37,6 +38,11 @@ Note: It is OK to create your PR as "[WIP]" on the upstream repo before the impl

Before making a pull request, be sure to build and test your changes locally with the build script ([windows](https://github.com/dotnet/vscode-dotnet-runtime/blob/main/build.cmd), [mac](https://github.com/dotnet/vscode-dotnet-runtime/blob/main/build.sh)) and test script ([windows](https://github.com/dotnet/vscode-dotnet-runtime/blob/main/test.cmd), [mac](https://github.com/dotnet/vscode-dotnet-runtime/blob/main/test.sh)). To lint your changes, run the test script with the parameter `--tslint`

You can also test only a specific set of tests using the following parameters with the test script:
Test SDK Extension Only: `test sdk` (Tests the SDK extension only.)
Test SDK Extension Only: `test rnt` (Tests the runtime extension only.)
Test SDK Extension Only: `test lib` (Tests the library only.)

## Building a .VSIX

To build an installable .vsix file locally, navigate to the directory containing the extension's package.json (either `vscode-dotnet-runtime-extension` or `vscode-dotnet-sdk-extension`) run the following commands:
Expand All @@ -54,7 +60,7 @@ If the CI build fails for any reason, the PR issue will be updated with a link t

## PR Feedback

Microsoft team and community members will provide feedback on your change. Community feedback is highly valued. You will often see the absence of team feedback if the community has already provided good review feedback.
Microsoft team and community members will provide feedback on your change. Community feedback is highly valued. You will often see the absence of team feedback if the community has already provided good review feedback.

1 or more Microsoft team members will review every PR prior to merge. They will often reply with "LGTM, modulo comments". That means that the PR will be merged once the feedback is resolved. "LGTM" == "looks good to me".

Expand Down
78 changes: 39 additions & 39 deletions Documentation/dev-spec.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
# .NET Runtime Acquisition Strategy
## Common Among All Scenarios
- Users (extension authors) ensure that they have a runtime installed by calling the `acquire` command, providing a Major.Minor version to install.
- Users are expected to call us on extension startup to ensure that the runtime exists.
- Downloaded runtimes are stored in [extension global storage](https://code.visualstudio.com/api/extension-capabilities/common-capabilities#data-storage).
## Scenarios
### First Acquisition
- Resolve version by fetching release.json
- If we are offline, we will fail here because the user also will not be able to download a runtime offline.
- Check if version has been installed previously or is currently being installed
- Fetch dotnet-install script
- Install runtime via script
- Validate installation was successful
- Return path to runtime
### Subsequent Acquisitions (No Runtime Patches)
- Resolve version with the cached release.json
- We will update release.json in the background. If we are offline this will fail silently, which is fine as we can use the cached version.
- Check if version has been installed previously or is currently being installed
- As the resolved version is already installed, return path to runtime
Note: This scenario can be conducted offline successfully.
### Subsequent Acquisitions (Runtime Patche Released)
- Resolve version with the cached release.json
- We will update release.json in the background.
- **Note**: For efficiency, we do not block on release.json acquisition. This means that we may not install the most updated runtime until the following acquisition (once the release.json with the update has been acquired and cached).
- Check if version has been installed previously or is currently being installed
- Install runtime via cached install script
- We will update the install script in the background. If we are offline this will fail silently.
- Validate installation was successful
- Return path to runtime
# .NET Runtime Acquisition Strategy

## Common Among All Scenarios

- Users (extension authors) ensure that they have a runtime installed by calling the `acquire` command, providing a Major.Minor version to install.
- Users are expected to call us on extension startup to ensure that the runtime exists.
- Downloaded runtimes are stored in [extension global storage](https://code.visualstudio.com/api/extension-capabilities/common-capabilities#data-storage).

## Scenarios

### First Acquisition

- Resolve version by fetching release.json
- If we are offline, we will fail here because the user also will not be able to download a runtime offline.
- Check if version has been installed previously or is currently being installed
- Fetch dotnet-install script
- Install runtime via script
- Validate installation was successful
- Return path to runtime

### Subsequent Acquisitions (No Runtime Patches)

- Resolve version with the cached release.json
- We will update release.json in the background. If we are offline this will fail silently, which is fine as we can use the cached version.
- Check if version has been installed previously or is currently being installed
- As the resolved version is already installed, return path to runtime

Note: This scenario can be conducted offline successfully.

### Subsequent Acquisitions (Runtime Patche Released)

- Resolve version with the cached release.json
- We will update release.json in the background.
- **Note**: For efficiency, we do not block on release.json acquisition. This means that we may not install the most updated runtime until the following acquisition (once the release.json with the update has been acquired and cached).
- Check if version has been installed previously or is currently being installed
- Install runtime via cached install script
- We will update the install script in the background. If we are offline this will fail silently.
- Validate installation was successful
- Return path to runtime
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
! This PR Description is a copy of the document made in `\Documentation\global-installs\early-global-code-changes-overview.md`)

# .NET Global Acquisition Engineering Spec

Resolves: https://github.com/dotnet/vscode-dotnet-runtime/issues/763.

Described below is an overview of the changes made to enable supporting global .NET SDK installs via our VS Code Extensions. This document's original function was to help during PR Review, as this functionality was added in 1-go. (This is terrible and I am sorry: but we had initially struggled to get reviewers during development and were trying to move swiftly.)

# Extension Plan

We have added functionality to the .NET SDK Extension to install the SDK Globally. That extension will also be able to install the .NET Runtime globally for use by the .NET SDK.

> :apple: The .NET Education Bundle APIs will be unaffected as we have just added a global option, however the extension will be re-branded to remove the remarks of 'do NOT use,' as well as the 'education bundle' marketing.

The API will change to installing the SDK globally by default in the future. (Because we do not want people to rely on the local SDK install feature in production, as it was intended only for the education bundle.) We are waiting for the education bundle to be prepared for that breaking change.

In the initial set of changes, the branding is not included. The changes to extension documentation, names, etc, will go in a separate PR.

# Overview of How Global Installs are Done

> :exclamation: For Windows and Mac, we can leverage the .NET Installer that we ship. We can determine the correct installer and simply download and then execute it.

For Windows, if we are already running VS Code with admin, we can simply download and run the installer in quiet mode and the user will not see anything.

![image](https://github.com/dotnet/vscode-dotnet-runtime/assets/23152278/fba4223a-140c-40d5-b17e-94ce0b25a952)


In any other case on windows, and always on mac, we can make the .NET Installer appear above VS Code. That will handle any elevation/UAC prompts for us. It also will handle conflicting SDKs that could be on the machine, setup issues with currently running versions of dotnet, etc, and provides a consistent already-built user experience. We have greatly simplified our job by just downloading the correct installer file from your machine using data available from our releases APIs, and then executing said installer.

> :fire: For Linux we essentially had to write our own installer. We have a separate linux document, `[here](linux-global-install-design.md)` which I would suggest checking out.

The TLDR is the following: It uses the distro package manager to install the dotnet package on the system using commands such as `apt-get`. It will use the dotnet packages provided by the distro if it's version includes such packages, otherwise it will attempt to use the Microsoft feed packages.

Our initial push includes Ubuntu. We intend add RHEL and other supported linux versions within VS Code before launch. We also have a policy in place for the community to add support to other distros described in the linux document. :star: In the intial set of changes, only Ubuntu is supported.

A threat model must be developed. It will not be part of the initial PR.

# Changes Made

For those reviewing the code changes, it may be best to look at the isolated files and their tests so the review can be broken up into chunks. The changes should also be investigated from an end-to-end perspective. However, the changes are minimal and copy existing patterns, with a global flag that branches to its own logic. Here are the working pieces that were added/changed:

### Review Suggestions

The code should be under the most scrutiny. We will have PMs review the error messages. For decisions such as, 'WSL is not supported,' or, 'We support XYZ Distros,' or 'We do/don't allow this install,' every decision has been vetted by 3-5+ PMs, so while questioning these decisions may be of use, it is not something a reviewer needs to focus on.

## Version Resolver

The version resolver now has functionality to extract the feature band, patch version, major, minor, and more from modern .NET Core Versions. We don't expect this will be used to install older .NET versions or plan to support that, so this is OK.

## Global Installer Resolver

As defined in the spec here https://github.com/dotnet/vscode-dotnet-runtime/issues/763, users can request the SDK using different version formats when making a global request.

This class uses the new VersionResolver functionality to determine what version the user should install (aka the newest version that matches what they requested.) It should find the correct installer file to download for windows and mac and save a link to that file for others to access.

## Linux Version Resolver

The Linux Version Resolver has a few purposes. One, it determines what distro and version you are running on, and creates the correct distro class for you. Currently there is no special distro logic in place since only Ubuntu is supported, however, we anticipate the factory function this class has will be expanded to support more distros that have unique requirements to do an installation.

This class is also responsible for calling the correct APIs to validate and ensure that the correct action is taken: aka, if we can update instead of installing, if we do not need to install because an install already exists, or if we cannot install, this class handles all of that logic.

## Linux Installer

The Linux Global Installer exists to provide high level visiblity into the install so code calling the installer can make decisions it needs to make about the install, and mostly so we can match the API that is used by the windows and mac installer.

## GenericDistroProvider

All of the distro specific logic has been extracted out of the linux version resolver and put into this class. It is essentially a 'front' into the distro.json file that contains all of the commands that need to be executed for a particular distro to do an install.

> :question: We use a json file for several reasons which is described in the linux document. It makes it easier to support more distros and accept community contributions by holding all of the functions that are specific to a distro one 1 file. It makes it so we can make minimal code changes and just read the json file for each distro instead of writing unique code for each distro. It also makes it easier to transition to using a live API service for distro version support details once that is created.

The Generic Distro Provider was written under Ubuntu, but it is also 'generic' in the sense that for most commands, it simply runs the command in the json file for the matching distro and version, so it is relatively platform-agnostic. Ubuntu does not require much special logic to capture the output of the commands or run the commands, and so it is extendable to other distros.

> :exclamation: This interface currently supports more than what's used and exposed by our commands. This code has been tested. For example, we add the ability to uninstall the SDK, however, we have yet to add a global uninstall command. We do not have strong demand for such an API yet. But as we want to accept community contributions, we wanted to future-proof this API so everything that we could possibly need has been implemented.

## Windows & Mac Installer

The Windows and Mac installer provides ability to download the install file correctly and execute it using the correct flags. It will also have sign-checking in the future.

## File Utilities

This class allows us to check if we are elevated and will host any file related operations needed for managing installs.

## Command Executor

This library runs a command you give it. For linux, it will handle the sudo elevation prompts that are needed to gain elevation.

For sudo elevation we rely on the built-in `@vscode/sudo` library which will show a prompt above the user like that is not super encouraging. We plan to make changes in their library to improve the UX.

<img width="423" alt="MicrosoftTeams-image (1)" src="https://github.com/dotnet/vscode-dotnet-runtime/assets/23152278/6a35ceb0-78a5-4f89-990d-d3ea4425447e">


One of the key purposes of this class is to make the global installs mockable and testable, as we don't want to leave global install artifacts on dev-box or pipeline machines. It also enables us to fake responses from the OS when running commands or installs.
Loading