Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

[JENKINS-30222] Multibranch/global var incompatibility #198

Merged
merged 3 commits into from
Aug 31, 2015

Conversation

jglick
Copy link
Member

@jglick jglick commented Aug 28, 2015

@kohsuke FYI

@jglick
Copy link
Member Author

jglick commented Aug 28, 2015

@@ -208,13 +206,13 @@ public class SCMBinderTest {
                     "  body.delegate = config\n" +
                     "  body()\n" +
                     "  node {\n" +
-                    "    checkout scm\n" +
+                    "    checkout config.scm\n" +
                     "    echo \"loaded ${readFile config.file}\"\n" +
                     "  }\n" +
                     "}\n");
                 // Then a project using it:
                 sampleGitRepo.init();
-                sampleGitRepo.write("Jenkinsfile", "standardJob {file = 'resource'}");
+                sampleGitRepo.write("Jenkinsfile", "def _scm = scm; standardJob {scm = _scm; file = 'resource'}");
                 sampleGitRepo.write("resource", "resource content");
                 sampleGitRepo.git("add", "Jenkinsfile");
                 sampleGitRepo.git("add", "resource");

works but the Jenkinsfile side is too ugly to take seriously.

@jglick
Copy link
Member Author

jglick commented Aug 28, 2015

This also works, and has the benefit of making the library code comprehensible to mere mortals, though it is still a little cumbersome on the Jenkinsfile side, and looks a little less like a configuration file (the original goal):

@@ -202,19 +200,15 @@ public class SCMBinderTest {
                 File vars = new File(repo.workspace, /*UserDefinedGlobalVariable.PREFIX*/ "vars");
                 vars.mkdirs();
                 FileUtils.writeStringToFile(new File(vars, "standardJob.groovy"),
-                    "def call(body) {\n" +
-                    "  def config = [:]\n" +
-                    "  body.resolveStrategy = Closure.DELEGATE_FIRST\n" +
-                    "  body.delegate = config\n" +
-                    "  body()\n" +
+                    "def call(config) {\n" +
                     "  node {\n" +
-                    "    checkout scm\n" +
+                    "    checkout config.scm\n" +
                     "    echo \"loaded ${readFile config.file}\"\n" +
                     "  }\n" +
                     "}\n");
                 // Then a project using it:
                 sampleGitRepo.init();
-                sampleGitRepo.write("Jenkinsfile", "standardJob {file = 'resource'}");
+                sampleGitRepo.write("Jenkinsfile", "standardJob scm: scm, file: 'resource'");
                 sampleGitRepo.write("resource", "resource content");
                 sampleGitRepo.git("add", "Jenkinsfile");
                 sampleGitRepo.git("add", "resource");

@jglick
Copy link
Member Author

jglick commented Aug 28, 2015

Working on using GlobalVariable rather than GroovyShellDecorator, but have to figure out how to store the value in the program when the build starts.

@jglick
Copy link
Member Author

jglick commented Aug 28, 2015

Nothing I try with GlobalVariable works. The problem is that bindings in the GroovyShell are not visible from within the library. Steps work only because each CpsScript instance (there is a new one for the library) redefines steps to a new DSL.

DockerDSL manages to use GlobalVariable, but it simply loads a new Docker object for each CpsScript which requests it. That is not an option here: I need to use the SCM which is available only when the build starts, and I can find no place to “stash” it in the program state.

Suppose a build used a library and tried to access scm after a restart. Where would it get it from? The CpsScript of the library has no apparent backreference to the original CpsScript or its GroovyShell bindings; all it has is a CpsFlowExecution and thus a WorkflowRun. I could store the SCM in an Action on the build but that adds even more redundancy stuff to an already cluttered build.xml.

@jglick
Copy link
Member Author

jglick commented Aug 28, 2015

The best I could manage so far. @reviewbybees esp. @kohsuke

@ghost
Copy link

ghost commented Aug 28, 2015

This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation.

@oleg-nenashev
Copy link
Member

If I understand correctly, this test demonstrates a problem and provides a workaround, which is not very graceful. Is is correct?

🐝 if yes

@tfennelly
Copy link
Member

The solution, as I understand it, does seem too funky.

From what I read here, seems to me like the best solution is to use an Action. I hear what you are saying about that adding more crap persisted in the build.xml, but that seems like another problem that should be solved.

Actions have always seemed cumbersome to me as a way of storing state. It seems to me like there's a need for a general purpose context storage scoped at different levels (Job, Run etc) and with different persistence specs. That's for another discussion though.

@jglick
Copy link
Member Author

jglick commented Aug 31, 2015

If I understand correctly, this test demonstrates a problem and provides a workaround, which is not very graceful. Is is correct?

Correct. cdfee0a (the first commit) demonstrates what I expected to work at the start. Basically remove the body.owner. prefix when accessing scm.

My current thinking is that the messy list of scopes could be cleaned up (and this problem solved) if we created a special Binding which was attached to the CpsThreadGroup: the program as a whole. Each CpsScript, whether the “main” script or some other file that got loaded, would delegate to this overall binding. That would hold

  • steps (a DSL, which raw function names delegate to)
  • GlobalVariables:
    • the standard currentBuild and env
    • also docker, from docker-workflow
    • and in this case I could add scm
  • parameter values (though I would like to deprecate these and replace with a global variable like params)

@amuniz
Copy link
Member

amuniz commented Aug 31, 2015

🐝

@jglick jglick changed the title Multibranch/global var incompatibility [JENKINS-30222] Multibranch/global var incompatibility Aug 31, 2015
@jglick
Copy link
Member Author

jglick commented Aug 31, 2015

Filed JENKINS-30222 to track improvements.

jglick added a commit that referenced this pull request Aug 31, 2015
[JENKINS-30222] Multibranch/global var incompatibility
@jglick jglick merged commit 2394bf9 into jenkinsci:master Aug 31, 2015
@jglick jglick deleted the multibranch-globalVariable branch August 31, 2015 14:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants