protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Yield(); IReadOnlyCollection <DeploymentTargetId> targetIds; try { if (!int.TryParse( _configuration[DeployerAppConstants.StartupTargetsTimeoutInSeconds], out int startupTimeoutInSeconds) || startupTimeoutInSeconds <= 0) { startupTimeoutInSeconds = 30; } using CancellationTokenSource startupToken = _timeoutHelper.CreateCancellationTokenSource(TimeSpan.FromSeconds(startupTimeoutInSeconds)); using var linkedToken = CancellationTokenSource.CreateLinkedTokenSource( stoppingToken, startupToken.Token); targetIds = (await _deploymentTargetReadService.GetDeploymentTargetsAsync(stoppingToken: linkedToken.Token)) .Select(deploymentTarget => deploymentTarget.Id) .ToArray(); _logger.Debug("Found deployment target IDs {IDs}", targetIds); } catch (Exception ex) when(!ex.IsFatal()) { _logger.Warning(ex, "Could not get target ids"); IsCompleted = true; return; } foreach (var targetId in targetIds) { var deploymentTargetWorker = new DeploymentTargetWorker(targetId, _logger, _mediator, _workerConfiguration, _timeoutHelper, _clock, _serviceProvider); _holder.Add(new NamedInstance <DeploymentTargetWorker>( deploymentTargetWorker, targetId.TargetId)); await _mediator.Send(new StartWorker(deploymentTargetWorker), stoppingToken); } IsCompleted = true; }
public async Task SeedAsync(CancellationToken cancellationToken) { AgentPoolListResult types = await _mediator.Send(new GetAgentPoolsQuery(), cancellationToken); if (!types.AgentPools.IsDefaultOrEmpty) { return; } var agentPoolId = new AgentPoolId("Default"); var result = await _mediator.Send(new CreateAgentPool(agentPoolId, new AgentPoolName("Default")), cancellationToken); _logger.Debug("CreateAgentPool result for Id {Id}: {Status}", agentPoolId, result); var deploymentTargets = await _deploymentTargetReadService.GetDeploymentTargetsAsync(stoppingToken : cancellationToken); foreach (var deploymentTarget in deploymentTargets) { await _mediator.Send(new AssignTargetToPool(agentPoolId, deploymentTarget.Id), cancellationToken); } var agents = await _mediator.Send(new GetAgentsQuery(), cancellationToken); var assignedAgents = await _mediator.Send(new GetAssignedAgentsInPoolsQuery(), cancellationToken); foreach (var agent in agents.Agents) { bool assigned = false; foreach (var assignedAgentsAssignedAgent in assignedAgents.AssignedAgents) { if (assignedAgentsAssignedAgent.Value.Contains(agent.Id)) { assigned = true; break; } } if (!assigned) { await _mediator.Send(new AssignAgentToPool(agentPoolId, agent.Id), cancellationToken); } } }
public async Task SeedAsync(CancellationToken cancellationToken) { try { var environmentTypes = await _environmentTypeService.GetEnvironmentTypes(cancellationToken); var targets = await _deploymentTargetReadService.GetDeploymentTargetsAsync(stoppingToken : cancellationToken); foreach (DeploymentTarget deploymentTarget in targets) { await UpdateTarget(cancellationToken, deploymentTarget, environmentTypes); } } catch (TaskCanceledException ex) { _logger.Error(ex, "Could not run seeder task"); } }
public async Task Handle(PackageUpdatedEvent notification, CancellationToken cancellationToken) { var deploymentTargets = await _readService.GetDeploymentTargetsAsync(stoppingToken : cancellationToken); DeploymentTarget[] targetsMatchingPackage = deploymentTargets .Where( target => target.PackageId.Equals( notification.PackageVersion.PackageId, StringComparison.OrdinalIgnoreCase)) .ToArray(); if (targetsMatchingPackage.Length == 0) { return; } IClientProxy clientProxy = _targetHubContext.Clients.All; await clientProxy.SendAsync(TargetHub.TargetsWithUpdates, notification.PackageVersion.PackageId, notification.PackageVersion.Version.ToNormalizedString(), targetsMatchingPackage.Select(target => target.Id).ToArray(), cancellationToken); }
public async Task Handle(PackageUpdatedEvent notification, CancellationToken cancellationToken) { if (!(await _applicationSettingsStore.GetApplicationSettings(cancellationToken)).AutoDeploy.Enabled) { _logger.Information("Auto deploy is disabled, skipping package web hook notification"); return; } PackageVersion packageIdentifier = notification.PackageVersion; if (packageIdentifier is null) { throw new ArgumentException(nameof(packageIdentifier)); } _logger.Information("Received hook for package {Package}", packageIdentifier); IReadOnlyCollection <DeploymentTarget> deploymentTargets = (await _targetSource.GetDeploymentTargetsAsync(stoppingToken: cancellationToken)) .SafeToReadOnlyCollection(); DeploymentTarget[] withAutoDeploy = deploymentTargets.Where(target => target.AutoDeployEnabled).ToArray(); if (!withAutoDeploy.Any()) { _logger.Information("No target has auto deploy enabled"); } else { foreach (DeploymentTarget deploymentTarget in withAutoDeploy) { if (deploymentTarget.PackageId.Equals( packageIdentifier.PackageId, StringComparison.OrdinalIgnoreCase)) { if (deploymentTarget.NuGet.NuGetConfigFile is {} &&
public async Task AutoDeployAsync([NotNull] IReadOnlyCollection <PackageVersion> packageIdentifiers) { if (packageIdentifiers == null) { throw new ArgumentNullException(nameof(packageIdentifiers)); } _logger.Information("Received hook for packages {Packages}", string.Join(", ", packageIdentifiers.Select(p => p.ToString()))); IReadOnlyCollection <DeploymentTarget> deploymentTargets = (await _targetSource.GetDeploymentTargetsAsync(CancellationToken.None)) .SafeToReadOnlyCollection(); DeploymentTarget[] withAutoDeploy = deploymentTargets.Where(t => t.AutoDeployEnabled).ToArray(); if (!withAutoDeploy.Any()) { _logger.Information("No target has auto deploy enabled"); } else { foreach (DeploymentTarget deploymentTarget in withAutoDeploy) { foreach (PackageVersion packageIdentifier in packageIdentifiers) { if (deploymentTarget.PackageId.Equals( packageIdentifier.PackageId, StringComparison.OrdinalIgnoreCase)) { bool allowDeployment = !packageIdentifier.Version.IsPrerelease || deploymentTarget.AllowPreRelease; if (allowDeployment) { AppVersion metadata = await _monitoringService.GetAppMetadataAsync( deploymentTarget, CancellationToken.None); if (metadata.SemanticVersion != null) { if (packageIdentifier.Version > metadata.SemanticVersion) { _logger.Information("Auto deploying package {PackageIdentifier} to target {Name} from web hook", packageIdentifier, deploymentTarget.Name); DeploymentTaskResult result = await _deploymentService.ExecuteDeploymentAsync( new DeploymentTask( $"{packageIdentifier.PackageId}, {packageIdentifier.Version.ToNormalizedString()}", deploymentTarget.Id, Guid.NewGuid() ), _logger, CancellationToken.None); _logger.Information("Deployed package {PackageIdentifier} to target {Name} from web hook with result {Result}", packageIdentifier, deploymentTarget.Name, result); } else { _logger.Information("Auto deployment skipped for {PackageIdentifier} since deployed version is higher {V}", packageIdentifier, metadata.SemanticVersion.ToNormalizedString()); } } else { _logger.Information("Auto deployment skipped for {PackageIdentifier} since the target version could not be determined", packageIdentifier); } } else { _logger.Information("Auto deployment skipped for {PackageIdentifier} since the target does not allow pre-release", packageIdentifier); } } else { _logger.Information("No package id matched {PackageIdentifier} for target {Name}", packageIdentifier, deploymentTarget.Name); } } } } }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { if (!_autoDeployConfiguration.Enabled) { return; } await Task.Delay(TimeSpan.FromSeconds(_autoDeployConfiguration.StartupDelayInSeconds), stoppingToken); while (!stoppingToken.IsCancellationRequested) { ImmutableArray <DeploymentTarget> deploymentTargets; using (var targetsTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(_autoDeployConfiguration.DefaultTimeoutInSeconds))) { using (CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, targetsTokenSource.Token)) { deploymentTargets = (await _deploymentTargetReadService.GetDeploymentTargetsAsync(linked.Token)) .Where(target => target.Enabled && target.AutoDeployEnabled) .ToImmutableArray(); } } if (deploymentTargets.IsDefaultOrEmpty) { _logger.Verbose("Found no deployment targets with auto deployment enabled, waiting {DelayInSeconds} seconds", _autoDeployConfiguration.EmptyTargetsDelayInSeconds); await Task.Delay(TimeSpan.FromSeconds(_autoDeployConfiguration.EmptyTargetsDelayInSeconds), stoppingToken); continue; } ImmutableArray <DeploymentTarget> targetsWithUrl = deploymentTargets.Where(target => target.Url.HasValue()).ToImmutableArray(); if (targetsWithUrl.IsDefaultOrEmpty) { _logger.Verbose("Found no deployment targets with auto deployment enabled and URL defined, waiting {DelayInSeconds} seconds", _autoDeployConfiguration.EmptyTargetsDelayInSeconds); await Task.Delay(TimeSpan.FromSeconds(_autoDeployConfiguration.EmptyTargetsDelayInSeconds), stoppingToken); continue; } AppVersion[] appVersions; using (var cancellationTokenSource = new CancellationTokenSource( TimeSpan.FromSeconds(_autoDeployConfiguration.MetadataTimeoutInSeconds))) { using (CancellationTokenSource linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, stoppingToken)) { CancellationToken cancellationToken = linkedCancellationTokenSource.Token; IEnumerable <Task <AppVersion> > tasks = targetsWithUrl.Select(target => _monitoringService.GetAppMetadataAsync(target, cancellationToken)); appVersions = await Task.WhenAll(tasks); } } foreach (DeploymentTarget deploymentTarget in targetsWithUrl) { AppVersion appVersion = appVersions.SingleOrDefault(v => v.Target.Id.Equals(deploymentTarget.Id, StringComparison.OrdinalIgnoreCase)); if (appVersion?.SemanticVersion is null || appVersion.PackageId.IsNullOrWhiteSpace()) { continue; } ImmutableHashSet <PackageVersion> packageVersions; using (var packageVersionCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(_autoDeployConfiguration.DefaultTimeoutInSeconds))) { using (CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, packageVersionCancellationTokenSource.Token)) { packageVersions = (await _packageService.GetPackageVersionsAsync(deploymentTarget.PackageId, cancellationToken: linked.Token, logger: _logger)).ToImmutableHashSet(); } } if (packageVersions.IsEmpty) { continue; } ImmutableHashSet <PackageVersion> filteredPackages = !deploymentTarget.AllowPreRelease ? packageVersions.Where(p => !p.Version.IsPrerelease).ToImmutableHashSet() : packageVersions; if (filteredPackages.IsEmpty) { continue; } ImmutableHashSet <PackageVersion> newerPackages = filteredPackages .Where(package => package.PackageId.Equals(appVersion.PackageId, StringComparison.OrdinalIgnoreCase) && package.Version > appVersion.SemanticVersion) .ToImmutableHashSet(); PackageVersion packageToDeploy = newerPackages .OrderByDescending(package => package.Version) .FirstOrDefault(); if (packageToDeploy != null) { var task = new DeploymentTask(packageToDeploy, deploymentTarget.Id, Guid.NewGuid()); _logger.Information("Auto-deploying package {Package} to target {TargetId}", packageToDeploy, deploymentTarget.Id); _deploymentWorker.Enqueue(task); } } await Task.Delay(TimeSpan.FromSeconds(_autoDeployConfiguration.AfterDeployDelayInSeconds), stoppingToken); } }