When should post-script run? Currently, with a minimal example, post-script only runs if script succeeds. My interpretation of the documentation is that it should always run if script runs. Essentially, its acting as another exit-script from what I can tell. Is this the expected behaviour? If not, and post-script should always run if script runs, then job.sh should be modified to something like:
cylc__job__run_user_scripts() {
typeset func_name=
# Run the scripts prior to 'script'. If any fail, fail immediately.
for func_name in env_script user_env pre_script; do
cylc__job__run_inst_func "${func_name}" || return
done
# post-script should always run if script runs
typeset rc=0
typeset rc_post=0
cylc__job__run_inst_func script || rc=$?
cylc__job__run_inst_func post-script || rc_post=$?
# Return the return code from the 'script' if it was non-zero
if ((rc!=0)); then
return "$rc"
fi
# Otherwise, return the return code from the post-script, whether it is zero or not
return "$rc_post"
}
Noting that the above should work even if someone has done set +e.
The intention is that a job script functions as a single block of user-defined scripting embedded in some boilerplate code for signal trapping and messaging. If any error occurs (that is not explicitly handled in-script) the whole job script should abort.
It happens that the “single code block” may be constructed from several script items, in order to allow some basic inheritance of code fragments, and that each such item happens to be placed inside a function - but as I recall that’s just for internal tidiness reasons.
Oh, also, in Cylc 8 the user block is executed in a subshell so that users can’t accidentally break the job script by e.g. messing with the Python environment (which is needed when communicating status back to the scheduler).
So, no, the post-script is not supposed to run even if the main script failed. They are just - in principle at least - fragments of a single code block.
If you have a need for something more sophisticated than that, we can by all means discuss it. However, note that in-lined task scripting is supported by Cylc as a convenience for use in simple cases. Best practice is that anything non-trivial should really be put in an external script. Then:
you have complete control over what happens
you can write it in any language (e.g. Python)
it can be edited with appropriate language-specific tools
it can be tested separately, outside of the workflow
and Cylc just has to detect the global success/error status, of your script