About Plugins
Artifactory Pro allows you to easily extend Artifactory's behavior with your own plugins written in Groovy.
User plugins are used for running user's code in Artifactory. Plugins allow you to perform the following tasks:
- Add scheduled tasks
- Extend Artifactory with your own security realms
- Change resolution rules
- Manipulate downloaded content
- Respond to any storage events on items and properties
- Deploy and query artifacts and metadata
- Perform searches
- Query security information
- Invoke custom commands via REST
- Execute custom promotion logic
- Provide information and strategies for Artifactory's Build Servers Plugins.
During the development phase, you can change plugin source files and have your plugins redeployed on-the-fly. You can even debug the plugin code using your favorite IDE.
Deploying Plugins
Place your plugin files under ${ARTIFACTORY_HOME}/etc/plugins
.
Any file name ending with .groovy
is loaded on startup. You can have multiple plugin files which are loaded in alphabetical order. Callbacks defined in plugins are called by the order they were loaded.
Auto Reload
By default, plugins are not reloaded after Artifactory has started-up. You can configure Artifactory to automatically detect plugin changes on disk or new plugin files and automatically reload them in runtime (plugin removals are not detected).
To do this, set the number of seconds to check for plugin updates to a number greater than 0, by changing the following property in ${ARTIFACTORY_HOME}/etc/artifactory.system.properties
, or by specifying the property with -D to the JVM running Artifactory:
artifactory.plugin.scripts.refreshIntervalSecs=0
NOTE! that deleting or renaming plugin files while auto-reloading is active is not fully supported and requires an Artifactory restart.
Plugins Lib Directory
If your plugin requires any external dependencies, you can place them under the ${ARTIFACTORY_HOME}/etc
/plugins/lib
directory.
Writing Plugins
Artifactory plugins are written as Groovy scripts in regular files and have a simple DSL to wrap users code in closures inside well-known extension points.
Scripts have a couple of helper objects that are globally bound (see the plugin script template).
The Artifactory Public API (PAPI)
Scripts have access to the full classpath of Artifactory, however, the only API supported for plugins is the
Artifactory Public API, defined in the artifactory-papi.jar
.
The artifactory-papi.jar
can be found under WEB-INF/lib
folder inside the artifactory.war
.
Please see the Plugin Code Template and Sample Plugin below for more details.
Globally Bound Variables
Plugin Execution Points
The following table summarizes the available execution points. For more details about specific plugin look follow the section links.
Plugin Type | Code block name | When executed | Description |
Download |
Event Callback (with return values)
| altResponse | On any download | Provide an alternative response, by setting a success/error status code value and an optional error message or by setting new values for the inputStream and size context variables (For succeeded resolutions). |
altRemotePath | When reaching out to remote repositories | Provides an alternative download path under the same remote repository, by setting a new value to the path variable. |
altRemoteContent | After fetching content from remote repositories | Provide an alternative download content, by setting new values for the inputStream and size context variables. |
afterDownloadError | After failing during content fetching from remote repositories | Provide an alternative response, by setting a success/error status code value and an optional error message or by setting new values for the inputStream and size context variables (For failed resolutions). |
Event Callback (without return value)
| beforeRemoteDownload | Before fetching content from remote repositories | Handle before remote download events. |
afterRemoteDownload | After fetching content from remote repositories | Handle after remote download events. |
beforeDownload | On any download | Handle before download events. |
beforeDownloadRequest | On any download | Handle before download requset events, executed before Artifactory starts to handle the original client request, useful for intercepting expirable resources (other than the default ones like maven-metadata.xml). |
Storage |
Event Callback (without return value) | before/after Create, Delete, Move, Copy, PropertyCreate, PropertyDelete | Before / After selected storage operation | Handle events before and after Create, Delete, Move and Copy operations |
Jobs |
Scheduled execution | any valid Groovy (Java) literal as execution name | According to provided interval/delay or
cron expression | Job runs are controlled by the provided interval or
cron expression, which are mutually exclusive. The actual code to run as part of the job should be part of the job's closure. |
Executions |
User-driven execution | any valid Groovy (Java) literal as execution name | By REST call | External executions are invoked via REST requests. |
Realms |
Event Callback (without return value) | any valid Groovy (Java) literal as realm name with nested blocks: authenticate userExists | During user authentication | Newly added realms are added before any built-in realms (Artifactory internal realm, LDAP, Crowd etc.). User authentication will be attempted against these realms first, by the order they are defined. |
Build |
Event Callback (without return value) | beforeSave | Before the build info is saved in Artifactory | Handle before build info save events |
afterSave | After the build info is saved in Artifactory | Handle after build info save events |
Promotions |
User or build server driven execution | any valid Groovy (Java) literal as promotion name | By REST call | Promotes integration (a.k.a. snapshot) build to be a release invoking any code associated with it. |
Staging Strategy |
|
|
|
build server driven execution | any valid Groovy (Java) literal as staging strategy name | During build server driven staging build configuration | The strategy provides the build server with the following information: - How the artifacts in the staged build should be versioned;
- How the artifacts in the next integration build should be versioned;
- Should the build server create a release branch/tag/stream in VCS and how it should be called;
- To which repository in Artifactory the built artifacts should be submitted.
|
Replication |
|
|
|
Event callback (with return value) | beforeFileReplication | Before file is replicated | Handle before file replication events. File replication can be skipped. |
beforeDirectoryReplication | Before directory is replicated | Handle before directory replication events. Directory replication can be skipped. |
beforeDeleteReplication | Before file/directory is deleted | Handle before file or directory are deleted. |
beforePropertyReplication | Before properties are replicated | Handle properties replication. |
Execution Context
The Download, Storage, Execution and Build plugin types are executed under the identity of the user request that triggered them.
It is possible to force a block of plugin code to execute under the "system" role, which is not bound to any authorization rules and can therefore perform actions that are otherwise forbidden for the original user.
To run under the "system" role wrap your code with the asSystem
closure:
... someCode ...
asSystem {
//This code runs as the system role
}
... someOtherCode ...
The Realm and Job plugin types already execute under the "system" role. This cannot be changed.
Including AQL Queries
User plugins may include AQL queries opening up the full set of search capabilities that AQL has to offer. AQL queries are implemented within the Searches
object as shown in the example below.
import org.artifactory.addon.AddonsManager
import org.artifactory.addon.gems.GemsAddon
import org.artifactory.api.context.ContextHelper
import org.artifactory.repo.RepoPathFactory
import org.artifactory.search.Searches
import org.artifactory.search.aql.AqlResult
executions {
gemPropsPopulator() {
def gemAddon = ContextHelper.get().beanForType(AddonsManager.class).addonByType(GemsAddon.class)
def repoKey = "gem-local"
((Searches) searches).aql(
"items.find({" +
"\"repo\": \"" + repoKey + "\"," +
"\"\$or\":[" +
"{\"property.key\":{\"\$ne\":\"gem.name\"}}," +
"{\"property.key\":{\"\$ne\":\"gem.version\"}}" +
"]})" +
".include(\"path\", \"name\")") {
AqlResult result ->
result.each {
...
...
...
}
}
}
}
Plugin Template Source
General Info
General info....
/*
* Copyright (C) 2011 JFrog Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* Globally bound variables:
*
* log (org.slf4j.Logger)
* repositories (org.artifactory.repo.Repositories)
* security (org.artifactory.security.Security)
* searches (org.artifactory.search.Searches) [since: 2.3.4]
* builds (org.artifactory.build.Builds) [since 2.5.2]
*
* ctx (org.artifactory.spring.InternalArtifactoryContext) - NOT A PUBLIC API - FOR INTERNAL USE ONLY!
*/
Download
Handling and manipulating "download" events...
download {
/**
* Provide an alternative response, by one of the following methods:
* (1) Setting a success/error status code value and an optional error message.
* (2) Provide an alternative download content, by setting new values for the inputStream and size context variables.
*
* Note that, unless specifically handled, checksum requests for altered responses will return the checksum of the
* original resource, which may not match the checksum of the alternate response.
*
* Will not be called if the response is already committed (e.g. a previous error occurred).
* Currently called only for GET requests where the resource was found.
*
* Context variables:
* status (int) - a response status code. Defaults to -1 (unset).
* message (java.lang.String) - a text message to return in the response body, replacing the response content.
* Defaults to null.
* inputStream (java.io.InputStream) - a new stream that provides the response content. Defaults to null.
* size (long) - the size of the new content (helpful for clients processing the response). Defaults to -1.
* headers (java.util.Map<String,String>) - Map containing the extra headers to override or add if not exists to the response.
*
* Usage example:
* headers = ["ExtraHeader":"SpecialHeader"]
*
*
*
* Closure parameters:
* request (org.artifactory.request.Request) - a read-only parameter of the request.
* responseRepoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the response RepoPath (containing the
* physical repository the resource was found in).
*/
altResponse { request, responseRepoPath ->
}
/**
* Provides an alternative download path under the same remote repository, by setting a new value to the path
* variable.
*
* Context variables:
* path (java.lang.String) - the new path value. Defaults to the originalRepoPath's path.
*
* Closure parameters:
* repoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the original request RepoPath.
*/
altRemotePath { repoPath ->
}
/**
* Provide an alternative download content, by setting new values for the inputStream and size context variables.
*
* Context variables:
* inputStream (java.io.InputStream) - a new stream that provides the response content. Defaults to null.
* size (long) - the size of the new content (helpful for clients processing the response). Defaults to -1.
*
* Closure parameters:
* repoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the original request RepoPath.
*/
altRemoteContent { repoPath ->
}
/**
* In case of resolution error provide an alternative response, by setting a success/error status code value and an optional error message.
* Will not be called if the response is already committed (e.g. a previous error occurred).
* As opposite to altResponse, called only for GET requests during which error occurred (e.g. 404 - not found, or 409 - conflict).
*
* Context variables:
* status (int) - a response error status code (may be overridden in the plugin).
* message (java.lang.String) - a response error message (may be overridden in the plugin).
* inputStream (java.io.InputStream) - a new stream that provides the response content. Defaults to null.
* size (long) - the size of the new content (helpful for clients processing the response). Defaults to -1.
*
* Closure parameters:
* request (org.artifactory.request.Request) - a read-only parameter of the request.
*/
afterDownloadError { request ->
}
/**
* Handle before remote download events.
*
* Context variables:
* headers (java.util.Map<String,String>) - Map containing the extra headers to insert into the remote server request
*
* Usage example:
* headers = ["ExtraHeader":"SpecialHeader"]
*
* Note: The following cannot be used as extra headers and Artifactory will always override them:
* "X-Artifactory-Originated". "Origin-Artifactory", "Accept-Encoding"
*
* Closure parameters:
* request (org.artifactory.request.Request) - a read-only parameter of the request. [since: 2.3.4]
* repoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the original request RepoPath.
*/
beforeRemoteDownload { request, repoPath ->
}
/**
* Handle after remote download events.
*
* Closure parameters:
* request (org.artifactory.request.Request) - a read-only parameter of the request. [since: 2.3.4]
* repoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the original request RepoPath.
*/
afterRemoteDownload { request, repoPath ->
}
/**
* Handle before local download events.
*
* Closure parameters:
* request (org.artifactory.request.Request) - a read-only parameter of the request.
* responseRepoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the response RepoPath (containing the
* physical repository the resource was found in).
*/
beforeDownload { request, responseRepoPath ->
}
/**
* Handle before any download events, at this point the request passed all of Artifactory's filters (authentication etc) and is about to reach the repositories.
*
* Context variables:
* expired (boolean) - Mark the requested resource as expired. Defaults to false (unset).
* An expired resource is one that it's (now() - (last updated time)) time is higher than the repository retrieval cache period milliseconds.
* Setting this option to true should be treated with caution, as it means both another database hit (for updating the last updated time)
* as well as network overhead since if the resource is expired, a remote download will occur to re-download it to the cache.
* A common implementation of this extension point is to check if the resource comply with a certain pattern (for example: a *.json file)
* AND the original request was to the remote repository (and not directly to it's cache)
* AND a certain amount of time has passed since the last expiry check (to minimize DB hits).
* See our public GitHub for an example here: https://github.com/JFrog/artifactory-user-plugins/blob/master/download/beforeDownloadRequest/beforeDownloadRequest.groovy
*
* modifiedRepoPath (org.artifactory.repo.RepoPath)
* Forces Artifactory to store the file at the specified repository path in the remote cache.
* See our public GitHub for an example here: https://github.com/JFrog/artifactory-user-plugins/blob/master/download/modifyMD5File/ModifyMD5FileTest.groovy
* Closure parameters:
* request (org.artifactory.request.Request) - a read-only parameter of the request.
* repoPath (org.artifactory.repo.RepoPath) - a read-only parameter of the response RepoPath (containing the
* physical repository the resource was found in).
*/
beforeDownloadRequest { request, repoPath ->
}
}
Storage
Handling and manipulating "storage" events...
If you want to abort an action, you can do that in 'before' methods by throwing a runtime org.artifactory.exception.CancelException with an error message and a proper http error code.
storage {
/**
* Handle before create events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the original item being created.
*/
beforeCreate { item ->
}
/**
* Handle after create events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the original item being created.
*/
afterCreate { item ->
}
/**
* Handle before delete events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the original item being being deleted.
*/
beforeDelete { item ->
}
/**
* Handle after delete events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the original item deleted.
*/
afterDelete { item ->
}
/**
* Handle before move events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the source item being moved.
* targetRepoPath (org.artifactory.repo.RepoPath) - the target repoPath for the move.
*/
beforeMove { item, targetRepoPath, properties ->
}
/**
* Handle after move events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the source item moved.
* targetRepoPath (org.artifactory.repo.RepoPath) - the target repoPath for the move.
*/
afterMove { item, targetRepoPath, properties ->
}
/**
* Handle before copy events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the source item being copied.
* targetRepoPath (org.artifactory.repo.RepoPath) - the target repoPath for the copy.
*/
beforeCopy { item, targetRepoPath, properties ->
}
/**
* Handle after copy events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the source item copied.
* targetRepoPath (org.artifactory.repo.RepoPath) - the target repoPath for the copy.
*/
afterCopy { item, targetRepoPath, properties ->
}
/**
* Handle before property create events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the item on which the property is being set.
* name (java.lang.String) - the name of the property being set.
* values (java.lang.String[]) - A string array of values being assigned to the property.
*/
beforePropertyCreate { item, name, values ->
}
/**
* Handle after property create events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the item on which the property has been set.
* name (java.lang.String) - the name of the property that has been set.
* values (java.lang.String[]) - A string array of values assigned to the property.
*/
afterPropertyCreate { item, name, values ->
}
/**
* Handle before property delete events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the item from which the property is being deleted.
* name (java.lang.String) - the name of the property being deleted.
*/
beforePropertyDelete { item, name ->
}
/**
* Handle after property delete events.
*
* Closure parameters:
* item (org.artifactory.fs.ItemInfo) - the item from which the property has been deleted.
* name (java.lang.String) - the name of the property that has been deleted.
*/
afterPropertyDelete { item, name ->
}
}
Jobs
Defining scheduled jobs...
jobs {
/**
* A job definition.
* The first value is a unique name for the job.
* Job runs are controlled by the provided interval or cron expression, which are mutually exclusive.
* The actual code to run as part of the job should be part of the job's closure.
*
* Parameters:
* delay (long) - An initial delay in milliseconds before the job starts running (not applicable for a cron job).
* interval (long) - An interval in milliseconds between job runs.
* cron (java.lang.String) - A valid cron expression used to schedule job runs (see: http://www.quartz-scheduler.org/docs/tutorial/TutorialLesson06.html)
*/
myJob(interval: 1000, delay: 100) {
}
mySecondJob(cron: "0/1 * * * * ?") {
}
}
Executions
Defining external executions...
curl -X GET -v -u admin:password "http://localhost:8080/artifactory/api/plugins/execute/myExecution?params=msg=And+the+result+is:|no1=10|no2=15&async=0"
executions {
/**
* An execution definition.
* The first value is a unique name for the execution.
*
* Context variables:
* status (int) - a response status code. Defaults to -1 (unset). Not applicable for an async execution.
* message (java.lang.String) - a text message to return in the response body, replacing the response content.
* Defaults to null. Not applicable for an async execution.
*
* Plugin info annotation parameters:
* version (java.lang.String) - Closure version. Optional.
* description (java.lang.String) - Closure description. Optional.
* httpMethod (java.lang.String, values are GET|PUT|DELETE|POST) - HTTP method this closure is going
* to be invoked with. Optional (defaults to POST).
* params (java.util.Map<java.lang.String, java.lang.String>) - Closure default parameters. Optional.
* users (java.util.Set<java.lang.String>) - Users permitted to query this plugin for information or invoke it.
* groups (java.util.Set<java.lang.String>) - Groups permitted to query this plugin for information or invoke it.
*
* Closure parameters:
* params (java.util.Map) - An execution takes a read-only key-value map that corresponds to the REST request
* parameter 'params'. Each entry in the map contains an array of values. This is the default closure parameter,
* and so if not named it will be "it" in groovy.
* ResourceStreamHandle body - Enables you to access the full input stream of the request body.
* This will be considered only if the type ResourceStreamHandle is declared in the closure.
*/
myExecution(version:version, description:description, httpMethod: 'GET', users:[], groups:[], params:[:]) { params ->
}
execWithBody(version:version, description:description, httpMethod: 'GET', users:[], groups:[], params:[:]) { params, ResourceStreamHandle body ->
}
}
Realms
Management of security realms...
Realms defined here are added before any built-in realms (Artifactory internal realm, LDAP, Crowd etc.). User authentication will be attempted against these realms first, by the order they are defined.
realms {
/**
* A security realm definition.
* The first value is a unique name for the realm.
*
* Closure parameters:
* autoCreateUsers (boolean) - Whether to automatically create users in Artifactory upon successful login. Defaults to
* true. When false, the user will be transient and their privileges will be managed according to permissions defined for auto-join groups.
* realmPolicy (org.artifactory.security.RealmPolicy): (Optional) - If included with value RealmPolicy.ADDITIVE, plugin will be executed only if the user has previously been authenticated, and allows enrichment of the authenticated
* user with additional data.
* See our public GitHub for an example here: https://github.com/JFrog/artifactory-user-plugins/blob/master/security/synchronizeLdapGroups/synchronizeLdapGroups.groovy
*/
myRealm(autoCreateUsers: true, realmPolicy: RealmPolicy.ADDITIVE) {
/**
* Implementation should return true/false as the result of the authentication.
*
* Context variables:
* groups (java.lang.String[]) - An array of groups that the authenticated user should be associated with (since 3.0.2).
* user (org.artifactory.security.User) - The authenticated user.
*
* Closure parameters:
* username (java.lang.String) - The username
* credentials (java.lang.String) - The password
*/
authenticate { username, credentials ->
}
/**
* Implementation should return true if the user is found in the realm.
* Closure parameters:
* username (java.lang.String) - The username
*/
userExists { username ->
}
}
}
Build
Handling "Build Info" events...
build {
/**
* Handle before build info save events
*
* Closure parameters:
* buildRun (org.artifactory.build.DetailedBuildRun) - Build Info model to be saved. Partially mutable.
*/
beforeSave { buildRun ->
}
/**
* Handle after build info save events
*
* Closure parameters:
* buildRun (org.artifactory.build.DetailedBuildRun) - Build Info that was saved. Partially mutable.
*/
afterSave { buildRun ->
}
}
Defining REST executable build promotion operations...
promotions {
/**
* A REST executable build promotion definition.
*
* Context variables:
* status (int) - a response status code. Defaults to -1 (unset).
* message (java.lang.String) - a text message to return in the response body, replacing the response content. Defaults to null.
*
* Plugin info annotation parameters:
* version (java.lang.String) - Closure version. Optional.
* description (java.lang.String - Closure description. Optional.
* params (java.util.Map<java.lang.String, java.lang.String>) - Closure parameters. Optional.
* users (java.util.Set<java.lang.String>) - Users permitted to query this plugin for information or invoke it.
* groups (java.util.Set<java.lang.String>) - Groups permitted to query this plugin for information or invoke it.
*
* Closure parameters:
* buildName (java.lang.String) - The build name specified in the REST request.
* buildNumber (java.lang.String) - The build number specified in the REST request.
* params (java.util.Map<java.lang.String, java.util.List<java.lang.String>>) - The parameters specified in the REST request.
*/
promotionName(version, description, users, groups, params) { buildName, buildNumber, params ->
}
}
Staging
Defining REST retrievable build staging strategy construction...
/**
* Set of staging strategy definitions to be used by the build server during staging process.
* The strategy provides the build server with the following information:
* 1. How the artifacts in the staged build should be versioned;
* 2. How the artifacts in the next integration build should be versioned;
* 3. Should the build server create a release branch/tag/stream in VCS and how it should be called;
* 4. To which repository in Artifactory the built artifacts should be submitted.
*
* This user plugin is called by the build server using REST call.
*/
staging {
/**
* A build staging strategy definition.
*
* Closure delegate:
* org.artifactory.build.staging.BuildStagingStrategy - The strategy that's to be returned.
*
* Plugin info annotation parameters:
* version (java.lang.String) - Closure version. Optional.
* description (java.lang.String - Closure description. Optional.
* params (java.util.Map<java.lang.String, java.lang.String>) - Closure parameters. Optional.
* users (java.util.Set<java.lang.String>) - Users permitted to query this plugin for information or invoke it.
* groups (java.util.Set<java.lang.String>) - Groups permitted to query this plugin for information or invoke it.
*
* Closure parameters:
* buildName (java.lang.String) - The build name specified in the REST request.
* params (java.util.Map<java.lang.String, java.util.List<java.lang.String>>) - The parameters specified in the REST request.
*/
strategyName(version, description, users, groups, params) { buildName, params ->
}
}
Replication
Handling and filtering replication events (since version 3.0.4)...
replication {
/**
* Handle before file replication events.
*
* Context variables:
* skip (boolean) - whether to skip replication for the current item. Defaults to false. Set to true to skip replication.
* targetInfo (org.artifactory.addon.replication.ReplicationTargetInfo) - contains information about the replication target server
*
* Closure parameters:
* localRepoPath (org.artifactory.repo.RepoPath) - the repoPath of the item on the local Artifactory server.
*/
beforeFileReplication { localRepoPath ->
}
/**
* Handle before directory replication events.
*
* Context variables:
* skip (boolean) - whether to skip replication for the current item. Defaults to false. Set to true to skip replication.
* targetInfo (org.artifactory.addon.replication.ReplicationTargetInfo) - contains information about the replication target server
*
* Closure parameters:
* localRepoPath (org.artifactory.repo.RepoPath) - the repoPath of the item on the local Artifactory server.
*/
beforeDirectoryReplication { localRepoPath ->
}
/**
* Handle before delete replication events.
*
* Context variables:
* skip (boolean) - whether to skip replication for the current item. Defaults to false. Set to true to skip replication.
* targetInfo (org.artifactory.addon.replication.ReplicationTargetInfo) - contains information about the replication target server
*
* Closure parameters:
* localRepoPath (org.artifactory.repo.RepoPath) - the repoPath of the item on the local Artifactory server.
*/
beforeDeleteReplication { localRepoPath ->
}
/**
* Handle before property replication events.
*
* Context variables:
* skip (boolean) - whether to skip replication for the current item. Defaults to false. Set to true to skip replication.
* targetInfo (org.artifactory.addon.replication.ReplicationTargetInfo) - contains information about the replication target server
*
* Closure parameters:
* localRepoPath (org.artifactory.repo.RepoPath) - the repoPath of the item on the local Artifactory server.
*/
beforePropertyReplication { localRepoPath ->
}
/**
* Handle before statistics replication events.
*
* Context variables:
* skip (boolean) - whether to skip replication for the current item. Defaults to false. Set to true to skip replication.
* targetInfo (org.artifactory.addon.replication.ReplicationTargetInfo) - contains information about the replication target server
*
* Closure parameters:
* localRepoPath (org.artifactory.repo.RepoPath) - the repoPath of the item on the local Artifactory server.
*/
beforeStatisticsReplication { localRepoPath ->
}
}
Controlling Plugin Log Level
The default log level for user plugins is "warn". To change a plugin log level, add the following to ${ARTIFACTORY_HOME}/etc/logback.xml
:
<logger name="my-plugin">
<level value="info"/>
</logger>
The logger name is the name of the plugin file without the ".groovy
" extension (in the example above the plugin file name is my-plugin.groovy
). The logging levels can be either error, warn, info, debug or trace.
Sample Plugin
Sample plugin is available to download.