Skip to content

Commit

Permalink
Merge branch 'master' into v-mpetrov/us-2127964-Provide-discoverable-…
Browse files Browse the repository at this point in the history
…resource-utilization-information
  • Loading branch information
vmapetr committed Dec 19, 2023
2 parents acc32c9 + 8cb16d9 commit e7d85ce
Show file tree
Hide file tree
Showing 23 changed files with 515 additions and 53 deletions.
1 change: 1 addition & 0 deletions .azure-pipelines/build-job.yml
Expand Up @@ -109,6 +109,7 @@ jobs:
- ${{ if and(eq(parameters.arch, 'arm64'), ne(parameters.os, 'osx')) }}:
- script: sudo apt-get update && sudo apt-get -y install unzip
displayName: Install unzip
retryCountOnTaskFailure: 5

# Build agent layout
- script: ${{ variables.devCommand }} layout Release ${{ parameters.os }}-${{ parameters.arch }}
Expand Down
20 changes: 19 additions & 1 deletion .vsts.release.yml
Expand Up @@ -80,7 +80,23 @@ extends:
if ($isRelease) {
if ($isScheduledRelease) {
$agentVersion = "3.$($currentSprint.sprint).0"
$majorAndMinorVersion = "3.$($currentSprint.sprint)"
$patchVersion = 0
## Looking for a free patch version
while ($true) {
$agentVersion = "$majorAndMinorVersion.$patchVersion"
git ls-remote --exit-code --heads origin refs/heads/releases/$agentVersion
if ($LASTEXITCODE -ne 0) {
if ($LASTEXITCODE -eq 2) {
$LASTEXITCODE = 0
break
}
else {
Write-Error "git ls-remote failed with exit code $LASTEXITCODE" -ErrorAction Stop
}
}
$patchVersion++
}
} else {
$agentVersion = "${{ parameters.version }}"
if ($agentVersion -eq 'NotSet') {
Expand Down Expand Up @@ -293,6 +309,8 @@ extends:
- job: SendNotifications
displayName: Send notifications
dependsOn: create_ado_prs
variables:
IsRelease: $[ stageDependencies.Verify_release.Set_variables.outputs['SetReleaseVariables.isRelease'] ]
condition: and(succeeded(), eq(variables.IsRelease, 'True'))
steps:
- pwsh: release\Send-PRsNotification.ps1
Expand Down
4 changes: 2 additions & 2 deletions src/Agent.Listener/Agent.Listener.csproj
Expand Up @@ -16,8 +16,8 @@
<PackageReference Include="Azure.Identity" Version="1.10.2" />
<PackageReference Include="CommandLineParser" Version="2.7.82" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" Condition="$(CodeAnalysis)=='true'" />
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="16.205.1" />
<PackageReference Include="Microsoft.VisualStudio.Services.InteractiveClient" Version="16.205.1" />
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="19.230.0-preview" />
<PackageReference Include="Microsoft.VisualStudio.Services.InteractiveClient" Version="19.230.0-preview" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="6.0.0-preview.5.21301.5" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.1" />
Expand Down
4 changes: 3 additions & 1 deletion src/Agent.Listener/Configuration/FeatureFlagProvider.cs
Expand Up @@ -25,7 +25,6 @@ public interface IFeatureFlagProvider : IAgentService
/// <param name="featureFlagName">The name of the feature flag to get the status of.</param>
/// <param name="traceWriter">Trace writer for output</param>
/// <returns>The status of the feature flag.</returns>
/// <exception cref="VssUnauthorizedException">Thrown if token is not suitable for retriving feature flag status</exception>
/// <exception cref="InvalidOperationException">Thrown if agent is not configured</exception>
public Task<FeatureFlag> GetFeatureFlagAsync(IHostContext context, string featureFlagName, ITraceWriter traceWriter, CancellationToken ctk = default);

Expand Down Expand Up @@ -56,6 +55,9 @@ public class FeatureFlagProvider : AgentService, IFeatureFlagProvider
} catch (VssServiceException e) {
Trace.Warning("Unable to retrieve feature flag status: " + e.ToString());
return new FeatureFlag(featureFlagName, "", "", "Off", "Off");
} catch (VssUnauthorizedException e) {
Trace.Warning("Unable to retrieve feature flag with following exception: " + e.ToString());
return new FeatureFlag(featureFlagName, "", "", "Off", "Off");
}
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/Agent.Listener/Telemetry/TelemetryPublisher.cs
Expand Up @@ -81,7 +81,15 @@ public async Task PublishEvent(IHostContext context, Command command)

using var vsConnection = VssUtil.CreateConnection(new Uri(settings.ServerUrl), creds, Trace, agentCertManager.SkipServerCertificateValidation);
_ciService.Initialize(vsConnection);
await PublishEventsAsync(context, ciEvent);
/// This endpoint is not accepting data on some old Azure DevOps OnPremise versions
try
{
await PublishEventsAsync(context, ciEvent);
} catch (VssUnauthorizedException)
{
Trace.Warning("Unable to publish telemetry data");
}


}
// We never want to break pipelines in case of telemetry failure.
Expand All @@ -93,7 +101,12 @@ public async Task PublishEvent(IHostContext context, Command command)

private async Task PublishEventsAsync(IHostContext context, CustomerIntelligenceEvent ciEvent)
{
await _ciService.PublishEventsAsync(new CustomerIntelligenceEvent[] { ciEvent });
try
{
await _ciService.PublishEventsAsync(new CustomerIntelligenceEvent[] { ciEvent });
} catch (VssUnauthorizedException) {
Trace.Warning("Unable to publish telemetry data");
}
}
}
internal static class WellKnownEventTrackProperties
Expand Down
21 changes: 17 additions & 4 deletions src/Agent.Plugins/Artifact/FileContainerProvider.cs
Expand Up @@ -66,7 +66,7 @@ public FileContainerProvider(VssConnection connection, IAppTraceSource tracer)

if (downloadParameters.ExtractTars)
{
ExtractTarsIfPresent(context, fileArtifactPaths, downloadParameters.TargetDirectory, downloadParameters.ExtractedTarsTempPath);
ExtractTarsIfPresent(context, fileArtifactPaths, downloadParameters.TargetDirectory, downloadParameters.ExtractedTarsTempPath, cancellationToken);
}
}

Expand Down Expand Up @@ -95,7 +95,7 @@ public FileContainerProvider(VssConnection connection, IAppTraceSource tracer)

if (downloadParameters.ExtractTars)
{
ExtractTarsIfPresent(context, allFileArtifactPaths, downloadParameters.TargetDirectory, downloadParameters.ExtractedTarsTempPath);
ExtractTarsIfPresent(context, allFileArtifactPaths, downloadParameters.TargetDirectory, downloadParameters.ExtractedTarsTempPath, cancellationToken);
}
}

Expand Down Expand Up @@ -408,7 +408,7 @@ private string ResolveTargetPath(string rootPath, FileContainerItem item, string

// Checks all specified artifact paths, searches for files ending with '.tar'.
// If any files were found, extracts them to extractedTarsTempPath and moves to rootPath/extracted_tars.
private void ExtractTarsIfPresent(AgentTaskPluginExecutionContext context, IEnumerable<string> fileArtifactPaths, string rootPath, string extractedTarsTempPath)
private void ExtractTarsIfPresent(AgentTaskPluginExecutionContext context, IEnumerable<string> fileArtifactPaths, string rootPath, string extractedTarsTempPath, CancellationToken cancellationToken)
{
tracer.Info(StringUtil.Loc("TarSearchStart"));

Expand All @@ -427,7 +427,20 @@ private void ExtractTarsIfPresent(AgentTaskPluginExecutionContext context, IEnum

ExtractTar(fileArtifactPath, extractedFilesDir);

File.Delete(fileArtifactPath);
try
{
IOUtil.DeleteFileWithRetry(fileArtifactPath, cancellationToken).Wait();
}
// If file blocked by another process there are two different type exceptions.
// If file in use by another process really the UnauthorizedAccessException;
// If file in use by AV for scanning or monitoring the IOException appears.
catch (Exception ex)
{
tracer.Warn($"Unable to delete artifact files at {fileArtifactPath}, exception: {ex.GetType()}");
tracer.Verbose(ex.ToString());
throw;
}

}
}

Expand Down
36 changes: 30 additions & 6 deletions src/Agent.Plugins/BuildArtifact/BuildArtifactPluginV1.cs
Expand Up @@ -319,7 +319,7 @@ public class DownloadBuildArtifactTaskV1_0_0 : BuildArtifactTaskPluginBaseV1
string fullPath = this.CreateDirectoryIfDoesntExist(targetPath);
if (cleanDestinationFolderBool)
{
CleanDirectory(context, fullPath);
CleanDirectory(context, fullPath, token);
}
var downloadOption = downloadType == "single" ? DownloadOptions.SingleDownload : DownloadOptions.MultiDownload;

Expand Down Expand Up @@ -349,7 +349,7 @@ private string CreateDirectoryIfDoesntExist(string targetPath)
return fullPath;
}

private void CleanDirectory(AgentTaskPluginExecutionContext context, string directoryPath)
private void CleanDirectory(AgentTaskPluginExecutionContext context, string directoryPath, CancellationToken cancellationToken)
{
FileAttributes dirAttributes;
context.Output(StringUtil.Loc("CleaningDestinationFolder", directoryPath));
Expand Down Expand Up @@ -377,18 +377,42 @@ private void CleanDirectory(AgentTaskPluginExecutionContext context, string dire
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
foreach (FileInfo file in directoryInfo.GetFiles())
{
file.Delete();
try
{
IOUtil.DeleteFileWithRetry(file.FullName, cancellationToken).Wait() ;
}
catch (Exception ex)
{
tracer.Warn($"Unable to delete build artifact file, ex:{ex.GetType()}");
throw;
}
}

foreach (DirectoryInfo subDirectory in directoryInfo.GetDirectories())
{
subDirectory.Delete(true);
try
{
IOUtil.DeleteDirectoryWithRetry(subDirectory.FullName, cancellationToken).Wait() ;
}
catch (Exception ex)
{
tracer.Warn($"Unable to delete build subdirecotry, ex:{ex.GetType()}");
throw;
}
}
}
else
{
// specified folder is not a directory. Delete it.
File.Delete(directoryPath);
try
{
// specified folder is not a directory. Delete it.
IOUtil.DeleteDirectoryWithRetry(directoryPath, cancellationToken).Wait() ;
}
catch (Exception ex)
{
tracer.Warn($"Unable to delete build artifact data, ex:{ex.GetType()}");
throw;
}
}
}

Expand Down
21 changes: 19 additions & 2 deletions src/Agent.Plugins/PipelineCache/PipelineCacheServer.cs
Expand Up @@ -19,6 +19,7 @@
using Microsoft.VisualStudio.Services.WebApi;
using JsonSerializer = Microsoft.VisualStudio.Services.Content.Common.JsonSerializer;
using Microsoft.VisualStudio.Services.BlobStore.Common;
using Microsoft.VisualStudio.Services.Agent.Util;

namespace Agent.Plugins.PipelineCache
{
Expand Down Expand Up @@ -104,7 +105,15 @@ public PipelineCacheServer(AgentTaskPluginExecutionContext context)
{
if (File.Exists(uploadPath))
{
File.Delete(uploadPath);
try
{
await IOUtil.DeleteFileWithRetry(uploadPath, cancellationToken);
}
catch (Exception ex)
{
tracer.Warn($"Unable to delete pipeline cache file, ex:{ex.GetType()}");
throw;
}
}
}
catch { }
Expand Down Expand Up @@ -310,7 +319,15 @@ private async Task<string> GetUploadPathAsync(ContentFormat contentFormat, Agent
{
if (File.Exists(manifestPath))
{
File.Delete(manifestPath);
try
{
IOUtil.DeleteFileWithRetry(manifestPath, cancellationToken);
}
catch (Exception ex)
{
tracer.Warn($"Unable to delete manifest file, ex:{ex.GetType()}");
throw;
}
}
}
catch { }
Expand Down
21 changes: 19 additions & 2 deletions src/Agent.Plugins/RepositoryPlugin.cs
Expand Up @@ -206,7 +206,16 @@ public override async Task RunAsync(AgentTaskPluginExecutionContext executionCon
executionContext.Debug("Catch exception during repository move.");
executionContext.Debug(ex.ToString());
executionContext.Warning("Unable move and reuse existing repository to required location.");
IOUtil.DeleteDirectory(expectRepoPath, CancellationToken.None);

try
{
await IOUtil.DeleteDirectoryWithRetry(expectRepoPath, CancellationToken.None);
}
catch (Exception ioEx)
{
executionContext.Output($"Unable to delete existing repository on required location: {ioEx.GetType()}");
throw;
}
}

executionContext.Output($"Repository will be located at '{expectRepoPath}'.");
Expand Down Expand Up @@ -245,7 +254,15 @@ public override async Task RunAsync(AgentTaskPluginExecutionContext executionCon
if (!PlatformUtil.RunningOnWindows && !AgentKnobs.DisableTeePluginRemoval.GetValue(executionContext).AsBoolean())
{
initializeTeeUtil(executionContext, token);
teeUtil.DeleteTee();
try
{
teeUtil.DeleteTee();
}
catch (Exception ex)
{
executionContext.Output($"Unable to delete existing repository on required location. ex:{ex.GetType}");
throw;
}
}
}
}
Expand Down
21 changes: 19 additions & 2 deletions src/Agent.Plugins/TfsVCCliManager.cs
Expand Up @@ -172,7 +172,16 @@ protected async Task<int> RunCommandAsync(FormatTags formatFlags, bool quiet, bo

if (useSecureParameterPassing)
{
File.Delete(Path.Combine(this.SourcesDirectory, temporaryFileWithCommand));
try
{
await IOUtil.DeleteFileWithRetry(Path.Combine(this.SourcesDirectory, temporaryFileWithCommand), CancellationToken);
}
catch (Exception ex)
{
ExecutionContext.Output($"Unable to delete command file which is used to pass data, ex:{ex.GetType()}");
throw;

}
}

return result;
Expand Down Expand Up @@ -287,7 +296,15 @@ protected async Task<TfsVCPorcelainCommandResult> TryRunPorcelainCommandAsync(Fo
if (useSecretParameterPassing)
{
CleanupTfsVCOutput(ref result, formattedArguments);
File.Delete(Path.Combine(this.SourcesDirectory, cmdFileName));
try
{
await IOUtil.DeleteFileWithRetry(Path.Combine(this.SourcesDirectory, cmdFileName), CancellationToken);
}
catch (Exception ex)
{
ExecutionContext.Output($"Unable to delete command file, ex:{ex.GetType}");
throw;
}
}

return result;
Expand Down
9 changes: 8 additions & 1 deletion src/Agent.Plugins/TfsVCSourceProvider.cs
Expand Up @@ -420,7 +420,14 @@ public sealed class TfsVCSourceProvider : ISourceProvider
// Cleanup the comment file.
if (File.Exists(commentFile))
{
File.Delete(commentFile);
try
{
await IOUtil.DeleteFileWithRetry(commentFile, cancellationToken);
}
catch (Exception ex)
{
executionContext.Output($"Unable to delete comment file, ex:{ex.GetType()}");
}
}
}
}
Expand Down
7 changes: 0 additions & 7 deletions src/Agent.Sdk/Knob/AgentKnobs.cs
Expand Up @@ -152,13 +152,6 @@ public class AgentKnobs
new EnvironmentKnobSource("AGENT_USE_NODE10"),
new BuiltInDefaultKnobSource("false"));

public static readonly Knob UseNode16 = new Knob(
nameof(UseNode16),
"Forces the agent to use Node 16 handler for all Node-based tasks",
new RuntimeKnobSource("AGENT_USE_NODE16"),
new EnvironmentKnobSource("AGENT_USE_NODE16"),
new BuiltInDefaultKnobSource("false"));

public static readonly Knob UseNode20_1 = new Knob(
nameof(UseNode20_1),
"Forces the agent to use Node 20 handler for all Node-based tasks",
Expand Down

0 comments on commit e7d85ce

Please sign in to comment.