Beispiel #1
0
        public static async Task BuildEvent(
            [QueueTrigger(AzureConstants.QueueNames.BuildEvent)] string message,
            [Queue(AzureConstants.QueueNames.ProcessBuild)] CloudQueue processBuildQueue,
            [Table(AzureConstants.TableNames.UnprocessedBuild)] CloudTable unprocessedBuildTable,
            TextWriter logger,
            CancellationToken cancellationToken)
        {
            var messageJson = (BuildEventMessageJson)JsonConvert.DeserializeObject(message, typeof(BuildEventMessageJson));

            // First make sure that we note this value in the unprocessed table as it has not yet
            // been processed.
            var entity    = new UnprocessedBuildEntity(messageJson.BoundBuildId);
            var operation = TableOperation.InsertOrReplace(entity);
            await unprocessedBuildTable.ExecuteAsync(TableOperation.InsertOrReplace(entity));

            // If this is a finalized event then the build is ready.  Go ahead and process it now.
            if (messageJson.Phase == "FINALIZED")
            {
                logger.WriteLine($"Queue event to process build {messageJson.BuildId}");
                await StateUtil.EnqueueProcessBuild(processBuildQueue, messageJson.JenkinsHostName, messageJson.BuildId);
            }
        }
Beispiel #2
0
        private async Task UpdateEntity(UnprocessedBuildEntity entity, CloudQueue processBuildQueue, CancellationToken cancellationToken)
        {
            var jenkinsUri = entity.BoundBuildId.HostUri;
            var buildId    = entity.BuildId;
            var client     = CreateJenkinsClient(jenkinsUri, entity.JobId);

            try
            {
                var buildInfo = await client.GetBuildInfoAsync(buildId);

                if (buildInfo.State == BuildState.Running)
                {
                    _logger.WriteLine($"Build {buildId}: stil running");
                    if (string.IsNullOrEmpty(entity.StatusText))
                    {
                        entity.StatusText = "Still running";
                        try
                        {
                            await _unprocessedBuildTable.ExecuteAsync(TableOperation.Replace(entity));
                        }
                        catch
                        {
                            // Can be deleted in parallel.  That's okay and should be ignored.
                        }
                    }
                }
                else
                {
                    _logger.WriteLine($"Build {buildId}: sending for processing as it's completed");
                    await EnqueueProcessBuild(processBuildQueue, jenkinsUri.Host, buildId);
                }
            }
            catch (Exception e)
            {
                _logger.WriteLine($"Build {buildId}: error querying Jenkins: {e}");
            }
        }
Beispiel #3
0
        /// <summary>
        /// Populate the given build and update the unprocessed table accordingly.  If there is no
        /// existing entity in the unprocessed table, this won't add one.  It will only update existing
        /// ones.
        /// </summary>
        internal async Task Populate(BuildId buildId, BuildTablePopulator populator, bool force, CancellationToken cancellationToken)
        {
            var key = UnprocessedBuildEntity.GetEntityKey(buildId);

            try
            {
                // If we are not forcing the update then check for the existence of a completed run before
                // requerying Jenkins.
                if (force || !(await populator.IsPopulated(buildId)))
                {
                    await populator.PopulateBuild(buildId);
                }

                await AzureUtil.MaybeDeleteAsync(_unprocessedBuildTable, key, cancellationToken);
            }
            catch (Exception e)
            {
                // Update the error state for the row.
                var entity = await AzureUtil.QueryAsync <UnprocessedBuildEntity>(_unprocessedBuildTable, key, cancellationToken);

                if (entity != null)
                {
                    entity.StatusText = $"{e.Message} - {e.StackTrace.Take(1000)}";
                    var operation = TableOperation.Replace(entity);
                    try
                    {
                        await _unprocessedBuildTable.ExecuteAsync(operation);
                    }
                    catch
                    {
                        // It's possible the enity was deleted / updated in parallel.  That's okay.  This table
                        // is meant as an approximation of the build state and always moving towards complete.
                    }
                }
            }
        }