-
-
Notifications
You must be signed in to change notification settings - Fork 105
[JEP-206] Gather command output in a local encoding #64
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
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
dec68db
[JENKINS-31096] Gather command output in a local encoding.
jglick 6f2bf2e
Cannot downgrade Jenkins in tests!
jglick 23a1dde
Merge branch 'master' into UTF-8-JENKINS-31096
jglick 1f4493f
Bump.
jglick 0dcf951
Emphasizing that specifying an explicit encoding is wise.
jglick 35b0234
Merge branch 'incrementals' into UTF-8-JENKINS-31096
jglick 36722de
Review comments.
jglick 75181a5
Merge branch 'master' into UTF-8-JENKINS-31096
jglick 54b2187
Restricting doCheckEncoding.
jglick 8c763a4
Updated parent and incremental deps.
jglick d3508c3
Consume released workflow-support and durable-task plugins
svanoort File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| buildPlugin(jenkinsVersions: [null, '2.73.1']) | ||
| buildPlugin(jenkinsVersions: [null, '2.121.1']) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,13 +30,15 @@ | |
| import hudson.EnvVars; | ||
| import hudson.FilePath; | ||
| import hudson.Launcher; | ||
| import hudson.Util; | ||
| import hudson.model.TaskListener; | ||
| import hudson.util.DaemonThreadFactory; | ||
| import hudson.util.FormValidation; | ||
| import hudson.util.LogTaskListener; | ||
| import hudson.util.NamingThreadFactory; | ||
| import java.io.IOException; | ||
| import java.nio.charset.Charset; | ||
| import java.nio.charset.StandardCharsets; | ||
| import java.util.Set; | ||
| import java.util.concurrent.ScheduledFuture; | ||
| import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
|
|
@@ -56,6 +58,8 @@ | |
| import org.jenkinsci.plugins.workflow.steps.StepExecution; | ||
| import org.jenkinsci.plugins.workflow.support.concurrent.Timeout; | ||
| import org.jenkinsci.plugins.workflow.support.concurrent.WithThreadName; | ||
| import org.kohsuke.accmod.Restricted; | ||
| import org.kohsuke.accmod.restrictions.DoNotUse; | ||
| import org.kohsuke.stapler.DataBoundSetter; | ||
| import org.kohsuke.stapler.QueryParameter; | ||
|
|
||
|
|
@@ -67,7 +71,7 @@ public abstract class DurableTaskStep extends Step { | |
| private static final Logger LOGGER = Logger.getLogger(DurableTaskStep.class.getName()); | ||
|
|
||
| private boolean returnStdout; | ||
| private String encoding = DurableTaskStepDescriptor.defaultEncoding; | ||
| private String encoding; | ||
| private boolean returnStatus; | ||
|
|
||
| protected abstract DurableTask task(); | ||
|
|
@@ -85,7 +89,7 @@ public String getEncoding() { | |
| } | ||
|
|
||
| @DataBoundSetter public void setEncoding(String encoding) { | ||
| this.encoding = encoding; | ||
| this.encoding = Util.fixEmpty(encoding); | ||
| } | ||
|
|
||
| public boolean isReturnStatus() { | ||
|
|
@@ -102,17 +106,16 @@ public boolean isReturnStatus() { | |
|
|
||
| public abstract static class DurableTaskStepDescriptor extends StepDescriptor { | ||
|
|
||
| public static final String defaultEncoding = "UTF-8"; | ||
|
|
||
| @Restricted(DoNotUse.class) | ||
| public FormValidation doCheckEncoding(@QueryParameter boolean returnStdout, @QueryParameter String encoding) { | ||
| if (encoding.isEmpty()) { | ||
| return FormValidation.ok(); | ||
| } | ||
| try { | ||
| Charset.forName(encoding); | ||
| } catch (Exception x) { | ||
| return FormValidation.error(x, "Unrecognized encoding"); | ||
| } | ||
| if (!returnStdout && !encoding.equals(DurableTaskStepDescriptor.defaultEncoding)) { | ||
| return FormValidation.warning("encoding is ignored unless returnStdout is checked."); | ||
| } | ||
| return FormValidation.ok(); | ||
| } | ||
|
|
||
|
|
@@ -154,7 +157,6 @@ static final class Execution extends AbstractStepExecutionImpl implements Runnab | |
| private String node; | ||
| private String remote; | ||
| private boolean returnStdout; // serialized default is false | ||
| private String encoding; // serialized default is irrelevant | ||
| private boolean returnStatus; // serialized default is false | ||
|
|
||
| Execution(StepContext context, DurableTaskStep step) { | ||
|
|
@@ -164,7 +166,6 @@ static final class Execution extends AbstractStepExecutionImpl implements Runnab | |
|
|
||
| @Override public boolean start() throws Exception { | ||
| returnStdout = step.returnStdout; | ||
| encoding = step.encoding; | ||
| returnStatus = step.returnStatus; | ||
| StepContext context = getContext(); | ||
| ws = context.get(FilePath.class); | ||
|
|
@@ -173,6 +174,11 @@ static final class Execution extends AbstractStepExecutionImpl implements Runnab | |
| if (returnStdout) { | ||
| durableTask.captureOutput(); | ||
| } | ||
| if (step.encoding != null) { | ||
| durableTask.charset(Charset.forName(step.encoding)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Catch/rethrow exception with more debug details?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which debug details are you looking for here? |
||
| } else { | ||
| durableTask.defaultCharset(); | ||
| } | ||
| controller = durableTask.launch(context.get(EnvVars.class), ws, context.get(Launcher.class), context.get(TaskListener.class)); | ||
| this.remote = ws.getRemote(); | ||
| setupTimer(); | ||
|
|
@@ -327,7 +333,7 @@ private void check() { | |
| LOGGER.log(Level.FINE, "last-minute output in {0} on {1}", new Object[] {remote, node}); | ||
| } | ||
| if (returnStatus || exitCode == 0) { | ||
| getContext().onSuccess(returnStatus ? exitCode : returnStdout ? new String(controller.getOutput(workspace, launcher()), encoding) : null); | ||
| getContext().onSuccess(returnStatus ? exitCode : returnStdout ? new String(controller.getOutput(workspace, launcher()), StandardCharsets.UTF_8) : null); | ||
| } else { | ||
| if (returnStdout) { | ||
| listener.getLogger().write(controller.getOutput(workspace, launcher())); // diagnostic | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 10 additions & 1 deletion
11
...rces/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStep/help-encoding.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,12 @@ | ||
| <div> | ||
| Encoding of standard output, if it is being captured. | ||
| Encoding of process output. | ||
| In the case of <code>returnStdout</code>, applies to the return value of this step; | ||
| otherwise, or always for standard error, controls how text is copied to the build log. | ||
| If unspecified, uses the system default encoding of the node on which the step is run. | ||
| If there is any expectation that process output might include non-ASCII characters, | ||
| it is best to specify the encoding explicitly. | ||
| For example, if you have specific knowledge that a given process is going to be producing UTF-8 | ||
| yet will be running on a node with a different system encoding | ||
| (typically Windows, since every Linux distribution has defaulted to UTF-8 for a long time), | ||
| you can ensure correct output by specifying: <code>encoding: 'UTF-8'</code> | ||
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Note that this is a behavioral change—we are changing the default value of
encodingfromUTF-8to null (i.e., use the node’s system encoding). Also the encoding now applies to regular streamed output, whereas previously it only mattered forreturnStdout: true. (Which is the main point of this whole exercise: JENKINS-31096.)I tried to think of a way to keep the previous default but it was just going to be ugly. With the change of the overall build log to UTF-8, it would mean that you would get mojibake in case you were running, say, entirely on CP-1252 Windows (with or without agents) and just did something simple like
node { bat 'something producing Western European characters…' }which seems wrong.
This interpretation of
encodingis also consistent with thereadFileandwriteFilesteps, as well as the behavior of freestyle builds (which define the entire build’s log encoding by the node’s system encoding), and I think would be considered most intuitive going forward. Otherwise we would need a special value ('','system', …) indicating system default encoding, and then try to explain that in the snippet generator.Obviously if you have specific knowledge that a given process is going to be producing UTF-8 yet will be running on a node with a different system encoding (typically Windows, since every Linux distribution has defaulted to UTF-8 for a long time), you can make that explicit with
encoding: 'UTF-8'.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 should be called out really explicitly in the documentation / UI 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.
Yeah I can emphasize that.
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.
Seems reasonable. Whatever is done with encodings in Durable Task and this plugin, it is a risky change anyway. Since the idea is to NOT enforce the UTF encoding, the current approach looks preferable