How Does Build Promotion work

Ariel Kabov
2019-08-18 09:22

The Build Promotion in Artifactory is the action of changing the status of a build, usually into a more mature status. 
Maturity refers to the package maturity level, such as the development, staging and release stages. 
Artifact Maturity
Build Promotion allows you to change the status of a build, optionally moving or copying the build's artifacts and its dependencies to a target repository, and setting properties on the promoted artifacts.

The Build Promotion can be triggered via REST API, JFrog CLI, or via any of the CI integrations.
The Build Promotion operation is triggered for a selected Build-info identity in Artifactory. 
It is important to note how the Build-info identity tracks related build artifacts. Each Build-info object is a JSON file with a description of the build's information.

In the build-info.json, the produced artifacts and used dependencies are referenced as SHA1 values.
The build is agnostic to their location in Artifactory, their location is designed to be dynamic for promotions.

The Build identity knows its produced artifacts by their SHA1 value, and the build.name & build.number properties.

Once a Build Promotion is triggered, Artifactory will first search for a list of artifacts it should promote. It will search based on the SHA1 values from the Build-info JSON, and the build.name & build.number properties. 
After retrieving the list of artifacts it has to promote, it will trigger the move/copy operation on each one of the files in this list.
Then, if selected, new properties will be attached to the promoted artifacts. 
Lastly, the status of the build gets updated.

Troubleshooting Build Promotions

In order to troubleshoot build promotion issues, applying these debug loggers should come handy. 

Disclaimer: Changing log levels from their original value may result in performance degradation. Handle with care when applying to production systems.

This XML snippet goes in the $ARTIFACTORY_HOME/etc/logback.xml file and does not require a restart to take effect:   <appender name="build-promotion" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <File>${artifactory.home}/logs/build-promotion.log</File>
      <encoder>
         <pattern>%date ${artifactory.contextId}[%thread] [%-5p] \(%-20c{3}:%L\) - %m%n</pattern>
      </encoder>
      <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
         <FileNamePattern>${artifactory.home}/logs/build-promotion.%i.log</FileNamePattern>
         <maxIndex>13</maxIndex>
      </rollingPolicy>
      <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
         <MaxFileSize>25MB</MaxFileSize>
      </triggeringPolicy>
   </appender>

   <logger name="org.artifactory.build" additivity="false">
      <level value="trace"/>
      <appender-ref ref="build-promotion"/>
   </logger>

The build promotion mechanism uses AQL in order to search the items to promote. We can add this logger to debug the query:   <logger name="org.artifactory.storage.db.aql" additivity="false">
      <level value="trace"/>
      <appender-ref ref="build-promotion"/>
   </logger>

To troubleshoot issues around the copy/move operations of the Build Promotion, this should be added:   <logger name="org.artifactory.repo.service.mover" additivity="false">
      <level value="trace"/>
      <appender-ref ref="build-promotion"/>
   </logger>

 

A Common misconception

A relatively common scenario is when a build usually publishes to a specific target location:libs-snapshot-local:buildA/$(build-number)/artifacts/

As a user, you see that all produced artifacts are in the directory, so you assume that after promotion same artifacts will exist at:libs-promoted-local:buildA/$(build-number)/artifacts/

However, this may not always occur. As mentioned above, build promotion searches for artifacts with the same SHA1 and build.name & build.number properties.
Therefore, if the originally produced artifacts were copied into another location in Artifactory, the new location may return first for the search query during the promotion. As promotion triggers a copy/move per artifacts, the path where the artifact was found will remain in the target repository. This means, if an artifact was copied with the properties to the root of the repository, after promotion it may exist in the root of the target repository rather in the expected location.