From cdba86707cb833591471030993345f8ed9f6cb4a Mon Sep 17 00:00:00 2001 From: Sandro Figo Date: Tue, 3 Jan 2023 12:23:34 +0100 Subject: [PATCH 1/2] Move validation code to target --- .nuke/build.schema.json | 6 ++-- build/Build.cs | 70 +++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index a3624f0..b4eb72b 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -84,7 +84,8 @@ "PublishPackageToGithub", "PublishPackageToNuGet", "Restore", - "Test" + "Test", + "Validate" ] } }, @@ -105,7 +106,8 @@ "PublishPackageToGithub", "PublishPackageToNuGet", "Restore", - "Test" + "Test", + "Validate" ] } }, diff --git a/build/Build.cs b/build/Build.cs index 5d738f5..f3da13b 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -52,43 +52,45 @@ class Build : NukeBuild [GitRepository] readonly GitRepository GitRepository; - protected override void OnBuildInitialized() - { - if (GitRepository.CurrentCommitHasVersionTag()) - { - // Validate latest version in changelog file matches the version tag in git - Assert.True(ChangelogTasksExtensions.TryGetLatestVersionInChangelog(RootDirectory / "CHANGELOG.md", out SemanticVersion version, out string rawVersionValue) && version == GitRepository.GetLatestVersionTag(), - $"Latest version '{rawVersionValue}' in the changelog file does not match the version tag '{GitRepository.GetLatestVersionTag()}'!"); - - // Verify version in Unity package file matches the version tag in git - dynamic packageFile = JsonConvert.DeserializeObject(File.ReadAllText(Solution.VoxReader.Directory / "package.json")); - SemanticVersion versionInPackageFile = SemanticVersion.Parse(packageFile.version.ToString()); - - SemanticVersion versionTag = GitRepository.GetLatestVersionTag(); - - Assert.True(versionInPackageFile == versionTag, $"The version '{versionInPackageFile}' in the Unity package file does not match the latest version tag '{versionTag}'!"); - } - - // Verify that all *.cs files have a Unity meta file (if the meta file is missing the file will be ignored when imported into Unity) - // TODO: check meta file for all files and directories - // TODO: check if meta file count is equal to source file count - var voxReaderSourceFiles = Solution.VoxReader.Directory.GlobFiles("**/*.cs") - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "obj")) - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "bin")) - .OrderBy(f => f.ToString()) - .ToHashSet(); - var voxReaderSourceMetaFiles = Solution.VoxReader.Directory.GlobFiles("**/*.cs.meta") - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "obj")) - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "bin")) - .OrderBy(f => f.ToString()).ToHashSet(); - - foreach (AbsolutePath sourceFile in voxReaderSourceFiles) + Target Validate => _ => _ + .Executes(() => { - Assert.True(voxReaderSourceMetaFiles.Contains((AbsolutePath)(sourceFile + ".meta")), $"'{sourceFile}' is missing a Unity .meta file!"); - } - } + if (GitRepository.CurrentCommitHasVersionTag()) + { + // Validate latest version in changelog file matches the version tag in git + Assert.True(ChangelogTasksExtensions.TryGetLatestVersionInChangelog(RootDirectory / "CHANGELOG.md", out SemanticVersion version, out string rawVersionValue) && version == GitRepository.GetLatestVersionTag(), + $"Latest version '{rawVersionValue}' in the changelog file does not match the version tag '{GitRepository.GetLatestVersionTag()}'!"); + + // Verify version in Unity package file matches the version tag in git + dynamic packageFile = JsonConvert.DeserializeObject(File.ReadAllText(Solution.VoxReader.Directory / "package.json")); + SemanticVersion versionInPackageFile = SemanticVersion.Parse(packageFile.version.ToString()); + + SemanticVersion versionTag = GitRepository.GetLatestVersionTag(); + + Assert.True(versionInPackageFile == versionTag, $"The version '{versionInPackageFile}' in the Unity package file does not match the latest version tag '{versionTag}'!"); + } + + // Verify that all *.cs files have a Unity meta file (if the meta file is missing the file will be ignored when imported into Unity) + // TODO: check meta file for all files and directories + // TODO: check if meta file count is equal to source file count + var voxReaderSourceFiles = Solution.VoxReader.Directory.GlobFiles("**/*.cs") + .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "obj")) + .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "bin")) + .OrderBy(f => f.ToString()) + .ToHashSet(); + var voxReaderSourceMetaFiles = Solution.VoxReader.Directory.GlobFiles("**/*.cs.meta") + .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "obj")) + .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "bin")) + .OrderBy(f => f.ToString()).ToHashSet(); + + foreach (AbsolutePath sourceFile in voxReaderSourceFiles) + { + Assert.True(voxReaderSourceMetaFiles.Contains((AbsolutePath)(sourceFile + ".meta")), $"'{sourceFile}' is missing a Unity .meta file!"); + } + }); Target Clean => _ => _ + .DependsOn(Validate) .Executes(() => { EnsureCleanDirectory(PublishDirectory); From 98863ed766ee1d9156a27d085272d2ee47be5a2b Mon Sep 17 00:00:00 2001 From: Sandro Figo Date: Tue, 3 Jan 2023 13:21:14 +0100 Subject: [PATCH 2/2] Extend Unity meta file validation --- CHANGELOG.md | 6 ++++++ build/Build.cs | 43 ++++++++++++++++++------------------------- build/Helper.cs | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb8c20..717d021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --> +## [Unreleased] + +### Added + +- Better validation for Unity meta files in build pipeline + ## [2.1.2] - 2023-01-03 ### Fixed diff --git a/build/Build.cs b/build/Build.cs index f3da13b..871c70d 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -55,38 +55,31 @@ class Build : NukeBuild Target Validate => _ => _ .Executes(() => { + bool changelogHasValidVersion = ChangelogTasksExtensions.TryGetLatestVersionInChangelog(RootDirectory / "CHANGELOG.md", out SemanticVersion latestChangelogVersion, out string latestRawChangelogVersionValue); + + SemanticVersion versionInUnityPackageFile = Helper.GetVersionFromUnityPackageFile(Solution.VoxReader.Directory / "package.json"); + if (GitRepository.CurrentCommitHasVersionTag()) { - // Validate latest version in changelog file matches the version tag in git - Assert.True(ChangelogTasksExtensions.TryGetLatestVersionInChangelog(RootDirectory / "CHANGELOG.md", out SemanticVersion version, out string rawVersionValue) && version == GitRepository.GetLatestVersionTag(), - $"Latest version '{rawVersionValue}' in the changelog file does not match the version tag '{GitRepository.GetLatestVersionTag()}'!"); + SemanticVersion versionTag = GitRepository.GetLatestVersionTag(); - // Verify version in Unity package file matches the version tag in git - dynamic packageFile = JsonConvert.DeserializeObject(File.ReadAllText(Solution.VoxReader.Directory / "package.json")); - SemanticVersion versionInPackageFile = SemanticVersion.Parse(packageFile.version.ToString()); + Assert.True(changelogHasValidVersion, $"Could not parse '{latestRawChangelogVersionValue}' as the latest version from the changelog file!"); - SemanticVersion versionTag = GitRepository.GetLatestVersionTag(); + Assert.True(latestChangelogVersion == versionInUnityPackageFile, + $"The latest version '{latestChangelogVersion}' in the changelog file does not match the version '{versionInUnityPackageFile}' in the Unity package file!"); + + Assert.True(latestChangelogVersion == versionTag, + $"Latest version '{latestRawChangelogVersionValue}' in the changelog file does not match the version tag '{versionTag}'!"); - Assert.True(versionInPackageFile == versionTag, $"The version '{versionInPackageFile}' in the Unity package file does not match the latest version tag '{versionTag}'!"); + Assert.True(versionInUnityPackageFile == versionTag, + $"The version '{versionInUnityPackageFile}' in the Unity package file does not match the latest version tag '{versionTag}'!"); } - // Verify that all *.cs files have a Unity meta file (if the meta file is missing the file will be ignored when imported into Unity) - // TODO: check meta file for all files and directories - // TODO: check if meta file count is equal to source file count - var voxReaderSourceFiles = Solution.VoxReader.Directory.GlobFiles("**/*.cs") - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "obj")) - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "bin")) - .OrderBy(f => f.ToString()) - .ToHashSet(); - var voxReaderSourceMetaFiles = Solution.VoxReader.Directory.GlobFiles("**/*.cs.meta") - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "obj")) - .Where(f => !f.ToString().Contains(Solution.VoxReader.Directory / "bin")) - .OrderBy(f => f.ToString()).ToHashSet(); - - foreach (AbsolutePath sourceFile in voxReaderSourceFiles) - { - Assert.True(voxReaderSourceMetaFiles.Contains((AbsolutePath)(sourceFile + ".meta")), $"'{sourceFile}' is missing a Unity .meta file!"); - } + // Verify that all files and directories have a Unity meta file (if the meta file is missing the file will be ignored when imported into Unity) + Helper.AssertThatUnityMetaFilesExist(Solution.VoxReader.Directory, p => + p.StartsWith(Solution.VoxReader.Directory / "bin") + || p.StartsWith(Solution.VoxReader.Directory / "obj") + ); }); Target Clean => _ => _ diff --git a/build/Helper.cs b/build/Helper.cs index ecb2bf9..ae46432 100644 --- a/build/Helper.cs +++ b/build/Helper.cs @@ -1,7 +1,11 @@ -using System.Text.RegularExpressions; +using System; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using Newtonsoft.Json; using NuGet.Versioning; using Nuke.Common; -using Nuke.Common.Git; +using Nuke.Common.IO; public static class Helper { @@ -22,4 +26,43 @@ public static bool IsValidVersionTag(string version, out SemanticVersion semanti return true; } + + /// + /// Checks recursively if all files and folders have a Unity meta file. + /// + /// The directory to check. + /// All paths to check are passed to this function. Return TRUE to exclude the current path. + public static void AssertThatUnityMetaFilesExist(AbsolutePath directory, Func excludePredicate = null) + { + var directories = directory.GlobDirectories("**").Where(d => d != directory); + + foreach (AbsolutePath d in directories) + { + if (excludePredicate != null && excludePredicate(d)) + continue; + + Assert.True((d.Parent / (d.Name + ".meta")).FileExists(), $"The directory '{d}' does not have a Unity meta file!"); + } + + var files = directory.GlobFiles("**/*").Where(f => !f.ToString().EndsWith(".meta")); + + foreach (AbsolutePath f in files) + { + if (excludePredicate != null && excludePredicate(f)) + continue; + + Assert.True((f.Parent / (f.Name + ".meta")).FileExists(), $"The file '{f}' does not have a Unity meta file!"); + } + } + + public static bool StartsWith(this AbsolutePath path, AbsolutePath other) + { + return path.ToString().StartsWith(other); + } + + public static SemanticVersion GetVersionFromUnityPackageFile(AbsolutePath file) + { + dynamic packageFile = JsonConvert.DeserializeObject(File.ReadAllText(file)); + return SemanticVersion.Parse(packageFile.version.ToString()); + } } \ No newline at end of file