CruiseControl.Net - Can the labeller be made to run after MSBuild? - cruisecontrol.net

I have created a custom labeller for CC.Net which is working almost perfectly, however it appears that the labeller runs before the application is built. The issue I have with this is that I want my build label to be that of my AssemblyVersion.
I have the following in my labeller:
public string Generate(IIntegrationResult previousResult)
{
if (File.Exists(this.OutputExecutable))
{
Assembly assembly = System.Reflection.Assembly.Load(System.IO.File.ReadAllBytes(this.OutputExecutable));
string version = assembly.GetName().Version.ToString();
assembly = null;
return version;
}
else
{
return "0.0.0.0";
}
}
This gets the version of the provided DLL/Exe so that I can use it as my build label. I'll probably go on to add the actual build number in later, but I just want to get this bit working first.
The issue is that my Revision number is in the format 2.0.93601.254 major.minor.date.svnrevision. When a check-in occurs, I build the codebase and the revision number would go to 2.0.93601.255. Unfortunately CC.Net still produces a Build Label of .254 until a force build is called when it will be successfully changed to .255.
Is there any way I can force the labeller to wait until the build process is complete? Or are there any alternative ways I should be doing this?

The answer to this I believe is no. What I did was to create my own console application that updates the assemblyinfo.cs file before the MSBuild task in CC.Net's project configuration. Problem (kind of) solved.

This is backwards from how most people do this; you make ccnet set the version of your code & assemblies automatically, pulling the version from config and say the svn rev #.
This is why it is critically important the labeller runs before tasks.

Related

In a Kotlin multi-platform (or JS) project, (how) can one pass custom command line arguments to Node.js?

I'm working on a Kotlin multi-platform project, and I need my JS tests to run on Node.js but with custom command line arguments (specifically I need node to run with the --expose-gc flag, because some tests need to trigger garbage collection).
Looking at the documentation for the Gradle Kotlin JS DSL I didn't find any mention of how to do that; does anyone know whether it's at all possible and how?
Unfortunately can not answer your question directly, but there is some suggestion to help you with reverse engineering.
Let's start from some example. We have Gradle tasks to run our project using webpack's dev server such as browserDevelopmentRun, browserProductionRun (not sure if multi-platform projects have it, but JS projects do). We can add:
println(tasks.named("browserProductionRun").get().javaClass)
to build.gradle.kts to find out the exact class used for this task. When we sync Gradle, it outputs:
org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack_Decorated
Now we know the exact class of this task so we can investigate its API. The auto completion or navigating inside of the KotlinWebpack class helps us to find out that it has a helpful nodeArgs property to configure NodeJS arguments for it, so we can set them, for example:
tasks.named("browserProductionRun", org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack::class).get().nodeArgs.add("--trace-deprecation")
Getting back to your question.
In your case I guess you need to investigate the browserTest task. Let's get some info about it by adding:
println(tasks.named("browserTest").get().javaClass)
to build.gradle.kts - a-ha - it seems to be of the org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest_Decorated type. Let's check what's inside. Open KotlinJsTest.kt somehow - for example by typing its name into the window being opened by CMD + Shift + O (make sure to select "All Places" here) or just by typing its name somewhere in build.gradle.kts and navigating inside it.
The only interesting thing I see inside this open class is the following block:
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
val forkOptions = DefaultProcessForkOptions(fileResolver)
forkOptions.workingDir = npmProject.dir
forkOptions.executable = nodeJs.requireConfigured().nodeExecutable
val nodeJsArgs = mutableListOf<String>()
return testFramework!!.createTestExecutionSpec(
task = this,
forkOptions = forkOptions,
nodeJsArgs = nodeJsArgs,
debug = debug
)
}
So maybe it can work out to create your own extension of this class, override its createTestExecutionSpec method and provide nodeJsArgs as you need inside it. After that you'll be needing to declare another Gradle task to launch tests inside build.gradle.kts which will use this new extended class.

Karate - Cucumber reports - How can I get cucumber to generate a unique .html report file each time I run a build [duplicate]

I have recently upgraded to version 1.0.0 from 0.9.6 and noticed that the generated karate-summary.html file, it doesn't display all the tested feature files in the JUnit 5 Runner unlike in 0.9.6.
What it displays instead was the last tested feature file only.
The below screenshots are from the provided SampleTest.java sample code (excluding other Tests for simplicity).
package karate;
import com.intuit.karate.junit5.Karate;
class SampleTest {
#Karate.Test
Karate testSample() {
return Karate.run("sample").relativeTo(getClass());
}
#Karate.Test
Karate testTags() {
return Karate.run("tags").relativeTo(getClass());
}
}
This is from Version 0.9.6.
And this one is from Version 1.0.0
However, when running the test below in 1.0.0, all the features are displayed in the summary correctly.
#Karate.Test
Karate testAll() {
return Karate.run().relativeTo(getClass());
}
Would anyone be kind to confirm if they are getting the similar result? It would be very much appreciated.
What it displays instead was the last tested feature file only.
This is because for each time you run a JUnit method, the reports directory is backed up by default. Look for other directories called target/karate-reports-<timestamp> and you may find your reports there. So maybe what is happening is that you have multiple JUnit tests that are all running, so you see this behavior. You may be able to over-ride this behavior by calling the method: .backupReportDir(false) on the builder. But I think it may not still work - because the JUnit runner has changed a little bit. It is designed to run one method at a time, when you are in local / dev-mode.
So the JUnit runner is just a convenience. You should use the Runner class / builder for CI execution, and when you want to run multiple tests and see them in one report: https://stackoverflow.com/a/65578167/143475
Here is an example: ExamplesTest.java
But in case there is a bug in the JUnit runner (which is quite possible) please follow the process and help the project developers replicate and then fix the issue to release as soon as possible.

InstallShield: How can single custom actions be tested?

(I'm using InstallShield2012 V.18)
In setup.rul I defined a function per prototype declaration, included the file with the function definition and compiled it successfully (InstallShield compile).
Now I'd like to test this function (only).
I don't want to run the whole installation, not even test (Ctrl-T) because I want to avoid a complete re-build which takes too long time to do it often.
Is there a way to test only the custom function in InstallShield or per command line?
Not really although I can give you some tips.
Create a dummy feature with a release flag of DEVONLY.
Create a dummy component for that feature.
Create a ProductConfiguration that builds a single MSI with no EXE and a release flag of DEVONLY.
Building this production configuration will be very fast. A couple seconds on my laptop with an SSD. You can selectivly include other features through the use of release flags if you need certain components in order to setup the test environment for your CA.
Another strategy is to develop your CA in a test harness project and then transplant the code into your real installer when you know it all works.
Christopher, thanks for this fast reply. I have to put my answer here because commenting was restricted, because too long.
I also thought about using such a workaround but first wanted to avoid it if possible.
But ok, now I tried these steps, 1 and 2 no problem, but 3: InstallShield didn't allow me to configure a Product Configuration without Setup.exe in my .ism file (although we have IS2012 Pro).
Then I tried to do it in a Basic MSI Project (is that what you meant?), which really builds in very short time. And now I can see my scripting during Test Release, yeah :-)
To "transplant" my script now to the main ism I'm missing an export function for .rul files as it exists for custom actions, but there is only a import. So I will have to copy-paste while switching between ism files, but never mind.

Why does failed source control in CruiseControl.net not fail the build?

I'm using cruisecontrol.net for integration builds along with external source control. The source control (GETMODS) script fails, this is fine and I know why, but the build stays green for some reason when it's expected to fail. CruiseControl shows the exception on the output window below, so why doesn't the build fail?
ThoughtWorks.CruiseControl.Core.CruiseControlException: Source control operation failed:
at ThoughtWorks.CruiseControl.Core.Sourcecontrol.ProcessSourceControl.Execute
(ProcessInfo processInfo)
at ThoughtWorks.CruiseControl.Core.Sourcecontrol.ProcessSourceControl.GetModifications(ProcessInfo info, DateTime from, DateTime to)
at ThoughtWorks.CruiseControl.Core.Sourcecontrol.ExternalSourceControl.GetMod ifications(IIntegrationResult from, IIntegrationResult to)
at ThoughtWorks.CruiseControl.Core.Sourcecontrol.QuietPeriod.GetModifications(ISourceControl sourceControl, IIntegrationResult lastBuild, IIntegrationResultthisBuild)
at ThoughtWorks.CruiseControl.Core.IntegrationRunner.GetModifications(IIntegrationResult from, IIntegrationResult to)
at ThoughtWorks.CruiseControl.Core.IntegrationRunner.Integrate(IntegrationRequest request)
at ThoughtWorks.CruiseControl.Core.Project.Integrate(IntegrationRequest request)
at ThoughtWorks.CruiseControl.Core.ProjectIntegrator.Integrate()
at ThoughtWorks.CruiseControl.Core.ProjectIntegrator.Run()
I guess the reasoning would be that the source control block is only used:
to check if there are any changes in the source code which require a rebuild, and
to get all the source code needed for the build.
If this action fails it has nothing to do with the source code and the commits to it. It's an infrastructural problem that prevents the build from happening at all therefore technically the build hasn't fails. It hasn't even started.
With a version control block inside cc.net, it search for repository modification.
If cc.net is unable to contact the repository, it can't start the job.
The result is an exception.
If you want to ignore this, this can help (simple retry counter) !
Can we tell CruiseControl.NET to ignore source control timeout errors?
<maxSourceControlRetries>5</maxSourceControlRetries>
<stopProjectOnReachingMaxSourceControlRetries>true</stopProjectOnReachingMaxSourceControlRetries>
<sourceControlErrorHandling>ReportOnRetryAmount</sourceControlErrorHandling>
I believe this is a recent change to ccnet. We are running two versions on separate machines. Version 1.4 breaks the build if it can't get to our svn repository, but version 1.5 will not break the build. I haven't looked into it yet, but there may be a switch to force 1.5 to break on failure to retrieve code.

How do I delete a directory with cc.net / cruiscontrol? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Pre-build task - deleting the working copy in CruiseControl.NET
I would like to delete my working directory during the cruisecontrol build process...I'm sure this is easy, but I have been unable to find an example of it...
If you know how to create a directory, that would be useful as well.
Thanks.
One of two ways.
If you're already using an MSBuild file or something similar, add the action to the MSBuild file.
Instead of directly executing some command, create a batch file that executes that command and then deletes the directory, and have CCnet call that batch file instead.
My guess is that you want to delete the working directory before CruiseControl.NET gets the latest code from source control. If this is the case, then the only way to accomplish this is to write a custom source control provider for CruiseControl.NET that first deletes the working directory and then gets the latest code. Have a look at CruiseControl.NET's source code for examples of how to write a source control provider.
If you want to delete the working directory after the latest code is retrieved from source control, then you can use CruiseControl.NET's executable task by running "cmd /c del directoryname".
In the ASP.NET work, for me, the easiest way I do it (which allows me to hit either MSBUild or NAnt depending upon the project) was to roll my own exe that takes an argument which I pass in with a bat file fired by CC.NET. It's not the safest thing in the world, but if you have total control over your automated build machine; it's not too shabby. Quick and reusable.
Drop in the exe somewhere that does the recursive delete:
static void Main(string[] args)
{
for (int n = 0; n < args.Length; n++)
{
if (Directory.Exists(args[n].ToString()))
{
Directory.Delete(args[n].ToString(), true);
}
}
}
Drop it in somewhere multiple files can pass arguments to it and just write a custom .bat file for each project. So my task block looks like this:
<tasks>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
<workingDirectory>Z:\WorkingDirectory</workingDirectory>
<projectFile>YourSolution.sln</projectFile>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
<exec>
<executable>Z:\SomePathToBuildScripts\YourCustomBat.bat</executable>
</exec>
</tasks>
Then the final step is setting up that .bat file to perform the delete/rebuild functions after use. In the bat file just make sure you rebuild ("MD") the directories you deleted if youexpect to publish a site back to them. On our dev boxes I found this to be the best way to prevent the beloved Frankenbuild.
The way I've done this in the past is to not have CC.Net checkout source itself. Instead, there are two <msbuild> elements for the project, the first one calling a build target that runs svn-clean.pl (compiled to .exe), and then updates the source using svn.exe. The second <msbuild> element starts the main build process.
You can easily replace svn-clean with a delete command. For my projects, deleting chaff from a checkout has always been faster than checking out a fresh working copy.
The two msbuild elements are necessary because the main project build file is often updated. This is important because updates to your build file(s) will only be reloaded if you start a new msbuild process.
This setup breaks down when I (very rarely) move or change the dependencies of that clean-and-update build target to the extent that the msbuild process would need to reload for valid instructions to run the clean-and-update target. When this happens, I stop CC.Net before committing, go into the CC.Net server, and do an 'svn update' by hand.
Sidelight: It could well be that CC.Net has a natural clean-before-build operation by now. I've since moved to TeamCity, which is configurable to do this every build or only when the developer chooses (e.g., when you know you've made a change that would not update cleanly--svn moves of directories with build products comes to mind).

Resources