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

[xaprepare] Download and install dotnet ourselves, with caching #7026

Merged
merged 6 commits into from
May 25, 2022

Conversation

grendello
Copy link
Contributor

Context: dotnet/install-scripts#15
Context: https://dot.net/v1/dotnet-install.sh
Context: https://dot.net/v1/dotnet-install.ps1

We've been installing dotnet versions using the Unix shell and Windows
powershell scripts, which work fine. However, they do not cache the
downloaded archive and therefore we end up re-downloading the same
archive over and over again on CI servers as well as locally.
Additionally, if one finds themselves without internet connection,
there's no way to install the required version of dotnet.

The installation scripts don't provide a way to cache the payloads and
they appear to be in maintenance mode, so there's rather no chance to
add caching support to them.

Instead of relying on the scripts, we can do the downloading and
installation ourselves, which lets us take the first step towards fully
"offline" builds (and smaller downloads on CI servers).

With this commit, we will cache both the scripts and the payloads and we
will perform the installation ourselves. Scripts are still used to
obtain the download URL(s) for dotnet and as a fallback should our
attempt to download dotnet archives fail.

@grendello
Copy link
Contributor Author

I believe the test failures here are irrelevant

Copy link
Member

@jonathanpeppers jonathanpeppers 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 if it improves local dev (& CI times, too).

We'll have an issue if we ever need to use our internal fork, see:

https://github.com/xamarin/xamarin-android-private/commit/5c8a5432fa20e26926caee470ed3391010d33a93#diff-0c0b66132e0302109aa285ab068fe84839ed41e1898ef711300b45d2f61ab1c7R101

If we have to consume an internal .NET build with a security fix, we use --internal --azure-feed --feed-credential. We've not had to use this yet, maybe we can just wait until then?

@grendello
Copy link
Contributor Author

@jonathanpeppers if we need to do that, it will be easy to modify our code for this

@grendello grendello requested a review from dellis1972 as a code owner May 24, 2022 13:37
@grendello grendello force-pushed the dotnet-download-caching branch from d50c678 to 1ae83e9 Compare May 24, 2022 13:38
args.AddRange (new string [] { "-Runtime", "dotnet" });
}
if (onlyGetUrls) {
args.Add ("--dry-run");
Copy link
Contributor

Choose a reason for hiding this comment

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

don't we already add --dry-run on line 163? Do we need this as well or do we need the arg on line 163?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good eye, it's a mistake, will fix

}

if (!ReportAndCheckCached (message)) {
return false;
Copy link
Member

@pjcollins pjcollins May 24, 2022

Choose a reason for hiding this comment

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

We shouldn't return here if the GetDownloadSizeWithStatus check is non-fatal.

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 return false from ReportAndCheckCached only when the script isn't found in ~/android-archives/. The idea was to let the code continue if we have the script, assuming that the network failures here would be because of actually having no internet access, but I think it does make more sense to make it non-critical in all cases. Will update

grendello added 5 commits May 24, 2022 19:17
Context: dotnet/install-scripts#15
Context: https://dot.net/v1/dotnet-install.sh
Context: https://dot.net/v1/dotnet-install.ps1

We've been installing dotnet versions using the Unix shell and Windows
powershell scripts, which work fine.  However, they do not cache the
downloaded archive and therefore we end up re-downloading the same
archive over and over again on CI servers as well as locally.
Additionally, if one finds themselves without internet connection,
there's no way to install the required version of dotnet.

The installation scripts don't provide a way to cache the payloads and
they appear to be in maintenance mode, so there's rather no chance to
add caching support to them.

Instead of relying on the scripts, we can do the downloading and
installation ourselves, which lets us take the first step towards fully
"offline" builds (and smaller downloads on CI servers).

With this commit, we will cache both the scripts and the payloads and we
will perform the installation ourselves.  Scripts are still used to
obtain the download URL(s) for dotnet and as a fallback should our
attempt to download dotnet archives fail.
@grendello grendello force-pushed the dotnet-download-caching branch from 7f6bbba to 9518175 Compare May 24, 2022 17:17
The reason is that if the size check fails, the subsequent Download
will throw an exception, terminating xaprepare. We don't want that
because dotnet install scripts can return multiple URLs and not all of
them will be available, so we need to try them all.
@jonpryor
Copy link
Member

For the commit message, "what does this do?"

What this change does is run:

% dotnet-install.sh --version 7.0.100-preview.5.22273.1 --install-dir IGNORED --verbose --dry-run  | grep 'dotnet-install: URL'

Which returns strings such as:

dotnet-install: URL #0 - primary: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
dotnet-install: URL #1 - legacy: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz
dotnet-install: URL #2 - primary: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
dotnet-install: URL #3 - legacy: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz

We then split each line on :, grab the 3rd item (the URL), and then download the URLs into ~/android-archives. Not all URLs are valid; for me, the first two URLs are HTTP-404s with an XML payload saying The specified blob does not exist.

When we want to actually install/provision dotnet, we extract the downloaded archive into bin/$(Configuration).

@grendello
Copy link
Contributor Author

grendello commented May 24, 2022

@jonpryor yes, some of those URLs are 404, we keep on trying until we find one that works or we run out of URLs.

@jonpryor
Copy link
Member

[xaprepare] cache .NET install artifacts (#7026)

Context: https://github.com/dotnet/install-scripts/issues/15
Context: https://dot.net/v1/dotnet-install.sh
Context: https://dot.net/v1/dotnet-install.ps1

We've been installing dotnet versions using the [`dotnet-install`][0]
scripts for Unix & Windows.  However, they do not cache the
downloaded archive, and therefore we end up re-downloading the same
archive over and over again.

Additionally, if one finds themselves without an internet connection,
there's no way to easily install the required version of dotnet.

The installation scripts don't provide a way to cache the payloads
and they appear to be in maintenance mode (dotnet/install-scripts#15),
so there doesn't appear to be a chance to add caching support to them.

Fortunately, we can "ask" the scripts what they're downloading:

	% curl -o dotnet-install.sh 'https://dot.net/v1/dotnet-install.sh'
	% ./dotnet-install.sh --version 7.0.100-preview.5.22273.1 --verbose --dry-run  \
	| grep 'dotnet-install: URL'

This returns a list of URLs, which may or may not exist:

	dotnet-install: URL #0 - primary: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
	dotnet-install: URL #1 - legacy: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz
	dotnet-install: URL #2 - primary: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
	dotnet-install: URL #3 - legacy: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz

We now parse this output, extract the URLs, then download and cache
the URL contents into `$(AndroidToolchainCacheDirectory)`.

When we need to install .NET, we just extract the cached archive
into the appropriate directory.

If no `dotnet-install: URL…` messages are generated, then we run
the `dotnet-install` script as we previously did.

This process lets us take a first step towards fully "offline" builds,
along with smaller downloads on CI servers.

[0]: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script

@jonpryor jonpryor merged commit 90aec41 into dotnet:main May 25, 2022
@grendello grendello deleted the dotnet-download-caching branch May 25, 2022 20:09
simonrozsival pushed a commit to simonrozsival/xamarin-android that referenced this pull request May 31, 2022
Context: dotnet/install-scripts#15
Context: https://dot.net/v1/dotnet-install.sh
Context: https://dot.net/v1/dotnet-install.ps1

We've been installing dotnet versions using the [`dotnet-install`][0]
scripts for Unix & Windows.  However, they do not cache the
downloaded archive, and therefore we end up re-downloading the same
archive over and over again.

Additionally, if one finds themselves without an internet connection,
there's no way to easily install the required version of dotnet.

The installation scripts don't provide a way to cache the payloads
and they appear to be in maintenance mode (dotnet/install-scripts#15),
so there doesn't appear to be a chance to add caching support to them.

Fortunately, we can "ask" the scripts what they're downloading:

	% curl -o dotnet-install.sh 'https://dot.net/v1/dotnet-install.sh'
	% ./dotnet-install.sh --version 7.0.100-preview.5.22273.1 --verbose --dry-run  \
	| grep 'dotnet-install: URL'

This returns a list of URLs, which may or may not exist:

	dotnet-install: URL #0 - primary: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
	dotnet-install: URL #1 - legacy: https://dotnetcli.azureedge.net/dotnet/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz
	dotnet-install: URL #2 - primary: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-sdk-7.0.100-preview.5.22273.1-osx-x64.tar.gz
	dotnet-install: URL #3 - legacy: https://dotnetbuilds.azureedge.net/public/Sdk/7.0.100-preview.5.22273.1/dotnet-dev-osx-x64.7.0.100-preview.5.22273.1.tar.gz

We now parse this output, extract the URLs, then download and cache
the URL contents into `$(AndroidToolchainCacheDirectory)`.

When we need to install .NET, we just extract the cached archive
into the appropriate directory.

If no `dotnet-install: URL…` messages are generated, then we run
the `dotnet-install` script as we previously did.

This process lets us take a first step towards fully "offline" builds,
along with smaller downloads on CI servers.

[0]: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script
@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2024
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.

5 participants