Skip to content

Commit

Permalink
Merge pull request #19 from abayer/jenkins-38331
Browse files Browse the repository at this point in the history
[JENKINS-38331] Per-stage configuration for agent
  • Loading branch information
abayer committed Oct 14, 2016
2 parents 263a17a + 8cf6fd2 commit b7a3ec6
Show file tree
Hide file tree
Showing 107 changed files with 984 additions and 337 deletions.
60 changes: 37 additions & 23 deletions SYNTAX.md
Expand Up @@ -10,8 +10,9 @@
These are sections that are specified directly within the `pipeline` argument closure.

### agent
* *Description*: Specifies where the build will run.
* *Required*: Yes
* *Description*: Specifies where the build or stage will run.
* *Required*: Yes for the top-level `pipeline` closure, optional for individual `stage` closures.
* *Allowed In*: Top-level `pipeline` closure and individual `stage` closures.
* *Parameters*: Either a `Map` of one or more arguments or one of two constants - `none` or `any`.
* *Map Keys*:
* Note that this will be an `ExtensionPoint`, so plugins will be able to add to the available image providers.
Expand Down Expand Up @@ -41,6 +42,7 @@ These are sections that are specified directly within the `pipeline` argument cl
* *Description*: A sequence of `key = value` pairs, which will be passed to the `withEnv` step the build will be
executed within.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: One or more lines with `foo = 'bar'` variable name/value pairs.
Expand All @@ -59,6 +61,7 @@ environment {
### stages
* *Description*: A sequence of one or more Pipeline `stage`s, each of which consist of a sequence of steps.
* *Required*: Yes
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: one or more `stage` blocks, as described below.
Expand All @@ -69,27 +72,35 @@ to-be-released block-scoped `stage` syntax in base Pipeline.
* *Required*: At least one is required.
* *Parameters*: A single `String`, the name for the `stage`.
* *Takes a Closure*: Yes
* *Closure Contents*: One or more Pipeline steps, including block-scoped steps and the special `script` block described below.
* *Closure Contents*: A `steps` block containing one or more Pipeline steps, including block-scoped steps and the
special `script` block described below, and optionally, certain configuration sections that allow being set on a
per-stage basis.
* *NOTE*: Currently only the `agent` section can be configured per-stage.
* *NOTE*: Only the "declarative subset" of Groovy is allowed by default. See below for details on that subset.
* *NOTE*: The `parallel` step is a special case - it can only be used if it's the sole step in the `stage`.
* *Examples*:

```
stages {
stage('foo') {
echo 'bar'
steps {
echo 'bar'
}
}
}
stages {
stage('first') {
timeout(time:5, unit:'MINUTES') {
sh "mvn clean install -DskipTests"
steps {
timeout(time:5, unit:'MINUTES') {
sh "mvn clean install -DskipTests"
}
}
}
stage('second') {
node('some-node') {
agent label:'some-node'
steps {
checkout scm
sh "mvn clean install"
}
Expand All @@ -98,14 +109,16 @@ stages {
stages {
stage('parallel-stage') {
parallel(
firstBlock: {
echo "First block of the parallel"
},
secondBlock: {
echo "Second block of the parallel"
}
)
steps {
parallel(
firstBlock: {
echo "First block of the parallel"
},
secondBlock: {
echo "Second block of the parallel"
}
)
}
}
}
```
Expand Down Expand Up @@ -136,6 +149,7 @@ stages {
* *Description*: A top-level section defining tools to auto-install and put on the PATH. This is ignored if `image none`
is specified.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: Names and versions of tools configured in Jenkins to install.
Expand All @@ -155,6 +169,7 @@ tools {
### notifications
* *Description*: Defines notifications to be sent after build completion, assuming build status conditions are met.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: A sequence of one or more build conditions containing Pipeline steps to run. See below for
Expand All @@ -164,6 +179,7 @@ definition of build conditions and their contents.
* *Description*: Defines post build actions to be run after build completion, assuming build status conditions are met.
Note that `postBuild` steps are run *before* `notifications`.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: A sequence of one or more build conditions containing Pipeline steps to run. See below for
Expand Down Expand Up @@ -205,8 +221,9 @@ postBuild {
```

### Triggers
* *Description*:
* *Description*: Triggers for this job, as used in other Jenkins jobs.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: A sequence of one or more trigger configurations, using `@Symbol` names for constructors.
Expand All @@ -221,8 +238,9 @@ triggers {
```

### Build Parameters
* *Description*:
* *Description*: Build parameters that will be prompted for at build time.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: A sequence of one or more parameter definition configurations, using `@Symbol` names for constructors.
Expand All @@ -237,8 +255,9 @@ parameters {
```

### Job Properties
* *Description*:
* *Description*: Other job properties, such as build discarding, limiting concurrent builds, and more.
* *Required*: No
* *Allowed In*: Top-level `pipeline` closure only.
* *Parameters*: None
* *Takes a Closure*: Yes
* *Closure Contents*: A sequence of one or more job property configurations, using `@Symbol` names for constructors.
Expand Down Expand Up @@ -272,8 +291,3 @@ jobProperties {
* Method calls where the left hand side is a variable reference or a sequence of property references: `x.y.z(...)`
* Method calls (including `@Symbol` constructors like used above in job properties, triggers and build parameters) where there is no left hand side.
* Closure without parameters: `{ ... }`

## Script mode
* *Description*: A flag which, when set, allows usage of standard non-declarative-subset Pipeline code throughout the Jenkinsfile.
* *Usage*: Set by putting `use script` at the beginning of the Jenkinsfile
* *Examples*: (hard to figure out a good example here since we've moved to the `pipeline` step?)
Expand Up @@ -20,6 +20,7 @@ import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public final class ModelASTStage extends ModelASTElement {
String name
ModelASTAgent agent
List<ModelASTBranch> branches = []

public ModelASTStage(Object sourceLocation) {
Expand All @@ -32,9 +33,13 @@ public final class ModelASTStage extends ModelASTElement {
branches.each { br ->
a.add(br.toJSON())
}
return new JSONObject()
.accumulate("name",name)
.accumulate("branches",a)
JSONObject o = new JSONObject()
o.accumulate("name",name)
o.accumulate("branches",a)
if (agent != null) {
o.accumulate("agent", agent.toJSON())
}
return o
}

@Override
Expand All @@ -43,13 +48,17 @@ public final class ModelASTStage extends ModelASTElement {
branches.each { b ->
b?.validate(validator)
}
agent?.validate(validator)
}

@Override
public String toGroovy() {
StringBuilder retString = new StringBuilder()
retString.append("stage(\"${name}\") {\n")

if (agent != null) {
retString.append(agent.toGroovy())
}
retString.append("steps {\n")
if (branches.size() > 1) {
retString.append("parallel(\n")
List<String> branchStrings = branches.collect { b ->
Expand All @@ -63,6 +72,8 @@ public final class ModelASTStage extends ModelASTElement {

retString.append("}\n")

retString.append("}\n")

return retString.toString()
}

Expand All @@ -72,5 +83,6 @@ public final class ModelASTStage extends ModelASTElement {
branches.each { b ->
b.removeSourceLocation()
}
agent?.removeSourceLocation()
}
}
@@ -0,0 +1,37 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/


package org.jenkinsci.plugins.pipeline.modeldefinition.model

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings

/**
* Special wrapper for checking the contents of a {@link Closure}.
*
* @author Andrew Bayer
*/
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public class ClosureContentsChecker extends MappedClosure<Object,ClosureContentsChecker> {
}
Expand Up @@ -36,19 +36,47 @@ import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted
@ToString
@EqualsAndHashCode
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public class Stage implements StepBlockWithOtherArgs, Serializable {
public class Stage implements NestedModel, Serializable {

@Whitelisted
String name

@Whitelisted
StepsBlock closureWrapper
StepsBlock steps

@Whitelisted
Agent agent

@Whitelisted
public Stage(String n, StepsBlock w) {
Stage name(String n) {
this.name = n
this.closureWrapper = w
return this
}

@Whitelisted
Stage agent(Agent a) {
this.agent = a
return this
}

@Whitelisted
Stage agent(Map<String,String> args) {
this.agent = new Agent(args)
return this
}

@Whitelisted
Stage steps(StepsBlock s) {
this.steps = s
return this
}

@Override
@Whitelisted
public void modelFromMap(Map<String,Object> m) {
m.each { k, v ->
this."${k}"(v)
}
}

}
Expand Up @@ -167,6 +167,10 @@ class JSONParser {

stage.name = j.getString("name")

if (j.has("agent")) {
stage.agent = parseAgent(j.get("agent"))
}

j.getJSONArray("branches").each { b ->
JSONObject o = (JSONObject)b
stage.branches.add(parseBranch(o))
Expand All @@ -175,6 +179,8 @@ class JSONParser {

}



public @CheckForNull ModelASTBranch parseBranch(JSONObject j) {
ModelASTBranch branch = new ModelASTBranch(j)
branch.name = j.getString("name")
Expand Down

0 comments on commit b7a3ec6

Please sign in to comment.