In the source code documentation of the hub, there is marked, that an pre.. callback can modify the state:
self.runCallbacks('preTaskStateChange', info, 'state', state) self.runCallbacks('preTaskStateChange', info, 'completion_ts', now) # get the result from the info dict, so callbacks have a chance to modify it update = UpdateProcessor('task', clauses=['id = %(task_id)d'], values={'task_id': self.id}, data={'result': info['result'], 'state': state}, rawdata={'completion_time': 'NOW()'}) update.execute()
But the callback can't do it. Sample code:
@callback("preTaskStateChange") def receive_event(cbtype, *args, **kws) -> None if kws["attribute"] == "state": if (kws["new"] == "CLOSED") and (kws["info"]["method"] == "buildArch"): kws["old"] = kws["new"] kws["new"] = koji.TASK_STATES["FAILED"]
The task result is always closed instant of FAILED. In my case the add on need the possibility to let task fails. Raising an koji.CallbackError exception will let the task fail, but the log the the hub, the error: During handling of the above exception, another exception occurred
This is quirk of a particular callback hook. This comment buried in the code should not be construed as a general property of callbacks. The callback framework itself does not prevent callbacks from modifying mutable values that are passed to them. However, whether such modification actually results in a change is dependent on the code. In general, it will not.
The preTaskStateChange callback is called from several points, basically whenever a task entry is changed. Most them do not accept such a change from a callback. The only place that does is the one you found with this comment, i.e. in Task._close(). The update that follows only updates three fields -- result, state, and completion_time. Only the result value is read from the info dict that could have been modified by the callback.
preTaskStateChange
Task._close()
So, you could modify the result field in a callback, but only on a close action. Otherwise you cannot.
result
This particular quirk dates from 2011. It appears to have been added to allow an internal plugin to tweak the result of a task. If I were reviewing that change today, I would ask the author do use a different approach.
Metadata Update from @mikem: - Custom field Size adjusted to None
Changing the state in the middle of a close operation seems extremely questionable to me. What is your end goal? I suspect there is a better way
The goal is to copy the packages via scp after mock has successfully built and signed them. The reason I want to change the task status or throw an exception is that the scp operation can fail. In this case, the task should also fail. Copying the finished files via scp works, but I can't really catch the case where the copy fails.
At this point in the process the builder has completed the task and is just reporting the result. Trying to alter this is working against the system.
Since you seem to be intending to make these extra steps part of the task, it might make more sense to use a builder plugin to replace the build task with your own version that includes the extra steps.
That said. I would also question whether you really need the task to fail.
You might also consider using this hook to create a separate followup task that runs (or fails) independently. E.g kojihub.make_task('copy_task_rpms', [task_id]), with the new task handler defined in a builder plugin.
kojihub.make_task('copy_task_rpms', [task_id])
This issue has been migrated to Fedora Forge: https://forge.fedoraproject.org/koji/koji/issues/4194
Please continue any further discussion there.