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

Build and test images #65

Merged
merged 9 commits into from
Jan 8, 2018
Merged

Build and test images #65

merged 9 commits into from
Jan 8, 2018

Conversation

ravimeda
Copy link
Member

@ravimeda ravimeda commented Jan 4, 2018

Unit tests to validate the framework images are needed. Such validation is available in dotnet-docker. This PR lays the foundation to build and test the framework images. Current changes use ImageBuilder to build the framework images locally and in CI. A subsequent PR will bring the unit tests.

Fixes #66

@ravimeda ravimeda self-assigned this Jan 4, 2018
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$(docker version) | ForEach-Object { Write-Host "$_" }
Copy link
Member Author

@ravimeda ravimeda Jan 4, 2018

Choose a reason for hiding this comment

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

Docker version is emitted here and in ImageBuilder. Either move this statement into the if block where ImageBuilder image is pulled (or) remove version emit in ImageBuilder itself. Any preferences? #Closed

Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Since ImageBuilder is emitting, I don't think this is necessary at all. #Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

Agree. My thinking earlier was - Docker is a prerequisite for the build-test experience. If a prerequisite is not available, in this case Docker version command fails, then exit immediately. #Closed

}
if (-not [string]::IsNullOrEmpty($OSFilter))
{
$buildFilter = "$buildFilter$OSFilter/*"
Copy link
Member Author

@ravimeda ravimeda Jan 4, 2018

Choose a reason for hiding this comment

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

-OSFilter 1709 would match all 1709 Dockerfiles. So one might expect -OSFilter ltsc would match all ltsc. But it wouldn't. This is due to 2016 suffix, which means -OSFilter ltsc2016 is how the parameter value should be for LTSC images.
Any preferences on the usage? #Closed

Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Seems like there should be a - if an OSFilter is specified but not a VersionFilter - e.g. $buildFilter-$OSFilter/*.

I think it is just fine that -OSFilter ltsc is not supported. The user can specify *ltsc* for this to work. #Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

*ltsc* sounds fine.

Hyphen - is not required. But would make it more accurate. I will update this as follows -

$buildFilter = "*"
if (-not [string]::IsNullOrEmpty($VersionFilter))
{
    $buildFilter = "$VersionFilter-$buildFilter"
}
if (-not [string]::IsNullOrEmpty($OSFilter))
{
    if ([string]::IsNullOrEmpty($VersionFilter))
    {
        $buildFilter = "$buildFilter-$OSFilter/*"
    }
    else
    {
        $buildFilter = "$buildFilter$OSFilter/*"
    }
}
``` #Closed

netci.groovy Outdated
def branch = GithubBranchName
def isPR = true
def platformList = ['Windows_2016:WindowsServerCore-ltsc2016', 'Windows_2016:WindowsServerCore-1709']
def versionList = ['3.5', '4.6.2', '4.7.1']
Copy link
Member Author

@ravimeda ravimeda Jan 4, 2018

Choose a reason for hiding this comment

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

Each time a new version is added/removed, one has to edit this list. In a way it is good to revisit the coverage but there is maintenance cost. #Closed

Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Shouldn't 4.7 be included? #Resolved

Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

This is the same pattern used in .NET Core. It has to be this way if we want to run each version as a separate leg. I think the real issue here is the CI system in that it is incapable of picking up changes to CI immediately. #Resolved

Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Just realized there is an issue here - 3.5 and 4.7.1 are the only versions supported on 1709. You can see it in https://github.com/Microsoft/dotnet-framework-docker/blob/master/build-pipeline/pipeline.json. CI is going to have to account for this. #Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

Good point! I will update accordingly. #Closed

netci.groovy Outdated
def branch = GithubBranchName
def isPR = true
def platformList = ['Windows_2016:WindowsServerCore-ltsc2016', 'Windows_2016:WindowsServerCore-1709']
def versionList = ['3.5', '4.6.2', '4.7.1']
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Shouldn't 4.7 be included? #Resolved

netci.groovy Outdated
def branch = GithubBranchName
def isPR = true
def platformList = ['Windows_2016:WindowsServerCore-ltsc2016', 'Windows_2016:WindowsServerCore-1709']
def versionList = ['3.5', '4.6.2', '4.7.1']
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

This is the same pattern used in .NET Core. It has to be this way if we want to run each version as a separate leg. I think the real issue here is the CI system in that it is incapable of picking up changes to CI immediately. #Resolved

netci.groovy Outdated
def machineLabel = 'latest-docker'

versionList.each { version ->
def newJobName = Utilities.getFullJobName(project, "${containerOS}_${version}", isPR)
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

I think it may be easier to reason over this name if it were changed to ${version}-${containerOS} because this will align with the folder names #Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

Ok. will update. #Closed

@@ -0,0 +1,32 @@
import jobs.generation.Utilities
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

You are going to need to make a PR to change https://github.com/dotnet/dotnet-ci/blob/master/data/repolist.txt as well in order to get CI enabled. #Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

Done. #Closed

}

$imageBuilderExe = [System.IO.Path]::Combine($imageBuilderFolder, "image-builder", "Microsoft.DotNet.ImageBuilder.exe")
$imageBuilderArgs = 'build --repo microsoft/dotnet-framework --path "$buildFilter"'
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

This doesn't look correct - --repo microsoft/dotnet-framework. This causes microsoft/dotnet-framework-build to be skipped. I don't think the --repo filter should be specified at all. #Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

You are correct. repo is not needed for build command. It is needed for other commands such as the one that generates and updates readme. #Closed

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$(docker version) | ForEach-Object { Write-Host "$_" }
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Since ImageBuilder is emitting, I don't think this is necessary at all. #Resolved

$buildFilter = "$buildFilter$OSFilter/*"
}

$imageBuilderFolder = ".Microsoft.DotNet.ImageBuilder"
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

I think it may be better to explicitly add the PSScriptRoot to this path so that there is consistence in case the script is not run from root.
#Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

Ok. Will update. #Closed

}

$imageBuilderFolder = ".Microsoft.DotNet.ImageBuilder"
if (-not (Test-Path -Path "$imageBuilderFolder" -PathType Container))
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

I think we should consider checking for the presence of the exe. If any of the docker steps fail, the script should retry on additional runs.
#Resolved

Copy link
Member Author

@ravimeda ravimeda Jan 5, 2018

Choose a reason for hiding this comment

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

Good point! Will update accordingly. #Closed

}
if (-not [string]::IsNullOrEmpty($OSFilter))
{
$buildFilter = "$buildFilter$OSFilter/*"
Copy link
Member

@MichaelSimons MichaelSimons Jan 4, 2018

Choose a reason for hiding this comment

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

Seems like there should be a - if an OSFilter is specified but not a VersionFilter - e.g. $buildFilter-$OSFilter/*.

I think it is just fine that -OSFilter ltsc is not supported. The user can specify *ltsc* for this to work. #Resolved

try {
New-Item -Path "$imageBuilderFolder" -ItemType Directory -Force | Out-Null

Invoke-Expression "docker pull $imageBuilderImageName"
Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed offline, it would be simpler if ImageBuilder binaries were available as a compressed file hosted in Azure storage. Acquiring ImageBuilder would then be simpler - download and extract,

Copy link
Member Author

Choose a reason for hiding this comment

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

netci.groovy Outdated
def(hostOS, containerOS) = platform.tokenize(':')
def machineLabel = 'latest-docker'

if (containerOS == 'WindowsServerCore-1709') {
Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

Per 1f61282, this can now be updated to a single static list - ['3.5', '4.*'] #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok. Updated as def versionList = ['3.5', '4.*']

}

$imageBuilderFolder = [System.IO.Path]::Combine("$PSScriptRoot", ".Microsoft.DotNet.ImageBuilder")
$imageBuilderExe = [System.IO.Path]::Combine($imageBuilderFolder, "image-builder", "Microsoft.DotNet.ImageBuilder.exe")
Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

Why create the image-builder sub folder? This seems to add unnecessary nesting. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed offline, this is due to moby/moby#34638

try {
New-Item -Path "$imageBuilderFolder" -ItemType Directory -Force | Out-Null

Invoke-Expression "docker pull $imageBuilderImageName"
Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

I think the docker pull is the only thing that should be in the retry. It is the only call that is intermittent. If the other cmds fail, something is drastically wrong and a retry isn't going to succeed.. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok. Will move rest of the command outside wait-retry block.

Get-ImageBuilder
}

$imageBuilderArgs = 'build --path "$buildFilter"'
Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

Now that the tests have been checked in, you will need to pass the OSFilter and VersionFilter as build-args. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Clarification - did you mean invoke tests as in -
./tests/run-test.ps1 -VersionFilter $VersionFilter -OSFilter $OSFilter

Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

I mean you will need to pass in `--test-var VersionFilter=$VersionFilter --test-var OSFilter=$OSFilter' into ImageBuilder #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok. I didn't notice the recent commit (e618fa1) that introduced testCommands section in the manifest. Yes, I will pass those args.

$ErrorActionPreference = 'Stop'

$buildFilter = "*"
if (-not [string]::IsNullOrEmpty($VersionFilter))
Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

What do you think about defaulting VersionFilter and OSFilter to '*' if not specified? Then this logic could be simplified to - buildFilter = "{VersionFilter}-{OSFilter}/*" #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this works. Thanks!

$imageBuilderContainerName = "ImageBuilder-$(Get-Date -Format yyyyMMddhhmmss)"
New-Item -Path "$imageBuilderFolder" -ItemType Directory -Force | Out-Null

$attempt = 0
Copy link
Member

@MichaelSimons MichaelSimons Jan 5, 2018

Choose a reason for hiding this comment

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

I think it would help the readability to factor out the logic to perform the retry into a separate function. #Resolved

$imageBuilderImageName = 'microsoft/dotnet-buildtools-prereqs:image-builder-nanoserver-20180105103709'
$imageBuilderContainerName = "ImageBuilder-$(Get-Date -Format yyyyMMddhhmmss)"
New-Item -Path "$imageBuilderFolder" -ItemType Directory -Force | Out-Null
function ExecuteCommand {
Copy link
Member

@MichaelSimons MichaelSimons Jan 8, 2018

Choose a reason for hiding this comment

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

I think it would be helpful if the name called out that that retry logic exists. This helps clarify why the function is used over Invoke-Expression. e.g. ExecuteWithRetry #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

I did consider the name ExecuteWithRetry. However, with the word Retry the questions that come to my (user's) mind is - how do I set the number of retries, wait time? Is the wait time in seconds or minutes, etc.

Copy link
Member

Choose a reason for hiding this comment

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

Since this is a local method, I think it is reasonable for the reader to look at the implementation. I think ExecuteWithRetry addresses the point I raised on why the method exists over using the built in Invoke-Expression and why this method is only being used for the pull cmd.

if ($IsDryRun)
{
$imageBuilderArgs = "build --path $buildFilter --test-var VersionFilter=$VersionFilter --test-var OSFilter=$OSFilter"
if ($IsDryRun) {
Copy link
Member

@MichaelSimons MichaelSimons Jan 8, 2018

Choose a reason for hiding this comment

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

What do you think about replacing the IsDryRun parameter with a string CustomImageBuilderArgs? This would make this script more robust so that it could be used within the official builds. The CustomImageBuilderArgs could be used to specify the push related arguments. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

To clarify - change the type of the parameter to string, and append the parameter value to the default args. So in that case, I think ImageBuilderCustomArgs would convey better, and the logic would be -

$imageBuilderArgs = "build --path $buildFilter --test-var VersionFilter=$VersionFilter --test-var OSFilter=$OSFilter"
if ([string]::IsNullOrWhiteSpace($ImageBuilderCustomArgs)) {
    $imageBuilderArgs += " $ImageBuilderCustomArgs"
}

Copy link
Member

Choose a reason for hiding this comment

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

yes that is what I was thinking - and I like your suggested name.

@ravimeda
Copy link
Member Author

ravimeda commented Jan 8, 2018

@dotnet-bot test ci please

@ravimeda
Copy link
Member Author

ravimeda commented Jan 8, 2018

@dotnet-bot test ci please

@ravimeda ravimeda merged commit dfe728b into microsoft:master Jan 8, 2018
@ravimeda
Copy link
Member Author

ravimeda commented Jan 8, 2018

Thanks @mmitche for enabling CI!

@ravimeda ravimeda deleted the utests branch February 13, 2018 16:07
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.

None yet

2 participants