Esempio n. 1
0
        protected override async Task <bool> DoFetchReleasesAsync()
        {
            if (ReleaseBranch == Branch.Unknown)
            {
                throw new ArgumentException("ReleaseBranch must not be unknown when fetching releases.");
            }

            var hasNewRelease = false;

            var releases      = (await _gitHubClient.Repository.Release.GetAll("Radarr", "Radarr")).ToArray();
            var validReleases = releases
                                .Take(3)
                                .Where(r =>
                                       r.TagName.StartsWith("v") && VersionUtil.IsValid(r.TagName.Substring(1)) &&
                                       r.Prerelease == (ReleaseBranch == Branch.Develop)
                                       ).Reverse();

            foreach (var release in validReleases)
            {
                // Check if release has been published.
                if (!release.PublishedAt.HasValue)
                {
                    continue;
                }

                var version = release.TagName.Substring(1);

                // Get an updateEntity
                var updateEntity = _database.UpdateEntities
                                   .Include(x => x.UpdateFiles)
                                   .FirstOrDefault(x => x.Version.Equals(version) && x.Branch.Equals(ReleaseBranch));

                if (updateEntity == null)
                {
                    // Create update object
                    updateEntity = new UpdateEntity
                    {
                        Version     = version,
                        ReleaseDate = release.PublishedAt.Value.UtcDateTime,
                        Branch      = ReleaseBranch
                    };

                    // Start tracking this object
                    await _database.AddAsync(updateEntity);

                    // Set new release to true.
                    hasNewRelease = true;
                }

                // Parse changes
                var releaseBody = release.Body;

                var features = RegexUtil.ReleaseFeaturesGroup.Match(releaseBody);
                if (features.Success)
                {
                    updateEntity.New.Clear();

                    foreach (Match match in RegexUtil.ReleaseChange.Matches(features.Groups["features"].Value))
                    {
                        if (match.Success)
                        {
                            updateEntity.New.Add(match.Groups["text"].Value);
                        }
                    }
                }

                var fixes = RegexUtil.ReleaseFixesGroup.Match(releaseBody);
                if (fixes.Success)
                {
                    updateEntity.Fixed.Clear();

                    foreach (Match match in RegexUtil.ReleaseChange.Matches(fixes.Groups["fixes"].Value))
                    {
                        if (match.Success)
                        {
                            updateEntity.Fixed.Add(match.Groups["text"].Value);
                        }
                    }
                }

                // Process release files.
                foreach (var releaseAsset in release.Assets)
                {
                    // Detect target operating system.
                    OperatingSystem operatingSystem;

                    if (releaseAsset.Name.Contains("windows."))
                    {
                        operatingSystem = OperatingSystem.Windows;
                    }
                    else if (releaseAsset.Name.Contains("linux."))
                    {
                        operatingSystem = OperatingSystem.Linux;
                    }
                    else if (releaseAsset.Name.Contains("osx."))
                    {
                        operatingSystem = OperatingSystem.Osx;
                    }
                    else
                    {
                        continue;
                    }

                    // Check if exists in database.
                    var updateFileEntity = _database.UpdateFileEntities
                                           .FirstOrDefault(x =>
                                                           x.UpdateEntityId == updateEntity.UpdateEntityId &&
                                                           x.OperatingSystem == operatingSystem);

                    if (updateFileEntity != null)
                    {
                        continue;
                    }

                    // Calculate the hash of the zip file.
                    var    releaseZip = Path.Combine(_config.DataDirectory, ReleaseBranch.ToString(), releaseAsset.Name);
                    string releaseHash;

                    if (!File.Exists(releaseZip))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(releaseZip));

                        using (var fileStream = File.OpenWrite(releaseZip))
                            using (var artifactStream = await _httpClient.GetStreamAsync(releaseAsset.BrowserDownloadUrl))
                            {
                                await artifactStream.CopyToAsync(fileStream);
                            }
                    }

                    using (var stream = File.OpenRead(releaseZip))
                    {
                        using (var sha = SHA256.Create())
                        {
                            releaseHash = BitConverter.ToString(sha.ComputeHash(stream)).Replace("-", "").ToLower();
                        }
                    }

                    File.Delete(releaseZip);

                    // Add to database.
                    updateEntity.UpdateFiles.Add(new UpdateFileEntity
                    {
                        OperatingSystem = operatingSystem,
                        Filename        = releaseAsset.Name,
                        Url             = releaseAsset.BrowserDownloadUrl,
                        Hash            = releaseHash
                    });
                }

                // Save all changes to the database.
                await _database.SaveChangesAsync();
            }

            return(hasNewRelease);
        }
        protected override async Task <bool> DoFetchReleasesAsync()
        {
            LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: DoFetchReleasesAsync");
            if (ReleaseBranch == Branch.Unknown)
            {
                throw new ArgumentException("ReleaseBranch must not be unknown when fetching releases.");
            }

            var hasNewRelease = false;
            var historyUrl    = $"https://ci.appveyor.com/api/projects/{AccountName}/{ProjectSlug}/history?recordsNumber=10&branch=develop";

            var historyData = await _httpClient.GetStringAsync(historyUrl);

            var history = JsonConvert.DeserializeObject <AppVeyorProjectHistory>(historyData);

            // Store here temporarily so we don't break on not processed builds.
            var lastBuild = _lastBuildId;

            // Make sure we dont distribute;
            // - pull requests,
            // - unsuccesful builds,
            // - tagged builds (duplicate).
            foreach (var build in history.Builds.Where(x => !x.PullRequestId.HasValue && !x.IsTag).ToList())
            {
                LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: Build > " + build.Version);

                if (lastBuild.HasValue &&
                    lastBuild.Value >= build.BuildId)
                {
                    break;
                }

                if (build.PullRequestId.HasValue ||
                    build.IsTag)
                {
                    continue;
                }

                var buildExtendedData = await _httpClient.GetStringAsync($"https://ci.appveyor.com/api/projects/{AccountName}/{ProjectSlug}/build/{build.Version}");

                var buildExtended = JsonConvert.DeserializeObject <AppVeyorProjectLastBuild>(buildExtendedData).Build;

                LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: Got extended data");

                // Filter out incomplete builds
                var buildJob = buildExtended.Jobs.FirstOrDefault();
                if (buildJob == null ||
                    buildJob.ArtifactsCount == 0 ||
                    !buildExtended.Started.HasValue)
                {
                    continue;
                }

                // Grab artifacts
                var artifactsPath = $"https://ci.appveyor.com/api/buildjobs/{buildJob.JobId}/artifacts";
                var artifactsData = await _httpClient.GetStringAsync(artifactsPath);

                var artifacts = JsonConvert.DeserializeObject <AppVeyorArtifact[]>(artifactsData);

                LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: Got artifacts");

                // Get an updateEntity
                var updateEntity = await _database.UpdateEntities
                                   .Include(x => x.UpdateFiles)
                                   .FirstOrDefaultAsync(x =>
                                                        x.Version.Equals(buildExtended.Version) &&
                                                        x.Branch.Equals(ReleaseBranch));

                if (updateEntity == null)
                {
                    // Create update object
                    updateEntity = new UpdateEntity
                    {
                        Version     = buildExtended.Version,
                        ReleaseDate = buildExtended.Started.Value.UtcDateTime,
                        Branch      = ReleaseBranch,
                        New         = new List <string>
                        {
                            build.Message
                        }
                    };

                    // Add extra message
                    if (!string.IsNullOrWhiteSpace(build.MessageExtended))
                    {
                        updateEntity.New.Add(build.MessageExtended);
                    }

                    // Start tracking this object
                    await _database.AddAsync(updateEntity);

                    // Set new release to true.
                    hasNewRelease = true;
                }

                // Process artifacts
                foreach (var artifact in artifacts)
                {
                    // Detect target operating system.
                    OperatingSystem operatingSystem;

                    if (artifact.FileName.Contains("windows."))
                    {
                        operatingSystem = OperatingSystem.Windows;
                    }
                    else if (artifact.FileName.Contains("linux."))
                    {
                        operatingSystem = OperatingSystem.Linux;
                    }
                    else if (artifact.FileName.Contains("osx."))
                    {
                        operatingSystem = OperatingSystem.Osx;
                    }
                    else
                    {
                        continue;
                    }

                    // Check if exists in database.
                    var updateFileEntity = _database.UpdateFileEntities
                                           .FirstOrDefault(x =>
                                                           x.UpdateEntityId == updateEntity.UpdateEntityId &&
                                                           x.OperatingSystem == operatingSystem);

                    if (updateFileEntity != null)
                    {
                        continue;
                    }

                    // Calculate the hash of the zip file.
                    var    releaseDownloadUrl = $"{artifactsPath}/{artifact.FileName}";
                    var    releaseFileName    = artifact.FileName.Split('/').Last();
                    var    releaseZip         = Path.Combine(_config.DataDirectory, ReleaseBranch.ToString(), releaseFileName);
                    string releaseHash;

                    LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: Dest " + releaseZip);

                    if (!File.Exists(releaseZip))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(releaseZip));
                        LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: Created dir");
                        await File.WriteAllBytesAsync(releaseZip, await _httpClient.GetByteArrayAsync(releaseDownloadUrl));

                        LogManager.GetCurrentClassLogger().Warn("AppVeyorReleaseSource: Wrote all bytes");
                    }

                    using (var stream = File.OpenRead(releaseZip))
                    {
                        using (var sha = SHA256.Create())
                        {
                            releaseHash = BitConverter.ToString(sha.ComputeHash(stream)).Replace("-", "").ToLower();
                        }
                    }

                    File.Delete(releaseZip);

                    // Add to database.
                    updateEntity.UpdateFiles.Add(new UpdateFileEntity
                    {
                        OperatingSystem = operatingSystem,
                        Filename        = releaseFileName,
                        Url             = releaseDownloadUrl,
                        Hash            = releaseHash
                    });
                }

                // Save all changes to the database.
                await _database.SaveChangesAsync();

                // Make sure we atleast skip this build next time.
                if (_lastBuildId == null ||
                    _lastBuildId.Value < build.BuildId)
                {
                    _lastBuildId = build.BuildId;
                }
            }

            return(hasNewRelease);
        }
Esempio n. 3
0
        protected override async Task <bool> DoFetchReleasesAsync()
        {
            if (ReleaseBranch == Branch.Unknown)
            {
                throw new ArgumentException("ReleaseBranch must not be unknown when fetching releases.");
            }

            var hasNewRelease = false;
            var historyUrl    = $"https://dev.azure.com/{AccountName}/{ProjectSlug}/_apis/build/builds?api-version=5.1&branchName=refs/heads/{BranchName}&reasonFilter=individualCI&statusFilter=completed&resultFilter=succeeded&queryOrder=startTimeDescending&$top=5";
            var historyData   = await _httpClient.GetStringAsync(historyUrl);

            var history = JsonConvert.DeserializeObject <AzureList <AzureProjectBuild> >(historyData).Value;

            // Store here temporarily so we don't break on not processed builds.
            var lastBuild = _lastBuildId;

            // URL query has filtered to most recent 5 successful, completed builds
            foreach (var build in history)
            {
                if (lastBuild.HasValue && lastBuild.Value >= build.BuildId)
                {
                    break;
                }

                // Found a build that hasn't started yet..?
                if (!build.Started.HasValue)
                {
                    break;
                }

                // Get build changes
                var changesPath = $"https://dev.azure.com/{AccountName}/{ProjectSlug}/_apis/build/builds/{build.BuildId}/changes?api-version=5.1";
                var changesData = await _httpClient.GetStringAsync(changesPath);

                var changes = JsonConvert.DeserializeObject <AzureList <AzureChange> >(changesData).Value;

                // Grab artifacts
                var artifactsPath = $"https://dev.azure.com/{AccountName}/{ProjectSlug}/_apis/build/builds/{build.BuildId}/artifacts?api-version=5.1";
                var artifactsData = await _httpClient.GetStringAsync(artifactsPath);

                var artifacts = JsonConvert.DeserializeObject <AzureList <AzureArtifact> >(artifactsData).Value;

                // there should be a single artifact called 'Packages' we parse for packages
                var artifact = artifacts.FirstOrDefault(x => x.Name == PackageArtifactName);
                if (artifact == null)
                {
                    continue;
                }

                // Download the manifest
                var manifestPath = $"https://dev.azure.com/{AccountName}/{ProjectSlug}/_apis/build/builds/{build.BuildId}/artifacts?artifactName={artifact.Name}&fileId={artifact.Resource.Data}&fileName=manifest&api-version=5.1";
                var manifestData = await _httpClient.GetStringAsync(manifestPath);

                var files = JsonConvert.DeserializeObject <AzureManifest>(manifestData).Files;

                // Get an updateEntity
                var updateEntity = _database.UpdateEntities
                                   .Include(x => x.UpdateFiles)
                                   .FirstOrDefault(x => x.Version.Equals(build.Version) && x.Branch.Equals(ReleaseBranch));

                if (updateEntity == null)
                {
                    // Create update object
                    updateEntity = new UpdateEntity
                    {
                        Version     = build.Version,
                        ReleaseDate = build.Started.Value.UtcDateTime,
                        Branch      = ReleaseBranch,
                        New         = changes.Select(x => x.Message).ToList()
                    };

                    // Start tracking this object
                    await _database.AddAsync(updateEntity);

                    // Set new release to true.
                    hasNewRelease = true;
                }

                // Process artifacts
                foreach (var file in files)
                {
                    // Detect target operating system.
                    OperatingSystem operatingSystem;

                    if (file.Path.Contains("windows.") && file.Path.ToLower().Contains(".zip"))
                    {
                        operatingSystem = OperatingSystem.Windows;
                    }
                    else if (file.Path.Contains("linux."))
                    {
                        operatingSystem = OperatingSystem.Linux;
                    }
                    else if (file.Path.Contains("osx."))
                    {
                        operatingSystem = OperatingSystem.Osx;
                    }
                    else
                    {
                        continue;
                    }

                    // Check if exists in database.
                    var updateFileEntity = _database.UpdateFileEntities
                                           .FirstOrDefault(x =>
                                                           x.UpdateEntityId == updateEntity.UpdateEntityId &&
                                                           x.OperatingSystem == operatingSystem);

                    if (updateFileEntity != null)
                    {
                        continue;
                    }

                    // Calculate the hash of the zip file.
                    var    releaseFileName    = Path.GetFileName(file.Path);
                    var    releaseDownloadUrl = $"https://dev.azure.com/{AccountName}/{ProjectSlug}/_apis/build/builds/{build.BuildId}/artifacts?artifactName={artifact.Name}&fileId={file.Blob.Id}&fileName={releaseFileName}&api-version=5.1";
                    var    releaseZip         = Path.Combine(_config.DataDirectory, ReleaseBranch.ToString(), releaseFileName);
                    string releaseHash;

                    if (!File.Exists(releaseZip))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(releaseZip));

                        using (var fileStream = File.OpenWrite(releaseZip))
                            using (var artifactStream = await _httpClient.GetStreamAsync(releaseDownloadUrl))
                            {
                                await artifactStream.CopyToAsync(fileStream);
                            }
                    }

                    using (var stream = File.OpenRead(releaseZip))
                    {
                        using (var sha = SHA256.Create())
                        {
                            releaseHash = BitConverter.ToString(sha.ComputeHash(stream)).Replace("-", "").ToLower();
                        }
                    }

                    File.Delete(releaseZip);

                    // Add to database.
                    updateEntity.UpdateFiles.Add(new UpdateFileEntity
                    {
                        OperatingSystem = operatingSystem,
                        Filename        = releaseFileName,
                        Url             = releaseDownloadUrl,
                        Hash            = releaseHash
                    });
                }

                // Save all changes to the database.
                await _database.SaveChangesAsync();

                // Make sure we atleast skip this build next time.
                if (_lastBuildId == null ||
                    _lastBuildId.Value < build.BuildId)
                {
                    _lastBuildId = build.BuildId;
                }
            }

            return(hasNewRelease);
        }