Creating calendar entry in Jenkins using pre email script - groovy

I am currently using Jenkins version 1.617 with the latest Editable Email notification plugin.
What we are trying to do is take the changes from the build and put them into a meeting notice (Calendar Entry).
We are currently stuck using lotus notes 8.5.3FP6.
Here are our variables in the plugin:
Project Recipient List = $SERVER_GROUP
Content Type = HTML(text/html)
Default Subject = $DEFAULT_SUBJECT
Default Content =
$DEFAULT_CONTENT
Repo: myRepo
Install Location: S:\Build\VAT - Visual Authoring Tool\SERVICELOGIQ \GM\VAT_${ENV, var="miniVersion"}\VAT_${ENV, var="releaseversion"}_SERVICELOGIQ [${ENV, var="BUILD_NUMBER"}]
Change Log:
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, showPaths=true}
We are trying to use the following presend script:
import javax.mail.Message
import javax.mail.Message.RecipientType
import javax.mail.Address
import javax.mail.Multipart
import javax.mail.BodyPart
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeMessage
import javax.mail.Session
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMessage
import javax.mail.internet.MimeMultipart
import javax.mail.util.ByteArrayDataSource
import java.util.Date
import java.util.Calendar
import java.util.TimeZone
import java.text.DateFormat
import java.text.SimpleDateFormat
import javax.activation.DataHandler
msg.addHeaderLine("method=REQUEST");
msg.addHeaderLine("charset=UTF-8");
msg.addHeaderLine("component=VEVENT");
final Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR, 1);
final Date start = cal.getTime();
cal.add(Calendar.HOUR, 1);
final Date end = cal.getTime();
SimpleDateFormat dateFmt = new SimpleDateFormat("yyyyMMdd'T'hhmmssZ");
String fmtStartDate = dateFmt.format(start);
String fmtEndDate = dateFmt.format(end);
String subject = msg.getSubject()
Multipart multi = (Multipart)msg.getContent()
BodyPart part = multi.getBodyPart(0)
String body = part.getContent().toString()
String from = "jenkins#ignore.com"
Address[] toAddresses = msg.getAllRecipients()
String to = toAddresses.each{ it.toString() }.join(",")
String content =
"BEGIN:VCALENDAR\n"+
"PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN\n"+
"VERSION:2.0\n" +
"METHOD:REQUEST\n" +
"BEGIN:VEVENT\n" +
"ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:" + to + "\n" +
"ORGANIZER:MAILTO:" + from + "\n" +
"DTSTART:" + fmtStartDate + "\n" +
"DTEND:" + fmtEndDate + "\n" +
"LOCATION:Jenkins Build\n" +
"TRANSP:OPAQUE\n" +
"SEQUENCE:0\n" +
"UID:040000008200E00074C5B7101A82E00800000000002FF466CE3AC5010000000000000000100\n" +
" 000004377FE5C37984842BF9440448399EB02\n" +
"DTSTAMP:20051206T120102Z\n" +
"CATEGORIES:Meeting\n" +
"DESCRIPTION:" + body + "\n\n" +
"SUMMARY:" + subject + "\n" +
"PRIORITY:5\n" +
"CLASS:PUBLIC\n" +
"BEGIN:VALARM\n" +
"TRIGGER:PT1440M\n" +
"ACTION:DISPLAY\n" +
"DESCRIPTION:Reminder\n" +
"END:VALARM\n" +
"END:VEVENT\n" +
"END:VCALENDAR";
// Create the message part
MimeBodyPart messageBodyPart = new MimeBodyPart();
// Fill the message
messageBodyPart.setHeader("Content-Class", "urn:content-classes:calendarmessage");
messageBodyPart.setHeader("Content-ID","calendar_message");
messageBodyPart.setDataHandler(new DataHandler(
new ByteArrayDataSource(content, "text/calendar")));//very important
// Create a Multipart
MimeMultipart multipart = new MimeMultipart();
// Add part one
multipart.addBodyPart(messageBodyPart);
// Put parts in message
msg.setContent(multipart);
This is what we understand from this script, it looks like the script is taking a email that has already been created, parsing the values and changing it into a calendar entry. However, when we run this script, it does create the calendar entry, but only gets the first line of text in the default content section of the email.
Here is an example of the email that is created:
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:myemail
ORGANIZER:MAILTO:jenkins#ignore.com
DTSTART:20150716T123802-0400
DTEND:20150716T013802-0400
LOCATION:Jenkins Build
TRANSP:OPAQUE
SEQUENCE:0
UID:040000008200E00074C5B7101A82E00800000000002FF466CE3AC5010000000000000000100
000004377FE5C37984842BF9440448399EB02
DTSTAMP:20051206T120102Z
CATEGORIES:Meeting
DESCRIPTION:Check console output at http://localhost:8080/job/Test_Project_Sean2/77/ to view the results.
Repo: http://server/hg/hgweb.cgi/ServiceLogiq
Install Location: S:\Build\VAT - Visual Authoring Tool\SERVICELOGIQ\VAT_SERVICELOGIQ [77]
Change Log:
Changes for Build #77
No changes
SUMMARY:Test_Project_Sean2 Build Successful!
PRIORITY:5
CLASS:PUBLIC
BEGIN:VALARM
TRIGGER:PT1440M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR
Our actual meeting notice is displayed like the following:
Check console output at
http://servername to
view the results.
With the email file listed above attached.
Please note that the line that was output is the DEFAULT_CONTENT variable listed above.
We have already tried the following:
def env = System.getenv()
def version = env['CHANGES_SINCE_LAST_SUCCESS']
However, this returned a NULL value.
I would appreciate any help we could get to solve our problem.

For multiple lines in a description in a calendar file, you need to put in an escaped \n instead of real newlines.

Related

How to set revision interval and add commit field to output in pysvn Subversion?

Why does the output not work correctly, taking into account the revision interval? Print all files from all revisions!
enter image description here
How to print commit in the general output?
import pysvn
url = 'http://svn.code.sf.net/p/keepass/code/trunk/'
client = pysvn.Client()
url_info = client.list(
url,
peg_revision=pysvn.Revision(pysvn.opt_revision_kind.number, 137),
revision=pysvn.Revision(pysvn.opt_revision_kind.head),
recurse=True,
dirent_fields=pysvn.SVN_DIRENT_ALL,
patterns=["*.txt"]
)
for entry in url_info:
print(str(entry[0]["created_rev"].number) + " " + str(entry[0]["last_author"]) + " " + str(entry[0]["repos_path"]))

How can I return a string from a Google BigQuery row iterator object?

My task is to write a Python script that can take results from BigQuery and email them out. I've written a code that can successfully send an email, but I am having trouble including the results of the BigQuery script in the actual email. The query results are correct, but the actual object I am returning from the query (results) always returns as a Nonetype.
For example, the email should look like this:
Hello,
You have the following issues that have been "open" for more than 7 days:
-List issues here from bigquery code
Thanks.
The code reads in contacts from a contacts.txt file, and it reads in the email message template from a message.txt file. I tried to make the bigquery object into a string, but it still results in an error.
from google.cloud import bigquery
import warnings
warnings.filterwarnings("ignore", "Your application has authenticated using end user credentials")
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from string import Template
def query_emailtest():
client = bigquery.Client(project=("analytics-merch-svcs-thd"))
query_job = client.query("""
select dept, project_name, reset, tier, project_status, IssueStatus, division, store_number, top_category,
DATE_DIFF(CURRENT_DATE(), in_review, DAY) as days_in_review
from `analytics-merch-svcs-thd.MPC.RESET_DETAILS`
where in_review IS NOT NULL
AND IssueStatus = "In Review"
AND DATE_DIFF(CURRENT_DATE(), in_review, DAY) > 7
AND ready_for_execution IS NULL
AND project_status = "Active"
AND program_name <> "Capital"
AND program_name <> "SSI - Capital"
LIMIT 50
""")
results = query_job.result() # Waits for job to complete.
return results #THIS IS A NONETYPE
def get_queryresults(results): #created new method to put query results into a for loop and store it in a variable
for i,row in enumerate(results,1):
bq_data = (i , '. ' + str(row.dept) + " " + row.project_name + ", Reset #: " + str(row.reset) + ", Store #: " + str(row.store_number) + ", " + row.IssueStatus + " for " + str(row.days_in_review)+ " days")
print (bq_data)
def get_contacts(filename):
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
def read_template(filename):
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
names, emails = get_contacts('mycontacts.txt') # read contacts
message_template = read_template('message.txt')
results = query_emailtest()
bq_results = get_queryresults(query_emailtest())
import smtplib
# set up the SMTP server
s = smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
s.starttls()
s.login('email', 'password')
# For each contact, send the email:
for name, email in zip(names, emails):
msg = MIMEMultipart() # create a message
# bq_data = get_queryresults(query_emailtest())
# add in the actual person name to the message template
message = message_template.substitute(PERSON_NAME=name.title())
message = message_template.substitute(QUERY_RESULTS=bq_results) #SUBSTITUTE QUERY RESULTS IN MESSAGE TEMPLATE. This is where I am having trouble because the Row Iterator object results in Nonetype.
# setup the parameters of the message
msg['From']='email'
msg['To']='email'
msg['Subject']="This is TEST"
# body = str(get_queryresults(query_emailtest())) #get query results from method to put into message body
# add in the message body
# body = MIMEText(body)
#msg.attach(body)
msg.attach(MIMEText(message, 'plain'))
# query_emailtest()
# get_queryresults(query_emailtest())
# send the message via the server set up earlier.
s.send_message(msg)
del msg
Message template:
Dear ${PERSON_NAME},
Hope you are doing well. Please find the following alert for Issues that have been "In Review" for greater than 7 days.
${QUERY_RESULTS}
If you would like more information, please visit this link that contains a complete dashboard view of the alert.
ISE Services
The BQ result() function returns a generator, so I think you need to change your return to yield from.
I'm far from a python expert, but the following pared-down code worked for me.
from google.cloud import bigquery
import warnings
warnings.filterwarnings("ignore", "Your application has authenticated using end user credentials")
def query_emailtest():
client = bigquery.Client(project=("my_project"))
query_job = client.query("""
select field1, field2 from `my_dataset.my_table` limit 5
""")
results = query_job.result()
yield from results # NOTE THE CHANGE HERE
results = query_emailtest()
for row in results:
print(row.field1, row.field2)

Groovy XML SLurper can't access child node

I've recently started using XML Slurper and am trying to access a specific child node from a SOAP envelope. Below is an extract of the XML I'm working with:
<cons:ConsumerName>
<cons:FirstName>Robert</cons:FirstName>
<cons:MiddleName>John</cons:MiddleName>
<cons:FamilyName>Smith</cons:FamilyName>
</cons:ConsumerName>
<cons:ContactPersonName>
<cons:FirstName>William</cons:FirstName>
<cons:MiddleName>Michael</cons:MiddleName>
<cons:FamilyName>Doe</cons:FamilyName>
</cons:ContactPersonName>
I'm trying to access the value of FirstName in the ConusmerName block, I've only been able to get a list of both of the first name values by using:
def block = new XmlSlurper().parseText(text).'**'.findAll{it.name()=='FirstName'}
I tried to get the first name for the ConsumerName block only, by using:
def block = new XmlSlurper().parseText(text).'ConsumerName'.findAll{it.name()=='FirstName'}
But nothing gets returned by that, I can't work out what I'm doing wrong?
I fixed up your xml and providing an answer here:
def text = '<?xml version="1.0" encoding="UTF-8"?>' +
'<cons:Consumer xmlns:cons="urn:corp:cons">' +
' <cons:ConsumerName>' +
' <cons:FirstName>Robert</cons:FirstName>' +
' <cons:MiddleName>John</cons:MiddleName>' +
' <cons:FamilyName>Smith</cons:FamilyName>' +
' </cons:ConsumerName>' +
'' +
' <cons:ContactPersonName>' +
' <cons:FirstName>William</cons:FirstName>' +
' <cons:MiddleName>Michael</cons:MiddleName>' +
' <cons:FamilyName>Doe</cons:FamilyName>' +
' </cons:ContactPersonName>' +
'</cons:Consumer>'
def consumer = new XmlSlurper().parseText(text)
println "Consumer first name: ${consumer.ConsumerName.FirstName}"
Output:
Consumer first name: Robert
To get the firstName value in the ConsumerName block of XML, I used the following:
def text = new File(requestFilePath).text
def fieldValue = new XmlSlurper().parseText(text).'**'.findAll{it.name()==tagBlockName}.getAt(tagName)[0]
def var = (String)fieldValue

Groovy: How to make script that read node name and based on that sends email notifications to different person

Ok so i have one test job in jenkins that works on 5-6 nodes. So what i need is to make script that will read the node name and based on that send notification emails to different people.
Before you start create mailing list variables that contain your slave label and "" after name (SLAVE1 and u can create it like this also SLAVE1_SLAVE2_...)
import hudson.model.*
import javax.mail.Message
import javax.mail.internet.InternetAddress
def envMap = build.getEnvironment(listener)
def NODE_NAME = envMap?.NODE_NAME
def NODE_ADDR_LIST = envMap.find{ it.key.contains(NODE_NAME + "_") }.value
listener.getLogger().println("Found adresses for node " + NODE_NAME + " - " + NODE_ADDR_LIST);
NODE_ADDR_LIST.split(',').each{ msg.addRecipient(Message.RecipientType.TO, new InternetAddress(it + "#example.com")) }

WSGI - importing user made classes

Setup is following:
Apache with WSGI successfully set up and running on bare bones application
import sys
# Path of the directory where scripts directory is located.
sys.path.insert(0, 'C:\\Users\\xxx\\Documents\\Programming\\www\\scripts')
from Blog import Blog #Blog.py is a file in the scripts directory
def application(environ, start_response):
status = '200 OK'
output = ''
b = Blog()
for key in environ.keys():
output = output + str(key) + ' : ' + str(environ[key]) + '<br/>'
output = "Test: " + b.title + "<br/>" + b.text + "<br/>" + output
output = b.get_blog() + "<br/>" + output
response_headers = [('Content-type', 'text/html'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
the relevant parts of Blog.py looks like this
class Blog:
#blogid is a str
def get_blog(self):
conn = sqlite3.connect(self.database)
c = conn.cursor()
# get the blog
c.execute('select * from blogs')
results = []
for row in c:
results.append(row)
c.close()
return results
Apache error log gives me:
line 21, in application
output = b.get_blog() + "<br/>" + output
AttributeError: Blog instance has no attribute 'get_blog'
Changing the b.get_blog to str(dir(b)) gives me:
['doc', 'init', 'module', 'get_data', 'text', 'title'] which is an old version of the Blog class, one that I included in the wsgi file a while ago. I can't find where it's being cached or then why it's not being over written by the Blog import because if I change the import to just import Blog and the instantiation to Blog.Blog() it still gives the same dir contents.
Imported modules have an '__file__' attribute. Print that out, it will tell you where the file is that it loaded for the module. Then you can work out the conflict.
Maybe a version elsewhere on module search path or could be an old .pyc file.

Resources