Skip to content
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

Warn user when forgetting def on a variable #994

Merged
merged 9 commits into from
Feb 27, 2025

Conversation

jglick
Copy link
Member

@jglick jglick commented Feb 27, 2025

Following up #925: not only avoiding the symptom, but warning about the mistake. (Though not from @NonCPS methods.)

Note that this uses a distinct logging system from either #211 or #280, since in this case at the point at which the warning is printed we have easy access to a TaskListener (though PropertyAccessBlock would have additional access to a SourceLocation which may be helpful).

@jglick jglick requested review from Vlatombe and dwnusbaum February 27, 2025 21:27
…sing from some tests which could equally well have used lexical variables
@@ -137,6 +138,23 @@ private void maybeRecord(Class<?> clazz, Supplier<String> message) {
Class<?> clazz = classOf(lhs);
maybeRecord(clazz, () -> clazz.getName() + "." + name);
delegate.setProperty(lhs, name, value);
if (value != null) {
var owner = findOwner(lhs);
if (owner instanceof CpsScript) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to work as desired also in libraries: assigning to an implicit field of a vars/*.groovy produces a warning, while assigning to a field of a named class in src/**/*.groovy does not.

@jglick jglick marked this pull request as ready for review February 27, 2025 22:35
@jglick jglick requested a review from a team as a code owner February 27, 2025 22:35
# TODO perhaps create a https://jenkins.io/redirect/pipeline-field-set/
LoggingInvoker.field_set=\
Did you forget the `def` keyword? \
{0} seems to be setting a field named {1} (to a value of type {2}) \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it's worth, "WorkflowScript seems to be setting a field..." sounds strange to me. I don't really have any better recommendations though. Maybe "Something is setting WorkflowScript.xyz (to ...)", but then I would expect users to ask "what something?" and there is no easy way for us to answer that question here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least in the cases I know about, it is code in the named script which is setting the field. I could try to make the SourceLocation available here (which would give you a line number) though it would be a bit more work since that is only available in groovy-cps whereas the TaskListener is only available in the plugin.

As to the naming WorkflowScript, rather than say Jenkinsfile, it would be nice to update that, though I would worry about the implications.

Copy link
Member

@dwnusbaum dwnusbaum Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, my concern is mainly that users may not realize that WorkflowScript means Jenkinsfile. I agree that we should always mention the real class name, but maybe it could make sense to add (your Jenkinsfile) or something if the class name is WorkflowScript, although that is not necessarily accurate depending on how the Pipeline is configured.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most simple declarative pipeline. Removed all global libraries (but I found zero reference of resolveStrategy or delgate anywhere in the code)

pipeline {
    agent none
    stages {
        stage('Hello') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

declarative

Looks I'm not the only one https://issues.jenkins.io/browse/JENKINS-75353

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, did not think to check Declarative syntax, will try to fix today.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved.

@dwnusbaum
Copy link
Member

dwnusbaum commented Feb 27, 2025

Oh, and it might be worth adding a system property to disable this. Previously, when security fixes broke @Field there were lots of complaints, so for people setting script fields intentionally these warning messages might be something they do not care about and will not fix.

@dwnusbaum
Copy link
Member

(Or I guess you could also check if the property matches a field defined on the script if @Field specifically is a concern)

@jglick jglick enabled auto-merge (squash) February 27, 2025 23:33
@jglick jglick merged commit 7c3a975 into jenkinsci:master Feb 27, 2025
17 checks passed
jglick added a commit to jglick/workflow-cps-plugin that referenced this pull request Feb 28, 2025
@jglick jglick deleted the field-set branch February 28, 2025 15:36
@PayBas
Copy link

PayBas commented Mar 7, 2025

@jglick I couldn't get rid of the warnings in some specific cases.

I've boiled it down to:

pipeline {
  agent none
  
  stages {
    stage('FOO') {
      matrix {
        axes {
          axis {
            name 'OS'
            values 'Windows', 'Linux'
          }
        }
        stages {
          stage('BAR') {
            agent any
            steps {
              script {
                echo "${OS}"
              }
            }
          }
        }
      }
    }
  }
}

Leading to:

[Pipeline] Start of Pipeline
Did you forget the `def` keyword? WorkflowScript seems to be setting a field named __model__Closure_0_1201446834__ (to a value of type CpsClosure2) which could lead to memory leaks or other issues.
[Pipeline] stage
[Pipeline] { (FOO)
[Pipeline] parallel
[Pipeline] { (Branch: Matrix - OS = 'Windows')
[Pipeline] { (Branch: Matrix - OS = 'Linux')
[Pipeline] stage
...

That's with 4043.va_fb_de6a_a_8b_f5

@dwnusbaum
Copy link
Member

@PayBas From a quick look, I think that anyone using the matrix directive as well as anyone using the SCRIPT_SPLITTING_TRANSFORMATION mode described in JENKINS-37984 will get false positive warnings similar to what you listed due to code like this and this. Whether this could be easily fixed, I do not know. Perhaps Wrapper.createScriptContextVariable could be adjusted to explicitly insert variables into Script.bindings to avoid these warnings.

@PayBas
Copy link

PayBas commented Mar 8, 2025

@dwnusbaum it's not a big deal. We can ignore it. But some of our developers were wondering if they missed something somewhere, which it turns out they didn't.
So I thought I'd at least notify you guys.

Keep up the good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants