/// <summary>
        /// Do not deploy applications if we are short on disk space.
        ///
        /// Throws an exception if size is below minSize
        /// </summary>
        /// <param name="minSize">Defaults to 500Mb</param>
        protected void CheckDiskSpace(long minSize = 524288000)
        {
            var applicationPath = this.GlobalSettings.GetDefaultApplicationStorage().path;

            long freeSpaceBytes = UtilsSystem.GetTotalFreeSpace(applicationPath);

            if (freeSpaceBytes < minSize)
            {
                throw new Exception($"Insuficient storage [{UtilsSystem.BytesToString(freeSpaceBytes)}] to run deployments in: {applicationPath}");
            }
        }
예제 #2
0
        /// <summary>
        /// Downloads (And extracts) single artifacts from jobs.
        /// </summary>
        /// <param name="applicationId"></param>
        /// <param name="build"></param>
        /// <param name="artifactRegex"></param>
        /// <param name="destinationPath"></param>
        /// <param name="logger"></param>
        public void DownloadSingleArtifactFromBuild(
            string applicationId,
            Build build,
            string artifactRegex,
            string destinationPath,
            ILoggerInterface logger)
        {
            UtilsSystem.EnsureDirectoryExists(destinationPath, true);

            // Use the first job in the build...
            var job      = build.jobs.First();
            var artifact = this.FindDefaultArtifactForBuild(job, build, artifactRegex);

            var filename  = artifact.fileName;
            var extension = Path.GetExtension(filename);

            string downloadTemporaryDir =
                UtilsSystem.EnsureDirectoryExists(UtilsSystem.CombinePaths(this.TempDir, "_appveyor", "dld", applicationId), true);

            int artifactRetentionNum     = 5;
            int artifactAgeHoursForStale = 24;

            // Do not touch the latest artifactRetentionNum artifacts or artifacts that are not older than artifactAgeHoursForStale hours
            var staleFiles = Directory.EnumerateFiles(downloadTemporaryDir)
                             .Select((i) => new FileInfo(i))
                             .Where((i) => i.Extension.Equals(".zip", StringComparison.CurrentCultureIgnoreCase))
                             .OrderByDescending((i) => i.CreationTimeUtc)
                             .Skip(artifactRetentionNum)
                             .Where((i) => (DateTime.UtcNow - i.LastWriteTime).TotalHours > artifactAgeHoursForStale)
                             .ToList();

            foreach (var f in staleFiles)
            {
                // Make this fail proof, it's just a cleanup.
                try
                {
                    this.Logger.LogInfo(true, "Removing stale artifact cache file {0}", f.FullName);
                    f.Delete();
                }
                catch
                {
                    // ignored
                }
            }

            // Use a short hash as the temporary file name, because long paths can have issues...
            var tmpFile = UtilsSystem.CombinePaths(downloadTemporaryDir, UtilsEncryption.GetShortHash(JsonConvert.SerializeObject(build) + filename) + extension);

            if (Path.GetExtension(tmpFile)?.ToLower() != ".zip")
            {
                throw new NotImplementedException("AppVeyor artifacts should only be Zip Files.");
            }

            if (!File.Exists(tmpFile))
            {
                // Use an intermediate .tmp file just in case the files does not finish to download,
                // if it exists, clear it.
                string tmpFileDownload = tmpFile + ".tmp";
                if (File.Exists(tmpFileDownload))
                {
                    UtilsSystem.RetryWhile(() => File.Delete(tmpFileDownload), (e) => true, 4000, this.Logger);
                }

                var url = $"/api/buildjobs/{job.jobId}/artifacts/{filename}";
                logger.LogInfo(true, "Downloading artifact from: '{0}' to '{1}'", url, tmpFileDownload);
                this.ExecuteApiCallToFile(url, tmpFileDownload);

                // Rename to the final cached artifact file
                logger.LogInfo(true, "Download succesful, moving to '{0}'", tmpFile);
                UtilsSystem.RetryWhile(() => File.Move(tmpFileDownload, tmpFile), (e) => true, 4000, this.Logger);
            }
            else
            {
                logger.LogInfo(true, "Skipping artifact download, already in local cache: {0}", tmpFile);
            }

            logger.LogInfo(true, "Unzipping {1} file to '{0}'...", destinationPath, UtilsSystem.BytesToString(new FileInfo(tmpFile).Length));

            ZipFile.ExtractToDirectory(tmpFile, destinationPath);

            logger.LogInfo(true, "Unzipping finished.");
        }