Teamcity Launch Test on build result - teamcity

I have two build steps
in second step I am launching some UI Test that looks like:
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", #"ViewBrowser/bin/Debug/ViewBrowser.exe");
appCapabilities.SetCapability("deviceName", "WPF");
var includeController = new WindowsDriver<WindowsElement>(new Uri(#"http://127.0.0.1:4723"), appCapabilities);
includeController.Manage().Window.Position = new System.Drawing.Point(20, 20);
includeController.CloseApp();
But in my code I need to specify #"ViewBrowser/bin/Debug/ViewBrowser.exe". In my case what i need to place there because Test cannot find .exe file. I am new in Teamcity. Can you advice something?

You can store ViewBrowser.exe in the resource folder or in the folder around your project.
and just take the file path. E.g.
string RunningPath = AppDomain.CurrentDomain.BaseDirectory
+ "path/to/folder/ViewBrowser.exe";
or take from resources
string FileName = string.Format("{0}Resources\\ViewBrowser.exe", Path.GetFullPath(Path.Combine(RunningPath, #"path/to/folder")));

Related

Problem Generating Html Report Using DbUp during Octopus Deployment

Using Octopus Deploy to deploy a simple API.
The first step of our deployment process is to generate an HTML report with the delta of the scripts run vs the scripts required to run. I used this tutorial to create the step.
The relevant code in my console application is:
var reportLocationSection = appConfiguration.GetSection(previewReportCmdLineFlag);
if (reportLocationSection.Value is not null)
{
// Generate a preview file so Octopus Deploy can generate an artifact for approvals
try
{
var report = reportLocationSection.Value;
var fullReportPath = Path.Combine(report, deltaReportName);
Console.WriteLine($"Generating upgrade report at {fullReportPath}");
upgrader.GenerateUpgradeHtmlReport(fullReportPath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return operationError;
}
}
The Powershell which I am using in the script step is:
# Get the extracted path for the package
$packagePath = $OctopusParameters["Octopus.Action.Package[DatabaseUpdater].ExtractedPath"]
$connectionString = $OctopusParameters["Project.Database.ConnectionString"]
$reportPath = $OctopusParameters["Project.HtmlReport.Location"]
Write-Host "Report Path: $($reportPath)"
$exeToRun = "$($packagePath)\DatabaseUpdater.exe"
$generatedReport = "$($reportPath)\UpgradeReport.html"
Write-Host "Generated Report: $($generatedReport)"
if ((test-path $reportPath) -eq $false){
New-Item "Creating new directory..."
} else {
New-Item "Directory already exists."
}
# Run this .NET app, passing in the Connection String and a flag
# which tells the app to create a report, but not update the database
& $exeToRun --connectionString="$($connectionString)" --previewReportPath="$($reportPath)"
New-OctopusArtifact -Path "$($generatedReport)"
The error reported by Octopus is:
'Could not find file 'C:\DeltaReports\Some API\2.9.15-DbUp-Test-9\UpgradeReport.html'.'
I'm guessing that is being thrown when this powershell line is hit: New-OctopusArtifact ...
And that seems to indicate that the report was never created.
I've used a bit of logging to log out certain variables and the values look sound:
Report Path: C:\DeltaReports\Some API\2.9.15-DbUp-Test-9
Generated Report: C:\DeltaReports\Some API\2.9.15-DbUp-Test-9\UpgradeReport.html
Generating upgrade report at C:\DeltaReports\Some API\2.9.15-DbUp-Test-9\UpgradeReport.html
As you can see in the C#, the relevant code is wrapped in a try/catch block, but I'm not sure whether the error is being written out there or at a later point by Octopus (I'd need to do a pull request to add a marker in the code).
Can anyone see a way forward win resolving this? Has anyone else encountered this?
Cheers
I recently redid some of the work from that article for this video up on YouTube. I did run into some issues with the .SQL files not being included in the assembly. I think it was after I upgraded to .NET 6. But that might be a coincidence.
Anyway, because the files weren't being included in the assembly, when I ran the command line app via Octopus, it wouldn't properly generate the file for me. I ended up configuring the project to copy the .SQL files to a folder in the output directory instead of embedding them in the assembly. You can view a sample package here.
One thing that helped me is running the app in a debugger with the same parameters just to make sure it was actually generating the file. I'm sure you already thought of that, but I'd be remiss if I forgot to include it in my answer. :)
FWIW, this is my updated scripts.
First, the Octopus Script:
$packagePath = $OctopusParameters["Octopus.Action.Package[Trident.Database].ExtractedPath"]
$connectionString = $OctopusParameters["Project.Connection.String"]
$environmentName = $OctopusParameters["Octopus.Environment.Name"]
$reportPath = $OctopusParameters["Project.Database.Report.Path"]
cd $packagePath
$appToRun = ".\Octopus.Trident.Database.DbUp"
$generatedReport = "$reportPath\UpgradeReport.html"
& $appToRun --ConnectionString="$connectionString" --PreviewReportPath="$reportPath"
New-OctopusArtifact -Path "$generatedReport" -Name "$environmentName.UpgradeReport.html"
My C# code can be found here but for ease of use, you can see it all here (I'm not proud of how I parse the parameters).
static void Main(string[] args)
{
var connectionString = args.FirstOrDefault(x => x.StartsWith("--ConnectionString", StringComparison.OrdinalIgnoreCase));
connectionString = connectionString.Substring(connectionString.IndexOf("=") + 1).Replace(#"""", string.Empty);
var executingPath = Assembly.GetExecutingAssembly().Location.Replace("Octopus.Trident.Database.DbUp", "").Replace(".dll", "").Replace(".exe", "");
Console.WriteLine($"The execution location is {executingPath}");
var deploymentScriptPath = Path.Combine(executingPath, "DeploymentScripts");
Console.WriteLine($"The deployment script path is located at {deploymentScriptPath}");
var postDeploymentScriptsPath = Path.Combine(executingPath, "PostDeploymentScripts");
Console.WriteLine($"The deployment script path is located at {postDeploymentScriptsPath}");
var upgradeEngineBuilder = DeployChanges.To
.SqlDatabase(connectionString, null)
.WithScriptsFromFileSystem(deploymentScriptPath, new SqlScriptOptions { ScriptType = ScriptType.RunOnce, RunGroupOrder = 1 })
.WithScriptsFromFileSystem(postDeploymentScriptsPath, new SqlScriptOptions { ScriptType = ScriptType.RunAlways, RunGroupOrder = 2 })
.WithTransactionPerScript()
.LogToConsole();
var upgrader = upgradeEngineBuilder.Build();
Console.WriteLine("Is upgrade required: " + upgrader.IsUpgradeRequired());
if (args.Any(a => a.StartsWith("--PreviewReportPath", StringComparison.InvariantCultureIgnoreCase)))
{
// Generate a preview file so Octopus Deploy can generate an artifact for approvals
var report = args.FirstOrDefault(x => x.StartsWith("--PreviewReportPath", StringComparison.OrdinalIgnoreCase));
report = report.Substring(report.IndexOf("=") + 1).Replace(#"""", string.Empty);
if (Directory.Exists(report) == false)
{
Directory.CreateDirectory(report);
}
var fullReportPath = Path.Combine(report, "UpgradeReport.html");
if (File.Exists(fullReportPath) == true)
{
File.Delete(fullReportPath);
}
Console.WriteLine($"Generating the report at {fullReportPath}");
upgrader.GenerateUpgradeHtmlReport(fullReportPath);
}
else
{
var result = upgrader.PerformUpgrade();
// Display the result
if (result.Successful)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Success!");
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(result.Error);
Console.WriteLine("Failed!");
}
}
}
I hope that helps!
After long and detailed investigation, we discovered the answer was quite obvious.
We assumed the existing deploy process configuration was sound. Because we never had a problem with it (until now). As it transpires, there was a problem which led to the Development deployments being deployed twice.
Hence, the errors like the one above and others which talked about file handles being held by another process.
It was actually obvious in hindsight, but we were blind to it as we thought the existing process was sound 😣

FileOutputStream throw FileNotFoundException when get File with Japanese in path

When using Google Drive API, I'm having this downloadMetadataFile() here to handle file:
public void downloadMetadataFile(String fileId, String folderStorePath, String fileName) throws IOException, GeneralSecurityException, GoogleException {
String path = folderStorePath + "/" + fileName
java.io.File file = new java.io.File(path);
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
Drive drive = createDrive();
drive.files().get(fileId)
.executeMediaAndDownloadTo(fileOutputStream);
}
}
When using above method with folder exists (izakayaTemplate + 居酒屋):
When path=/reports/template/izakayaTemplate/template3.png, the method working file and download template3.png successful from Google Drive
When path=/reports/template/居酒屋/template3.png, the method throw a FileNotFoundException at line try (FileOutputStream fileOutputStream = new FileOutputStream(file))
Can somebody please explain for me about this behavior?
Note:
I'm using SpringBoot 2.5, Java 8, Drive API v3
I'm running this project on Amazon linux 1 as a service by DaemonTool.
In the run config file, I have set
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8 \
Update 1:
After debug for a while, I found out that the CanonicalPath is wrong for the new file I create but I don't know why it happen.
getPath: /reports/template/居酒屋/template3.png
getAbsolutePath: /reports/template/居酒屋/template3.png
getCanonicalPath: /reports/template/???/template3.png
After searching, I have found the solution for this problem:
Solution: Add export LANG=ja_JP.UTF-8 to the file run
Explanation: canonicalPath is the path file system considers the canonical means to reference the file system object to which it points. So in order for the system to get the canonicalPath to be correct, the environment must have set up correct language environment like in this document: https://docs.oracle.com/cd/E23824_01/html/E26033/glset.html. In my question, the correct language environment is ja_JP.UTF-8

How to launch terminal or command window on program run in IntelliJ

I'm writing a command line program and want the terminal to automatically open whenever I run my program is this possible in IntelliJ?
Yes, you can.
Use this code (you'll need a Project instance, you can get it from ActionEvent.getProject):
GeneralCommandLine commandLine = new GeneralCommandLine([List of your command line arguments]);
OSProcessHandler handler = new OSProcessHandler(commandLine);
TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
ConsoleView console = consoleBuilder.getConsole();
Executor executor = DefaultRunExecutor.getRunExecutorInstance();
DefaultActionGroup actionGroup = new DefaultActionGroup();
BorderLayoutPanel component = JBUI.Panels.simplePanel();
component = component.addToCenter(console.getComponent());
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("MainToolbar", actionGroup, false);
RunContentDescriptor descriptor = new RunContentDescriptor(console,
handler,
component.addToLeft(toolbar.getComponent()),
[Your title],
[Your icon]);
ExecutionManager manager = ExecutionManager.getInstance(project);
manager.getContentManager().showRunContent(executor, descriptor);
AnAction[] consoleActions = console.createConsoleActions();
for (AnAction action : consoleActions) actionGroup.add(action);
actionGroup.add(new PinActiveTabAction());
actionGroup.add(new CloseAction(executor, descriptor, project));
console.allowHeavyFilters();
console.attachToProcess(handler);
ProcessTerminatedListener.attach(handler);
handler.startNotify();

Invoke source control compare operation in vs2012 extension

I am writing a vs2012 extension that will talk to TFS 2010 (though I would prefer if it could also work with tfs2012).
I need to invoke a compare operations on a file from the extension.
I want to use the default compare tool that is configured in visual studio at the moment of the innovation (because the user can configure a different compare tool).
I have the location of the file and I want to be able to invoke the following:
open the default compare.
open a compare with latest version
open a compare with workspace version
Use IVsDifferenceService to invoke Visual Studio diff tool from your VSPackage:
private void Compare(string leftFile, string rightFile)
{
var diffService = (IVsDifferenceService)GetService(typeof(SVsDifferenceService));
if (diffService != null)
{
ErrorHandler.ThrowOnFailure(
diffService.OpenComparisonWindow(leftFile, rightFile).Show()
);
}
}
To test it you need to set the workspace and download the file you want to compare:
// TODO: add some error handling
var tpc = new TfsTeamProjectCollection(new Uri("http://tfs.company.com:8080/tfs"));
var vcs = tpc.GetService<VersionControlServer>();
var workspace = vcs.GetWorkspace(Environment.MachineName, vcs.AuthorizedUser);
string localItem = #"C:\workspace\project\somefile.cs";
var folder = workspace.GetWorkingFolderForLocalItem(localItem);
var item = vcs.GetItem(folder.ServerItem, VersionSpec.Latest);
var latestItem = string.Format("{0}~{1}", localItem, item.ChangesetId);
item.DownloadFile(latestItem);
Compare(localItem, latestItem);
References:
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

How do i check how long a file has been in the Recycle Bin?

As a test i wrote a .NET script which recursively looks in C:\$Recycle.Bin and i'd like to delete files after they been in there for X days.
I decided to check the access time but access time isn't updated on move. How do i check if a file has been in there for X period of time? (i'm using windows 7)
This c# version may help:
var Shl = new Shell(); Folder Recycler = Shl.NameSpace(10);
FI = Recycler.Items().Item(0);
string FileName = Recycler.GetDetailsOf(FI, 0);
string FilePath = Recycler.GetDetailsOf(FI, 1);
string RecyleDate = Recycler.GetDetailsOf(FI, 2);

Resources