When my buildbot fails, it is configured to send an email.
Current configuration is:
mailNotify = MailNotifier(fromaddr="****#****.com",
sendToInterestedUsers=True,
extraRecipients=['*****#*****.com', '****#****.com'],
relayhost="mail.****.com",
smtpPort=587,
addLogs = True,
addPatch = True,
useTls=True,
smtpUser="****#****.com",
smtpPassword="****"
mode="failing")
I have a buildmaster setup in my local network, at 192.168.1.11. Because of that, when an email comes, it contains the following information:
Full details are available at:
http://192.168.1.11:8020/builders/BuilderName/builds/136
Buildbot URL: http://192.168.1.11:8020/
Apart from that, I have a publicly accessible server, by which I can access buildbot, i.e. https://mydomain.com/buildbot/
What I want to get is
Full details are available at:
https://mydomain.com/buildbot/builders/BuilderName/builds/136
Buildbot URL: https://mydomain.com/buildbot/
I'd love NOT to rewrite a whole message formatter, but I couldn't find a way to do that. Is it even possible?
AFAIK the best way is to write your own messageFormatter(). It is not much of a pain. I have done it for my buildbot and it works like a charm.
If you look into the sources buildbot\status\mail.py there is function called defaultMesage(...). Just override this in your buildbot's configuration and pass it to the MailNotifier constructor ! Most likely you have to change just the line:108
def myMessageFormatter(mode, name, build, results, master_status)
# Copy everything from buildbot\status\mail.py:defaultMessage()
# Change this to point to https://mydomain.com/buildbot/
if master_status.getURLForThing(build):
text += "Full details are available at:\n %s\n" % master_status.getURLForThing(build)
text += "\n"
Related
I love testing-library, have used it a lot in a React project, and I'm trying to use it in an Angular project now - but I've always struggled with the enormous error output, including the HTML text of the render. Not only is this not usually helpful (I couldn't find an element, here's the HTML where it isn't); but it gets truncated, often before the interesting line if you're running in debug mode.
I simply added it as a library alongside the standard Angular Karma+Jasmine setup.
I'm sure you could say the components I'm testing are too large if the HTML output causes my console window to spool for ages, but I have a lot of integration tests in Protractor, and they are SO SLOW :(.
I would say the best solution would be to use the configure method and pass a custom function for getElementError which does what you want.
You can read about configuration here: https://testing-library.com/docs/dom-testing-library/api-configuration
An example of this might look like:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
You can then put this in any single test file or use Jest's setupFiles or setupFilesAfterEnv config options to have it run globally.
I am assuming you running jest with rtl in your project.
I personally wouldn't turn it off as it's there to help us, but everyone has a way so if you have your reasons, then fair enough.
1. If you want to disable errors for a specific test, you can mock the console.error.
it('disable error example', () => {
const errorObject = console.error; //store the state of the object
console.error = jest.fn(); // mock the object
// code
//assertion (expect)
console.error = errorObject; // assign it back so you can use it in the next test
});
2. If you want to silence it for all the test, you could use the jest --silent CLI option. Check the docs
The above might even disable the DOM printing that is done by rtl, I am not sure as I haven't tried this, but if you look at the docs I linked, it says
"Prevent tests from printing messages through the console."
Now you almost certainly have everything disabled except the DOM recommendations if the above doesn't work. On that case you might look into react-testing-library's source code and find out what is used for those print statements. Is it a console.log? is it a console.warn? When you got that, just mock it out like option 1 above.
UPDATE
After some digging, I found out that all testing-library DOM printing is built on prettyDOM();
While prettyDOM() can't be disabled you can limit the number of lines to 0, and that would just give you the error message and three dots ... below the message.
Here is an example printout, I messed around with:
TestingLibraryElementError: Unable to find an element with the text: Hello ther. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
...
All you need to do is to pass in an environment variable before executing your test suite, so for example with an npm script it would look like:
DEBUG_PRINT_LIMIT=0 npm run test
Here is the doc
UPDATE 2:
As per the OP's FR on github this can also be achieved without injecting in a global variable to limit the PrettyDOM line output (in case if it's used elsewhere). The getElementError config option need to be changed:
dom-testing-library/src/config.js
// called when getBy* queries fail. (message, container) => Error
getElementError(message, container) {
const error = new Error(
[message, prettyDOM(container)].filter(Boolean).join('\n\n'),
)
error.name = 'TestingLibraryElementError'
return error
},
The callstack can also be removed
You can change how the message is built by setting the DOM testing library message building function with config. In my Angular project I added this to test.js:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
This was answered here: https://github.com/testing-library/dom-testing-library/issues/773 by https://github.com/wyze.
I have added a custom locator in protractor, below is the code
const customLocaterFunc = function (locater: string, parentElement?: Element, rootSelector?: any) {
var using = parentElement || (rootSelector && document.querySelector(rootSelector)) || document;
return using.querySelector("[custom-locater='" + locater + "']");
}
by.addLocator('customLocater', customLocaterFunc);
And then, I have configured it inside protractor.conf.js file, in onPrepare method like this:
...
onPrepare() {
require('./path-to-above-file/');
...
}
...
When I run my tests on the localhost, using browser.get('http://localhost:4200/login'), the custom locator function works absolutely fine. But when I use browser.get('http://11.15.10.111/login'), the same code fails to locate the element.
Please note, that the test runs, the browser gets open, user input gets provided, the user gets logged-in successfully as well, but the element which is referred via this custom locator is not found.
FYI, 11.15.10.111 is the remote machine (a virtual machine) where the application is deployed. So, in short the custom locator works as expected on localhost, but fails on production.
Not an answer, but something you'll want to consider.
I remember adding this custom locator, and encounter some problems with it and realised it's just an attribute name... nothing fancy, so I thought it's actually much faster to write
let elem = $('[custom-locator="locator"]')
which is equivalent to
let elem = element(by.css('[custom-locator="locator"]'))
than
let elem = element(by.customLocator('locator'))
And I gave up on this idea. So maybe you'll want to go this way too
I was able to find a solution to this problem, I used data- prefix for the custom attribute in the HTML. Using which I can find that custom attribute on the production build as well.
This is an HTML5 principle to prepend data- for any custom attribute.
Apart from this, another mistake that I was doing, is with the selector's name. In my code, the selector name is in camelCase (loginBtn), but in the production build, it was replaced with loginbtn (all small case), that's why my custom locater was not able to find it on the production build.
I have some code which was working at one point but no longer works, which strongly suggests that the redmine configuration is involved somehow (I'm not the redmine admin), but the lack of any error messages makes it hard to determine what is wrong. Here is the code:
#!/usr/bin/env ruby
require "rubygems"
gem "activeresource", "2.3.14"
require "active_resource"
class Issue < ActiveResource::Base
self.site = "https://redmine.mydomain.com/"
end
Issue.user = "myname"
Issue.password = "mypassword" # Don't hard-code real passwords :-)
issue = Issue.find 19342 # Created manually to avoid messing up real tickets.
field = issue.custom_fields.select { |x| x.name == "Release Number" }.first
issue.notes = "Testing at #{Time.now}"
issue.custom_field_values = { field.id => "Release-1.2.3" }
success = issue.save
puts "field.id: #{field.id}"
puts "success: #{success}"
puts "errors: #{issue.errors.full_messages}"
When this runs, the output is:
field.id: 40
success: true
errors: []
So far so good, except that when I go back to the GUI and look at this ticket, the "notes" part is updated correctly but the custom field is unchanged. I did put some tracing in the ActiveRecord code and that appears to be sending out my desired updates, so I suspect the problem is on the server side.
BTW if you know of any good collections of examples of accessing Redmine from Ruby using the REST API that would be really helpful too. I may just be looking in the wrong places, but all I've found are a few trivial ones that are just enough to whet one's appetite for more, and the docs I've seen on the redmine site don't even list all the available fields. (Ideally, it would be nice if the examples also specified which version of redmine they work with.)
When we are sending the airbrake error to the airbrake server, by default it includes the controller name and action name.
But the question is that I want to add some extra parameters like username, email of the current user. If anyone has any idea please suggest how to do that?
In my layout application.html:
- if ['development'].include?(Rails.env)
= airbrake_javascript_notifier
= render :partial => 'layouts/airbrake_notifier'
and in the partial I have written:
Airbrake.errorDefaults['name'] = "#{current_user.name}";<br/>
Airbrake.errorDefaults['email'] = "#{current_user.email}";<br/>
Airbrake.errorDefaults['phone'] = "#{current_user.phone}";<br/>
Airbrake.errorDefaults['title'] = "#{current_user.title;<br/>
Not a great solution, but the Airbrake Knowledge Base recommends essentially patching the airbrake gem source of the lib/airbrake/notice.rb file.
def initialize(args)
...
self.parameters = args[:parameters] ||
action_dispatch_params ||
rack_env(:params) ||
{'username' => current_user.name}
It would certainly be better to have this be configurable without patching source.
What I've done instead is simply add a few pieces of data to the session (current_user.name mainly), since session data is sent with the request. I wouldn't do this for more than a few little pieces of data.
We've just added getting current users into the Airbrake Gem.
https://github.com/airbrake/airbrake/wiki/Sending-current-user-information
You'll soon be able to sort by current user in an upcoming redesign of the UI.
I have a Nant build script which CruiseControl uses to build a solution on-demand.
However, we only recently got CruiseControl so our official build number is different from what is listed in CruiseControl.
I know CruiseControl injects some properties into build scripts so that I can access the CC build number in the script (CCNetLabel) but how do I pass a value back to CC to use as the build number on the UI screen?
Example, CC says build number 2
nAnt script increments a buildnumber.xml value every build, and the official build number is on 123.
I want the CC UI to show last successful build number: 123, not 2, so how do I pass that value back up?
A custom build labeler is required for this. Perforce is our source control provider and we derive our version number from it. The code is as follows:
/// <summary>
/// Gets the latest change list number from perforce, for ccnet to consume as a build label.
/// </summary>
[ReflectorType( "p4labeller" )]
public class PerforceLabeller : ILabeller
{
// perforce executable (optional)
[ReflectorProperty("executable", Required = false)]
public string P4Executable = "p4.exe";
// perforce port (i.e. myserver:1234)
[ReflectorProperty("port", Required = false)]
public string P4Port = String.Empty;
// perforce user
[ReflectorProperty("user", Required = false)]
public string P4User = String.Empty;
// perforce client
[ReflectorProperty("client", Required = false)]
public string P4Client = String.Empty;
// perforce view (i.e. //Dev/Code1/...)
[ReflectorProperty("view", Required = false)]
public string P4View = String.Empty;
// Returns latest change list
public string Generate( IIntegrationResult previousLabel )
{
return GetLatestChangelist();
}
// Stores latest change list into a label
public void Run( IIntegrationResult result )
{
result.Label = GetLatestChangelist();
}
// Gets the latest change list
public string GetLatestChangelist()
{
// Build the arguments to pass to p4 to get the latest changelist
string theArgs = "-p " + P4Port + " -u " + P4User + " -c " + P4Client + " changes -m 1 -s submitted " + P4View;
Log.Info( string.Format( "Getting latest change from Perforce using --> " + theArgs ) );
// Execute p4
ProcessResult theProcessResult = new ProcessExecutor().Execute( new ProcessInfo( P4Executable, theArgs ) );
// Extract the changelist # from the result
Regex theRegex = new Regex( #"\s[0-9]+\s", RegexOptions.IgnoreCase );
Match theMatch = theRegex.Match( theProcessResult.StandardOutput );
return theMatch.Value.Trim();
}
}
The method, GetLatestChangelist, is where you would probably insert your own logic to talk to your version control system. In Perforce there is the idea of the last changelist which is unique. Our build numbers, and ultimately version numbers are based off of that.
Once you build this (into an assembly dll), you'll have to hook it into ccnet. You can just drop the assembly into the server directory (next to ccnet.exe).
Next you modify your ccnet project file to utilize this labeller. We did this with the default labeller block. Something like the following:
<project>
<labeller type="p4labeller">
<client>myclient</client>
<executable>p4.exe</executable>
<port>myserver:1234</port>
<user>myuser</user>
<view>//Code1/...</view>
</labeller>
<!-- Other project configuration to go here -->
</project>
If you're just wanting the build number to show up in ccnet then you're done and don't really need to do anything else. However, you can access the label in your NAnt script if you wish by using the already provided CCNetLabel property.
Hope this helps some. Let me know if you have any questions by posting to the comments.
Did you try to use some environment variables? I believe CCNet can handle these.
I'll dig a bit on this.
Well I see a solution, quite dirty, but anyhow:
1- Add a defaultlabeller section in your CCNET project definition. It will contains the pattern of the build number you want to display.
2- Within NAnt, have a script to update your configuration file, inserting the build number you want to see.
3- Touch (in the Unix sense) the ccnet.exe.config file so as to make it re-load the projects configuration files.
et voilĂ .
We had this problem as well. I ended up writing a special CC labelling plugin.
If your build numbers are sequential, you can just hack the cruise control state file to give it the correct build number to start with. Your looking for a file called [projectName].state.
I changed the Label element to the correct number and the LastSuccessfulIntegrationLabel to be the new number.
However, we only recently got
CruiseControl so our official build
number is different from what is
listed in CruiseControl.
Sort of along the lines of what gbanfill said, you can tell CC what build numbers to start from, but there's no need to hack the .ser file. You can use the JMX interface to set the current build number to get it in sync with your NAnt build number.
You can also set the default label value to to your current build number, delete the .ser file and restart CC.
But maybe the easiest thing is to write the build number into a property file from NAnt and then use the property file label incrementer to read that file. (Be sure to to set setPreBuildIncrementer="true")