• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kobotoolbox / kpi / 30332723373
82%
master: 76%

Build:
Build:
LAST BUILD BRANCH: dev-2566-reduce-refresh-frequency-and-harden-reliability-of-the-billingusage
DEFAULT BRANCH: master
Ran 28 Jul 2026 05:53AM UTC
Jobs 10
Files 894
Run time 2min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

28 Jul 2026 05:47AM UTC coverage: 81.857% (-0.07%) from 81.931%
30332723373

push

github

web-flow
feat(assetVersion): add version_number to `/api/v2/assets/<uid>/versions/` DEV-1825 (#7300)

### 📣 Summary
This PR adds a `version_number` field to the asset versions API,
returning "12" for deployed versions and "11.4" for undeployed versions
(numbered relative to the deployment that precedes them), computed
server-side so the numbering stays correct regardless of pagination.

### 📖 Description
#### Why this needed to be done in the backend
The Form History UI (Project → Form tab) needs to label each version
like v12, v11.4, etc. - deployed versions get a whole "major" number,
and undeployed (draft) versions get a "minor" number counting up since
the last deployment.

The frontend currently derives this from array index, which only works
because the full list is loaded at once. We're moving this list to
paginated infinite scroll, and a version's correct number depends on the
entire history of the asset before it - not just the versions on the
current page. The frontend has no way to know, from a single page of
results, how many deployments happened earlier in history, so it can't
reliably compute this itself once pagination is introduced.

#### What changed
Added a `version_number` field to the versions serializer. For each
request, we fetch the asset's full version history as a lightweight (id,
deployed) list in a single ordered query, then walk it once in Python to
build a map of version id → label: deployed versions increment the major
number and reset the minor, undeployed versions increment the minor. The
serializer looks up each row's label from that map, so both the
paginated list endpoint and retrieve return identical,
pagination-independent numbers with no per-row queries.

#### Why computed on the fly instead of stored on the model
I considered storing these numbers as columns on AssetVersion, populated
at save time like the existing _content_hash field, but ruled it out
because the table has millions of rows and would need a long, risky
ba... (continued)

9534 of 12864 branches covered (74.11%)

28 of 29 new or added lines in 3 files covered. (96.55%)

4060 existing lines in 132 files now uncovered.

30866 of 37707 relevant lines covered (81.86%)

5.51 hits per line

Uncovered Changes

Lines Coverage ∆ File
1
78.79
-0.52% kpi/schema_extensions/v2/versions/extensions.py

Coverage Regressions

Lines Coverage ∆ File
312
0.0
-91.23% kobo/apps/openrosa/apps/viewer/pandas_mongo_bridge.py
209
19.15
-51.99% kobo/apps/openrosa/libs/utils/export_tools.py
206
0.0
-86.19% kobo/apps/openrosa/libs/utils/briefcase_client.py
196
55.43
-32.72% kobo/apps/openrosa/libs/utils/logger_tools.py
196
26.4
-55.06% kpi/serializers/v2/asset_permission_assignment.py
188
64.54
-29.24% kpi/serializers/v2/asset.py
139
37.13
-45.28% kpi/views/v2/data.py
97
61.89
-26.22% kpi/views/v2/asset.py
87
0.0
-87.88% kobo/apps/openrosa/libs/utils/backup_tools.py
87
29.29
-62.14% kpi/serializers/v2/asset_file.py
81
0.0
-93.1% kobo/apps/stripe/serializers.py
75
0.0
-41.9% kobo/apps/stripe/views.py
73
26.89
-61.34% kpi/serializers/v2/paired_data.py
66
33.33
-59.46% kobo/apps/openrosa/apps/viewer/views.py
66
31.09
-55.46% kpi/serializers/v2/export_task.py
64
27.2
-51.2% kobo/apps/stripe/utils/subscription_limits.py
64
34.55
-58.18% kpi/views/v2/paired_data.py
63
0.0
-51.64% kobo/apps/stripe/models.py
58
0.0
-90.63% kobo/apps/openrosa/libs/data/query.py
56
27.68
-50.0% kpi/utils/models.py
53
42.86
-50.48% kpi/views/v2/environment.py
50
0.0
-47.17% kobo/apps/openrosa/apps/logger/tasks.py
49
51.59
-38.89% kobo/apps/openrosa/apps/logger/signals.py
49
23.85
-37.69% kobo/apps/openrosa/apps/logger/utils/instance.py
49
28.57
-43.75% kobo/apps/openrosa/apps/logger/views.py
42
46.47
-15.61% kobo/apps/openrosa/apps/viewer/models/data_dictionary.py
42
49.47
-44.21% kpi/views/v2/asset_permission_assignment.py
41
40.69
-6.75% kpi/deployment_backends/openrosa_backend.py
41
43.7
-30.37% kpi/views/v2/asset_snapshot.py
40
0.0
-40.82% kobo/apps/openrosa/apps/viewer/xls_writer.py
40
23.29
-54.79% kobo/apps/openrosa/libs/utils/image_tools.py
39
23.08
-30.0% kobo/apps/openrosa/apps/viewer/tasks.py
36
24.49
-73.47% kobo/apps/openrosa/apps/logger/import_tools.py
36
20.21
-38.3% kobo/apps/stripe/utils/billing_dates.py
33
49.51
-32.04% kobo/apps/openrosa/apps/viewer/models/export.py
32
58.33
-13.33% kobo/apps/openrosa/apps/viewer/models/parsed_instance.py
32
50.75
-47.76% kpi/views/v2/asset_export_settings.py
31
36.52
-17.42% kpi/serializers/current_user.py
30
58.33
-25.0% kobo/apps/openrosa/apps/logger/models/attachment.py
28
30.14
-19.18% kobo/apps/openrosa/libs/utils/viewer_tools.py
27
62.73
-12.27% kpi/permissions.py
27
83.0
-13.5% kpi/utils/xml.py
26
27.5
-65.0% kpi/serializers/v2/attachment_delete.py
25
31.11
-55.56% kpi/serializers/v2/data.py
25
74.76
-24.27% kpi/utils/usage_calculator.py
24
33.33
-66.67% kobo/apps/openrosa/libs/utils/decorators.py
24
59.32
-40.68% kpi/views/v2/export_task.py
23
41.86
-53.49% kpi/serializers/v2/deployment.py
23
71.43
-27.38% kpi/serializers/v2/service_usage.py
22
50.98
-43.14% kpi/serializers/v2/asset_snapshot.py
22
55.56
-40.74% kpi/serializers/v2/permission.py
21
38.33
-35.0% kpi/serializers/v2/asset_export_settings.py
20
29.67
-21.98% kobo/apps/openrosa/libs/utils/user_auth.py
19
0.0
-65.52% kobo/apps/stripe/admin.py
19
33.33
-63.33% kpi/utils/paired_data.py
19
51.06
-40.43% kpi/views/v2/import_task.py
19
49.25
-28.36% kpi/views/v2/user.py
18
48.65
-48.65% kpi/views/v2/attachment_audio_duration.py
17
16.22
-45.95% kobo/apps/openrosa/apps/logger/utils/database_query.py
17
44.12
-50.0% kpi/utils/rename_xls_sheet.py
16
31.82
-36.36% kobo/apps/stripe/utils/limit_enforcement.py
16
28.0
-64.0% kpi/utils/audio_duration.py
16
62.9
-25.81% kpi/views/v2/attachment.py
15
31.71
-36.59% kobo/apps/openrosa/apps/logger/xform_fs.py
15
81.64
-5.86% kobo/apps/openrosa/apps/logger/xform_instance_parser.py
15
0.0
-20.55% kobo/apps/stripe/signals.py
14
47.62
-8.33% kobo/apps/openrosa/apps/main/models/meta_data.py
14
44.0
-56.0% kobo/apps/openrosa/libs/utils/model_tools.py
13
40.0
-43.33% kpi/serializers/v2/asset_counts.py
13
79.05
-12.38% kpi/utils/object_permission.py
13
30.43
-56.52% kpi/utils/private_storage.py
12
44.9
-24.49% kobo/apps/openrosa/apps/logger/utils/counters.py
12
35.0
-60.0% kobo/apps/stripe/utils/import_management.py
11
54.84
-35.48% kobo/apps/openrosa/libs/authentication.py
11
75.93
-20.37% kpi/serializers/v2/user.py
11
50.0
-16.18% kpi/utils/hash.py
10
77.44
-5.13% kobo/apps/openrosa/apps/logger/models/instance.py
10
63.33
-33.33% kpi/views/v2/asset_version.py
9
77.49
-4.71% kobo/apps/openrosa/apps/logger/models/xform.py
9
0.0
-29.03% kobo/apps/stripe/utils/manual_subscription.py
9
77.07
-4.39% kpi/utils/mongo_helper.py
9
79.17
-18.75% kpi/views/v2/asset_file.py
8
0.0
-100.0% kobo/apps/stripe/urls.py
8
85.71
-11.43% kpi/utils/cache.py
7
0.0
-100.0% kobo/apps/stripe/apps.py
7
65.19
-1.73% kpi/deployment_backends/base_backend.py
7
52.94
-41.18% kpi/serializers/v2/reports.py
7
61.9
-16.67% kpi/utils/urls.py
7
74.07
-25.93% kpi/views/v2/attachment_delete.py
6
0.0
-100.0% kobo/apps/stripe/exceptions.py
6
0.0
-37.5% kobo/apps/stripe/utils/view_utils.py
5
84.75
-8.47% kobo/apps/openrosa/apps/logger/exceptions.py
5
72.22
-27.78% kobo/apps/openrosa/apps/logger/models/daily_xform_submission_counter.py
5
75.0
-25.0% kobo/apps/openrosa/apps/logger/models/monthly_xform_submission_counter.py
5
0.0
-38.46% kobo/apps/openrosa/apps/main/context_processors.py
5
62.07
-5.75% kpi/tasks.py
5
76.0
-20.0% kpi/views/v2/asset_submission_counts.py
5
61.54
-38.46% kpi/views/v2/logout.py
5
73.91
-21.74% kpi/views/v2/user_asset_subscription.py
4
53.56
-0.92% kobo/apps/audit_log/models.py
4
45.45
-36.36% kobo/apps/openrosa/koboform/__init__.py
4
76.19
-19.05% kpi/serializers/v2/user_asset_subscription.py
4
83.33
-16.67% kpi/views/v2/tag.py
3
69.29
-2.14% kobo/apps/audit_log/signals.py
3
95.76
-2.54% kobo/apps/openrosa/apps/api/viewsets/xform_submission_api.py
3
80.0
-20.0% kobo/apps/openrosa/apps/viewer/signals.py
3
31.43
-2.86% kobo/apps/organizations/admin/organization.py
3
61.21
-1.82% kobo/apps/organizations/models.py
3
60.53
-7.89% kobo/apps/organizations/utils.py
3
80.0
-20.0% kpi/serializers/v2/attachment_audio_duration.py
3
78.57
-10.71% kpi/utils/submission.py
3
75.0
-25.0% kpi/views/v2/open_rosa.py
3
84.21
-15.79% kpi/views/v2/permission.py
2
83.33
-6.67% kobo/urls.py
2
91.33
-0.35% kpi/models/asset.py
2
81.82
-18.18% kpi/serializers/v2/tag.py
2
91.43
-5.71% kpi/utils/project_views.py
2
85.92
-2.82% kpi/utils/sluggify.py
2
88.24
-11.76% kpi/views/v2/service_usage.py
1
78.57
-1.19% kobo/apps/audit_log/base_views.py
1
0.0
-100.0% kobo/apps/openrosa/apps/logger/constants.py
1
91.3
-4.35% kobo/apps/openrosa/libs/permissions.py
1
94.12
-1.18% kobo/apps/openrosa/libs/renderers/renderers.py
1
68.75
-6.25% kobo/apps/openrosa/libs/utils/string.py
1
67.95
-1.28% kpi/authentication.py
1
95.65
0.0% kpi/serializers/v2/asset_version.py
1
50.0
-50.0% kpi/utils/export_task.py
1
75.0
-25.0% kpi/utils/gravatar_url.py
1
94.12
-5.88% kpi/utils/strings.py
1
84.62
-7.69% kpi/versioning.py
1
55.56
-2.22% kpi/views/current_user.py
1
93.33
-6.67% kpi/views/v2/asset_usage.py
Jobs
ID Job ID Ran Files Coverage
1 30332723373.1 28 Jul 2026 05:53AM UTC 890
52.72
2 30332723373.2 28 Jul 2026 05:53AM UTC 890
44.12
3 30332723373.3 28 Jul 2026 05:53AM UTC 892
45.48
4 30332723373.4 28 Jul 2026 05:54AM UTC 890
49.35
5 30332723373.5 28 Jul 2026 05:54AM UTC 892
50.68
6 30332723373.6 28 Jul 2026 05:54AM UTC 892
53.97
7 30332723373.7 28 Jul 2026 05:56AM UTC 890
58.84
8 30332723373.8 28 Jul 2026 05:56AM UTC 892
67.12
9 30332723373.9 28 Jul 2026 05:57AM UTC 892
59.99
10 30332723373.10 28 Jul 2026 05:57AM UTC 894
69.49
Source Files on build 30332723373
  • Tree
  • List 894
  • Changed 10
  • Source Changed 0
  • Coverage Changed 10
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • 48db28bb on github
  • Prev Build on main (#30307597177)
  • Next Build on main (#30332765934)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc