File: qa.rst

package info (click to toggle)
debusine 0.14.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,056 kB
  • sloc: python: 193,072; sh: 848; javascript: 335; makefile: 116
file content (273 lines) | stat: -rw-r--r-- 12,348 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
.. workflow:: qa

Workflow ``qa``
===============

* ``task_data``:

  * ``prefix`` (string, optional): prefix this string to the item names
    provided in the internal collection
  * ``reference_prefix`` (string, optional unless
    ``enable_regression_tracking`` is set): prefix for the item names
    provided in the internal collection in the corresponding workflow run
    for reference tests

  * ``source_artifact`` (:ref:`lookup-single`, required): the
    :artifact:`debian:source-package` or :artifact:`debian:upload` artifact
    representing the source package to test
  * ``binary_artifacts`` (:ref:`lookup-multiple`, required): the
    :artifact:`debian:binary-package` or :artifact:`debian:upload`
    artifacts representing the binary packages to test

  * ``package_build_logs`` (:ref:`lookup-multiple`, optional): the
    :artifact:`debian:package-build-log` artifacts representing the build logs.
    Required if ``enable_blhc`` is True

  * ``qa_suite`` (:ref:`lookup-single`, optional unless
    ``enable_regression_tracking``,
    ``enable_reverse_dependencies_autopkgtest``, ``update_qa_results``,
    or ``enable_debdiff`` is True): the :collection:`debian:suite`
    collection that reference tests are being run against to detect
    regressions, to search for reverse-dependencies, and to debdiff
    against

  * ``reference_qa_results`` (:ref:`lookup-single`, optional unless
    ``enable_regression_tracking`` or ``update_qa_results`` is True): the
    :collection:`debian:qa-results` collection that contains the reference
    results of QA tasks to use to detect regressions
  * ``enable_regression_tracking`` (boolean, defaults to False): configure
    the workflow to detect and display regressions in QA results
  * ``update_qa_results`` (boolean, defaults to False): when set to True,
    the workflow runs QA tasks and updates the collection passed in
    ``reference_qa_results`` with the results.

  * ``vendor`` (string, required): the distribution vendor on which to run
    tests
  * ``codename`` (string, required): the distribution codename on which to
    run tests
  * ``extra_repositories`` (optional): see :task:`PackageBuild`
  * ``architectures`` (list of strings, optional): if set, only run on any
    of these architecture names

  * ``architectures_allowlist`` (list of strings, optional, either concrete
    architecture names or ``all``): if set, only run on any of these
    architecture names; while ``architectures`` is intended to be supplied
    by users or passed down from a higher-level workflow, this field is
    intended to be provided via :ref:`task-configuration`
  * ``architectures_denylist`` (list of strings, optional, either concrete
    architecture names or ``all``): if set, do not run on any of these
    architecture names; this field is intended to be provided via
    :ref:`task-configuration`
  * ``arch_all_build_architecture`` (string, defaults to ``amd64``): concrete
    architecture on which to run tasks for ``Architecture: all`` packages

  * ``enable_check_installability`` (boolean, defaults to True): whether to
    include installability-checking tasks
  * ``check_installability_suite`` (:ref:`lookup-single`, required if
    ``enable_check_installability`` is True): the
    :collection:`debian:suite` collection to check installability against;
    once we have a good way to look up the primary suite for a vendor and
    codename, this could default to doing so

  * ``enable_autopkgtest`` (boolean, defaults to True): whether to include
    autopkgtest tasks
  * ``autopkgtest_backend`` (string, optional): see :task:`Autopkgtest`

  * ``enable_reverse_dependencies_autopkgtest`` (boolean, defaults to
    False): whether to include autopkgtest tasks for reverse-dependencies

  * ``enable_lintian`` (boolean, defaults to True): whether to include
    lintian tasks
  * ``lintian_backend`` (string, optional): see :task:`Lintian`
  * ``lintian_fail_on_severity`` (string, optional): see :task:`Lintian`

  * ``enable_piuparts`` (boolean, defaults to True): whether to include
    piuparts tasks
  * ``piuparts_backend`` (string, optional): see :task:`Piuparts`
  * ``piuparts_environment`` (string, optional): the environment to run
    piuparts in

  * ``enable_debdiff`` (boolean, defaults to False): whether to include
    debdiff tasks for source and binary packages. Compares the supplied source
    package and the binary packages against the packages available in the
    distribution identified by ``qa_suite``.

  * ``enable_blhc`` (boolean, defaults to False): whether to include ``blhc``
    tasks for the build logs

  * ``fail_on`` (string, optional): indicate the conditions to trigger a
    failure of the whole workflow.  Allowed values are ``failure``,
    ``regression``, ``never``.  With ``failure``, the workflow is marked as
    failed if one of the QA task fails.  With ``regression``, the workflow
    fails only if one of the QA result is a regression compared to the
    former result.  With ``never``, the workflow always succeeds.  The
    default value is ``regression`` if ``enable_regression_tracking`` is
    True, otherwise it is ``failure``.

The workflow computes dynamic metadata as:

.. dynamic_data::
  :method: debusine.server.workflows.qa::QAWorkflow.build_dynamic_data

Any of the lookups in ``source_artifact`` or ``binary_artifacts`` may result
in :bare-data:`promises <debusine:promise>`, and in that case the workflow
adds corresponding dependencies.  Binary promises must include an
``architecture`` field in their data.

The effective set of architectures is ``{architectures}`` (defaulting to all
architectures supported by this Debusine instance and the
``{vendor}:{codename}`` suite, plus ``all``), intersecting
``{architectures_allowlist}`` if set, and subtracting
``{architectures_denylist}`` if set.

The workflow creates sub-workflows and tasks as follows, with substitutions
based on its own task data:

* if ``enable_check_installability`` is set, a single
  :task:`CheckInstallability`, with task data:

  * ``suite``: ``{check_installability_suite}``
  * ``binary_artifacts``: the subset of the lookup in this workflow's
    ``binary_artifacts`` for each available architecture

* if ``enable_autopkgtest`` is set, an :workflow:`autopkgtest` sub-workflow,
  with task data:

  * ``source_artifact``: ``{source_artifact}``
  * ``binary_artifacts``: the subset of the lookup in this workflow's
    ``binary_artifacts`` for each of ``all`` and the concrete architecture
    in question that exist
  * ``vendor``: ``{vendor}``
  * ``codename``: ``{codename}``
  * ``backend``: ``{autopkgtest_backend}``
  * ``architectures``: the effective set of architectures
  * ``arch_all_build_architecture``: ``{arch_all_build_architecture}``

* if ``enable_reverse_dependencies_autopkgtest`` is set, a
  :workflow:`reverse_dependencies_autopkgtest` sub-workflow, with task data:

  * ``source_artifact``: ``{source_artifact}``
  * ``binary_artifacts``: the subset of the lookup in this workflow's
    ``binary_artifacts`` for each of ``all`` and the concrete architecture
    in question that exist
  * ``qa_suite``: ``{qa_suite}``
  * ``vendor``: ``{vendor}``
  * ``codename``: ``{codename}``
  * ``backend``: ``{autopkgtest_backend}``
  * ``architectures``: the effective set of architectures
  * ``arch_all_build_architecture``: ``{arch_all_build_architecture}``

* if ``enable_lintian`` is set, a :workflow:`lintian` sub-workflow, with
  task data:

  * ``source_artifact``: ``{source_artifact}``
  * ``binary_artifacts``: the subset of the lookup in this workflow's
    ``binary_artifacts`` for each of ``all`` and the concrete architecture
    in question that exist
  * ``vendor``: ``{vendor}``
  * ``codename``: ``{codename}``
  * ``backend``: ``{lintian_backend}``
  * ``architectures``: the effective set of architectures
  * ``arch_all_build_architecture``: ``{arch_all_build_architecture}``
  * ``fail_on_severity``: ``{lintian_fail_on_severity}``

* if ``enable_piuparts`` is set, a :workflow:`piuparts` sub-workflow, with
  task data:

  * ``binary_artifacts``: the subset of the lookup in this workflow's
    ``binary_artifacts`` for each of ``all`` and the concrete architecture
    in question that exist
  * ``vendor``: ``{vendor}``
  * ``codename``: ``{codename}``
  * ``backend``: ``{piuparts_backend}``
  * ``architectures``: the effective set of architectures
  * ``arch_all_build_architecture``: ``{arch_all_build_architecture}``

.. todo::

    Not implemented: ``enable_check_installability`` and
    ``check_installability_suite``.

Behavior with ``update_qa_results`` set to True
-----------------------------------------------

When ``update_qa_results`` is set to True, the goal of the workflow
is modified: its only purpose is to provide reference results to
be stored in a :collection:`debian:qa-results` collection. Task failures are
never fatal for the parent workflow or for dependent tasks.

During orchestration, the workflow compares the data available in the
:collection:`debian:qa-results` collection together with information about
the submitted ``source_artifact`` and ``binary_artifacts``.

When a missing or outdated QA result is detected, it schedules the
appropriate QA task, and it creates a corresponding promise in the internal
collection (the name of the promise is the prefix followed by the expected
name of the collection entry).  The QA task has the following event
reactions:

* ``on_assignment``: an action to :ref:`skip the work request
  <action-skip-if-lookup-result-changed>` if the latest relevant item in the
  :collection:`debian:qa-results` collection has changed since the work
  request has created; this avoids wasting resources if multiple parallel
  workflows trigger an update of the same QA results
* ``on_success``: an action to add the result to the
  :collection:`debian:qa-results` collection
* ``on_failure``: same as ``on_success``

Note that when ``enable_reverse_dependencies_autopkgtest`` is set to True,
it must also update the autopkgtest results of the reverse dependencies
and thus compute the same list of packages as the
``reverse_dependencies_autopkgtest`` workflow (using the same
``qa_suite`` collection).

Behavior with ``enable_regression_tracking`` set to True
--------------------------------------------------------

When ``enable_regression_tracking`` is set to True, the orchestrator
of the ``qa`` workflow schedules :ref:`workflow callbacks
<workflow-callback>` that will perform the regression analysis. In order
to wait for the availability of the QA result(s), those callbacks have
dependencies against:

* the promises associated to the QA result(s) that are required from the
  additional ``qa`` workflow building reference results
* the promises associated to the QA result(s) that are required from the
  sub-workflows

The ``workflow_data`` field for those workflow callbacks have:

* ``visible`` set to False so that they do not show up in the workflow
  hierarchy (new feature to implement)
* ``step`` set to ``regression-analysis``

As part of the callback, the analysis is performed and the result
of the analysis is stored in the ``output_data`` field of the workflow.

.. note::

   We use simple workflow callbacks instead of full-fledged worker
   tasks or server tasks because we assume that regression analysis
   can be completed just by comparing the artifact metadata and/or
   the collection item. Workflow callbacks are already dealt through
   celery tasks so they are relatively cheap. Note however that the
   large number of callbacks requires use of careful locking to
   serialize the operations between concurrent runs trying to update
   the same workflow.

Handling of ``fail_on``
-----------------------

With ``fail_on: never`` or ``fail_on: regression``, all the sub-workflows
are run with ``workflow_data.allow_failure: true``.

With ``fail_on: regression``, a final orchestrator callback is scheduled:

* it depends on all the ``regression-analysis`` callbacks
* ``workflow_data.visible`` is set to True
* ``workflow_data.step`` is ``final-regression-analysis``
* ``workflow_data.display_name`` is ``Regression analysis``

The callback reviews the data in ``output_data.regression_analysis``
and sets its own result to FAILURE in case of regression, or SUCCESS
otherwise.