This Jenkins plugin sends Eiffel events to a Message Queue. For now, only RabbitMQ is supported. The plugin can be extended with more events and or more data but the required data is there. A detailed list of event representations can be found in the table below.
Read more about the Eiffel protocol at https://eiffel-community.github.io/. The plugin and its features were presented at the 2021 Eiffel Summit; the presentation slides and a video are available.
A number of Jenkins events automatically result in Eiffel events. Additionally, builds have various options of emitting events of their own.
Jenkins Event | Eiffel Event |
---|---|
Job Queued | EiffelActivityTriggeredEvent |
Job Dequeued (canceled) | EiffelActivityCanceledEvent |
Job Starts | EiffelActivityStartedEvent |
Job Finishes | EiffelActivityFinishedEvent |
Job Successful | EiffelActivityFinishedEvent |
Job Unstable | EiffelActivityFinishedEvent |
Job Failed | EiffelActivityFinishedEvent |
Job Aborted | EiffelActivityFinishedEvent |
The plugin conforms to the Paris edition of the Eiffel protocol for the events it emits. Users of the provided sendEiffelEvent pipeline step may choose to emit events from any Eiffel edition up to and including the Lyon edition. See the documentation of each event for details of the corresponding event version used.
If a build needs to emit Eiffel events of its own they should probably have a CONTEXT or CAUSE link to the build's EiffelActivityTriggeredEvent. The plugins injects the following environment variables with the contents of the previously sent events:
EIFFEL_ACTIVITY_TRIGGERED
: The build's EiffelActivityTriggeredEvent event.EIFFEL_ACTIVITY_STARTED
: The build's EiffelActivityStartedEvent event.
The contents of the data.categories
member in EiffelActivityTriggeredEvent
is configurable in two ways:
- A global plugin setting.
- A setting in each job, configured via the UI or the
eiffelActivity
pipeline property:
properties([
eiffelActivity(categories: ['jenkins', 'maven'])
])
Categories can e.g. be used to distinguish Eiffel activities that represent Jenkins builds from other kinds of activities, or distinguish between different kinds of Jenkins builds.
Globally configured categories will be merged with the categories specified in each job. Duplicate entries will be eliminated.
The createPackageURL pipeline step accepts individual components of a Package URL and returns a properly formatted and quoted string that e.g. can be used when piecing together an EiffelArtifactedCreatedEvent. See the Package URL specification for details on what the components mean.
Argument | Required | Description |
---|---|---|
type | ✔ | The package "type" or package "protocol" such as maven, npm, nuget, gem, pypi, etc. |
namespace | A name prefix such as a Maven groupid, a Docker image owner, a GitHub user or organization. | |
name | ✔ | The name of the package. |
version | The version of the package. | |
qualifiers | A Groovy map with extra qualifying data for a package such as an OS, architecture, a distro, etc. | |
subpath | Extra subpath within a package, relative to the package root. |
Example:
def purl = createPackageURL type: 'generic', namespace: 'name/space',
name: 'pkgname', version: '1.0', subpath: 'some/path', qualifiers: [a: 'b']
echo "Here's the resulting purl: ${purl}"
The publishEiffelArtifacts pipeline step sends an EiffelArtifactPublishedEvent
for each EiffelArtifactCreatedEvent that has been recorded in the build using
a sendEiffelEvent step with the publishArtifact
argument enabled and for
each artifact recorded in the specified JSON files in the workspace.
This requires that each EiffelArtifactPublishedEvent has at least one file
defined in its data.fileInformation
array and that each relative file path
in data.fileInformation.name
matches a Jenkins artifact in the build.
Because of the latter requirement it's normally used after an
archiveArtifacts
step.
The EiffelArtifactPublishedEvent will have two links; one ARTIFACT link to the EiffelArtifactCreatedEvent and one CONTEXT link to the parent build's EiffelActivityTriggeredEvent.
Argument | Required | Description |
---|---|---|
artifactEventFiles | An Ant-style glob expression that selects files containing JSON representations (one per line) of EiffelArtifactCreatedEvent to publish. |
Example of publishing artifacts connected to the build:
def event = [
'meta': [
'type': 'EiffelArtifactCreatedEvent',
'version': '3.0.0',
],
'data': [
'identity': 'pkg:generic/myprogram@1.0',
'fileInformation': [
[
'name': 'myprogram-1.0.tar.gz',
],
],
],
]
sendEiffelEvent event: event, publishArtifact: true
archiveArtifacts artifacts: 'myprogram-1.0.tar.gz'
publishEiffelArtifacts()
Example of publishing artifacts from a file:
def event = [
'meta': [
'type': 'EiffelArtifactCreatedEvent',
'version': '3.0.0',
],
'data': [
'identity': 'pkg:generic/myprogram@1.0',
'fileInformation': [
[
'name': 'myprogram-1.0.tar.gz',
],
],
],
]
writeJSON file: 'events.json', json: event
archiveArtifacts artifacts: 'myprogram-1.0.tar.gz'
publishEiffelArtifacts artifactEventFiles: '*.json'
The sendEiffelEvent pipeline step sends an Eiffel event from that's built in the Groovy code or read into a Groovy map from another location. It accepts the following parameters:
Argument | Required | Description |
---|---|---|
event | ✔ | A map with the event payload. The meta.id and meta.time members will be populated automatically. |
linkToActivity | If true (default) the event sent will automatically include link to the current build's EiffelActivityTriggeredEvent. | |
activityLinkType | The link type to use when linking to the EiffelActivityTriggeredEvent. Defaults to CONTEXT but can be set to CAUSE. | |
publishArtifact | If true and the event being sent is EiffelArtifactCreatedEvent it will be recorded for possible later use by the publishEiffelArtifacts step. |
Example:
def event = [
"meta": [
"type": "EiffelCompositionDefinedEvent",
"version": "3.0.0",
],
"data": [
"name": "my-composition",
],
]
def sent = sendEiffelEvent event: event
echo "This event was sent: ${sent}"
// Make the activity link a CAUSE link
sendEiffelEvent event: event, activityLinkType: "CAUSE"
// Skip the activity link altogether
sendEiffelEvent event: event, linkToActivity: false
This step returns immediately as soon as the event has been validated and put in the internal outbound queue. The actual delivery of the event to the broker might not have happened at the time of the return. The validation supports all events and event versions up to and including the Lyon edition.
The plugin will do its best to populate the emitted
EiffelActivityTriggeredEvent with information taken from the causes of
the build, but in many cases you'll want to inject additional Eiffel links
that the plugin can't figure out on its own. This can be done with the
$JOB_URL/eiffel/build API endpoint which works nearly identially to the
standard $JOB_URL/build endpoint except that it requires an additional
eiffellinks
form parameter that contains the Eiffel links to include in
the EiffelActivityTriggeredEvent. eiffellinks
follows the same schema
as the links
value in Eiffel events. Example (payload lacking URL
encoding to improve readability):
POST $JOB_URL/eiffel/build
Content-Type: application/x-www-form-urlencoded
json={"eiffellinks": [{"target": "662b3813-bef4-4588-bf75-ffaead24a6d5", "type": "CAUSE"}], "parameter": [{"name": "PARAM_NAME", "value": "param value"}]}
The eiffellinks
key is mandatory for this endpoint but parameter
is
optional. If the latter is omitted and the job is parameterized the default
values for all parameters will be used.
If at least one CAUSE link is included in eiffellinks
, an EIFFEL_EVENT
trigger will be included in the EiffelActivityTriggeredEvent.
In the EiffelBroadcaster root folder, use maven to compile.
$ mvn compile
In the EiffelBroadcaster root folder, use maven to build the .hpi file.
$ mvn hpi:hpi
- In the Jenkins web interface go to: Manage Jenkins -> Plugin Manager -> Advanced
- At "Upload Plugin", Browse to the .hpi file located in the EiffelBroadcaster/target directory and press "Upload"
The plugin should install without the need to reboot Jenkins.
- Isac Holm <isac.holm@axis.com>
- Magnus Bäck <magnus.back@axis.com>
The MIT License
Copyright 2018-2021 Axis Communications AB.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.