Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

176 lines
6.0 KiB
Python

#!/usr/bin/env python3
"""Seed link-analytics test data for the `link-analytics` UI shard.
The /metrics/links page derives its domain cards entirely from
``ResearchResource`` rows (see ``get_link_analytics`` in
``web/routes/metrics_routes.py``). A freshly-initialized CI database
(``scripts/ci/init_test_database.py``) has none, so the page renders the
"No domain data available" placeholder and ``test_link_analytics_full.js``
times out waiting for ``#domain-list .ldr-domain-item-expanded``.
This script inserts a small, deterministic fixture (2 researches, 7 resources
across 4 domains) for the ``test_admin`` user so the page renders real domain
cards with frequency/diversity badges and a populated "Recent Researches
(N total)" header.
It is wired into ``.github/workflows/docker-tests.yml`` **only** for the
``link-analytics`` shard. Other shards (and the responsive / empty-state
screenshot suites that assert the placeholder on /metrics/links) keep seeing
an empty database.
Usage:
python scripts/ci/seed_link_analytics.py
Environment variables (must match init_test_database.py / the server):
LDR_DATA_DIR: Directory for database files.
LDR_TEST_MODE / LDR_DB_CONFIG_KDF_ITERATIONS: SQLCipher key-derivation
parameters — must match the values used to create the DB or the
encryption key will not match.
"""
import os
import uuid
from datetime import UTC, datetime, timedelta
from pathlib import Path
from sqlalchemy.orm import Session
# Credentials must match CI_TEST_USER in tests/ui_tests/auth_helper.js and the
# user created by scripts/ci/init_test_database.py.
TEST_USERNAME = "test_admin"
TEST_PASSWORD = "testpass123" # pragma: allowlist secret
# A stable namespace UUID so re-running on a fresh DB always produces the same
# ids (keeps the fixture idempotent and easy to reason about).
_SEED_NS = uuid.UUID("00000000-0000-0000-0000-00000000a11a")
def main():
data_dir = Path(
os.environ.get(
"LDR_DATA_DIR",
Path.home() / ".local" / "share" / "local-deep-research",
)
)
print(f"Using data directory: {data_dir}")
# Imported after the env is set so path/SQLCipher config is picked up.
from local_deep_research.database.encrypted_db import db_manager
from local_deep_research.database.models.research import (
ResearchHistory,
ResearchResource,
)
engine = db_manager.open_user_database(TEST_USERNAME, TEST_PASSWORD)
if engine is None:
raise RuntimeError(
f"Could not open encrypted database for user '{TEST_USERNAME}'. "
"Was init_test_database.py run first with matching "
"LDR_TEST_MODE / LDR_DB_CONFIG_KDF_ITERATIONS?"
)
research_a = str(uuid.uuid5(_SEED_NS, "research-a"))
research_b = str(uuid.uuid5(_SEED_NS, "research-b"))
# created_at lands a day ago so it falls inside the default 30d window the
# /metrics/links page queries with. Stored as ISO strings to match the
# rest of the codebase (created_at columns are Text/String, not DateTime).
created = (datetime.now(UTC) - timedelta(days=1)).isoformat()
researches = [
ResearchHistory(
id=research_a,
query="Seed: deep learning survey for link analytics",
mode="quick_summary",
status="completed",
created_at=created,
completed_at=created,
),
ResearchHistory(
id=research_b,
query="Seed: transformer architectures for link analytics",
mode="quick_summary",
status="completed",
created_at=created,
completed_at=created,
),
]
# (research_id, url, title, source_type). Spread across 4 domains with
# uneven counts so frequency_rank / usage_percentage vary, and across both
# researches so research_diversity is >1 for the busiest domains.
resources = [
(
research_a,
"https://en.wikipedia.org/wiki/Deep_learning",
"Deep learning - Wikipedia",
"web",
),
(
research_a,
"https://en.wikipedia.org/wiki/Neural_network",
"Neural network - Wikipedia",
"web",
),
(
research_a,
"https://arxiv.org/abs/1706.03762",
"Attention Is All You Need",
"academic",
),
(
research_a,
"https://www.nature.com/articles/nature14539",
"Deep learning - Nature",
"academic",
),
(
research_b,
"https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)",
"Transformer - Wikipedia",
"web",
),
(research_b, "https://arxiv.org/abs/1810.04805", "BERT", "academic"),
(
research_b,
"https://github.com/huggingface/transformers",
"huggingface/transformers",
"code",
),
]
with Session(engine) as session:
# Idempotent: a fresh CI DB is created per attempt, but guard anyway so
# a manual re-run does not duplicate the fixture.
already = (
session.query(ResearchHistory)
.filter(ResearchHistory.id == research_a)
.first()
)
if already:
print("Link analytics fixture already present — nothing to do.")
return
session.add_all(researches)
for research_id, url, title, source_type in resources:
session.add(
ResearchResource(
research_id=research_id,
url=url,
title=title,
source_type=source_type,
created_at=created,
)
)
session.commit()
domains = {url.split("/")[2] for _, url, _, _ in resources}
print(
f"✅ Seeded {len(researches)} researches and {len(resources)} resources "
f"across {len(domains)} domains for '{TEST_USERNAME}'"
)
if __name__ == "__main__":
main()