Skip to content

Commit 97e8e3d

Browse files
authored
feat: deps.dev package import (#4158)
Signed-off-by: Uroš Marolt <uros@marolt.me>
1 parent 8a0c1d4 commit 97e8e3d

56 files changed

Lines changed: 5177 additions & 8 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/.env.dist.local

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ CROWD_TINYBIRD_BASE_URL=http://localhost:7181/
170170
# Auth0
171171
CROWD_AUTH0_ISSUER_BASE_URLS=
172172
CROWD_AUTH0_AUDIENCE=
173+
173174
# packages DB (osspckgs)
174175
CROWD_PACKAGES_DB_READ_HOST=localhost
175176
CROWD_PACKAGES_DB_WRITE_HOST=localhost
@@ -184,6 +185,10 @@ ENRICHER_BATCH_SIZE=100
184185
ENRICHER_REPO_UPDATE_INTERVAL_HOURS=24
185186
ENRICHER_IDLE_SLEEP_SEC=60
186187

188+
OSSPCKGS_GCP_PROJECT=
189+
OSSPCKGS_GCS_BUCKET=
190+
OSSPCKGS_GCP_CREDENTIALS_B64=
191+
187192
# osv-sync (Temporal-scheduled; see services/apps/packages_worker/src/osv/schedule.ts)
188193
# OSV_ECOSYSTEMS uses OSV's canonical bucket case (npm lowercase, Maven titlecase) because
189194
# the bucket URL <BASE>/<ecosystem>/all.zip is case-sensitive (Maven/all.zip exists,

backend/src/osspckgs/migrations/V1779710880__initial_schema.sql

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
-- Staging schema — used by gcsParquetToStaging activity for temporary unlogged tables.
2+
CREATE SCHEMA IF NOT EXISTS staging;
3+
14
-- ============================================================
25
-- DOMAIN 1: UNIVERSE (Tier 3 → Tier 2 ranking input)
36
-- ============================================================
@@ -130,7 +133,12 @@ CREATE TABLE versions (
130133
-- Nullable for same reason: yanked status comes from registry-specific workers, not deps.dev.
131134
is_yanked bool,
132135
is_prerelease bool NOT NULL DEFAULT FALSE,
133-
license text, -- SPDX where available; can differ per version
136+
-- Denormalized from packages for fast deps merge resolution.
137+
-- Allows resolving (ecosystem, namespace, name, number) → version_id in one index lookup.
138+
namespace text,
139+
name text NOT NULL,
140+
licenses text[], -- SPDX array, deterministically sorted; can differ per version
141+
download_count bigint, -- per-version where available (npm, crates)
134142
last_synced_at timestamptz NOT NULL DEFAULT NOW(),
135143
PRIMARY KEY (id, package_id),
136144
UNIQUE (package_id, number)
@@ -239,6 +247,8 @@ CREATE INDEX ON versions (package_id)
239247
WHERE
240248
is_latest;
241249

250+
CREATE INDEX ON versions (ecosystem, COALESCE(namespace, ''), name, number);
251+
242252
-- ============================================================
243253
-- PACKAGE DEPENDENCIES — PARTITION BY HASH(depends_on_id)
244254
--
@@ -658,7 +668,8 @@ CREATE UNIQUE INDEX ON advisory_affected_ranges (
658668
COALESCE(last_affected, '')
659669
);
660670

661-
CREATE INDEX ON advisory_affected_ranges (advisory_package_id);
671+
-- advisory_package_id prefix lookups are served by the UNIQUE index on
672+
-- (advisory_package_id, introduced_version, fixed_version) — no separate index needed.
662673

663674
-- ============================================================
664675
-- MAINTAINERS
@@ -844,8 +855,9 @@ BEGIN
844855
-- ranking effectively reduces to:
845856
-- LN(1 + dependent_repos_count) * weight_dependent_repos
846857
-- + LN(1 + dependent_packages_count) * weight_dependent_packages
847-
UPDATE packages_universe SET last_rank_pass_at = NOW();
848-
858+
--
859+
-- last_rank_pass_at is set at INSERT time in rankPackagesUniverse activity (TRUNCATE + INSERT
860+
-- before each call), so no separate full-table UPDATE needed here.
849861
WITH new_scores AS (
850862
SELECT
851863
id,
@@ -910,3 +922,56 @@ BEGIN
910922
RETURN QUERY SELECT n_scored, n_ranked, n_propagated;
911923
END;
912924
$$;
925+
926+
-- ============================================================
927+
-- INGEST JOB TRACKING
928+
-- Tracks each BQ → GCS → Postgres ingest run per job_kind.
929+
-- snapshot_at = SnapshotAt date used as watermark for incremental diff.
930+
-- ============================================================
931+
CREATE TABLE osspckgs_ingest_jobs (
932+
id bigserial PRIMARY KEY,
933+
job_kind text NOT NULL CHECK (job_kind IN (
934+
'packages', 'versions', 'package_dependencies',
935+
'repos', 'package_repos',
936+
'advisories', 'advisory_packages',
937+
'dependent_counts'
938+
)),
939+
status text NOT NULL CHECK (status IN (
940+
'pending', 'exporting', 'exported',
941+
'loading', 'merging', 'done', 'failed', 'cleaned'
942+
)),
943+
sync_mode text NOT NULL DEFAULT 'incremental'
944+
CHECK (sync_mode IN ('full', 'incremental')),
945+
snapshot_at date, -- committed watermark: promoted from provisional unconditionally on 'done' (including 0-row quiet windows)
946+
provisional_snapshot_at date, -- set at job creation; promoted to snapshot_at when job reaches 'done'
947+
gcs_prefix text, -- gs://bucket/packages/2026-05-26T00-00-00Z/
948+
row_count_bq bigint,
949+
row_count_staging bigint, -- rows loaded into staging table from GCS parquet files
950+
row_count_pg bigint, -- total rows inserted into final table(s) after merge
951+
table_row_counts jsonb, -- per-table inserted row counts, e.g. {"packages": 5000000}
952+
bq_bytes_billed bigint, -- totalBytesProcessed from BQ (cost metric, not GCS export size)
953+
bq_job_id text, -- GCP BigQuery job ID (project:location.jobId)
954+
bq_stats jsonb, -- full BQ job statistics: bytesProcessed, bytesBilled, slotMs, cacheHit, etc.
955+
bq_cost_usd numeric(12, 8) GENERATED ALWAYS AS (
956+
ROUND(COALESCE(bq_bytes_billed, 0)::numeric / 1000000000000.0 * 5.0, 8)
957+
) STORED, -- estimated BQ cost at $5/TB on-demand pricing
958+
export_name text, -- named export group (e.g. "cargo-may-2026") for --export-name bootstrap
959+
error_message text,
960+
started_at timestamptz NOT NULL DEFAULT NOW(),
961+
finished_at timestamptz,
962+
cleaned_at timestamptz
963+
);
964+
965+
CREATE INDEX ON osspckgs_ingest_jobs (job_kind, started_at DESC);
966+
967+
CREATE INDEX ON osspckgs_ingest_jobs (status)
968+
WHERE status NOT IN ('done', 'cleaned');
969+
970+
CREATE INDEX ON osspckgs_ingest_jobs (job_kind, snapshot_at DESC)
971+
WHERE status = 'done';
972+
973+
CREATE INDEX ON osspckgs_ingest_jobs (bq_job_id)
974+
WHERE bq_job_id IS NOT NULL;
975+
976+
CREATE INDEX ON osspckgs_ingest_jobs (job_kind, export_name)
977+
WHERE export_name IS NOT NULL;

pnpm-lock.yaml

Lines changed: 104 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)