Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-18907

Expose svn 'current' revision in addition to the 'last-changed' revision

    • Icon: Improvement Improvement
    • Resolution: Unresolved
    • Icon: Major Major
    • subversion-plugin
    • None
    • Win7 x64
      Jenkins v1.590.1
      SVN plugin v1.48

      Currently the SVN plugin only provides a single SVN revision number for any given URL (ignoring for the moment the fact you can provide multiple URLs in one configuration). Further, ad-hoc tests reveal that this one SVN revision number represents the "last changed revision" for the provided URL.

      In certain cases it would be useful to also have access to the "latest" revision as well - ie: the revision of the repository after the most recent checkout or update operation.

      I suspect such an enhancement could be made in a non-breaking way as well. For example, perhaps the SVN plugin could provide an option - either globally in the main Jenkins configuration area, or per-job in the SCM configuration section of each job - to have the SVN_REVISION Jenkins property defined by either the last changed revision or the latest revision, as desired. Alternatively, perhaps a new Jenkins property could be introduced, say SVN_LATEST_REVISION, which would contain the appropriate value.

      NOTE: I suspect that this enhancement could be used as a workaround to some (but not all) of the workflows being discussed on JENKINS-1241. Also given the fact that either solution I suggested would be non-breaking it could conceivably be implemented and released on all currently supported versions of the plugin.

          [JENKINS-18907] Expose svn 'current' revision in addition to the 'last-changed' revision

          Potential Use Case #3:
          Suppose again that you have a single SVN repository and you have a Jenkins configuration with 2 jobs, one dependent on the other, both stored in this single repository. Next lets suppose you have the Parameterized Trigger Plugin installed and configured so that downstream job A triggers upstream job B, passing along the Subversion revision number - to ensure the triggered instance of Job B uses the same revision as job A.

          Now, lets suppose you are working on a change that requires modification to both module A and B. Since both modules are in independent folders (albeit in the same repo) the commits to module A and B will generate two unique revision numbers (say revision 123 and 124 respectively).

          So when job A triggers (ie: via an SCM polling operation) it will first do an update to module A and set the SVN revision number. Now because the Jenkins plugin uses the last change revision it will set the revision of this execution to 123. Once complete job A will trigger job B passing revision 123 - and job B will fail... because it needs revision 124 to be successful.

          In this case, if Jenkins were to use the "latest revision" rather than the "last change revision", then job A would have performed its update and pulled down the latest version of itself (ie: v123) but the latest revision would actually be v124 (assuming that both changes were committed before job A started it's build - which is often the case so long as you have a reasonable "quiet period" configured for the job). Then, if this more appropriate version number were propagated to job B then it would have succeeded as expected.

          Kevin Phillips added a comment - Potential Use Case #3: Suppose again that you have a single SVN repository and you have a Jenkins configuration with 2 jobs, one dependent on the other, both stored in this single repository. Next lets suppose you have the Parameterized Trigger Plugin installed and configured so that downstream job A triggers upstream job B, passing along the Subversion revision number - to ensure the triggered instance of Job B uses the same revision as job A. Now, lets suppose you are working on a change that requires modification to both module A and B. Since both modules are in independent folders (albeit in the same repo) the commits to module A and B will generate two unique revision numbers (say revision 123 and 124 respectively). So when job A triggers (ie: via an SCM polling operation) it will first do an update to module A and set the SVN revision number. Now because the Jenkins plugin uses the last change revision it will set the revision of this execution to 123. Once complete job A will trigger job B passing revision 123 - and job B will fail... because it needs revision 124 to be successful. In this case, if Jenkins were to use the "latest revision" rather than the "last change revision", then job A would have performed its update and pulled down the latest version of itself (ie: v123) but the latest revision would actually be v124 (assuming that both changes were committed before job A started it's build - which is often the case so long as you have a reasonable "quiet period" configured for the job). Then, if this more appropriate version number were propagated to job B then it would have succeeded as expected.

          In response to this earlier comment, while I think it may be helpful in certain cases to expose the revisions of any / all externals to Jenkins builds, to help limit the scope of this particular enhancement request (and possibly to keep the resulting changes as generic and generally applicable as possible) I think it will suffice to simply expose the "latest" SVN revision for a checkout to the build environment as mentioned in the description.

          Kevin Phillips added a comment - In response to this earlier comment , while I think it may be helpful in certain cases to expose the revisions of any / all externals to Jenkins builds, to help limit the scope of this particular enhancement request (and possibly to keep the resulting changes as generic and generally applicable as possible) I think it will suffice to simply expose the "latest" SVN revision for a checkout to the build environment as mentioned in the description.

          Kevin Phillips added a comment - - edited

          Also, in response to this other earlier comment, while I do agree the plugin is working as intended, the use cases I describe in my earlier comments illustrate the need for accessing the latest revision instead of / as well as the last changed revision. These revisions serve different purposes for different use cases - which is why the SVN tools expose them both to the user as needed.

          To relate this request to functionality in the standard SVN client toolset, currently the SVN plugin exposes the revision generated by the command "svnversion . -c" but I would also like the ability to get the results of "svnversion ." as well.

          Kevin Phillips added a comment - - edited Also, in response to this other earlier comment , while I do agree the plugin is working as intended, the use cases I describe in my earlier comments illustrate the need for accessing the latest revision instead of / as well as the last changed revision. These revisions serve different purposes for different use cases - which is why the SVN tools expose them both to the user as needed. To relate this request to functionality in the standard SVN client toolset, currently the SVN plugin exposes the revision generated by the command "svnversion . -c" but I would also like the ability to get the results of "svnversion ." as well.

          kutzi added a comment -

          I've some reservations about use case 1 (IMO externals should better be avoided if possible), but 2 and 3 sound indeed realistic.
          I guess the way to go is to add another set of Environment Variables (e.g. SVN_CURRENT_REVISION_n) containing the 'current' revision.
          According to most documentation I could find, this seems to be the common name for this: current revision - in contrast to the latest-changed revision

          kutzi added a comment - I've some reservations about use case 1 (IMO externals should better be avoided if possible), but 2 and 3 sound indeed realistic. I guess the way to go is to add another set of Environment Variables (e.g. SVN_CURRENT_REVISION_n) containing the 'current' revision. According to most documentation I could find, this seems to be the common name for this: current revision - in contrast to the latest-changed revision

          kutzi added a comment -

          Feel free to create a pull request for the improvement

          kutzi added a comment - Feel free to create a pull request for the improvement

          Your proposal indeed sounds reasonable.

          I was actually considering putting in a pull request. I am not that familiar with that process as I've never done that before but I had considered figuring that out at some point.

          Kevin Phillips added a comment - Your proposal indeed sounds reasonable. I was actually considering putting in a pull request. I am not that familiar with that process as I've never done that before but I had considered figuring that out at some point.

          Kevin Phillips added a comment - - edited

          I had one somewhat-unrelated question. You mention that externals should be avoided if possible - do you know of another way of managing complex sets of dependencies between subsystems without using externals? I am working in a C++ shop so we don't have the luxury of advanced dependency management tools like Maven, Nexus and such..... Externals seem like the only practical solution for this in our case.

          Also, just so you know, all three of the "potential use cases" I outlined above we actually do use (or have tried) at our site... so they aren't really "potential" in that regard. And use case #1 is our most common usage pattern at the moment.

          Kevin Phillips added a comment - - edited I had one somewhat-unrelated question. You mention that externals should be avoided if possible - do you know of another way of managing complex sets of dependencies between subsystems without using externals? I am working in a C++ shop so we don't have the luxury of advanced dependency management tools like Maven, Nexus and such..... Externals seem like the only practical solution for this in our case. Also, just so you know, all three of the "potential use cases" I outlined above we actually do use (or have tried) at our site... so they aren't really "potential" in that regard. And use case #1 is our most common usage pattern at the moment.

          kutzi added a comment -

          Basically, the workflow I would propose is this:
          Fork the Jenkins repository at Github
          Clone your forked repository
          Create a new branch for the change
          Do the changes
          Send out the pull request

          See also https://wiki.jenkins-ci.org/display/JENKINS/Governance+Document#GovernanceDocument-pullrequest

          kutzi added a comment - Basically, the workflow I would propose is this: Fork the Jenkins repository at Github Clone your forked repository Create a new branch for the change Do the changes Send out the pull request See also https://wiki.jenkins-ci.org/display/JENKINS/Governance+Document#GovernanceDocument-pullrequest

          kutzi added a comment -

          "do you know of another way of managing complex sets of dependencies between subsystems without using externals? I am working in a C++ shop so we don't have the luxury of advanced dependency management tools like Maven, Nexus and such"

          Dependency management would have been my recommendation... - It's vastly superior to externals IMO
          I don't know much about C++ development, so I cannot give you any advise how to do dep management there.

          kutzi added a comment - "do you know of another way of managing complex sets of dependencies between subsystems without using externals? I am working in a C++ shop so we don't have the luxury of advanced dependency management tools like Maven, Nexus and such" Dependency management would have been my recommendation... - It's vastly superior to externals IMO I don't know much about C++ development, so I cannot give you any advise how to do dep management there.

          I figured it was a long shot, but that is the story of my life

          Dependency management in C++ is a complex beast and I haven't found any good tools (and very few not-so-good tools) to do the job. Externals handle the basics code dependencies for us, and we use Visual Studio to handle some of the project / module dependencies but VS doesn't scale well to very-large-scale cross-team projects unfortunately (and it isn't cross platform either which sucks).

          I just mention all this because even if use case #1 should be avoided, I think it is a very real and important use case that isn't all that uncommon. I wouldn't discount it out-of-hand.

          Kevin Phillips added a comment - I figured it was a long shot, but that is the story of my life Dependency management in C++ is a complex beast and I haven't found any good tools (and very few not-so-good tools) to do the job. Externals handle the basics code dependencies for us, and we use Visual Studio to handle some of the project / module dependencies but VS doesn't scale well to very-large-scale cross-team projects unfortunately (and it isn't cross platform either which sucks). I just mention all this because even if use case #1 should be avoided, I think it is a very real and important use case that isn't all that uncommon. I wouldn't discount it out-of-hand.

            Unassigned Unassigned
            leedega Kevin Phillips
            Votes:
            3 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: