-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JENKINS-41748, JENKINS-41890 - Fix env var references and WORKSPACE #110
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to be super confusing. Everywhere else when we want to substitute values in strings we put them in double quotes, but in this one area we need to put them in single quotes? I understand the underlying design/implementation issue, but this implementation exposes and highlights that to the user, making their lives harder instead handling it internally.
Can we take GStrings and do the work internally instead?
@bitwiseman I don't believe we can, no, or at least not with the current runtime translation tech. The |
Would this fix allow me to write something like this?
|
@staffanf I...am not honestly sure, but I don't think so. I'll dig into that. |
I did a quick test and I have an issue
dies with
Maybe I didn't installed correctly the plugin and its dependencies ... |
Same with |
@aheritier Fixed. And from my most recent commit message: Now we can do I don't love it. It's hackish. There's additional hackery involved in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so much better. Thanks!
Some added tests needed.
Also need a test for a validation error message for any unsupported GStrings.
stage("foo") { | ||
environment { | ||
BAZ = "${FOO}BAZ" | ||
SPLODE = "${params.WUT ?: 'banana'}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a version of this working?
BAZA = "${env.BAR ?: 'nope'}"
Also, in this second env block would this work?
"BAR = "${BAR}FOO"
And would BAR return to the original value outside this particular stage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So...I should probably rename the variable from SPLODE
, since, well, it doesn't 'splode. It works. =)
Yes, BAR = "${BAR}FOO"
would result in echoing BAR is FOOBARFOO
, and yes, the stage overrides would "reset" - they're only scoped in the context of the withEnv
block within the stage they're specified in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, just wanted to make sure there are tests that ensure that behavior. 👍
@rsandell @kzantow - 4fab096 is of interest to both of you, I think. I may yank it from here and just do it over in https://github.com/jenkinsci/pipeline-model-definition-plugin/tree/JENKINS-41759, but I wanted to make sure it worked. =) |
JSONParser.MethArgsMissing=Method arguments missing or not an array | ||
JSONParser.MethCallMustBeObj=Method call definition must be a JSON object | ||
JSONParser.MethArgsMustBeObj=Individual method or function arguments must be a JSON object | ||
JSONParser.MethArgsMissing=Method orfunction arguments missing or not an array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No likey the inheritance model. And some other questionable things.
And ouch this is gonna be a merge from hell with JENKINS-41759 :)
@@ -31,7 +31,7 @@ | |||
* @author Andrew Bayer | |||
* @author Kohsuke Kawaguchi | |||
*/ | |||
public abstract class ModelASTValue extends ModelASTElement implements ModelASTMethodArg { | |||
public abstract class ModelASTValue extends ModelASTElement implements ModelASTMethodArg, ModelASTEnvironmentValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing me off again with strange domain model hierarchies eh? I do not see the logic in that every ModelASTValue
is a ModelASTEnvironmentValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means that every ModelASTValue
could be used as a ModelASTEnvironmentValue
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So why have a ModelASTEnvironmentValue
at all then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorta agree with @rsandell here, if every ModelASTValue
is a ModelASTEnvironmentValue
what's the point in differentiating them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rsandell and I talked about this last week - ModelASTEnvironmentValue
means "This element type can be used as a value for an environment variable".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So why not the reverse inheritance? (mostly irrelevant to this PR, and more of a question than anything else)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ModelASTEnvironmentValue
(and friends like ModelASTWhenContent
and ModelASTMethodArg
) are just marker interfaces - saying "any type implementing this interface can be used as a value where this interface is specified as the type". So ModelASTValue
, for example, implements both ModelASTEnvironmentValue
and ModelASTMethodArg
because it can be used in both places (as well as any place that explicitly calls out ModelASTValue
), but ModelASTInternalFunctionCall
only implements ModelASTEnvironmentValue
- so it can be used in contexts looking for ModelASTEnvironmentValue
s but not those looking for ModelASTMethodArg
, or any context that's explicitly looking for a ModelASTValue
.
Thinking out loud, albeit a bit pedantically, as I try to make sure I understand what I'm saying... =) Imagine Human
, Lizard
, and Cat
classes, with interfaces HasTail
and Mammal
. Lizard
and Cat
(ignore Manx cats for the moment!) would have the HasTail
interface, while Human
and Cat
would have the Mammal
interface (yes, not a great example since Human
and Cat
could just inherit from a Mammal
class, but roll with me here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, yes, ModelASTInternalFunctionCall
does overlap to some extent with ModelASTMethodCall
. The main difference is that ModelASTInternalFunctionCall
doesn't allow recursive nesting of instances of itself as arguments, while ModelASTMethodCall
does. Might want to rename/reorganize that at some point.
// We save the caught error, if any, for throwing at the end of the build. | ||
inDeclarativeAgent(root, root.agent) { | ||
// Entire build, including notifications, runs in the agent. | ||
inDeclarativeAgent(root, root.agent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you can no longer use environment variables to declare agent? Sort of hinders one of the use cases of JENKINS-41759 where the properties would be the marker file and declare what docker image to run in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's one or the other - either you get WORKSPACE
available when we evaluate the environment or you get the environment available when we evaluate the agent.
List<String> evaledEnv = new ArrayList<>() | ||
for (int i = 0; i < envVars.size(); i++) { | ||
// Evaluate to deal with any as-of-yet unresolved expressions. | ||
evaledEnv.add((String)script.evaluate('"' + envVars.get(i) + '"')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we jumping out of the sandbox here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't be, no - it still gets run through the CpsScript
's GroovyShell
.
FYI, gonna table this until #112 lands - it'll be easier to do this once that's in rather than the other way around. |
This is very much needed to get go-lang builds to work. As you need to set the GOPATH to the workspace as changing dir to /go does not work. |
Does this make use of jenkinsci/workflow-durable-task-step-plugin#29 or does PMD set |
@jglick Interesting question. It seems |
34ea445
to
9b63c9f
Compare
Marking this as aimed at 1.1. |
fa29e40
to
2ba0be7
Compare
cf4498f
to
0eb5073
Compare
Un-tabling this - it'll go in 1.1, while #112 will wait for 1.2. @bitwiseman @rsandell - please re-review ASAP. |
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. |
8fd7387
to
2d85905
Compare
* | ||
* @author Andrew Bayer | ||
*/ | ||
public interface ModelASTEnvironmentValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extends ModelASTMarkerInterface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
@@ -45,7 +45,7 @@ | |||
private final String credentialId; | |||
private final List<Map<String, Object>> withCredentialsParameters; | |||
|
|||
CredentialWrapper(String credentialId, List<Map<String, Object>> withCredentialsParameters) { | |||
public CredentialWrapper(String credentialId, List<Map<String, Object>> withCredentialsParameters) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Restricted(NoExternalUse.class)
since this will be refactored a bit later and you now made it public
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
JSONParser.MethArgsMissing=Method arguments missing or not an array | ||
JSONParser.MethCallMustBeObj=Method call definition must be a JSON object | ||
JSONParser.MethArgsMustBeObj=Individual method or function arguments must be a JSON object | ||
JSONParser.MethArgsMissing=Method orfunction arguments missing or not an array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 AFAICT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐝
This changes things to now properly expand environment variable names referred to in `environment` values, building from the job context's environment to the parent context (if per-stage `environment`) and lastly to the immediate `environment` context. This is not exactly *perfect*, per se - you still need to either single quote or escape the dollar sign due to the `GString` getting resolved before we can populate anything. May revisit that in the future to see if there's a workaround we can use.
This is to make sure we have `WORKSPACE` in the environment. Note that this won't quite work right for per-stage agent/environment, though - `WORKSPACE` there will still refer to the top-level `WORKSPACE` (if there is one) or be null if `agent none` is used at the top level. This is so that we have the per-stage environment populated before evaluating any when condition, while not launching in a per-stage agent until said when condition has already been evaluated. Might reconsider this in the future. Also added `.logMatches(String... patterns)` to `AbstractModelDefTest.ExpectationsBuilder` so that we can do regular expression matching against logs, which we needed to verify this.
Now we can do `"${FOO}bar"` and `"${params.SOMETHING ?: 'something-else'}"`, but we can only do this thanks to some weird black magic, no longer doing runtime translation for environment blocks and instead pulling it from the ModelAST directly. I don't love it. It's hackish. There's additional hackery involved in `script.evaluate`ing to get the more complicated expressions to resolve as well.
Still gotta add negative-case tests, and will probably end up folding JENKINS-41759 into this effort at some point, since that's where this will *really* start to be valuable.
🐝 Looks good now. |
In a declarative script I have tried: When the script runs I get exception:
Is my syntax incorrect? (Pipeline: Declarative Agent API v1.1.1, Jenkins 2.79) |
Assuming you have a top level agent, that should theoretically work, but you'll probably find it more reliable with 1.2, which releases late today or first thing tomorrow. |
Thanks Andrew, the problem was that I had no top level agent, as you hinted. Works ok now. |
environment
section so that referring to existing env vars (either from the overall build context or, when in astage
, in the top-levelenvironment
actually works right.environment
andagent
at top-level so that we already have aWORKSPACE
(if notagent none
) before evaluating theenvironment
- this is JENKINS-41890, which depended on the other change and didn't seem to merit a separate PR.