diff --git a/WebDeployHelper/WebDeployHelper.sln b/WebDeployHelper/WebDeployHelper.sln new file mode 100644 index 0000000..5446a9c --- /dev/null +++ b/WebDeployHelper/WebDeployHelper.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebDeployHelper", "WebDeployHelper\WebDeployHelper.csproj", "{C43BDD5D-FDC9-45BF-B2C8-233F9E339624}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C43BDD5D-FDC9-45BF-B2C8-233F9E339624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43BDD5D-FDC9-45BF-B2C8-233F9E339624}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43BDD5D-FDC9-45BF-B2C8-233F9E339624}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43BDD5D-FDC9-45BF-B2C8-233F9E339624}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WebDeployHelper/WebDeployHelper/ConfigReader.cs b/WebDeployHelper/WebDeployHelper/ConfigReader.cs new file mode 100644 index 0000000..e65e5a4 --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/ConfigReader.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; + +namespace WebDeployHelper +{ + class ConfigReader + { + #region Read Config + + private readonly string _configDirectory; + + private static string _configDirUpload; + private static string _configReleaseType; + private static string _configSftpAddress; + private static string _configSftpUser; + private static string _configDevPath; + private static string _configReleasePath; + + private static string _remotePath; + + public ConfigReader() + { + _configDirectory = DeployConfig.DirConfig; + } + + public ConfigReader(string configDirectory, string vstoDirectory) + { + _configDirectory = configDirectory; + } + + public ConfigReader ReadConfig() + { + //Sequence matters + InitConfigVariables(); + InitRemotePath(); + InitDeployInfo(); + return this; + } + + public DeployConfig ToDeployConfig() + { + var config = new DeployConfig + { + ConfigDirUpload = _configDirUpload, + ConfigReleaseType = _configReleaseType, + ConfigSftpAddress = _configSftpAddress, + ConfigSftpUser = _configSftpUser, + RemotePath = _remotePath + }; + return config; + } + + private void InitConfigVariables() + { + string[] configContent = {}; + try + { + configContent = File.ReadAllLines(_configDirectory); + } + catch (Exception e) + { + Util.DisplayWarning(TextCollection.ErrorNoConfig, e); + } + + //index here refers to the line number in DeployHelper.conf + _configDirUpload = configContent[1]; + _configReleaseType = configContent[3]; + _configSftpAddress = configContent[5]; + _configSftpUser = configContent[7]; + _configDevPath = configContent[9]; + _configReleasePath = configContent[11]; + } + + private void InitRemotePath() + { + switch (_configReleaseType) + { + case TextCollection.VarRelease: + _remotePath = _configReleasePath; + break; + case TextCollection.VarDev: + _remotePath = _configDevPath; + break; + default: + Util.DisplayWarning(TextCollection.ErrorInvalidReleaseType, new Exception()); + break; + } + } + + private void InitDeployInfo() + { + PrintInfo("You are going to deploy PowerPointLabs Website"); + PrintInfo(""); + PrintInfo("Settings info:"); + PrintInfo("Upload Directory: ", _configDirUpload); + PrintInfo("Release Type: ", _configReleaseType); + PrintInfo("Remote Path: ", _remotePath); + PrintInfo(""); + } + + private void PrintInfo(string text, string highlightedText = "") + { + Console.Write(text); + Util.ConsoleWriteWithColor(highlightedText, ConsoleColor.Yellow); + Console.WriteLine(""); + } + #endregion + } +} diff --git a/WebDeployHelper/WebDeployHelper/DeployConfig.cs b/WebDeployHelper/WebDeployHelper/DeployConfig.cs new file mode 100644 index 0000000..31a1638 --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/DeployConfig.cs @@ -0,0 +1,16 @@ +using System; + +namespace WebDeployHelper +{ + class DeployConfig + { + public static readonly string DirConfig = Environment.CurrentDirectory + @"\WebDeployHelper.conf"; + + public string ConfigDirUpload; + public string ConfigReleaseType; + public string ConfigSftpAddress; + public string ConfigSftpUser; + + public string RemotePath; + } +} diff --git a/WebDeployHelper/WebDeployHelper/DeployUploader.cs b/WebDeployHelper/WebDeployHelper/DeployUploader.cs new file mode 100644 index 0000000..e6ee72b --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/DeployUploader.cs @@ -0,0 +1,34 @@ +using System; + +namespace WebDeployHelper +{ + class DeployUploader + { + #region SFTP upload + + private readonly DeployConfig _config; + + public DeployUploader(DeployConfig config) + { + _config = config; + } + + public void SftpUpload() + { + try + { + Console.WriteLine("Connecting the server..."); + var uploader = new Uploader(); + uploader.SetConfig(_config); + uploader.Upload(); + } + catch (Exception e) + { + Console.WriteLine("Error during SFTP uploading:"); + Util.DisplayWarning(e.Message, e); + } + } + + #endregion + } +} diff --git a/WebDeployHelper/WebDeployHelper/Program.cs b/WebDeployHelper/WebDeployHelper/Program.cs new file mode 100644 index 0000000..3cb47ce --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/Program.cs @@ -0,0 +1,65 @@ +using System; +#region WebDeployHelper Description +// +// WebDeployHelper Class +// ------------------ +// Simply double click the .exe file to patch PowerPointLabs Website, +// so that it uploads the files onto the PowerPointLabs server. +// +// HOW TO USE +// +// For the first time use, you need to setup the followings: +// +// 0. Compile WebDeployHelper using Visual Studio. .NET 4.5 is required. The output program is under bin/debug or bin/release folder. +// +// 1. Fill in WebDeployHelper.conf +// - Upload directory is the local directory to upload to the server +// - Release type is dev or release +// - SFTP address is the server to upload to +// - SFTP username is the username used to login the server +// - Dev path is the installation folder path on the server for dev version PowerPointLabs Website +// - Release path is the installation folder path on the server for release version PowerPointLabs Website +// +// 2. Copy WebDeployHelper.exe, WebDeployHelper.conf, WinSCP.exe and WinSCP.com from the output folder to the publish folder +// +// 3. Run WebDeployHelper.exe and follow the instructions. +// +// For the next time +// +// 0. Run WebDeployHelper.exe and follow the instructions. +// +// Have a nice day :) +// +//TODO: add testing +#endregion +namespace WebDeployHelper +{ + class Program + { + public static void Main(string[] args) + { + try + { + # region Init + + var config = new ConfigReader() + .ReadConfig() + .ToDeployConfig(); + + # endregion + + new DeployUploader(config) + .SftpUpload(); + Util.DisplayEndMessage(); + } + catch + { + Util.IgnoreException(); + } + finally + { + Console.ReadKey(); + } + } + } +} diff --git a/WebDeployHelper/WebDeployHelper/Properties/AssemblyInfo.cs b/WebDeployHelper/WebDeployHelper/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ccbebf6 --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DeployHelper")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DeployHelper")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("57277935-16d4-471b-9706-49fca9fa69cb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WebDeployHelper/WebDeployHelper/TextCollection.cs b/WebDeployHelper/WebDeployHelper/TextCollection.cs new file mode 100644 index 0000000..3b798c5 --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/TextCollection.cs @@ -0,0 +1,21 @@ + +namespace WebDeployHelper +{ + class TextCollection + { + public const string ErrorNoConfig = "Cannot find config file."; + public const string ErrorInvalidReleaseType = "Invalid release type in config file."; + + public const string DoneUploaded = "Uploaded."; + + public const string InfoEnterPassword = "Enter SFTP password: "; + + public const string VarDev = "dev"; + public const string VarRelease = "release"; + + public const string FileXmlLogName = "log.xml"; + + public const string PermissionsFile = "644"; + public const string PermissionsDirectory = "755"; + } +} diff --git a/WebDeployHelper/WebDeployHelper/Uploader.cs b/WebDeployHelper/WebDeployHelper/Uploader.cs new file mode 100644 index 0000000..1f93d57 --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/Uploader.cs @@ -0,0 +1,94 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.XPath; + +namespace WebDeployHelper +{ + class Uploader + { + private const bool IsToRemoveAfterUpload = false; + + protected DeployConfig Config; + + public void SetConfig(DeployConfig config) + { + Config = config; + } + + public void Upload() + { + var winscp = new Process(); + winscp.StartInfo.FileName = "winscp.com"; + winscp.StartInfo.Arguments = "/xmllog=\"" + TextCollection.FileXmlLogName + "\""; + winscp.StartInfo.UseShellExecute = false; + winscp.StartInfo.CreateNoWindow = true; + winscp.StartInfo.RedirectStandardInput = true; + winscp.Start(); + + var writer = winscp.StandardInput; + + WriteUploadCommands(writer); + + writer.Close(); + winscp.WaitForExit(); + + CheckForError(); + } + + private void WriteUploadCommands(StreamWriter writer) + { + writer.WriteLine("open sftp://" + Config.ConfigSftpUser + "@" + Config.ConfigSftpAddress + ":22 -hostkey=\"*\""); + + string password = null; + while (password == null || password.Trim() == "") + { + Console.Write(TextCollection.InfoEnterPassword); + password = Util.ReadPassword(); + } + writer.WriteLine(password); + password = null; + + writer.WriteLine("option confirm off"); + writer.WriteLine("put -permissions=" + TextCollection.PermissionsFile + " -transfer=binary \"" + Config.ConfigDirUpload + + "\" \"" + Config.RemotePath + "\""); + + var directoryInfos = new DirectoryInfo(Config.ConfigDirUpload).EnumerateDirectories("*", SearchOption.AllDirectories); + + foreach (var directoryInfo in directoryInfos) + { + string remoteDirectoryPath = Config.RemotePath + directoryInfo.FullName.Replace(Config.ConfigDirUpload, "").Replace("\\", "/"); + + writer.WriteLine("chmod " + TextCollection.PermissionsDirectory + " \"" + remoteDirectoryPath + "\""); + } + + writer.WriteLine("exit"); + } + + private void CheckForError() + { + var log = new XPathDocument(TextCollection.FileXmlLogName); + var xmlNamespace = new XmlNamespaceManager(new NameTable()); + xmlNamespace.AddNamespace("w", "http://winscp.net/schema/session/1.0"); + var navigator = log.CreateNavigator(); + var iterator = navigator.Select("//w:message", xmlNamespace); + + if (iterator.Count > 0) + { + var errorMessage = new StringBuilder(); + foreach (XPathNavigator message in iterator) + { + errorMessage.AppendLine(message.Value); + } + + throw new Exception(errorMessage.ToString()); + } + else + { + Console.WriteLine(TextCollection.DoneUploaded); + } + } + } +} diff --git a/WebDeployHelper/WebDeployHelper/Util.cs b/WebDeployHelper/WebDeployHelper/Util.cs new file mode 100644 index 0000000..8c07fba --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/Util.cs @@ -0,0 +1,64 @@ +using System; +using System.Text; + +namespace WebDeployHelper +{ + class Util + { + #region Helper functions + + public static void ConsoleWriteWithColor(String content, ConsoleColor color) + { + Console.ForegroundColor = color; + Console.Write(content); + Console.ResetColor(); + } + + public static void IgnoreException() + { + } + + public static void DisplayWarning(string content, Exception e) + { + ConsoleWriteWithColor(content, ConsoleColor.Red); + throw new InvalidOperationException(content, e); + } + + public static void DisplayDone(string content) + { + ConsoleWriteWithColor(content + "\n", ConsoleColor.Green); + } + + public static void DisplayEndMessage() + { + DisplayDone("All Done!"); + Console.WriteLine("Have a nice day :)"); + } + + public static string ReadPassword() + { + StringBuilder password = new StringBuilder(); + ConsoleKeyInfo info = Console.ReadKey(true); + while (info.Key != ConsoleKey.Enter) + { + if (info.Key != ConsoleKey.Backspace) + { + password.Append(info.KeyChar); + } + else if (info.Key == ConsoleKey.Backspace) + { + if (password.Length > 0) + { + password.Length--; + } + } + info = Console.ReadKey(true); + } + // add a new line because user pressed enter at the end of their password + Console.WriteLine(); + return password.ToString(); + } + + #endregion + } +} diff --git a/WebDeployHelper/WebDeployHelper/WebDeployHelper.conf b/WebDeployHelper/WebDeployHelper/WebDeployHelper.conf new file mode 100644 index 0000000..a6a5704 --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/WebDeployHelper.conf @@ -0,0 +1,12 @@ +//upload directory +... +//release type +dev +//SFTP address +... +//SFTP username +... +//Dev path +... +//Release path +... \ No newline at end of file diff --git a/WebDeployHelper/WebDeployHelper/WebDeployHelper.csproj b/WebDeployHelper/WebDeployHelper/WebDeployHelper.csproj new file mode 100644 index 0000000..3b6642a --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/WebDeployHelper.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {C43BDD5D-FDC9-45BF-B2C8-233F9E339624} + Exe + Properties + WebDeployHelper + WebDeployHelper + v4.5 + 512 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + \ No newline at end of file diff --git a/WebDeployHelper/WebDeployHelper/app.config b/WebDeployHelper/WebDeployHelper/app.config new file mode 100644 index 0000000..c5e1dae --- /dev/null +++ b/WebDeployHelper/WebDeployHelper/app.config @@ -0,0 +1,3 @@ + + +