public async Task Handle(MetricQueryRequest <WorkItemQueryWidget> request, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(request.DataContext.QueryId)) { return; } var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); var workItemQueryResult = await api.QueryWorkItemsByIdAsync(request.DataContext.QueryId, cancellationToken).ConfigureAwait(false); var ids = workItemQueryResult.WorkItems.Select(w => w.Id).ToList(); if (ids.Any()) { var workItems = await api.GetWorkItemsAsync(ids, cancellationToken).ConfigureAwait(false); _uiAction.Invoke(() => UpdateWidget(request.DataContext, workItemQueryResult.WorkItems, workItems)); } else { request.DataContext.Value = 0; request.DataContext.State = State.Ok; _uiAction.Invoke(request.DataContext.Clear); } }
public async Task Handle(InitializeRequest <WorkItemQueryWidget> request, CancellationToken cancellationToken) { var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); var workItemQueries = await api.GetWorkItemQueriesAsync(request.DataContext.Project, request.DataContext.Query, 1, cancellationToken).ConfigureAwait(false); if (workItemQueries.Count == 0) { request.DataContext.State = State.Unknown; request.DataContext.QueryId = string.Empty; request.DataContext.URL = string.Empty; _uiAction.Invoke(request.DataContext.Clear); request.DataContext.Clear(); _logger.Error($"Work item query {request.DataContext.Query} was not found."); } else { var query = workItemQueries.Value.First(); request.DataContext.QueryId = query.Id; request.DataContext.URL = query.Links["html"]["href"]; } }
public async Task Handle(StartRequest <ReleaseEnvironmentWidget> request, CancellationToken cancellationToken) { var dialog = new ConfirmationDialog($"Are you sure you want to start {request.DataContext.Name}?"); if (_dialogService.ShowDialog(dialog) != DialogResult.Yes) { return; } if (request.DataContext.Parent is ReleaseWidget parent) { var api = new AzureDevOpsApi(parent.ConnectionSettings); var response = await api.GetReleasesAsync(parent.Project, parent.DefinitionId, 1, cancellationToken).ConfigureAwait(false); if (response.Count == 0) { throw new Exception("Release not found."); } var release = response.Value.First(); await api.DeployAsync(parent.Project, release.Id, request.DataContext.DeploymentId, cancellationToken).ConfigureAwait(false); request.DataContext.State = State.Queued; } }
public async Task Handle(MetricQueryRequest <WorkItemsWidget> request, CancellationToken cancellationToken) { const string workItemsQuery = "SELECT [System.Id] FROM WorkItems " + "WHERE [System.AssignedTo] = {0} " + "AND [State] NOT IN ('Done','Closed','Inactive','Completed')"; var query = string.Format(workItemsQuery, request.DataContext.AssignedTo); var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); var workItemQueryResult = await api.QueryWorkItemsAsync(query, cancellationToken).ConfigureAwait(false); var ids = workItemQueryResult.WorkItems.Select(w => w.Id).ToList(); if (ids.Count != 0) { var workItems = await api.GetWorkItemsAsync(ids, cancellationToken).ConfigureAwait(false); _uiAction.Invoke(() => UpdateWidget(request.DataContext, workItemQueryResult.WorkItems, workItems)); } else { request.DataContext.Value = 0; request.DataContext.State = State.Ok; _uiAction.Invoke(request.DataContext.Clear); } }
public async Task Handle(HealthCheckRequest <ReleaseWidget> request, CancellationToken cancellationToken) { var widget = request.DataContext; var api = new AzureDevOpsApi(widget.ConnectionSettings); var releases = await api.GetReleasesAsync(widget.Project, widget.DefinitionId, 1, cancellationToken).ConfigureAwait(false); if (releases.Count == 0) { widget.State = State.None; return; } var release = releases.Value.First(); UpdateInfo(widget, release); _uiAction.Invoke(() => UpdateEnvironments(widget, release)); var deployments = await api.GetDeploymentsAsync(widget.Project, widget.DefinitionId, 10, cancellationToken).ConfigureAwait(false); if (deployments.Count > 0) { UpdateHistory(widget, deployments.Value.ToList()); } }
public async Task Handle(HealthCheckRequest <BuildWidget> request, CancellationToken cancellationToken) { var widget = request.DataContext; var api = new AzureDevOpsApi(widget.ConnectionSettings); var results = await api.GetBuildsAsync(widget.Project, widget.DefinitionId, 10, cancellationToken).ConfigureAwait(false); if (results.Count == 0) { widget.State = State.None; return; } var builds = results.Value.ToList(); UpdateInfo(widget, builds[0]); UpdateStats(widget, builds); builds.Reverse(); UpdateHistory(widget, builds); }
protected override async Task Handle(StatusRequest <AzureDevOpsWorkItemsWidget> request, CancellationToken cancellationToken) { var api = new AzureDevOpsApi(Endpoint); var wiql = string.Format(query, request.Context.Iteration); var response = await api.QueryWorkItemsAsync(request.Context.Account, request.Context.Project, wiql, cancellationToken); if (response.WorkItems.Any()) { var ids = response.WorkItems.Select(w => w.Id).ToList(); var workItems = await api.GetWorkItemsAsync(request.Context.Account, request.Context.Project, ids, cancellationToken); request.Context.Text = workItems.Count.ToString(); _dispatcher.Invoke(() => new AzureDevOpsWorkItemsSynchronizer(_mapper, request.Context) .Synchronize(workItems.Value.ToList(), request.Context.OfType <AzureDevOpsWorkItemWidget>().ToList())); } else { request.Context.Text = default; _dispatcher.Invoke(request.Context.Clear); } request.Context.Status = Status.OK; }
private static async Task <UpdateResult> CrawlReleases(ILogger log, CancellationToken ct) { var config = new ConfigurationBuilder() .AddJsonFile("host.json", optional: true, reloadOnChange: true) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var status = "starting"; using (var hc = new HealthchecksApi(config, log, "crawler")) using (var videoLan = new VideoLanApi()) using (var azure = new AzureDevOpsApi(config["azure-auth"])) { try { status = "reporting start to healthchecks"; await hc.Start(ct); status = "searching latest available version"; var(version, url) = await videoLan.GetLatestVersion(ct); status = "loading azure config"; var variables = await azure.GetBuildVariables(ct); if (variables.TryUpdate("latest.version", version)) { variables.TryUpdate("latest.url", url); status = "updating azure config"; await azure.UpdateBuildVariables(variables, ct); status = "queuing new build"; await azure.QueueBuild(ct); status = "reporting success to healthchecks"; await hc.Report(ct); return(UpdateResult.Succeeded()); } else { status = "reporting success (not changed) to healthchecks"; await hc.Report(ct); return(UpdateResult.NotChanged()); } } catch (Exception e) { await hc.Failed(ct); // cannot fail return(UpdateResult.Failed(status, e)); } } }
protected async override Task Handle(StatusRequest <AzureDevOpsPullRequestsWidget> request, CancellationToken cancellationToken) { var api = new AzureDevOpsApi(Endpoint); var pullRequests = await api.GetPullRequestsAsync(request.Context.Account, request.Context.Project).ConfigureAwait(false); request.Context.Text = pullRequests.Count.ToString(); if (pullRequests is null || pullRequests.Count == 0) { _dispatcher.InvokeAsync(request.Context.Clear); }
public async Task Handle(StopRequest <BuildWidget> request, CancellationToken cancellationToken) { var dialog = new ConfirmationDialog($"Are you sure you want to stop {request.DataContext.Name}?"); if (_dialogService.ShowDialog(dialog) != DialogResult.Yes) { return; } var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); await api.CancelBuildAsync(request.DataContext.Project, request.DataContext.LastBuildId, cancellationToken).ConfigureAwait(false); }
public async Task Handle(StartRequest <ReleaseWidget> request, CancellationToken cancellationToken) { var dialog = new ConfirmationDialog($"Are you sure you want to create a new release of {request.DataContext.Name}?"); if (_dialogService.ShowDialog(dialog) != DialogResult.Yes) { return; } var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); await api.CreateReleaseAsync(request.DataContext.Project, request.DataContext.DefinitionId, cancellationToken).ConfigureAwait(false); }
public async Task Handle(InitializeRequest <PullRequestsWidget> request, CancellationToken cancellationToken) { var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); var repository = await api.GetRepositoryAsync(request.DataContext.Project, request.DataContext.Repository, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(repository.Id)) { request.DataContext.State = State.Unknown; } else { request.DataContext.RepositoryId = repository.Id; } }
public async Task Handle(InitializeRequest <BuildWidget> request, CancellationToken cancellationToken) { var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); var response = await api.GetBuildDefinitionsAsync(request.DataContext.Project, request.DataContext.Definition, 1, cancellationToken).ConfigureAwait(false); var buildDefinition = response.Value.FirstOrDefault(); if (buildDefinition == null) { throw new Exception($"Build definition \"{request.DataContext.Definition}\" was not found."); } request.DataContext.DefinitionId = buildDefinition.Id; request.DataContext.URL = buildDefinition.Links["web"]["href"]; }
public async Task Handle(HealthCheckRequest <ReleaseEnvironmentWidget> request, CancellationToken cancellationToken) { var widget = request.DataContext; if (widget.Parent is ReleaseWidget parent && parent.DefinitionId != 0) { var api = new AzureDevOpsApi(parent.ConnectionSettings); var response = await api.GetDeploymentsAsync(parent.Project, parent.DefinitionId, widget.DefinitionEnvironmentId, 10, cancellationToken).ConfigureAwait(false); var deployments = response.Value.ToList(); if (deployments.Any()) { deployments.Reverse(); var maxDuration = deployments.Max(deployment => deployment.Duration); deployments.ForEach(deployment => deployment.Percentage = (double)deployment.Duration.Ticks / maxDuration.Ticks); } widget.JobHistory = deployments; } }
public async Task Handle(MetricQueryRequest <PullRequestsWidget> request, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(request.DataContext.RepositoryId)) { return; } var api = new AzureDevOpsApi(request.DataContext.ConnectionSettings); var pullRequests = await api.GetPullRequestsAsync( request.DataContext.Project, request.DataContext.RepositoryId, request.DataContext.SourceBranch, request.DataContext.TargetBranch, cancellationToken).ConfigureAwait(false); request.DataContext.Value = pullRequests.Count; var synchronizer = GetSynchronizer(request); _uiAction.Invoke(() => synchronizer.Synchronize(pullRequests.Value.ToList(), request.DataContext.Items)); request.DataContext.State = State.Ok; }
private static async Task <UpdateResult[]> CrawlReleases(string[] channels, ILogger log, CancellationToken ct) { var config = new ConfigurationBuilder() .AddJsonFile("host.json", optional: true, reloadOnChange: true) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); using (var hc = new HealthchecksApi(config, log)) using (var gitHub = new GitHubApi()) using (var azure = new AzureDevOpsApi(config["azureDevOpsAuth"])) { var releases = await gitHub.GetDuplicatiReleases(ct); var variables = await azure.GetBuildVariables(ct); var @default = variables["default"]; return(await Task.WhenAll(channels.Select(TryUpdateChannel))); async Task <UpdateResult> TryUpdateChannel(string channel) { var status = "parsing inputs"; try { status = "searching release"; if (!releases.TryGetValue(channel, out var release)) { throw new Exception($"Cannot find release for {channel}"); } status = "reporting start to healthchecks"; await hc.Start(channel, ct); // we report to HC only if we found a release. This prevent issue with the still awaited "stable" version :) status = "searching variable group"; if (!variables.TryGetValue(channel, out var group)) { throw new Exception($"Cannot find build variables for {channel}"); } status = "analyzing build config vs. found release"; var install = release.data.Assets.FirstOrDefault(a => a.Url.EndsWith(release.version + ".zip", StringComparison.OrdinalIgnoreCase))?.Url; var version = release.version; if (install.IsNullOrWhiteSpace() || version.IsNullOrWhiteSpace()) { throw new Exception($"The found release is invalid for {channel} (Failed to get required values 'install' and 'version')"); } var hasChanged = false; hasChanged |= group.TryUpdate("install", install); hasChanged |= group.TryUpdate("version", version); hasChanged |= group.TryUpdate("url", release.data.Url); hasChanged |= group.TryUpdate("notes", release.data.Notes); if (hasChanged) { status = "updating build variables"; await azure.UpdateBuildVariables(group, ct); if (@default["channel"] == channel) { status = "updating **default** build variables"; @default.TryUpdate("install", install); @default.TryUpdate("version", version); @default.TryUpdate("url", release.data.Url); @default.TryUpdate("notes", release.data.Notes); await azure.UpdateBuildVariables(@default, ct); status = "queuing new **default** build"; await azure.QueueBuild("default", ct); // So the image is tagged as 'latest' } else { status = "queuing new build"; await azure.QueueBuild(channel, ct); } status = "reporting success to healthchecks"; await hc.Report(channel, ct); return(UpdateResult.Succeeded(channel)); } else { status = "reporting success (not changed) to healthchecks"; await hc.Report(channel, ct); return(UpdateResult.NotChanged(channel)); } } catch (Exception e) { await hc.Failed(channel, ct); // cannot fail return(UpdateResult.Failed(channel, status, e)); } } } }