title: Jenkins not expanding macros
body: <p>I hope that is the right lingo. I've been fighting this for about 2 days now.</p>
  <h3>TL;DR</h3>
  <p>My plugin I'm developing is not replacing macros like <code>%BUILD_NUMBER%</code> or <code>%JOB_NAME%</code></p>
  <h3>Details</h3>
  <p>I'm making a notifier plugin for Jenkins that simply runs pickles on my specflow tests. (It generates a html report). I got all the configuration stuff figured out for both the ToolInstallation as well as the Notifier itself as a freestyle build step (I do have in place the workflow bits, but i've not tested that yet) This Notifier is replacing the builder step of running a windows batch file which is essentially this</p>
  <pre><code>C:\BuildTools\Pickles-2.10.0\pickles.exe ^
  --feature-directory=&quot;%WORKSPACE%\My.Program.AcceptanceTests&quot; ^
  --output-directory=&quot;\\some-server\c$\Features\my-program&quot; ^
  --documentation-format=dhtml ^
  --system-under-test-name=&quot;%JOB_NAME%&quot; ^
  --system-under-test-version=&quot;Build #%BUILD_NUMBER%&quot; ^
  --link-results-file=&quot;%WORKSPACE%\nunit-test-results\NUnitTestResults.xml&quot; ^
  --test-results-format=nunit
  </code></pre>
  <p>To replicate this I made a <code>BuildPicklesNotifierArguments</code> class.</p>
  <pre><code>package hudson.plugins.pickles.utilities;
  
  import hudson.EnvVars;
  import hudson.Util;
  import hudson.plugins.pickles.PicklesNotifier;
  import hudson.util.ArgumentListBuilder;
  
  import java.util.Map;
  
  public class BuildPicklesArguments {
  
      private final PicklesNotifier picklesArguments;
      private final Map&lt;String, String&gt; buildVariables;
      private final EnvVars env;
  
      public BuildPicklesArguments(PicklesNotifier picklesNotifier, Map&lt;String, String&gt; buildVariables, EnvVars env) {
          this.picklesArguments = picklesNotifier;
          this.buildVariables = buildVariables;
          this.env = env;
      }
  
      public void buildArguments(ArgumentListBuilder args){
          safeAdd(args, &quot;feature-directory&quot;, picklesArguments.getFeatureDirectory());
          safeAdd(args, &quot;output-directory&quot;, picklesArguments.getOutputDirectory());
          safeAdd(args, &quot;documentation-format&quot;, picklesArguments.getDocumentationFormat());
          safeAdd(args, &quot;system-under-test-name&quot;, picklesArguments.getSystemUnderTestName());
          safeAdd(args, &quot;system-under-test-version&quot;, picklesArguments.getSystemUnderTestVersion());
          safeAdd(args, &quot;link-results-file&quot;, picklesArguments.getLinkResultsFiles());
          safeAdd(args, &quot;test-results-format&quot;, picklesArguments.getTestResultFormat());
  
          if(!picklesArguments.getEnableComments())
              args.add(&quot;--enableComments=false&quot;);
          if(picklesArguments.getIncludeExperimentalFeatures())
              args.add(&quot;--include-experimental-features&quot;);
      }
  
      private void safeAdd(ArgumentListBuilder args, String switchString, String value) {
          if (value != null &amp;&amp; !value.isEmpty()) {
              String expanded = Util.replaceMacro(value, env);
              expanded = Util.replaceMacro(expanded, buildVariables);
              args.addKeyValuePair(&quot;--&quot;, switchString, expanded, false);
  //            args.addQuoted(String.format(&quot;--%s=\&quot;%s\&quot;&quot;, switchString, expanded));
          }
      }
  }
  </code></pre>
  <p>I wrote a unit test that shows the problem</p>
  <pre><code>package hudson.plugins.pickles.utilities;
  
  import hudson.EnvVars;
  import hudson.plugins.pickles.PicklesNotifier;
  import hudson.slaves.EnvironmentVariablesNodeProperty;
  import hudson.util.ArgumentListBuilder;
  import org.junit.Test;
  
  import java.util.HashMap;
  import java.util.Map;
  
  import static org.junit.Assert.assertEquals;
  
  public class BuildPicklesArgumentsTest {
      @Test
      public void buildArguments() throws Exception {
          ArgumentListBuilder args = new ArgumentListBuilder();
          Map&lt;String, String&gt; map = new HashMap&lt;&gt;();
          map.put(&quot;${BUILD_NUMBER}&quot;, &quot;4&quot;);
          EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty();
          EnvVars env = prop.getEnvVars();
          env.put(&quot;%BUILD_NUMBER%&quot;, &quot;4&quot;);
          PicklesNotifier pickles = new PicklesNotifier();
          pickles.setSystemUnderTestVersion(&quot;Build #%BUILD_NUMBER%&quot;);
          pickles.setEnableComments(true);
          pickles.setIncludeExperimentalFeatures(false);
          BuildPicklesArguments build = new BuildPicklesArguments(pickles, map, env);
  
          build.buildArguments(args);
  
          assertEquals(&quot;\&quot;--system-under-test-version=Build #4\&quot;&quot;, args.toString());
      }
  }
  </code></pre>
  <p>which fails:</p>
  <pre><code>Expected :&quot;--system-under-test-version=Build #4&quot;
  Actual   :&quot;--system-under-test-version=Build #%BUILD_NUMBER%&quot;
  </code></pre>
  <p>I'm struggling with the test because I don't know exactly what the environment variables look like so I've tried many variations, but outcome is the same when running in Jenkins as the test results. Lastly out of curiosity I took out all of the macros in my configuration and rebuilt and it was successful (the command looked like this) <code>C:\BuildTools\Pickles-2.10.0\pickles.exe --feature-directory=My.Program.AcceptanceTests --output-directory=C:\temp\testpickles --documentation-format=dhtml --system-under-test-name=Freestylnit &quot;--system-under-test-version=Build #5&quot; --link-results-file=NunitTestResults.xml --test-results-format=nunit</code>. I'm glad it works because I thought the argument <code>system-under-test-version</code> was going to cause problems being wrapped in a double quote, but apparently that wasn't the problem. FYI if you want to see the rest of the source code <a href="https://github.com/immeraufdemhund/pickles-notifier-plugin" rel="nofollow noreferrer">look at it in github</a></p>