Details

    • Similar Issues:

      Description

      having agent at the global level is nice, but it has come up a few times in conversations that having agents on a per-stage level is worth considering.

      This makes the "blocking for input" case a lot nicer and less wasteful (without the user needing to learn additional node syntax).

      CC James Dumay Patrick Wolf

        Attachments

          Issue Links

            Activity

            Hide
            hrmpw Patrick Wolf added a comment - - edited

            I think this ticket might be a duplicate but we should discuss how Input (and other steps that should be run outside of a node) should behave.

            Right now it is easier to use Input in Pipeline Script than it is in Declarative Pipeline. Using Input in Declarative is pretty much a non-starter right now.

            2 questions come to mind.

            1. Do we force input to be in its own stage entirely or do we want to create a withoutAgent section that can be used inside a stage ?

            2. Assuming it is in its own agent if I set a a global agent it makes sense that I can override that default on a stage rather than being forced to assign an agent on every stage just to use an input in one stage

            pipeline{
              agent docker:"maven"
              
              stages{
                stage("Build"){
                  doSomething()
                }
                stage("Test"){
                  doSomething()
                }
                stage("Input"){
                  agent none
                  input "move on?"
                }
              }
            }
            

            versus

            pipeline{
              agent none
            
              stages{
                stage("Build"){
                  agent docker:"maven"
                  doSomething()
                }
                 stage("Test"){
                  agent docker:"maven"
                  doSomething()
                 } 
                stage("Input"){
                  agent none
                  input "move on?"
                }
              }
            }
            
            Show
            hrmpw Patrick Wolf added a comment - - edited I think this ticket might be a duplicate but we should discuss how Input (and other steps that should be run outside of a node) should behave. Right now it is easier to use Input in Pipeline Script than it is in Declarative Pipeline. Using Input in Declarative is pretty much a non-starter right now. 2 questions come to mind. 1. Do we force input to be in its own stage entirely or do we want to create a withoutAgent section that can be used inside a stage ? 2. Assuming it is in its own agent if I set a a global agent it makes sense that I can override that default on a stage rather than being forced to assign an agent on every stage just to use an input in one stage pipeline{ agent docker: "maven" stages{ stage( "Build" ){ doSomething() } stage( "Test" ){ doSomething() } stage( "Input" ){ agent none input "move on?" } } } versus pipeline{ agent none stages{ stage( "Build" ){ agent docker: "maven" doSomething() } stage( "Test" ){ agent docker: "maven" doSomething() } stage( "Input" ){ agent none input "move on?" } } }
            Hide
            michaelneale Michael Neale added a comment -

            Patrick Wolf the most common use for input is blocking for approval, which does work well at least (that seems the vast majority) - but putting aside input utility for now (it will need to set env vars as it claims to)...

            Yes, I can understand the setting an agent as a "default" for a block, but we can't just automatically yield an agent because we use input, if a user is using input they need to "opt in" to handling the flow of built artifacts between long lived stages (ie they need to know to stash/unstash, and what) - that can't be done automatically for them. Hence my comment on having per stage agents.

            Or perhaps the user choses to opt out for a stage by saying "agent none" - they still need to ensure they are stashing/unstashing (ie you can't transparently drop and agent and resume)

            Currently they have to use the node syntax and nest the steps inside it (which isn't terrible, but is jarring).

            Show
            michaelneale Michael Neale added a comment - Patrick Wolf the most common use for input is blocking for approval, which does work well at least (that seems the vast majority) - but putting aside input utility for now (it will need to set env vars as it claims to)... Yes, I can understand the setting an agent as a "default" for a block, but we can't just automatically yield an agent because we use input, if a user is using input they need to "opt in" to handling the flow of built artifacts between long lived stages (ie they need to know to stash/unstash, and what) - that can't be done automatically for them. Hence my comment on having per stage agents. Or perhaps the user choses to opt out for a stage by saying "agent none" - they still need to ensure they are stashing/unstashing (ie you can't transparently drop and agent and resume) Currently they have to use the node syntax and nest the steps inside it (which isn't terrible, but is jarring).
            Hide
            hrmpw Patrick Wolf added a comment -

            I would argue that it is terrible, to the point of unusable. I would revert to Pipeline Script if I wanted to use Input in a Pipeline.

            Show
            hrmpw Patrick Wolf added a comment - I would argue that it is terrible, to the point of unusable. I would revert to Pipeline Script if I wanted to use Input in a Pipeline.
            Hide
            michaelneale Michael Neale added a comment -

            Patrick Wolf if you only are blocking for approval, it is the same.

            Show
            michaelneale Michael Neale added a comment - Patrick Wolf if you only are blocking for approval, it is the same.
            Hide
            hrmpw Patrick Wolf added a comment -

            Not sure what you mean, Michael Neale. What is the same?

            Right now to use an input to block for approval, or for any other reason, it is more complicated to use Declarative syntax than it is use to Pipeline Script. Not only do you have to use node blocks and docker.inside for all of your stages but you have to create a superfluous stage for your input step.

            Having people use agent on each stage improves that experience slightly but only to the point that it is on par with with using Pipeline Script. Input is the biggest gap in Declarative functionality.

            Show
            hrmpw Patrick Wolf added a comment - Not sure what you mean, Michael Neale . What is the same? Right now to use an input to block for approval, or for any other reason, it is more complicated to use Declarative syntax than it is use to Pipeline Script. Not only do you have to use node blocks and docker.inside for all of your stages but you have to create a superfluous stage for your input step. Having people use agent on each stage improves that experience slightly but only to the point that it is on par with with using Pipeline Script. Input is the biggest gap in Declarative functionality.
            Hide
            michaelneale Michael Neale added a comment - - edited

            In the case of using one single node (ie keeping it alive) and blocking for input there is no difference (try it).

            otherwise:

            stage "build"
              node {
                  sh "echo 42"
              }
            
            stage "Approval" 
                  input "Go ahead?"
              
            
            stage "End" 
               node {
                   sh "echo done"
                }
            

            becomes:

            pipeline {
              agent none
              stages {
                  stage("build") {
                    node {
                        sh "echo 42"
                    }      
                  }
                  
                  stage("Approval") {        
                    input "Go ahead?"        
                  }
                  
                  stage("End") {
                    node {
                        sh "echo done"
                     }
                  
                  } 
                  
                  
              }
            
            }
            

            is this what you mean? as it looks very similar

            Show
            michaelneale Michael Neale added a comment - - edited In the case of using one single node (ie keeping it alive) and blocking for input there is no difference (try it). otherwise: stage "build" node { sh "echo 42" } stage "Approval" input "Go ahead?" stage "End" node { sh "echo done" } becomes: pipeline { agent none stages { stage("build") { node { sh "echo 42" } } stage("Approval") { input "Go ahead?" } stage("End") { node { sh "echo done" } } } } is this what you mean? as it looks very similar
            Hide
            hrmpw Patrick Wolf added a comment -

            You wouldn't have the input inside a node in the former.

            My point is that in your example, there is no advantage of using Declarative. In fact, if you have to go to the trouble of setting up all your nodes or images manually anyway it is much simpler and more flexible to use Script:

            stage "build" {
              node {
                  sh "echo 42"
              }
            }
            stage "End" {
              input "Go ahead?"
               node {
                   sh "echo done"
                }
            }
            

            I don't need to create a superfluous stage just to break out of the node. In this case it is easier and more flexible to not use Declarative.

            This will be especially true for things like Checkpoints. If I create 2 or 3 Checkpoints in my pipeline that is 2-3 additional Stages that shouldn't necessarily be visualized. Why force users to create Stages when they aren't necessary?

            The goal should be to make things simpler in Declarative. We are trying to trade off flexibility for opinionated simplicity. Having it opinionated (limited) but not simpler is just wrong.

            Show
            hrmpw Patrick Wolf added a comment - You wouldn't have the input inside a node in the former. My point is that in your example, there is no advantage of using Declarative. In fact, if you have to go to the trouble of setting up all your nodes or images manually anyway it is much simpler and more flexible to use Script: stage "build" { node { sh "echo 42" } } stage "End" { input "Go ahead?" node { sh "echo done" } } I don't need to create a superfluous stage just to break out of the node. In this case it is easier and more flexible to not use Declarative. This will be especially true for things like Checkpoints. If I create 2 or 3 Checkpoints in my pipeline that is 2-3 additional Stages that shouldn't necessarily be visualized. Why force users to create Stages when they aren't necessary? The goal should be to make things simpler in Declarative. We are trying to trade off flexibility for opinionated simplicity. Having it opinionated (limited) but not simpler is just wrong.
            Hide
            michaelneale Michael Neale added a comment - - edited

            Patrick Wolf yes that was my typo - intended it to not be in a node (corrected).

            But I still don't get your point - is input a reasonable thing people would want to do in a declarative way or not? There are clearly advantages to the model - as there is a model, better error messages, editor round tripping. Inputs today need to be in a stage anyway (even for stage view) or they won't show up (other than in the log, in some cases)

            Do you mean that input should be a first class thing in pipeline model instead of "working around" the agents like this?

            Show
            michaelneale Michael Neale added a comment - - edited Patrick Wolf yes that was my typo - intended it to not be in a node (corrected). But I still don't get your point - is input a reasonable thing people would want to do in a declarative way or not? There are clearly advantages to the model - as there is a model, better error messages, editor round tripping. Inputs today need to be in a stage anyway (even for stage view) or they won't show up (other than in the log, in some cases) Do you mean that input should be a first class thing in pipeline model instead of "working around" the agents like this?
            Hide
            hrmpw Patrick Wolf added a comment - - edited

            Michael Neale I assumed it was a typo. Just pointing it out for anyone else reading.

            There were a few things. First, at a bare minimum we need per-stage agent directives when agent none is used but we should also allow per-stage directives that override any global agent.

            pipeline{
              agent docker:"ubuntu"
              stages{
                stage("Foo"){
                  agent none
                  echo "Foo"
                }
                stage("Bar"){
                    echo "Bar"
                }
              }
            }
            

            and

            pipeline{
              agent none
              stages{
                stage("Foo"){
                  echo "Foo"
                }
                stage("Bar"){
                    agent docker:"ubuntu"
                    echo "Bar"
                }
              }
            }
            

            Should both produce the same results and setup.

            The second point was whether we should consider not forcing things like Input (and Checkpoints or anything else that shouldn't be run inside a node) to run in an isolated Stage that then has to be visualized in your Pipeline.

            Show
            hrmpw Patrick Wolf added a comment - - edited Michael Neale I assumed it was a typo. Just pointing it out for anyone else reading. There were a few things. First, at a bare minimum we need per-stage agent directives when agent none is used but we should also allow per-stage directives that override any global agent . pipeline{ agent docker: "ubuntu" stages{ stage( "Foo" ){ agent none echo "Foo" } stage( "Bar" ){ echo "Bar" } } } and pipeline{ agent none stages{ stage( "Foo" ){ echo "Foo" } stage( "Bar" ){ agent docker: "ubuntu" echo "Bar" } } } Should both produce the same results and setup. The second point was whether we should consider not forcing things like Input (and Checkpoints or anything else that shouldn't be run inside a node) to run in an isolated Stage that then has to be visualized in your Pipeline.
            Hide
            hrmpw Patrick Wolf added a comment -

            btw, we should probably also flag things like "input inside a node" as part of our pre-compilation syntax checking.

            Show
            hrmpw Patrick Wolf added a comment - btw, we should probably also flag things like "input inside a node" as part of our pre-compilation syntax checking.
            Hide
            michaelneale Michael Neale added a comment -

            Patrick Wolf yes your last proposal sounds ok.

            I am wary of making it unclear when it switches node, but by having agent there, it is clear I think.
            For input - even in a GUI it would be represented as a stage (I think that is current intention and practice) - so it could certainly act as a stage (ie wrap itself in a stage)? (I would be interested what James Dumay thinks) - would make some things easier/clearer.

            However, I would want to let people have the option of having an input that keeps a node alive at least

            Show
            michaelneale Michael Neale added a comment - Patrick Wolf yes your last proposal sounds ok. I am wary of making it unclear when it switches node, but by having agent there, it is clear I think. For input - even in a GUI it would be represented as a stage (I think that is current intention and practice) - so it could certainly act as a stage (ie wrap itself in a stage)? (I would be interested what James Dumay thinks) - would make some things easier/clearer. However, I would want to let people have the option of having an input that keeps a node alive at least
            Hide
            abayer Andrew Bayer added a comment -

            So fyi, I'm going to take advantage of this opportunity (and the fact that GroovyStep is close to landing, which will allow me to implement the pluggable agent backend) to completely revisit what the agent config looks like. The map approach is going to become unwieldy very quickly, so I think something more like:

            agent {
                docker {
                    label "foo"
                    image "ubuntu"
                }
            }
            

            ...would be preferable. This would ideally still have backwards compatibility for the existing possible configurations. Thoughts?

            Show
            abayer Andrew Bayer added a comment - So fyi, I'm going to take advantage of this opportunity (and the fact that GroovyStep is close to landing, which will allow me to implement the pluggable agent backend) to completely revisit what the agent config looks like. The map approach is going to become unwieldy very quickly, so I think something more like: agent { docker { label "foo" image "ubuntu" } } ...would be preferable. This would ideally still have backwards compatibility for the existing possible configurations. Thoughts?
            Hide
            hrmpw Patrick Wolf added a comment -

            Would this also let us incorporate what docker args as requested in PR-17 ?

            Do we want to support docker args?

            What would this look like with a Kubernetes Pod?
            What would this look like with just a node label?

            Show
            hrmpw Patrick Wolf added a comment - Would this also let us incorporate what docker args as requested in PR-17 ? Do we want to support docker args? What would this look like with a Kubernetes Pod? What would this look like with just a node label?
            Hide
            abayer Andrew Bayer added a comment -

            Yes, it would, and yes we do want to support that.

            For Kubernetes...well, I don't know the config enough to say exactly what it would look like, but...similar. For just a label, the existing agent label:'foo' would still work, hopefully.

            Show
            abayer Andrew Bayer added a comment - Yes, it would, and yes we do want to support that. For Kubernetes...well, I don't know the config enough to say exactly what it would look like, but...similar. For just a label, the existing agent label:'foo' would still work, hopefully.
            Hide
            hrmpw Patrick Wolf added a comment -

            I'm fine with this approach. It gives us a lot more room to grow instead of an every growing map that gets unwieldy.

            Show
            hrmpw Patrick Wolf added a comment - I'm fine with this approach. It gives us a lot more room to grow instead of an every growing map that gets unwieldy.
            Hide
            ndeloof Nicolas De Loof added a comment -

            I can't see how a label would be useful in this context, as the docker-based agent would be dedicated to this build (aka "one-shot").
            I also suggest to consider during design a docker-based executor is not a single container, as demonstrated by docker-slaves-plugin : one can compose a build container with "sidecars" container (typically for test database, selenium browser, etc) and jenkins plumbing container to support agent slave.jar

            Show
            ndeloof Nicolas De Loof added a comment - I can't see how a label would be useful in this context, as the docker-based agent would be dedicated to this build (aka "one-shot"). I also suggest to consider during design a docker-based executor is not a single container, as demonstrated by docker-slaves-plugin : one can compose a build container with "sidecars" container (typically for test database, selenium browser, etc) and jenkins plumbing container to support agent slave.jar
            Hide
            hrmpw Patrick Wolf added a comment -

            we don't have one-shot right now. Docker pipeline needs a node with docker engine running on it. Until we have deprecated all physical agents and everything is running one-shot then label is a must have here.

            Show
            hrmpw Patrick Wolf added a comment - we don't have one-shot right now. Docker pipeline needs a node with docker engine running on it. Until we have deprecated all physical agents and everything is running one-shot then label is a must have here.
            Hide
            abayer Andrew Bayer added a comment -

            Nicolas De Loof - the agent section is going to be pluggable (see JENKINS-38433) so if you want to implement one for Docker Slaves (which, mind you, should be renamed to Docker Agents!), you'll be able to, but the out-of-the-box implementations will be "label", Docker Pipeline, and Dockerfile->Docker Pipeline.

            Show
            abayer Andrew Bayer added a comment - Nicolas De Loof - the agent section is going to be pluggable (see JENKINS-38433 ) so if you want to implement one for Docker Slaves (which, mind you, should be renamed to Docker Agents!), you'll be able to, but the out-of-the-box implementations will be "label", Docker Pipeline, and Dockerfile->Docker Pipeline.
            Hide
            abayer Andrew Bayer added a comment -
            Show
            abayer Andrew Bayer added a comment - First tentative PR is up at https://github.com/jenkinsci/pipeline-model-definition-plugin/pull/19 wooo
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Andrew Bayer
            Path:
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/ast/ModelASTStage.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/ast/ModelASTStageConfig.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/ClosureContentsChecker.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/Stage.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/StageConfig.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/JSONParser.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ModelParser.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/validator/ModelValidator.groovy
            src/main/java/org/jenkinsci/plugins/pipeline/modeldefinition/model/MethodMissingWrapperWhitelist.java
            src/main/resources/ast-schema.json
            src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ClosureModelTranslator.groovy
            src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AbstractModelDefTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AgentTest.java
            src/test/resources/json/perStageConfigAgent.json
            src/test/resources/perStageConfigAgent.groovy
            http://jenkins-ci.org/commit/pipeline-model-definition-plugin/385940d33c4184cb5f5947c00c45d7ed57566c47
            Log:
            JENKINS-38331 Very preliminary version of per-stage agent config

            Honestly, I'm doing this for JENKINS-38284 more, but I needed some
            section to actually have be per-stage to test it, so...tada?

            This is literally the result of three hours of slamming my head
            against the wall over stupid mistakes, so I'm fairly sure there are
            still a plethora of such mistakes in here. But I'm pretty sure it
            works - I just added the JSON version and conversion for
            perStageAgentConfig to this and the tests are actively running as I
            type this, but I got impatient and made a commit now. So ha.

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Andrew Bayer Path: src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/ast/ModelASTStage.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/ast/ModelASTStageConfig.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/ClosureContentsChecker.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/Stage.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/StageConfig.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/JSONParser.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ModelParser.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/validator/ModelValidator.groovy src/main/java/org/jenkinsci/plugins/pipeline/modeldefinition/model/MethodMissingWrapperWhitelist.java src/main/resources/ast-schema.json src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ClosureModelTranslator.groovy src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AbstractModelDefTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AgentTest.java src/test/resources/json/perStageConfigAgent.json src/test/resources/perStageConfigAgent.groovy http://jenkins-ci.org/commit/pipeline-model-definition-plugin/385940d33c4184cb5f5947c00c45d7ed57566c47 Log: JENKINS-38331 Very preliminary version of per-stage agent config Honestly, I'm doing this for JENKINS-38284 more, but I needed some section to actually have be per-stage to test it, so...tada? This is literally the result of three hours of slamming my head against the wall over stupid mistakes, so I'm fairly sure there are still a plethora of such mistakes in here. But I'm pretty sure it works - I just added the JSON version and conversion for perStageAgentConfig to this and the tests are actively running as I type this, but I got impatient and made a commit now. So ha.
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Andrew Bayer
            Path:
            SYNTAX.md
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/ast/ModelASTStage.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/ClosureContentsChecker.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/Stage.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/JSONParser.groovy
            src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ModelParser.groovy
            src/main/resources/ast-schema.json
            src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ClosureModelTranslator.groovy
            src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AbstractModelDefTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AgentTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/BasicModelDefTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/EnvironmentTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/ScriptStepTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/ToolsTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/ValidatorTest.java
            src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ExecuteConvertedTest.java
            src/test/resources/abortedNotification.groovy
            src/test/resources/agentAny.groovy
            src/test/resources/agentDocker.groovy
            src/test/resources/agentDockerWithEmptyDockerArgs.groovy
            src/test/resources/agentDockerWithNullDockerArgs.groovy
            src/test/resources/agentLabel.groovy
            src/test/resources/agentNone.groovy
            src/test/resources/agentNoneWithNode.groovy
            src/test/resources/allStagesExist.groovy
            src/test/resources/buildPluginParentPOM.groovy
            src/test/resources/dockerGlobalVariable.groovy
            src/test/resources/dockerGlobalVariableInScript.groovy
            src/test/resources/errors/blockInJobProperties.groovy
            src/test/resources/errors/blockInParameters.groovy
            src/test/resources/errors/blockInTriggers.groovy
            src/test/resources/errors/closureAsMethodCallArg.groovy
            src/test/resources/errors/duplicateEnvironment.groovy
            src/test/resources/errors/duplicateNotificationConditions.groovy
            src/test/resources/errors/duplicatePostBuildConditions.groovy
            src/test/resources/errors/duplicateStageNames.groovy
            src/test/resources/errors/duplicateStepParameter.groovy
            src/test/resources/errors/emptyAgent.groovy
            src/test/resources/errors/emptyEnvironment.groovy
            src/test/resources/errors/emptyJobProperties.groovy
            src/test/resources/errors/emptyNotifications.groovy
            src/test/resources/errors/emptyParallel.groovy
            src/test/resources/errors/emptyParameters.groovy
            src/test/resources/errors/emptyPostBuild.groovy
            src/test/resources/errors/emptyTriggers.groovy
            src/test/resources/errors/globalLibraryNonStepBody.groovy
            src/test/resources/errors/globalLibraryObjectMethodCall.groovy
            src/test/resources/errors/importAndFunctionShouldNotSkipParsing.groovy
            src/test/resources/errors/invalidBuildCondition.groovy
            src/test/resources/errors/invalidMetaStepSyntax.groovy
            src/test/resources/errors/invalidParameterTypeMethodCall.groovy
            src/test/resources/errors/invalidStepParameterType.groovy
            src/test/resources/errors/missingAgent.groovy
            src/test/resources/errors/missingRequiredStepParameters.groovy
            src/test/resources/errors/mixedMethodArgs.groovy
            src/test/resources/errors/notInstalledToolType.groovy
            src/test/resources/errors/notInstalledToolVersion.groovy
            src/test/resources/errors/packageShouldNotSkipParsing.groovy
            src/test/resources/errors/perStageConfigEmptyAgent.groovy
            src/test/resources/errors/perStageConfigEmptySteps.groovy
            src/test/resources/errors/perStageConfigMissingSteps.groovy
            src/test/resources/errors/perStageConfigUnknownSection.groovy
            src/test/resources/errors/rejectMapsForTriggerDefinition.groovy
            src/test/resources/errors/rejectParallelInNotifications.groovy
            src/test/resources/errors/rejectParallelMixedInSteps.groovy
            src/test/resources/errors/rejectPropertiesStepInMethodCall.groovy
            src/test/resources/errors/rejectStageInSteps.groovy
            src/test/resources/errors/stageWithoutName.groovy
            src/test/resources/errors/tooFewMethodCallArgs.groovy
            src/test/resources/errors/unknownStepParameter.groovy
            src/test/resources/errors/unlistedToolType.groovy
            src/test/resources/errors/wrongParameterNameMethodCall.groovy
            src/test/resources/executionModelAction.groovy
            src/test/resources/failingNotifications.groovy
            src/test/resources/failingPipeline.groovy
            src/test/resources/failingPostBuild.groovy
            src/test/resources/globalLibrarySuccess.groovy
            src/test/resources/globalLibrarySuccessInScript.groovy
            src/test/resources/json/errors/perStageConfigEmptySteps.json
            src/test/resources/json/errors/perStageConfigMissingSteps.json
            src/test/resources/json/errors/perStageConfigUnknownSection.json
            src/test/resources/json/perStageConfigAgent.json
            src/test/resources/legacyMetaStepSyntax.groovy
            src/test/resources/metaStepSyntax.groovy
            src/test/resources/multipleProperties.groovy
            src/test/resources/noCheckoutScmInWrongContext.groovy
            src/test/resources/nonLiteralEnvironment.groovy
            src/test/resources/notificationOnChangeChanged.groovy
            src/test/resources/notificationOnChangeFailed.groovy
            src/test/resources/parallelPipeline.groovy
            src/test/resources/perStageConfigAgent.groovy
            src/test/resources/postBuildAndNotifications.groovy
            src/test/resources/shInNotification.groovy
            src/test/resources/simpleEnvironment.groovy
            src/test/resources/simpleJobProperties.groovy
            src/test/resources/simpleNotification.groovy
            src/test/resources/simpleParameters.groovy
            src/test/resources/simplePipeline.groovy
            src/test/resources/simplePostBuild.groovy
            src/test/resources/simpleScript.groovy
            src/test/resources/simpleTools.groovy
            src/test/resources/simpleTriggers.groovy
            src/test/resources/stringsNeedingEscapeLogic.groovy
            src/test/resources/twoStagePipeline.groovy
            src/test/resources/unstableNotification.groovy
            src/test/resources/validStepParameters.groovy
            http://jenkins-ci.org/commit/pipeline-model-definition-plugin/b7a3ec68779e2b8edc4da667cf9d42551d067fc6
            Log:
            Merge pull request #19 from abayer/jenkins-38331

            JENKINS-38331 Per-stage configuration for agent

            Compare: https://github.com/jenkinsci/pipeline-model-definition-plugin/compare/263a17adae4a...b7a3ec68779e

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Andrew Bayer Path: SYNTAX.md src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/ast/ModelASTStage.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/ClosureContentsChecker.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/Stage.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/JSONParser.groovy src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ModelParser.groovy src/main/resources/ast-schema.json src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ClosureModelTranslator.groovy src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/ModelInterpreter.groovy src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AbstractModelDefTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AgentTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/BasicModelDefTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/EnvironmentTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/ScriptStepTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/ToolsTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/ValidatorTest.java src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ExecuteConvertedTest.java src/test/resources/abortedNotification.groovy src/test/resources/agentAny.groovy src/test/resources/agentDocker.groovy src/test/resources/agentDockerWithEmptyDockerArgs.groovy src/test/resources/agentDockerWithNullDockerArgs.groovy src/test/resources/agentLabel.groovy src/test/resources/agentNone.groovy src/test/resources/agentNoneWithNode.groovy src/test/resources/allStagesExist.groovy src/test/resources/buildPluginParentPOM.groovy src/test/resources/dockerGlobalVariable.groovy src/test/resources/dockerGlobalVariableInScript.groovy src/test/resources/errors/blockInJobProperties.groovy src/test/resources/errors/blockInParameters.groovy src/test/resources/errors/blockInTriggers.groovy src/test/resources/errors/closureAsMethodCallArg.groovy src/test/resources/errors/duplicateEnvironment.groovy src/test/resources/errors/duplicateNotificationConditions.groovy src/test/resources/errors/duplicatePostBuildConditions.groovy src/test/resources/errors/duplicateStageNames.groovy src/test/resources/errors/duplicateStepParameter.groovy src/test/resources/errors/emptyAgent.groovy src/test/resources/errors/emptyEnvironment.groovy src/test/resources/errors/emptyJobProperties.groovy src/test/resources/errors/emptyNotifications.groovy src/test/resources/errors/emptyParallel.groovy src/test/resources/errors/emptyParameters.groovy src/test/resources/errors/emptyPostBuild.groovy src/test/resources/errors/emptyTriggers.groovy src/test/resources/errors/globalLibraryNonStepBody.groovy src/test/resources/errors/globalLibraryObjectMethodCall.groovy src/test/resources/errors/importAndFunctionShouldNotSkipParsing.groovy src/test/resources/errors/invalidBuildCondition.groovy src/test/resources/errors/invalidMetaStepSyntax.groovy src/test/resources/errors/invalidParameterTypeMethodCall.groovy src/test/resources/errors/invalidStepParameterType.groovy src/test/resources/errors/missingAgent.groovy src/test/resources/errors/missingRequiredStepParameters.groovy src/test/resources/errors/mixedMethodArgs.groovy src/test/resources/errors/notInstalledToolType.groovy src/test/resources/errors/notInstalledToolVersion.groovy src/test/resources/errors/packageShouldNotSkipParsing.groovy src/test/resources/errors/perStageConfigEmptyAgent.groovy src/test/resources/errors/perStageConfigEmptySteps.groovy src/test/resources/errors/perStageConfigMissingSteps.groovy src/test/resources/errors/perStageConfigUnknownSection.groovy src/test/resources/errors/rejectMapsForTriggerDefinition.groovy src/test/resources/errors/rejectParallelInNotifications.groovy src/test/resources/errors/rejectParallelMixedInSteps.groovy src/test/resources/errors/rejectPropertiesStepInMethodCall.groovy src/test/resources/errors/rejectStageInSteps.groovy src/test/resources/errors/stageWithoutName.groovy src/test/resources/errors/tooFewMethodCallArgs.groovy src/test/resources/errors/unknownStepParameter.groovy src/test/resources/errors/unlistedToolType.groovy src/test/resources/errors/wrongParameterNameMethodCall.groovy src/test/resources/executionModelAction.groovy src/test/resources/failingNotifications.groovy src/test/resources/failingPipeline.groovy src/test/resources/failingPostBuild.groovy src/test/resources/globalLibrarySuccess.groovy src/test/resources/globalLibrarySuccessInScript.groovy src/test/resources/json/errors/perStageConfigEmptySteps.json src/test/resources/json/errors/perStageConfigMissingSteps.json src/test/resources/json/errors/perStageConfigUnknownSection.json src/test/resources/json/perStageConfigAgent.json src/test/resources/legacyMetaStepSyntax.groovy src/test/resources/metaStepSyntax.groovy src/test/resources/multipleProperties.groovy src/test/resources/noCheckoutScmInWrongContext.groovy src/test/resources/nonLiteralEnvironment.groovy src/test/resources/notificationOnChangeChanged.groovy src/test/resources/notificationOnChangeFailed.groovy src/test/resources/parallelPipeline.groovy src/test/resources/perStageConfigAgent.groovy src/test/resources/postBuildAndNotifications.groovy src/test/resources/shInNotification.groovy src/test/resources/simpleEnvironment.groovy src/test/resources/simpleJobProperties.groovy src/test/resources/simpleNotification.groovy src/test/resources/simpleParameters.groovy src/test/resources/simplePipeline.groovy src/test/resources/simplePostBuild.groovy src/test/resources/simpleScript.groovy src/test/resources/simpleTools.groovy src/test/resources/simpleTriggers.groovy src/test/resources/stringsNeedingEscapeLogic.groovy src/test/resources/twoStagePipeline.groovy src/test/resources/unstableNotification.groovy src/test/resources/validStepParameters.groovy http://jenkins-ci.org/commit/pipeline-model-definition-plugin/b7a3ec68779e2b8edc4da667cf9d42551d067fc6 Log: Merge pull request #19 from abayer/jenkins-38331 JENKINS-38331 Per-stage configuration for agent Compare: https://github.com/jenkinsci/pipeline-model-definition-plugin/compare/263a17adae4a...b7a3ec68779e
            Hide
            bitwiseman Liam Newman added a comment -

            Bulk closing resolved issues.

            Show
            bitwiseman Liam Newman added a comment - Bulk closing resolved issues.

              People

              • Assignee:
                abayer Andrew Bayer
                Reporter:
                michaelneale Michael Neale
              • Votes:
                0 Vote for this issue
                Watchers:
                6 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: