Search code examples
jenkinsjenkins-pipelineperforce

Determine perforce changelist number after running p4.run("sync") in Jenkins SCM pipeline


On the Jenkins server, Perforce plugin (P4) is installed.
Within my Jenkins server job pipeline (implemented as shared library in groovy-lang), there is a pipeline stage to sync from perforce to the jenkins workspace as:

p4.run("sync")

I want to determine the changelist number of this operation. I need to use this changelist number in the later stages of the pipeline.

I am thinking to do as follows:

p4.run("sync")
changelist_number = p4.run("changes -m1 #have")

Will this work? Or give me a better solution. Also I am very unfamiliar about this topic. It would be nice if you can explain what all this means.


Solution

  • The changelist number (that is, the highest changelist number associated with any synced revision) is returned as part of the p4 sync output if you're running in tagged mode:

    C:\Perforce\test\merge>p4 changes ...
    Change 226 on 2020/11/12 by Samwise@Samwise-dvcs-1509687817 'foo'
    Change 202 on 2020/10/28 by Samwise@Samwise-dvcs-1509687817 'Populate //stream/test.'
    
    C:\Perforce\test\merge>p4 -Ztag sync ...
    ... depotFile //stream/test/merge/foo.txt
    ... clientFile c:\Perforce\test\merge\foo.txt
    ... rev 2
    ... action updated
    ... fileSize 20
    ... totalFileSize 20
    ... totalFileCount 1
    ... change 226
    

    Tagged output is converted into a dictionary that's returned by the run method, so you should be able to just do:

    changelist_number = p4.run("sync")[0]["change"]
    

    to sync and get the changelist number as a single operation.

    There are some edge cases here -- deleted files aren't synced and so the deleted revisions won't factor into that changelist number.

    A more ironclad method is to put the horse before the cart -- get the current changelist number (from the depot, not limited to what's in your client), and then sync to that exact number. That way consistency is guaranteed; if a new changelist is submitted between the two commands, your stored changelist number still matches what you synced to.

    changelist_number = p4.run("changes", "-m1", "-ssubmitted")[0]["change"]
    p4.run("sync", "@{changelist_number}")
    

    Any other client syncing to that changelist number is guaranteed to get the same set of revisions (subject to its View).