diff --git a/.github/skills/update-expected-app-size/SKILL.md b/.github/skills/update-expected-app-size/SKILL.md index 88d888c17a0..1537c6cc59b 100644 --- a/.github/skills/update-expected-app-size/SKILL.md +++ b/.github/skills/update-expected-app-size/SKILL.md @@ -21,13 +21,13 @@ Download updated expected app size files from Azure DevOps artifacts for the cur The app size tests (`tests/dotnet/UnitTests/AppSizeTest.cs`) compare the built app's size and preserved APIs against expected files stored in `tests/dotnet/UnitTests/expected/`. When the test detects a difference and `WRITE_KNOWN_FAILURES` is not set, it writes the updated expected file to `$(Build.ArtifactStagingDirectory)/updated-expected-sizes/`, and a pipeline step publishes this directory as a build artifact. -The artifact name follows the pattern `updated-expected-sizes-{testPrefix}-{attempt}` (e.g., `updated-expected-sizes-dotnettests_ios-1`). Inside the artifact, files are named: -- `{Platform}-{Runtime}-size.txt` — e.g., `iOS-MonoVM-size.txt` -- `{Platform}-{Runtime}-preservedapis.txt` — e.g., `iOS-MonoVM-preservedapis.txt` +The artifact name follows the pattern `{uploadPrefix}updated-expected-sizes-{testPrefix}-{attempt}` (e.g., `updated-expected-sizes-dotnettests_ios-1`). Inside the artifact, files are named after the test variant: +- `{Platform}-{Variant}-size.txt` — e.g., `iOS-MonoVM-size.txt`, `iOS-MonoVM-interpreter-size.txt`, `iOS-NativeAOT-TrimmableStatic-size.txt`, `MacOSX-CoreCLR-Interpreter-size.txt` +- `{Platform}-{Variant}-preservedapis.txt` — e.g., `iOS-MonoVM-preservedapis.txt`, `MacCatalyst-MonoVM-interpreter-preservedapis.txt` The expected files on disk are at: -- `tests/dotnet/UnitTests/expected/{Platform}-{Runtime}-size.txt` -- `tests/dotnet/UnitTests/expected/{Platform}-{Runtime}-preservedapis.txt` +- `tests/dotnet/UnitTests/expected/{Platform}-{Variant}-size.txt` +- `tests/dotnet/UnitTests/expected/{Platform}-{Variant}-preservedapis.txt` ## Workflow @@ -111,8 +111,8 @@ After placing the files: If automated download fails (auth issues, etc.), provide the user with: 1. The Azure DevOps build URL 2. Instructions to navigate to the build → Summary → Artifacts section -3. Look for individual artifacts whose names match the patterns above -4. Download each file and place it as `tests/dotnet/UnitTests/expected/{artifactName}.txt` +3. Look for individual artifacts whose names contain `updated-expected-sizes` +4. Download the artifact zip, extract it, and copy the `.txt` files (e.g., `iOS-MonoVM-interpreter-size.txt`) into `tests/dotnet/UnitTests/expected/` ## Fallback: Run Locally diff --git a/tests/dotnet/UnitTests/AppSizeTest.cs b/tests/dotnet/UnitTests/AppSizeTest.cs index db6d4d432db..701aed8bbf7 100644 --- a/tests/dotnet/UnitTests/AppSizeTest.cs +++ b/tests/dotnet/UnitTests/AppSizeTest.cs @@ -201,15 +201,16 @@ static void AssertAppSize (ApplePlatform platform, string name, string appPath, Console.WriteLine ($" Updated expected file: {expectedSizeReportPath}"); } else if (hasDifferences) { UploadUpdatedExpectedFile (expectedSizeReportPath, report.ToString ()); + var updateHint = GetUpdateHint (); if (hasFileDifferences) { var details = new List (); foreach (var key in filesAdded) details.Add ($"added: '{key}'"); foreach (var key in filesRemoved) details.Add ($"removed: '{key}'"); - Assert.Fail ($"The app bundle's file list changed ({string.Join (", ", details)}). The updated expected file is available as a build artifact (set WRITE_KNOWN_FAILURES=1 to update locally)."); + Assert.Fail ($"The app bundle's file list changed ({string.Join (", ", details)}). {updateHint}"); } - Assert.Fail ($"{msg} The updated expected file is available as a build artifact (set WRITE_KNOWN_FAILURES=1 to update locally)."); + Assert.Fail ($"{msg} {updateHint}"); } } @@ -251,9 +252,9 @@ void AssertAssemblyReport (ApplePlatform platform, string name, string appPath, if (!update) { if (addedAPIs.Count > 0 || removedAPIs.Count > 0) { UploadUpdatedExpectedFile (expectedFile, string.Join ('\n', preservedAPIs) + "\n"); - var updateMsg = " The updated expected file is available as a build artifact (set WRITE_KNOWN_FAILURES=1 to update locally)."; - Assert.That (addedAPIs, Is.Empty, "No added APIs." + updateMsg); - Assert.That (removedAPIs, Is.Empty, "No removed APIs." + updateMsg); + var updateHint = " " + GetUpdateHint (); + Assert.That (addedAPIs, Is.Empty, "Unexpected APIs were added to the preserved set." + updateHint); + Assert.That (removedAPIs, Is.Empty, "APIs were unexpectedly removed from the preserved set." + updateHint); } } } @@ -274,6 +275,13 @@ static void UploadUpdatedExpectedFile (string expectedFilePath, string content) Console.WriteLine ($" Updated expected file written to: {outputFile}"); } + static string GetUpdateHint () + { + if (IsInCI) + return "The updated expected file is available as a build artifact (set WRITE_KNOWN_FAILURES=1 to update locally)."; + return "Set WRITE_KNOWN_FAILURES=1 to update the expected files in-place."; + } + static string FormatBytes (long bytes, bool alwaysShowSign = false) { return $"{(alwaysShowSign && bytes > 0 ? "+" : "")}{bytes:N0} bytes ({bytes / 1024.0:N1} KB = {bytes / (1024.0 * 1024.0):N1} MB)"; diff --git a/tools/devops/automation/templates/tests/run-tests.yml b/tools/devops/automation/templates/tests/run-tests.yml index 40c85db23a1..483f3afbb30 100644 --- a/tools/devops/automation/templates/tests/run-tests.yml +++ b/tools/devops/automation/templates/tests/run-tests.yml @@ -173,13 +173,20 @@ steps: condition: succeededOrFailed() # Upload updated expected app size files if the app size tests produced any. +- bash: | + if [ -d "$(Build.ArtifactStagingDirectory)/updated-expected-sizes" ]; then + echo "##vso[task.setvariable variable=HAS_UPDATED_EXPECTED_SIZES]true" + fi + displayName: 'Check for updated expected app size files' + condition: succeededOrFailed() + - task: PublishPipelineArtifact@1 displayName: 'Publish Artifact: Updated expected app size files' inputs: targetPath: '$(Build.ArtifactStagingDirectory)/updated-expected-sizes' artifactName: '${{ parameters.uploadPrefix }}updated-expected-sizes-${{ parameters.testPrefix }}-$(System.JobAttempt)' continueOnError: true - condition: succeededOrFailed() + condition: and(succeededOrFailed(), eq(variables['HAS_UPDATED_EXPECTED_SIZES'], 'true')) - pwsh: | $summaryName = "TestSummary-${{ parameters.testPrefix }}.md"