Skip to content

Commit 4498228

Browse files
committed
feat: scope widget pipes by collection for Collections widget tabs
Adds segments_filtered_by_collection.pipe, the collection-scoped counterpart to segments_filtered.pipe: resolves a collectionSlug to every member project's insightsProjectId/segmentId/repositories via insights_projects_populated_ds.collectionsSlugs, instead of a single project's segment. Updates the 7 leaf pipes that widgets in the Contributors, Popularity, and Development tabs depend on to accept either project or collectionSlug, switching their scalar '= (SELECT ... FROM segments_filtered)' subquery to 'IN (SELECT ... FROM segments_filtered_by_collection)' when scoped by collection: activities_filtered, activities_filtered_retention, activity_heatmap_by_weekday_and_2hours_blocks, pull_requests_filtered, active_contributors (its own maintainers_count node), package_metrics, packages, search_volume. Every other widget pipe (leaderboards, dependency, retention, geo-distribution, median times, review efficiency, merge lead time) inherits collection scoping transparently through these 7, since they already read from activities_filtered/pull_requests_filtered rather than segments_filtered directly. segments_filtered itself and its ~25 other dependents (health scores, vulnerabilities, etc.) are left untouched. Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
1 parent e5a299d commit 4498228

9 files changed

Lines changed: 92 additions & 18 deletions

services/libs/tinybird/pipes/active_contributors.pipe

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ DESCRIPTION >
44
- **When `granularity` is NOT provided, returns total unique contributor count** for the specified filters.
55
- **When `granularity` is provided, returns time-series data** showing unique contributor counts for each time period.
66
- Parameters:
7-
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
7+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`. Required unless `collectionSlug` is given.
8+
- `collectionSlug`: Collection slug (e.g., 'cncf') - inherited from `segments_filtered_by_collection`. Required unless `project` is given.
89
- `repos`: Optional array of repository URLs for filtering (inherited from `segments_filtered`)
910
- `startDate`: Optional DateTime filter for activities after timestamp (e.g., '2024-01-01 00:00:00')
1011
- `endDate`: Optional DateTime filter for activities before timestamp (e.g., '2024-12-31 23:59:59')
@@ -55,7 +56,11 @@ SQL >
5556
SELECT uniqIf(memberId, memberId != '') AS maintainerCount
5657
FROM maintainers_roles_copy_ds
5758
WHERE
58-
insightsProjectId = (SELECT insightsProjectId FROM segments_filtered) AND role = 'maintainer'
59+
{% if defined(collectionSlug) %}
60+
insightsProjectId IN (SELECT insightsProjectId FROM segments_filtered_by_collection)
61+
{% else %} insightsProjectId = (SELECT insightsProjectId FROM segments_filtered)
62+
{% end %}
63+
AND role = 'maintainer'
5964
{% if defined(repos) %}
6065
AND repoUrl
6166
IN {{ Array(repos, 'String', description="Filter maintainer repo list", required=False) }}

services/libs/tinybird/pipes/activities_filtered.pipe

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ DESCRIPTION >
22
- `activities_filtered.pipe` is the core filtering infrastructure pipe for activity data across the entire analytics platform.
33
- This pipe serves as the foundation for most activity-related widgets, by providing a consistent, filtered view of contribution activities.
44
- It filters activities from `activityRelations_deduplicated_cleaned_ds` datasource based on project segment, time ranges, repositories, platforms, and activity types.
5-
- The pipe automatically scopes data to the current project using `segments_filtered` pipe for security and data isolation.
5+
- The pipe scopes data either to a single project (via `segments_filtered`) or to every project in a collection
6+
(via `segments_filtered_by_collection`), for security and data isolation. Exactly one of `project`/`collectionSlug`
7+
must be provided by the caller.
68
- Parameters:
7-
- `project`: Inherited from `segments_filtered`, project slug (e.g., 'k8s', 'tensorflow')
9+
- `project`: Project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`. Required unless `collectionSlug` is given.
10+
- `collectionSlug`: Collection slug (e.g., 'cncf') - inherited from `segments_filtered_by_collection`. Required unless `project` is given.
811
- `repos`: Optional array of repository URLs for filtering (e.g., ['https://github.com/kubernetes/kubernetes']). Inherited from `segments_filtered`.
912
- `startDate`: Optional DateTime filter for activities after timestamp (e.g., '2024-01-01 00:00:00')
1013
- `endDate`: Optional DateTime filter for activities before timestamp (e.g., '2024-12-31 23:59:59')
@@ -23,7 +26,10 @@ SQL >
2326
SELECT activityId as id, timestamp, type, platform, memberId, organizationId, segmentId
2427
FROM activityRelations_bucket_routing a
2528
where
26-
segmentId = (SELECT segmentId FROM segments_filtered)
29+
{% if defined(collectionSlug) %}
30+
segmentId IN (SELECT segmentId FROM segments_filtered_by_collection)
31+
{% else %} segmentId = (SELECT segmentId FROM segments_filtered)
32+
{% end %}
2733
{% if defined(startDate) %}
2834
AND a.timestamp
2935
> {{ DateTime(startDate, description="Filter activity timestamp after", required=False) }}

services/libs/tinybird/pipes/activities_filtered_retention.pipe

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ DESCRIPTION >
55
- This time extension ensures retention rate calculations have the necessary baseline data from the preceding period for comparing distinct member activity for the first given period.
66
- Primary use case: providing data foundation for member retention analysis and cohort studies.
77
- Parameters:
8-
- `project`: Inherited from `segments_filtered`, project slug (e.g., 'k8s', 'tensorflow')
8+
- `project`: Inherited from `segments_filtered`, project slug (e.g., 'k8s', 'tensorflow'). Required unless `collectionSlug` is given.
9+
- `collectionSlug`: Inherited from `segments_filtered_by_collection`, collection slug (e.g., 'cncf'). Required unless `project` is given.
910
- `repos`: Inherited from `segments_filtered`, array of repository URLs for filtering
1011
- `startDate`: Optional DateTime filter, automatically extended backwards by one granularity period
1112
- `endDate`: Optional DateTime filter for activities before timestamp (e.g., '2024-12-31 23:59:59')
@@ -24,7 +25,10 @@ SQL >
2425
SELECT activityId as id, timestamp, type, platform, memberId, organizationId, segmentId
2526
FROM activityRelations_bucket_routing a
2627
where
27-
segmentId = (SELECT segmentId FROM segments_filtered)
28+
{% if defined(collectionSlug) %}
29+
segmentId IN (SELECT segmentId FROM segments_filtered_by_collection)
30+
{% else %} segmentId = (SELECT segmentId FROM segments_filtered)
31+
{% end %}
2832
{% if defined(startDate) %}
2933
AND a.timestamp
3034
> {% if defined(granularity) and granularity == "daily" %}

services/libs/tinybird/pipes/activity_heatmap_by_weekday_and_2hours_blocks.pipe

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ DESCRIPTION >
55
- Returns a complete grid of all weekday/time combinations with zero counts for periods with no activity, ensuring consistent heatmap visualization.
66
- Primary use case: identifying contribution patterns outside traditional work hours for community health analysis.
77
- Parameters:
8-
- `project`: Inherited from `segments_filtered`, project slug (e.g., 'k8s', 'tensorflow')
8+
- `project`: Inherited from `segments_filtered`, project slug (e.g., 'k8s', 'tensorflow'). Required unless `collectionSlug` is given.
9+
- `collectionSlug`: Inherited from `segments_filtered_by_collection`, collection slug (e.g., 'cncf'). Required unless `project` is given.
910
- `repos`: Inherited from `segments_filtered`, array of repository URLs for filtering
1011
- `startDate`: Optional DateTime filter for activities after timestamp (e.g., '2024-01-01 00:00:00')
1112
- `endDate`: Optional DateTime filter for activities before timestamp (e.g., '2024-12-31 23:59:59')
@@ -18,7 +19,10 @@ SQL >
1819
select count(id) as activityCount, weekday, two_hours_block
1920
from contributions_with_local_time_ds a
2021
where
21-
segmentId = (SELECT segmentId FROM segments_filtered)
22+
{% if defined(collectionSlug) %}
23+
segmentId IN (SELECT segmentId FROM segments_filtered_by_collection)
24+
{% else %} segmentId = (SELECT segmentId FROM segments_filtered)
25+
{% end %}
2226
{% if defined(startDate) %}
2327
AND a.timestamp
2428
> {{ DateTime(startDate, description="Filter activity timestamp after", required=False) }}

services/libs/tinybird/pipes/package_metrics.pipe

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ DESCRIPTION >
66
- Uses custom time-series generation logic specifically designed for package download data patterns.
77
- Primary use case: powers package downloads and package dependency widgets.
88
- Parameters:
9-
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
9+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`. Required unless `collectionSlug` is given.
10+
- `collectionSlug`: Collection slug (e.g., 'cncf') - inherited from `segments_filtered_by_collection`. Required unless `project` is given.
1011
- `startDate`: Optional DateTime filter for package data after timestamp (e.g., '2024-01-01 00:00:00')
1112
- `endDate`: Optional DateTime filter for package data before timestamp (e.g., '2024-12-31 23:59:59')
1213
- `ecosystem`: Optional string to filter by package ecosystem (e.g., 'npm', 'pypi', 'maven')
@@ -23,7 +24,10 @@ SQL >
2324
SELECT *
2425
FROM packageDownloads p FINAL
2526
where
26-
insightsProjectId = (select insightsProjectId from segments_filtered)
27+
{% if defined(collectionSlug) %}
28+
insightsProjectId IN (select insightsProjectId from segments_filtered_by_collection)
29+
{% else %} insightsProjectId = (select insightsProjectId from segments_filtered)
30+
{% end %}
2731
{% if defined(startDate) %}
2832
AND p.date > toDate(
2933
{{ DateTime(startDate, description="Filter package downloads after", required=False) }}

services/libs/tinybird/pipes/packages.pipe

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ DESCRIPTION >
55
- Uses `segments_filtered` for automatic project scoping and optional repository filtering.
66
- Primary use case: powers package selection dropdown in the package downloads widget.
77
- Parameters:
8-
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
8+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`. Required unless `collectionSlug` is given.
9+
- `collectionSlug`: Collection slug (e.g., 'cncf') - inherited from `segments_filtered_by_collection`. Required unless `project` is given.
910
- `search`: Optional string for searching package names or ecosystems (case-insensitive with wildcards)
1011
- `repos`: Optional array of repository URLs to filter packages by specific repositories (e.g., ['https://github.com/kubernetes/kubernetes'])
1112
- Response: `repo`, `name`, `ecosystem` (distinct packages matching the filters)
@@ -16,7 +17,10 @@ SQL >
1617
SELECT distinct p.repo, p.name, p.ecosystem
1718
FROM packageDownloads p
1819
where
19-
p.insightsProjectId = (select insightsProjectId from segments_filtered)
20+
{% if defined(collectionSlug) %}
21+
p.insightsProjectId IN (select insightsProjectId from segments_filtered_by_collection)
22+
{% else %} p.insightsProjectId = (select insightsProjectId from segments_filtered)
23+
{% end %}
2024
{% if defined(search) %}
2125
AND (
2226
p.name

services/libs/tinybird/pipes/pull_requests_filtered.pipe

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@ DESCRIPTION >
22
- `pull_requests_filtered.pipe` is the core filtering infrastructure for pull request analytics across the platform.
33
- Provides consistent, reusable PR filtering logic for all pull request-related widgets and analytics.
44
- Uses `pull_requests_analyzed` datasource which contains pre-calculated PR metrics and timing data.
5-
- Automatically scopes data to the current project using `segments_filtered` pipe for security and data isolation.
5+
- Scopes data either to a single project (via `segments_filtered`) or to every project in a collection (via
6+
`segments_filtered_by_collection`), for security and data isolation. Exactly one of `project`/`collectionSlug`
7+
must be provided by the caller.
68
- Supports repository-level filtering for targeted PR analysis within projects.
79
- Primary use case: serving as the foundation for all PR analytics pipes including lead times, review metrics, and velocity analysis.
810
- Parameters:
9-
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
11+
- `project`: Project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`. Required unless `collectionSlug` is given.
12+
- `collectionSlug`: Collection slug (e.g., 'cncf') - inherited from `segments_filtered_by_collection`. Required unless `project` is given.
1013
- `repos`: Optional array of repository URLs for filtering PRs by specific repositories (e.g., ['https://github.com/kubernetes/kubernetes'])
1114
- Response: All fields from `pull_requests_analyzed` including PR metadata, timing metrics, and calculated fields
1215

1316
NODE pull_requests_filtered_0
1417
SQL >
18+
%
1519
SELECT *
1620
FROM pull_requests_analyzed pra
1721
WHERE
18-
pra.segmentId = (SELECT segmentId FROM segments_filtered)
22+
{% if defined(collectionSlug) %}
23+
pra.segmentId IN (SELECT segmentId FROM segments_filtered_by_collection)
24+
{% else %} pra.segmentId = (SELECT segmentId FROM segments_filtered)
25+
{% end %}
1926
AND pra.channel IN (SELECT channel FROM repos_to_channels)

services/libs/tinybird/pipes/search_volume.pipe

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ DESCRIPTION >
55
- Formats timestamps for consistent date representation in visualizations.
66
- Primary use case: displaying search trend analytics and project popularity metrics in dashboard widgets.
77
- Parameters:
8-
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`
8+
- `project`: Required string for project slug (e.g., 'k8s', 'tensorflow') - inherited from `segments_filtered`. Required unless `collectionSlug` is given.
9+
- `collectionSlug`: Collection slug (e.g., 'cncf') - inherited from `segments_filtered_by_collection`. Required unless `project` is given.
910
- `startDate`: Optional DateTime filter for search volume data after timestamp (e.g., '2024-01-01 00:00:00')
1011
- `endDate`: Optional DateTime filter for search volume data before timestamp (e.g., '2024-12-31 23:59:59')
1112
- Response: `insightsProjectId`, `project`, `dataTimestamp` (formatted as YYYY-MM-DD), `volume`, `updatedAt`
@@ -21,7 +22,11 @@ SQL >
2122
updatedAt
2223
FROM searchVolume FINAL
2324
WHERE
24-
insightsProjectId = toUUID((select insightsProjectId from segments_filtered))
25+
{% if defined(collectionSlug) %}
26+
insightsProjectId
27+
IN (select toUUID(insightsProjectId) from segments_filtered_by_collection)
28+
{% else %} insightsProjectId = toUUID((select insightsProjectId from segments_filtered))
29+
{% end %}
2530
{% if defined(startDate) %}
2631
AND searchVolume.dataTimestamp >= parseDateTimeBestEffort(
2732
{{
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
DESCRIPTION >
2+
- `segments_filtered_by_collection.pipe` is the collection-scoped counterpart to `segments_filtered.pipe`:
3+
it establishes project scope for the widget pipes that back the Collection detail page's Contributors,
4+
Popularity, and Development tabs, resolving a collection to every one of its member projects instead of
5+
a single project.
6+
- **Requires `collectionSlug` parameter** - without it, returns no results (WHERE clause becomes AND false).
7+
- Returns one row per project in the collection (not a single aggregate row) - `insights_projects_populated_ds.collectionsSlugs`
8+
already lists every collection each project belongs to (see `insightsProjects_filtered.pipe` and
9+
`collection_insights_aggregate.pipe` for the same `has(collectionsSlugs, ...)` filter pattern), so this
10+
pipe resolves collection membership directly rather than requiring the caller to first look up a project
11+
id list.
12+
- Downstream pipes that today do `segmentId = (SELECT segmentId FROM segments_filtered)` (a single-value
13+
scalar subquery) must switch to `segmentId IN (SELECT segmentId FROM segments_filtered_by_collection)`
14+
when scoping by collection instead of by project, since this pipe can return multiple rows.
15+
- Ensures only enabled projects are accessible.
16+
- Parameters:
17+
- `collectionSlug`: Required string for collection slug (e.g., 'cncf', 'agentic-ai-foundation')
18+
- Response: `insightsProjectId`, `segmentId`, `repositories` (array of the project's own repositories) - one row per project in the collection
19+
20+
TAGS "Infrastructure", "Core", "Project scoping", "Security", "Collection"
21+
22+
NODE segments_filtered_by_collection_0
23+
SQL >
24+
%
25+
SELECT id as insightsProjectId, segmentId, repositories
26+
FROM insights_projects_populated_ds
27+
WHERE
28+
enabled = 1
29+
{% if defined(collectionSlug) %}
30+
AND has(
31+
collectionsSlugs,
32+
{{ String(collectionSlug, description="Filter by collection slug", required=True) }}
33+
)
34+
{% else %} AND false
35+
{% end %}

0 commit comments

Comments
 (0)