private async Task <DependencyVersionsFile> TryDownloadLineupDepsFile() { if (string.IsNullOrEmpty(LineupDependenciesFile)) { return(null); } var path = LineupDependenciesFile; string text; if (path.StartsWith("http")) { using (var client = new HttpClient()) { text = await client.GetStringAsync(path); } } else { text = File.ReadAllText(path); } using (var stringReader = new StringReader(text)) using (var reader = new XmlTextReader(stringReader)) { var project = new Project(ProjectRootElement.Create(reader)); return(DependencyVersionsFile.LoadFromProject(project)); } }
public async Task <bool> ExecuteAsync() { if (!DependencyVersionsFile.TryLoad(DependenciesFile, out var localVersionsFile)) { Log.LogError($"Could not load file from {DependenciesFile}"); return(false); } if (!localVersionsFile.HasVersionsPropertyGroup()) { Log.LogKoreBuildWarning(KoreBuildErrors.PackageRefPropertyGroupNotFound, $"No PropertyGroup with Label=\"{DependencyVersionsFile.PackageVersionsLabel}\" could be found in {DependenciesFile}"); } if (localVersionsFile.VersionVariables.Count == 0) { Log.LogMessage(MessageImportance.High, $"No version variables could be found in {DependenciesFile}"); return(true); } var tmpNupkgPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); var logger = new MSBuildLogger(Log); try { var remoteDepsVersionFile = await TryDownloadLineupDepsFile() ?? await TryDownloadLineupPackage(logger, tmpNupkgPath); if (remoteDepsVersionFile == null) { return(false); } var updateCount = UpdateDependencies(localVersionsFile, remoteDepsVersionFile); if (updateCount > 0) { Log.LogMessage($"Finished updating {updateCount} version variables in {DependenciesFile}"); localVersionsFile.Save(DependenciesFile); } else { Log.LogMessage($"Versions in {DependenciesFile} are already up to date"); } return(!Log.HasLoggedErrors); } finally { if (File.Exists(tmpNupkgPath)) { File.Delete(tmpNupkgPath); } } }
private async Task <DependencyVersionsFile> TryDownloadLineupPackage(MSBuildLogger logger, string tmpNupkgPath) { VersionRange versionRange; if (string.IsNullOrEmpty(LineupPackageVersion)) { versionRange = VersionRange.AllFloating; } else if (!VersionRange.TryParse(LineupPackageVersion, out versionRange)) { Log.LogError($"{LineupPackageVersion} is not a valid NuGet package version"); return(null); } var packageVersion = await GetPackageVersion(versionRange); if (packageVersion == null) { Log.LogError($"Could not find a version of {LineupPackageId} in the version range {versionRange}."); return(null); } var packageId = new PackageIdentity(LineupPackageId, packageVersion); var request = new PackageDownloadRequest { Identity = packageId, OutputPath = tmpNupkgPath, Sources = new[] { LineupPackageRestoreSource }, }; var result = await new PackageDownloader(logger).DownloadPackagesAsync(new[] { request }, TimeSpan.FromSeconds(60), _cts.Token); if (!result) { Log.LogError("Could not download the lineup package"); return(null); } using (var nupkgReader = new PackageArchiveReader(tmpNupkgPath)) { using (var stream = nupkgReader.GetStream("build/dependencies.props")) { using (var reader = new XmlTextReader(stream)) { var projectRoot = ProjectRootElement.Create(reader); return(DependencyVersionsFile.Load(projectRoot)); } } } }
public override bool Execute() { if (Projects == null || Projects.Length == 0) { Log.LogMessage(MessageImportance.Low, "No projects or solutions were found. Skipping PackageReference validation."); return(true); } if (!File.Exists(DependenciesFile)) { Log.LogKoreBuildError(KoreBuildErrors.DependenciesFileDoesNotExist, $"Expected the dependencies file to exist at {DependenciesFile}"); return(false); } if (!DependencyVersionsFile.TryLoad(DependenciesFile, out var depsFile)) { Log.LogError($"Could not load the dependencies file from {DependenciesFile}"); return(false); } if (!depsFile.HasVersionsPropertyGroup()) { Log.LogKoreBuildWarning(KoreBuildErrors.PackageRefPropertyGroupNotFound, $"No PropertyGroup with Label=\"{DependencyVersionsFile.PackageVersionsLabel}\" could be found in {DependenciesFile}"); } foreach (var proj in Projects) { var ext = Path.GetExtension(proj.ItemSpec); if (ext == ".sln") { var solutionProps = MSBuildListSplitter.GetNamedProperties(Properties); var projectFiles = Projects.SelectMany(p => SolutionInfoFactory.GetProjects(p, solutionProps)).Distinct(); foreach (var project in projectFiles) { VerifyPackageReferences(project, depsFile.VersionVariables); } } else { VerifyPackageReferences(proj.ItemSpec, depsFile.VersionVariables); } } return(!Log.HasLoggedErrors); }
public void AdditionalImportsAreAdded_WithOverrideImportFalse() { // Arrange var path = "obj/test.props"; var depsFile = DependencyVersionsFile.Create(addOverrideImport: false, additionalImports: new[] { path }); depsFile.Save(_tempFile); // Act var project = ProjectRootElement.Open(_tempFile); _output.WriteLine(File.ReadAllText(_tempFile)); // Assert var import = Assert.Single(project.Imports); Assert.Equal(path, import.Project); }
public void SetIsCaseInsensitive() { var depsFile = DependencyVersionsFile.Create(addOverrideImport: true); depsFile.Set("XunitRunnerVisualStudioVersion", "2.3.0"); depsFile.Set("XunitRunnerVisualstudioVersion", "2.4.0"); depsFile.Save(_tempFile); var project = ProjectRootElement.Open(_tempFile); _output.WriteLine(File.ReadAllText(_tempFile)); var versions = Assert.Single(project.PropertyGroups, p => !string.IsNullOrEmpty(p.Label)); var prop = Assert.Single(versions.Properties); Assert.Equal("XunitRunnerVisualStudioVersion", prop.Name); Assert.Equal("2.4.0", prop.Value); }
public void ItSortsVariablesAlphabetically() { var depsFile = DependencyVersionsFile.Create(addOverrideImport: true); depsFile.Set("XyzPackageVersion", "123"); depsFile.Set("AbcPackageVersion", "456"); depsFile.Save(_tempFile); var project = ProjectRootElement.Open(_tempFile); _output.WriteLine(File.ReadAllText(_tempFile)); var versions = Assert.Single(project.PropertyGroups, p => !string.IsNullOrEmpty(p.Label)); Assert.Collection(versions.Properties, v => Assert.Equal("AbcPackageVersion", v.Name), v => Assert.Equal("XyzPackageVersion", v.Name)); }
public void AdditionalImportsAreAdded_WithOverrideImportTrue() { // Arrange var path = "obj/external.props"; var depsFile = DependencyVersionsFile.Create(addOverrideImport: true, additionalImports: new[] { path }); depsFile.Save(_tempFile); // Act var project = ProjectRootElement.Open(_tempFile); _output.WriteLine(File.ReadAllText(_tempFile)); // Assert Assert.Collection( project.Imports, import => Assert.Equal(path, import.Project), import => Assert.Equal("$(DotNetPackageVersionPropsPath)", import.Project)); }
private string CreateProjectDepsFile(string depsFilePath, params VersionVariable[] variables) { var proj = ProjectRootElement.Create(NewProjectFileOptions.None); var originalDepsFile = DependencyVersionsFile.Load(proj); foreach (var item in variables) { if (item.IsReadOnly) { originalDepsFile.AddPinnedVariable(item.Name, item.Version); } else { originalDepsFile.Update(item.Name, item.Version); } } originalDepsFile.Save(depsFilePath); return(depsFilePath); }
public async Task ModifiesVariableValueUsingDepsFile() { // arrange var depsFilePath = CreateProjectDepsFile(("PackageVersionVar", "1.0.0")); var updatedDepsFilePath = CreateProjectDepsFile(Path.Combine(_tempDir, "dependencies.props"), ("PackageVersionVar", "2.0.0")); // act var task = new UpgradeDependencies { BuildEngine = new MockEngine(_output), DependenciesFile = depsFilePath, LineupDependenciesFile = updatedDepsFilePath }; // assert Assert.True(await task.ExecuteAsync(), "Task is expected to pass"); var modifiedDepsFile = DependencyVersionsFile.Load(depsFilePath); Assert.Equal("2.0.0", modifiedDepsFile.VersionVariables["PackageVersionVar"]); }
public async Task ModifiesVariableValue() { // arrange var packageId = new PackageIdentity("Lineup", NuGetVersion.Parse("1.0.0")); var lineupPackagePath = CreateLineup(packageId, ("PackageVersionVar", "2.0.0")); var depsFilePath = CreateProjectDepsFile(("PackageVersionVar", "1.0.0")); // act var task = new UpgradeDependencies { BuildEngine = new MockEngine(_output), DependenciesFile = depsFilePath, LineupPackageId = packageId.Id, LineupPackageRestoreSource = _tempDir, }; // assert Assert.True(await task.ExecuteAsync(), "Task is expected to pass"); var modifiedDepsFile = DependencyVersionsFile.Load(depsFilePath); Assert.Equal("2.0.0", modifiedDepsFile.VersionVariables["PackageVersionVar"]); }
private int UpdateDependencies(DependencyVersionsFile localVersionsFile, DependencyVersionsFile remoteDepsVersionFile) { var updateCount = 0; foreach (var localVariable in localVersionsFile.VersionVariables.Values.Where(v => !v.IsReadOnly)) { string remoteVariableVersion; // special case any package bundled in ThunderBuild if (!string.IsNullOrEmpty(ThunderBuildVersion.Current) && localVariable.Name == "InternalAspNetCoreSdkPackageVersion") { remoteVariableVersion = ThunderBuildVersion.Current; Log.LogMessage(MessageImportance.Low, "Setting InternalAspNetCoreSdkPackageVersion to the current version of ThunderBuild"); } else { if (remoteDepsVersionFile.VersionVariables.TryGetValue(localVariable.Name, out var remoteVariable)) { remoteVariableVersion = remoteVariable.Version; } else { Log.LogThunderBuildWarning( DependenciesFile, ThunderBuildErrors.PackageVersionNotFoundInLineup, $"A new version variable for {localVariable.Name} could not be found in {LineupPackageId}. This might be an unsupported external dependency."); continue; } } if (remoteVariableVersion != localVariable.Version) { updateCount++; localVersionsFile.Update(localVariable.Name, remoteVariableVersion); } } return(updateCount); }
public async Task SnapsInternalAspNetCoreSdkToBuildTools() { // arrange var packageId = new PackageIdentity("Lineup", NuGetVersion.Parse("1.0.0")); var lineupPackagePath = CreateLineup(packageId, new VersionVariable("InternalAspNetCoreSdkPackageVersion", "2.0.0")); var depsFilePath = CreateProjectDepsFile(new VersionVariable("InternalAspNetCoreSdkPackageVersion", "1.0.0")); // act var task = new UpgradeDependencies { BuildEngine = new MockEngine(_output), DependenciesFile = depsFilePath, LineupPackageId = packageId.Id, LineupPackageRestoreSource = _tempDir, }; // assert Assert.True(await task.ExecuteAsync(), "Task is expected to pass"); var modifiedDepsFile = DependencyVersionsFile.Load(depsFilePath); Assert.Equal(KoreBuildVersion.Current, modifiedDepsFile.VersionVariables["InternalAspNetCoreSdkPackageVersion"].Version); }
public void GeneratesVariableName(string id, string varName) { Assert.Equal(varName, DependencyVersionsFile.GetVariableName(id)); }
public override bool Execute() { OutputPath = OutputPath.Replace('\\', '/'); Directory.CreateDirectory(Path.GetDirectoryName(OutputPath)); DependencyVersionsFile depsFile; if (File.Exists(OutputPath)) { if (!DependencyVersionsFile.TryLoad(OutputPath, out depsFile)) { depsFile = DependencyVersionsFile.Create(AddOverrideImport, AdditionalImports); Log.LogWarning($"Could not load the existing deps file from {OutputPath}. This file will be overwritten."); } } else { depsFile = DependencyVersionsFile.Create(AddOverrideImport, AdditionalImports); } var varNames = new HashSet <string>(); foreach (var pkg in Packages) { var packageVersion = pkg.GetMetadata("Version"); if (string.IsNullOrEmpty(packageVersion)) { Log.LogError("Package {0} is missing the Version metadata", pkg.ItemSpec); continue; } string packageVarName; if (!string.IsNullOrEmpty(pkg.GetMetadata("VariableName"))) { packageVarName = pkg.GetMetadata("VariableName"); if (!packageVarName.EndsWith("Version", StringComparison.Ordinal)) { Log.LogError("VariableName for {0} must end in 'Version'", pkg.ItemSpec); continue; } } else { packageVarName = DependencyVersionsFile.GetVariableName(pkg.ItemSpec); } if (varNames.Contains(packageVarName)) { Log.LogError("Multiple packages would produce {0} in the generated dependencies.props file. Set VariableName to differentiate the packages manually", packageVarName); continue; } var item = depsFile.Update(packageVarName, packageVersion); if (!SuppressVariableLabels) { item.SetLabel(pkg.ItemSpec); } } depsFile.Save(OutputPath); Log.LogMessage(MessageImportance.Normal, $"Generated {OutputPath}"); return(!Log.HasLoggedErrors); }
public override bool Execute() { var unifiedPackageList = new Dictionary <string, PackageReferenceInfo>(StringComparer.OrdinalIgnoreCase); var projects = new ProjectInfoFactory(Log).CreateMany(Projects, Properties, false, _cts.Token); var packageRefs = projects.SelectMany(p => p.Frameworks).SelectMany(f => f.Dependencies); foreach (var packageRef in packageRefs) { if (packageRef.Value.IsImplicitlyDefined) { // skip PackageReferences added by the SDK continue; } if (packageRef.Value.NoWarn.Contains(KoreBuildErrors.Prefix + KoreBuildErrors.ConflictingPackageReferenceVersions)) { // Make it possible to suppress version conflicts while generating this file. continue; } if (unifiedPackageList.TryGetValue(packageRef.Value.Id, out var other)) { if (other.Version != packageRef.Value.Version) { Log.LogKoreBuildError(KoreBuildErrors.ConflictingPackageReferenceVersions, $"Conflicting dependency versions for {packageRef.Value.Id}: {other.Project.FileName} references '{other.Version}' but {packageRef.Value.Project.FileName} references '{packageRef.Value.Version}'"); } } else { unifiedPackageList.Add(packageRef.Value.Id, packageRef.Value); Log.LogMessage(MessageImportance.Low, $"Found {packageRef.Value.Id} = {packageRef.Value.Version}"); } } if (Log.HasLoggedErrors) { return(false); } var items = unifiedPackageList.Values.Select(p => new TaskItem(p.Id, new Hashtable { ["Version"] = p.Version })).ToArray(); var task = new GeneratePackageVersionPropsFile { AddOverrideImport = true, SuppressVariableLabels = true, Packages = items, BuildEngine = BuildEngine, HostObject = HostObject, OutputPath = DependenciesFile, }; if (!task.Execute()) { return(false); } var otherImports = OtherImports != null ? OtherImports.Select(p => p.ItemSpec) : Array.Empty <string>(); foreach (var proj in projects.Select(p => p.FullPath).Concat(otherImports)) { var project = ProjectRootElement.Open(proj, ProjectCollection.GlobalProjectCollection, preserveFormatting: true); var changed = false; foreach (var item in project.Items.Where(i => i.ItemType == "PackageReference")) { var noWarn = item.Metadata.FirstOrDefault(m => m.Name == "NoWarn"); if (noWarn != null && noWarn.Value.Contains(KoreBuildErrors.Prefix + KoreBuildErrors.ConflictingPackageReferenceVersions)) { continue; } var versionMetadata = item.Metadata.LastOrDefault(p => p.Name == "Version"); if (versionMetadata != null && versionMetadata.Value.StartsWith("$(")) { continue; } changed = true; var varName = $"$({DependencyVersionsFile.GetVariableName(item.Include)})"; if (versionMetadata == null) { item.AddMetadata("Version", varName, expressAsAttribute: true); } else { versionMetadata.Value = varName; } } if (changed) { Log.LogMessage(MessageImportance.High, $"Updated {proj}"); project.Save(proj); } else { Log.LogMessage(MessageImportance.Normal, $"Skipping {proj}. Already up to date."); } } return(!Log.HasLoggedErrors); }