-
Notifications
You must be signed in to change notification settings - Fork 118
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
Is it possible to identify a Rule (or Cmd) in a "textual" way? #772
Comments
As a continuation of the original question, I discovered
As a continuation to point 3 above, I'm realizing that there is some impedance mismatch between my mental model and how Shake has been built (and this could be related to the problems that I've described in #758):
|
Have you seen EchoStdout - that would be a way of stopping everything going to stdout. As to your question, Rule () are a set of rules, so they don't have any unique designation, and don't correspond to just one rule in many cases. Functions such as Usually parallelism operates at the Rule level, but within an Action, you can use the Each Rule is identified as a Key. So shakeTrace seems to do exactly what you want there. I agree that passing failure information or exceptions would be possible - but currently shakeTrace is not bracketing - if there is an exception it doesn't get called on the way out. To do so would require setting up stack frames, more stack usage, more time spent. You might want to read through https://hackage.haskell.org/package/shake-0.19.1/docs/Development-Shake-Rule.html, which gives a fairly low-level view on what a Shake rule is. I think the Shake model is mostly like you describe in gulp, but with the oddity that in many cases build steps are specified by files. But they equally don't have to be. There is a single rule type (at the addBuiltinRule level) which describes files, one for oracles, one for does-file-exist etc. Then there are user rules (with addUserRule) that can be matched on by a builtin rule to see how it should be customised. So "*.css" %> is a user rule, but as far as Shake is concerned, its not a thing that Shake deals with - builtin rules may decide to use them if they want (and the file builtin rule definitely does). Shake is concerned with keys, which might be "File foo.css", and that's the key that exists as a dependency in Shake. |
I'm already using that, but how do I capture the output of every individual command in a separate handle/pipe/file? Let me rephrase my question to be more actionable, rather than being theoretical ==> In a parallel build (multiple rules/action/commands being executed in parallel), one, or more, commands fail. How does one display that particular rule/action/command's stdout & stderr in a fashion that makes sense to the user and allows him/her to debug things sensibly?
This was just an alternative that came to my mind because Shake doesn't seem to allow capturing the stdout/stderr of a rule/action/command at a granular level. What do you think of changing |
Is the information you are looking for in the exception message? Is being in the exception message sufficient? (Regarding the key -> FilePath, there are a lot of variations on that, so happy to discuss those, but probably best to focus on one thread of solution, and then circle back if its not enough) |
for my current use-case the information in the exception may be sufficient. But I'm also thinking about my (ambitious) project - https://github.com/saurabhnanda/shake-ui. For a general terminal-UI for shake, I'm envisioning a viewing-pane for build errors which display the complete stdout+stderr from the specific rule that failed without interspersing it with other outputs. Sometimes an exception makes sense only with a log of all the actions/commands that led up that that exception. |
I guess if you did had the key -> FilePath, would you put them in a temp dir, and have shakeTraced scan that directory to find them? I guess what's the plan to go from that to the more general UI? |
Yes, provided that
|
@ndmitchell Here's how I'm thinking of the general UI:
type RuleKey = String
data CmdOption = FileStdoutKey (RuleKey -> FilePath)
| FileStdErr (RuleKey -> FilePath)
| ...
runBuild = do
let myShakeOptions = shakeOptions
{ shakeThreads = 0
, shakeCommandOptions = [FileStdoutKey (ruleLogFile "out"), FileStderrKey (ruleLogFile "err")]
, shakeTrace = ruleTrace
}
shakeArgs myShakeOptions $ do ...
ruleLogFile :: String -> RuleKey -> FilePath
ruleLogFile ext key = "build-outputs" </> ext </> key
ruleTrace :: RuleKey -> String -> Bool -> IO ()
ruleTrace key c isStart = appendFile (ruleLogFile "out") $ "[ " <> (if isStart then "START" else "STOP") <> " ] " <> c <> "\n" Concerns:
What do you think? Should I attempt a PR for this? |
@ndmitchell bump |
I'm still a little concerned about putting the rule key into the CmdOption in that way - it feels wrong (I'll try and elucidate more when I've thought about it a little more). The concrete ask is that you want to produce a UI such that you can see which commands were run by which actions, and for any command see the stdout/stderr? |
At a UI level the "grouping" of stdout/stderr will either be at a cmd-level, or at a rule-level. I need to determine that based on practical.usefulness. |
I'm running into a similar need to @saurabhnanda's, I think, tho I haven't done as much homework as he did. We moved from a less efficient system full of shell scripts and a large Jenkinsfile that made Jenkins' Blue Ocean look like: To a more efficient one based on shake, that looks like: The problem is those 20+ build steps output to stdout/stderr all at the same time, making debugging unapproachable for folks not intimately familiar with our shake code. My needs differ a bit from his in how I want to use the data, I guess, but the data itself would be the same: either a hierarchical grouping of stdout/stderr by Rule->cmd, or at flat one by Rule. |
Could that be solved by simply buffering the stdout/stderr? That's a much more localised change.
In most systems there tends to be at most one cmd per rule, which makes me think the rule level might be sufficient. Although grouping command information with commands is much easier to do, since its more localised. |
I'd definitely help, but I'd still look for ways to improve visibility over our pipeline.
We might be using shake in an unorthodox manner then I guess, and we're using it a lot (14k LoC of shake or shake-adjacent code so far). One example is we run aws cli calls for setting up auth context, crane for pushing and tagging images, helm for deploying, plus a few kubectl calls, all in a single rule, to do blue/green deploys in kubernetes. In this scenario, it'd still be difficult to understand what's going on if we only buffer per I guess my needs would be totally satisfied if we had a view with rules -> cmds -> logs of all types, in shake's report.html, but it might too ambitious as a first step towards solving this :S |
When a lot of commands are executed in parallel, the STDOUT of the entire process becomes an unintelligible mess. I"m trying to setup a central way of organizing the output of all the build steps.
I found shakeCommandOptions that could possibly help in this scenario (by passing
[FileStdout fstdout, FileStderr fstderr]
, but it's going to end-up using the same two files for ALL commands.It might be possible to have the conceptual equivalent of
shakeCommandOptions :: Rules () -> [CmdOption]
, so that one could change the files based on the rule being evaluated, but that leads to three questions:Rules() -> FilePath
(ref: this issue's title - how to identify a Rule in a "textual" way)?PS: What exactly is the "unit of external computation" that Shake uses internally? how does that one associate it with the a
Rule
, or Cmd, or output file (whatever is appropriate)?The text was updated successfully, but these errors were encountered: