Salesforce DX – Jenkins – Jenkinsfile Revisited

So far we have Jenkins setup to run and configured for our repository from Salesforce DX – Setup Jenkins, added a Jenkinsfile to get a the pipeline to run in Salesforce DX – Setup Jenkins – Jenkinsfile, and configured our environment variables in Salesforce DX – Jenkins – Environment Variables.  So things should build and if you are using a *nix machine they might be.  Since I’m on Windows it’s not going that smoothly.  Let’s look at why.

Jenkinsfile Issues

When we setup the Jenkinsfile we used the example at /sfdx-dreamhouse to base it on, and by base it on I mean copy.  I didn’t realize this at the time but the pipeline environment for Jenkins is not isolated from the host machine meaning, if you are using a *nix machine the pipeline is executed in a shell (bash, zsh, csh, whathav eyoush) and if you are on a Windows machine it uses the cmd.exe.

Why does that matter?

Good questions.  The Windows cmd.exe doesn’t have the same commands as a *nix shell.  All the shell specific commands in the Jenkinsfile don’t work in cmd.exe.

Let’s fix the Jenkinsfile to work on Windows.

If you are using a *nix machine feel free to keep the Jenkinsfile they way it came 🙂

Update Jenkinsfile

The main things we need to change is all the sh commands to bat and the way we access the Salesforce DX command line tools.  Since the default install location on Windows (some where in the Program Files) causes issues because of the space in the path so we will need a work around for that.

For accessing sfdx we can address it in a couple of different ways.

Since we used C:\Program Files\sfdx\bin as the path to the cli we can add quotes around the call to sfdx by escaping them with backslashes \" so line 24:

rc = sh returnStatus: true, script: "${toolbelt}/sfdx force:auth:jwt:grant --clientid ${CONNECTED_APP_CONSUMER_KEY} --username ${HUB_ORG} --jwtkeyfile ${jwt_key_file} --setdefaultdevhubusername"

would be updated to:

rc = sh returnStatus: true, script: "\"${toolbelt}/sfdx\" force:auth:jwt:grant --clientid ${CONNECTED_APP_CONSUMER_KEY} --username ${HUB_ORG} --jwtkeyfile ${jwt_key_file} --setdefaultdevhubusername"

This is a little verbose those and probably more prone to errors than I would prefer.

Another way to address this would be to change our  toolkit custom tool path to "C:\Program Files\sfdx\bin\sfdx" and use ${toolkit} all by it’s self.

rc = sh returnStatus: true, script: "${toolbelt} force:auth:jwt:grant --clientid ${CONNECTED_APP_CONSUMER_KEY} --username ${HUB_ORG} --jwtkeyfile ${jwt_key_file} --setdefaultdevhubusername"

I will be doing this so I have less to type.  And less typing means less chance for errors.

Now commit the changes to your Jenkinsfile and get Jenkins to re-run, I use the Scan Multibranch Pipeline Now button inside the job.

Build Error

When it runs you may have a build error that reads like the following:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod

To resolve this go to  Manage Jenkins => In-process Script Approval and approve the script.

Approval Button

Approval Button

 

Try it again.

and see it….

Still Fail

Still Fail

ok so mine is still erroring out because I have too many Scratch Orgs already.

 

Conclusion

ok, at this point you may be wondering how many posts I can drag this out.   Shall we find out?  Let me know by leaving a comment below, emailing brett@wipdeveloper.com or following and yelling at me on Twitter/BrettMN.

13 thoughts on “Salesforce DX – Jenkins – Jenkinsfile Revisited

  1. Hi,
    your blog is most help for me. but here I got an error when I am integrating jenkins and salesforcedx in windows environment.Here I attach my error log.Please help me to fix the issue.

    Thanks

    error log

    [SalesforceDX_master-BZ353QSXAOM4R3QVQCQEDWHC4NF5AHRZZ3P63REGTG7C5SYT4V3A] Running batch script

    C:\Program Files (x86)\Jenkins\workspace\SalesforceDX_master-BZ353QSXAOM4R3QVQCQEDWHC4NF5AHRZZ3P63REGTG7C5SYT4V3A>”C:\Program Files\Heroku\bin/sfdx” force:auth:jwt:grant –clientid XXXXXXXXXXXXXXXXXXXXXXXXXXXXX –username raja.m.s@mstsolutions.com –jwtkeyfile **** –setdefaultdevhubusername
    The heroku command is not found.
    [Pipeline] error
    [Pipeline] }
    [Pipeline] // stage
    [Pipeline] }
    [Pipeline] // withCredentials
    [Pipeline] }
    [Pipeline] // node
    [Pipeline] End of Pipeline

    GitHub has been notified of this commit’s build result

    ERROR: hub org authorization failed
    Finished: FAILURE

    1. Hello Raja,

      Thanks for reading.

      Sorry you are having problems. At first glance it looks like maybe the Salesforce DX command line tools are not installed or are not installed at that location.

      Or the “user” the Jenkins service is running as does not have access to the folder containing the command line tools.

      I will try and get some time this week to see if I can get the same error to occur so I might be able get you a better answer.

      Brett

  2. Hi
    I resolved the previous error.But now i got an new error.

    started
    [Pipeline] bat
    [SalesforceDX_master-BZ353QSXAOM4R3QVQCQEDWHC4NF5AHRZZ3P63REGTG7C5SYT4V3A] Running batch script

    C:\Program Files (x86)\Jenkins\workspace\SalesforceDX_master-BZ353QSXAOM4R3QVQCQEDWHC4NF5AHRZZ3P63REGTG7C5SYT4V3A>”C:\Program Files\sfdx\bin\sfdx” force:auth:jwt:grant –clientid XXXXXXXXXXXXXXXXXXXXXXXXXX –username raja.m.s@mstsolutions.com –jwtkeyfile **** –setdefaultdevhubusername
    Installing required plugins for force… ! Invalid plugin. sfdx only supports plugins with a namespace.

    1. Hello Raja,

      From Start you can go to “Windows Administrative Tools” and select “Services”.

      Find “Jenkins” in the name column and right click it and choose “Properties”

      go to the “Log On” tab and choose “This Account” then specify an account and provide the password for that account.

      You may want to use an account that is not your actual account. Maybe get the IT Administrator to create an account that has just the rights Jenkins will require.

      Hope this helps!
      Brett

    2. Hello Raja,

      I am having the same issue, I did trying creating new user and changed Jenkins Service run as “This account” with that new user, still I am getting the same issue. Can you please suggest?

      Installing required plugins for force… ! Invalid plugin. sfdx only supports plugins with a namespace.
      [Pipeline] error
      [Pipeline] }
      [Pipeline] // stage
      [Pipeline] }
      [Pipeline] // withCredentials
      [Pipeline] }
      [Pipeline] // node
      [Pipeline] End of Pipeline
      ERROR: hub org authorization failed
      Finished: FAILURE

      Regards,
      Ajay

  3. thank you @Brett.
    Now I can login to my devhub org.but now I got an groovy error.Here I present my error log.Please help me to fix the issue.

    Thanks
    C:\Users\MSTCHENNAI\jenkins_workspace\workspace\SalesforceDX_master-BZ353QSXAOM4R3QVQCQEDWHC4NF5AHRZZ3P63REGTG7C5SYT4V3A>”C:\Program Files\Heroku\bin/sfdx” force:auth:jwt:grant –clientid XXXXXXXXXXXXXXXXXXXXXX –username raja.m.s@mstsolutions.com –jwtkeyfile **** –setdefaultdevhubusername
    Successfully authorized raja.m.s@mstsolutions.com with org id 00D7F000000z2XiUAI
    [Pipeline] bat
    [SalesforceDX_master-BZ353QSXAOM4R3QVQCQEDWHC4NF5AHRZZ3P63REGTG7C5SYT4V3A] Running batch script
    [Pipeline] }
    [Pipeline] // stage
    [Pipeline] }
    [Pipeline] // withCredentials
    [Pipeline] }
    [Pipeline] // node
    [Pipeline] End of Pipeline

    GitHub has been notified of this commit’s build result

    groovy.json.JsonException: Lexing failed on line: 1, column: 1, while reading ‘C’, no possible valid JSON value or punctuation could be recognized.
    at groovy.json.JsonLexer.nextToken(JsonLexer.java:82)
    at groovy.json.JsonSlurperClassic.parse(JsonSlurperClassic.java:91)
    at groovy.json.JsonSlurperClassic.parseText(JsonSlurperClassic.java:77)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1215)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
    at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:47)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:151)
    at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:21)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:115)
    at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:149)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:146)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:16)
    at WorkflowScript.run(WorkflowScript:36)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:82)
    at sun.reflect.GeneratedMethodAccessor135.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:76)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:66)
    at sun.reflect.GeneratedMethodAccessor208.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
    at com.cloudbees.groovy.cps.Next.step(Next.java:83)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:173)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:162)
    at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
    at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:162)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:19)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:35)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:32)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:32)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:330)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:82)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:242)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:230)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    Finished: FAILURE

  4. HI Brett,

    I am having the same issue, I did trying creating new user and changed Jenkins Service run as “This account” with that new user, still I am getting the same issue. Can you please suggest?

    Installing required plugins for force… ! Invalid plugin. sfdx only supports plugins with a namespace.
    [Pipeline] error
    [Pipeline] }
    [Pipeline] // stage
    [Pipeline] }
    [Pipeline] // withCredentials
    [Pipeline] }
    [Pipeline] // node
    [Pipeline] End of Pipeline
    ERROR: hub org authorization failed
    Finished: FAILURE

    Regards,
    Ajay

      1. HI Brett,

        Yes. The user has all the permissions to that folder. Not sure still I am getting the same issue. Any other place fix is needed?

        Regards,
        Ajay

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.