override public void PostprocessBuild(BuildReport report, OptionInclusion inclusion) { base.PostprocessBuild(report, inclusion); if (GetChild <OptionSaveBuildInfo>().Value) { if (BuildInfo.Current == null) { Debug.LogWarning("Save build info: BuildInfo.Current not set"); } else { var infoPath = OptionHelper.GetBuildBasePath(report.summary.outputPath); infoPath = System.IO.Path.Combine(infoPath, BuildInfo.DEFAULT_NAME); var json = BuildInfo.Current.ToJson(); File.WriteAllText(infoPath, json); } } }
IEnumerator Distribute(BuildPath buildPath) { Debug.Log("ItchDistro: Pushing " + buildPath.target); var path = OptionHelper.GetBuildBasePath(buildPath.path); var channel = ChannelNames[buildPath.target]; if (!string.IsNullOrEmpty(channelSuffix)) { channel += "-" + channelSuffix; } var version = Application.version; var buildInfo = BuildInfo.FromPath(path); if (buildInfo != null) { if (!buildInfo.version.IsDefined) { Debug.LogWarning("ItchDistro: build.json exists but contains no version."); } else { version = buildInfo.version.MajorMinorPatchBuild; } } var args = string.Format( "push '{0}' '{1}:{2}' --userversion '{3}' --ignore='*.DS_Store' --ignore='build.json'", path, project, channel, Application.version ); yield return(Execute(butlerPath, args)); var exitcode = GetSubroutineResult <int>(); yield return(exitcode == 0); }
async Task Distribute(BuildPath buildPath, TaskToken task) { task.Report(0, description: $"Pushing {buildPath.target}"); var path = OptionHelper.GetBuildBasePath(buildPath.path); var channel = ChannelNames[buildPath.target]; if (!string.IsNullOrEmpty(channelSuffix)) { channel += "-" + channelSuffix; } var version = Application.version; var buildInfo = BuildInfo.FromPath(path); if (buildInfo != null) { if (!buildInfo.version.IsDefined) { Debug.LogWarning("ItchDistro: build.json exists but contains no version."); } else { version = buildInfo.version.MajorMinorPatchBuild; } } var args = string.Format( "push '{0}' '{1}:{2}' --userversion '{3}' --ignore='*.DS_Store' --ignore='build.json'", path, project, channel, Application.version ); await Execute(new ExecutionArgs(butlerPath, args), task); }
protected IEnumerator Zip(BuildPath buildPath) { var target = buildPath.target; var path = buildPath.path; if (!File.Exists(path) && !Directory.Exists(path)) { Debug.LogError("ZipDistro: Path to compress does not exist: " + path); yield return(null); yield break; } if (ZipIgnorePatterns == null) { ZipIgnorePatterns = new Regex[ZipIgnore.Length]; for (int i = 0; i < ZipIgnore.Length; i++) { var regex = Regex.Escape(ZipIgnore[i]).Replace(@"\*", ".*").Replace(@"\?", "."); ZipIgnorePatterns[i] = new Regex(regex); } } var sevenZPath = Get7ZipPath(); if (sevenZPath == null) { yield return(null); yield break; } // Path can point to executable file but there might be files // in the containing directory we need as well var basePath = OptionHelper.GetBuildBasePath(path); // Check the files in containing directory var files = new List <string>(Directory.GetFileSystemEntries(basePath)); for (int i = files.Count - 1; i >= 0; i--) { var filename = Path.GetFileName(files[i]); foreach (var pattern in ZipIgnorePatterns) { if (pattern.IsMatch(filename)) { files.RemoveAt(i); goto ContinueOuter; } } ContinueOuter :; } if (files.Count == 0) { Debug.LogError("ZipDistro: Nothing to ZIP in directory: " + basePath); yield return(null); yield break; } // Determine output path first to make it consistent and use absolute path // since the script will be run in a different working directory var prettyName = GetPrettyName(target); if (prettyName == null) { prettyName = Path.GetFileNameWithoutExtension(basePath); } var versionSuffix = ""; if (appendVersion) { var buildInfo = BuildInfo.FromPath(path); if (buildInfo != null) { if (!buildInfo.version.IsDefined) { Debug.LogWarning("ZipDistro: build.json exists but contains no version"); } else { versionSuffix = " " + buildInfo.version.MajorMinorPatch; } } if (versionSuffix.Length == 0) { versionSuffix = " " + Application.version; } } var extension = FileExtensions[(int)format]; var zipName = prettyName + versionSuffix + extension; zipName = zipName.Replace(" ", "_"); var outputPath = Path.Combine(Path.GetDirectoryName(basePath), zipName); outputPath = Path.GetFullPath(outputPath); // Delete existing archive, otherwise 7za will update it if (File.Exists(outputPath)) { File.Delete(outputPath); } // In case it only contains a single file, just zip that file var singleFile = false; if (files.Count == 1) { singleFile = true; basePath = files[0]; } // Run 7za command to create ZIP file var excludes = ""; foreach (var pattern in ZipIgnore) { excludes += @" -xr\!'" + pattern + "'"; } var inputName = Path.GetFileName(basePath); var args = string.Format( "a '{0}' '{1}' -r -mx{2} {3}", outputPath, inputName, (int)compression, excludes ); var startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.FileName = sevenZPath; startInfo.Arguments = args; startInfo.WorkingDirectory = Path.GetDirectoryName(basePath); Debug.Log("ZipDistro: Archiving " + inputName); yield return(Execute(startInfo)); var exitcode = GetSubroutineResult <int>(); if (exitcode != 0) { yield return(null); yield break; } if (!singleFile && prettyName != inputName) { yield return(RenameRoot(outputPath, inputName, prettyName)); var success = GetSubroutineResult <bool>(); if (!success) { yield return(null); yield break; } } Debug.Log("ZipDistro: Archived to: " + outputPath); yield return(new BuildPath(target, outputPath)); }
protected override IEnumerator DistributeCoroutine(IEnumerable <BuildPath> buildPaths, bool forceBuild) { // Check SDK var cmd = FindSteamCmd(); if (cmd == null) { yield return(false); yield break; } // Check User if (string.IsNullOrEmpty(steamLogin.User)) { Debug.LogError("SteamDistro: No Steam user set."); yield return(false); yield break; } if (steamLogin.GetPassword(keychainService) == null) { Debug.LogError("SteamDistro: No Steam password found in Keychain."); yield return(false); yield break; } // Check scripts if (string.IsNullOrEmpty(scriptsFolder) || !Directory.Exists(scriptsFolder)) { Debug.LogError("SteamDistro: Path to scripts folder not set."); yield return(false); yield break; } if (string.IsNullOrEmpty(appScript)) { Debug.LogError("SteamDistro: Name of app script not set."); yield return(false); yield break; } var appScriptPath = Path.Combine(scriptsFolder, appScript); if (!File.Exists(appScriptPath)) { Debug.LogError("SteamDistro: App script not found in scripts folder."); yield return(false); yield break; } // Process scripts var tempDir = FileUtil.GetUniqueTempPathInProject(); Directory.CreateDirectory(tempDir); var targets = new HashSet <BuildTarget>(buildPaths.Select(p => p.target)); var convertError = false; foreach (var file in Directory.GetFiles(scriptsFolder)) { if (Path.GetExtension(file).ToLower() != ".vdf") { continue; } var contents = PathVarRegex.Replace(File.ReadAllText(file), (match) => { var platformName = match.Groups[1].Value.ToLower(); if (platformName == "project") { return(Path.GetDirectoryName(Application.dataPath)); } else if (platformName == "scripts") { return(Path.GetFullPath(scriptsFolder)); } BuildTarget target; try { target = (BuildTarget)System.Enum.Parse(typeof(BuildTarget), platformName, true); } catch { Debug.LogError("SteamDistro: Invalid build target path variable '" + platformName + "' in VDF script:" + file); convertError = true; return(""); } if (!buildPaths.Any(p => p.target == target)) { Debug.LogError("SteamDistro: Build target '" + platformName + "' not part of given build profile(s) in VDF script:" + file); convertError = true; return(""); } targets.Remove(target); var path = buildPaths.Where(p => p.target == target).Select(p => p.path).First(); path = OptionHelper.GetBuildBasePath(path); return(Path.GetFullPath(path)); }); if (convertError) { break; } var targetPath = Path.Combine(tempDir, Path.GetFileName(file)); File.WriteAllText(targetPath, contents); } if (convertError) { yield return(false); yield break; } if (targets.Count > 0) { Debug.LogWarning("SteamDistro: Not all build targets filled into variables. Left over: " + string.Join(", ", targets.Select(t => t.ToString()).ToArray())); } // Notarize mac builds if (macNotarization != null) { foreach (var path in buildPaths.Where(p => p.target == BuildTarget.StandaloneOSX)) { yield return(macNotarization.Notarize(path)); if (GetSubroutineResult <string>() == null) { yield return(false); yield break; } } } // Build var scriptPath = Path.GetFullPath(Path.Combine(tempDir, appScript)); var args = string.Format( "+login '{0}' '{1}' +run_app_build_http '{2}' +quit", steamLogin.User, steamLogin.GetPassword(keychainService), scriptPath ); yield return(Execute(cmd, args, null, (output) => { if (output.Contains("Logged in OK")) { Debug.Log("SteamDistro: Logged in"); } else if (output.Contains("Building depot")) { var match = BuildingDepotRegex.Match(output); if (match.Success) { Debug.Log("SteamDistro: Building depo " + match.Groups[1].Value); } } else if (output.Contains("")) { var match = SuccessBuildIdRegex.Match(output); if (match.Success) { Debug.Log("SteamDistro: Build uploaded, ID = " + match.Groups[1].Value); } } })); Directory.Delete(tempDir, true); yield return(true); }
protected override IEnumerator DistributeCoroutine(IEnumerable <BuildPath> buildPaths, bool forceBuild) { // Check Pipeline Builder Executable var cmd = FindPipelineBuilder(); if (cmd == null) { yield return(false); yield break; } // Check User if (string.IsNullOrEmpty(gogLogin.User)) { Debug.LogError("GOGDistro: No GOG user set."); yield return(false); yield break; } if (gogLogin.GetPassword(keychainService) == null) { Debug.LogError("GOGDistro: No GOG password found in Keychain."); yield return(false); yield break; } // Check projects if (string.IsNullOrEmpty(projectsFolder) || !Directory.Exists(projectsFolder)) { Debug.LogError("GOGDistro: Path to projects folder not set."); yield return(false); yield break; } // Check ignore list if (!string.IsNullOrEmpty(ignoreList) && !File.Exists(ignoreList)) { Debug.LogError("GOGDistro: Ignore list could not be found: " + ignoreList); yield return(false); yield break; } // Process projects var tempDir = FileUtil.GetUniqueTempPathInProject(); Directory.CreateDirectory(tempDir); var targets = new HashSet <BuildTarget>(buildPaths.Select(p => p.target)); var projects = new List <string>(); var convertError = false; foreach (var file in Directory.GetFiles(projectsFolder)) { if (Path.GetExtension(file).ToLower() != ".json") { continue; } var contents = PathVarRegex.Replace(File.ReadAllText(file), (match) => { var platformName = match.Groups[1].Value.ToLower(); if (platformName == "project") { return(Path.GetDirectoryName(Application.dataPath)); } else if (platformName == "projects") { return(Path.GetFullPath(projectsFolder)); } BuildTarget target; try { target = (BuildTarget)System.Enum.Parse(typeof(BuildTarget), platformName, true); } catch { Debug.LogError("GOGDistro: Invalid build target path variable '" + platformName + "' in project JSON:" + file); convertError = true; return(""); } if (!buildPaths.Any(p => p.target == target)) { Debug.LogError("GOGDistro: Build target '" + platformName + "' not part of given build profile(s) in project JSON:" + file); convertError = true; return(""); } targets.Remove(target); var path = buildPaths.Where(p => p.target == target).Select(p => p.path).First(); path = OptionHelper.GetBuildBasePath(path); return(Path.GetFullPath(path)); }); if (convertError) { break; } var targetPath = Path.Combine(tempDir, Path.GetFileName(file)); File.WriteAllText(targetPath, contents); projects.Add(targetPath); } if (convertError) { yield return(false); yield break; } if (targets.Count > 0) { Debug.LogWarning("GOGDistro: Not all build targets filled into variables. Left over: " + string.Join(", ", targets.Select(t => t.ToString()).ToArray())); } // Notarize mac builds if (macNotarization != null) { foreach (var path in buildPaths.Where(p => p.target == BuildTarget.StandaloneOSX)) { yield return(macNotarization.Notarize(path)); if (GetSubroutineResult <string>() == null) { yield return(false); yield break; } } } // Build foreach (var project in projects) { var args = string.Format( "build-game '{0}' --username='******' --password='******' --version={3}", Path.GetFullPath(project), gogLogin.User, gogLogin.GetPassword(keychainService), string.IsNullOrEmpty(overrideVersion) ? Application.version : overrideVersion ); if (!string.IsNullOrEmpty(ignoreList)) { args += $" --ignore_list='{Path.GetFullPath(ignoreList)}'"; } if (!string.IsNullOrEmpty(branch.User)) { args += $" --branch='{branch.User}'"; var pwd = branch.GetPassword(branchKeychainService); if (pwd != null) { args += $" --branch_password='******'"; } } yield return(Execute(cmd, args)); } Directory.Delete(tempDir, true); yield return(true); }
protected override async Task RunDistribute(IEnumerable <BuildPath> buildPaths, TaskToken task) { // Check Pipeline Builder Executable var cmd = FindPipelineBuilder(); // Check User if (string.IsNullOrEmpty(gogLogin.User)) { throw new Exception("GOGDistro: No GOG user set."); } if (gogLogin.GetPassword(keychainService) == null) { throw new Exception("GOGDistro: No GOG password found in Keychain."); } // Check projects if (string.IsNullOrEmpty(projectsFolder) || !Directory.Exists(projectsFolder)) { throw new Exception("GOGDistro: Path to projects folder not set."); } // Check ignore list if (!string.IsNullOrEmpty(ignoreList) && !File.Exists(ignoreList)) { throw new Exception("GOGDistro: Ignore list could not be found: " + ignoreList); } // Process projects var tempDir = FileUtil.GetUniqueTempPathInProject(); try { Directory.CreateDirectory(tempDir); var targets = new HashSet <BuildTarget>(buildPaths.Select(p => p.target)); var projects = new List <string>(); string convertError = null; foreach (var file in Directory.GetFiles(projectsFolder)) { if (Path.GetExtension(file).ToLower() != ".json") { continue; } var contents = PathVarRegex.Replace(File.ReadAllText(file), (match) => { var platformName = match.Groups[1].Value.ToLower(); if (platformName == "project") { return(Path.GetDirectoryName(Application.dataPath)); } else if (platformName == "projects") { return(Path.GetFullPath(projectsFolder)); } BuildTarget target; try { target = (BuildTarget)System.Enum.Parse(typeof(BuildTarget), platformName, true); } catch { convertError = $"Invalid build target path variable '{platformName}' in project JSON: {file}"; return(""); } if (!buildPaths.Any(p => p.target == target)) { convertError = $"Build target '{platformName}' not part of given build profile(s) in project JSON: {file}"; return(""); } targets.Remove(target); var path = buildPaths.Where(p => p.target == target).Select(p => p.path).First(); path = OptionHelper.GetBuildBasePath(path); return(Path.GetFullPath(path)); }); if (convertError != null) { break; } var targetPath = Path.Combine(tempDir, Path.GetFileName(file)); File.WriteAllText(targetPath, contents); projects.Add(targetPath); } if (convertError != null) { throw new Exception($"GOGDistro: {convertError}"); } if (targets.Count > 0) { Debug.LogWarning("GOGDistro: Not all build targets filled into variables. Left over: " + string.Join(", ", targets.Select(t => t.ToString()).ToArray())); } task.Report(0, targets.Count + 1); // Notarize mac builds if (macNotarization != null) { task.Report(0, description: "Notarizing macOS builds"); foreach (var path in buildPaths.Where(p => p.target == BuildTarget.StandaloneOSX)) { await macNotarization.Notarize(path, task); } } // Build task.baseStep++; foreach (var project in projects) { var args = string.Format( "build-game '{0}' --username='******' --password='******' --version={3}", Path.GetFullPath(project), gogLogin.User, gogLogin.GetPassword(keychainService), string.IsNullOrEmpty(overrideVersion) ? Application.version : overrideVersion ); if (!string.IsNullOrEmpty(ignoreList)) { args += $" --ignore_list='{Path.GetFullPath(ignoreList)}'"; } if (!string.IsNullOrEmpty(branch.User)) { args += $" --branch='{branch.User}'"; var pwd = branch.GetPassword(branchKeychainService); if (pwd != null) { args += $" --branch_password='******'"; } } task.Report(0, description: $"Uploading {Path.GetFileName(project)}"); await Execute(new ExecutionArgs(cmd, args), task); task.baseStep++; } } finally { // Always clean up temporary files Directory.Delete(tempDir, true); } }