Skip to content

Releases

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 10 Nov 08:02
37b4dff

Fixed

  • User sync no longer fails a search page because one pull request sits in a
    SAML-protected or forbidden repository. The node is skipped, counted in
    skipped, and named in a note with GitHub's message; the rest of the page is
    stored, and the cursor moves past it. Any other GraphQL error still fails the
    page.

Changed

  • Library API: fetch::user_search::parse_user_search_page takes the response's
    errors as a second argument, and UserSearchPage has a new inaccessible
    field.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 10 Nov 07:13
8d62896

Breaking

  • Library API: query::validate_select_only,
    storage::sync_state_repository::acquire_lock and release_lock are
    removed, and fetch::GhCommandLine is built with GhCommandLine::new().
    CLI flags and MCP tool inputs are unchanged.
  • prs_merged now counts by merge date, so metric values change.

Changed

  • prs_merged (user, repo and group metrics, and the top_mergers
    leaderboard) now counts pull requests merged in the window, by
    merged_date_key. It used to count pull requests opened in the window that
    are merged now, so period-over-period deltas ran low. Expect different
    numbers after upgrading.
  • query::validate_select_only is removed; raw_query now asks SQLite whether
    the prepared statement is read-only.

Fixed

  • query --group <name> for a group with no members returned every pull
    request; it now returns none, matching metrics. QueryBuilder::authors
    and repos do the same for an empty list.

  • raw_query refused nothing but a non-SELECT/WITH first word, so
    WITH x AS (SELECT 1) DELETE FROM ... ran. It also rejected a ; inside a
    string literal.

  • gh api graphql exits 1 when a response carries partial errors but
    still prints the data. That data is now kept, so a search with one
    SAML-protected or missing node stores the rest instead of failing.
    Rate-limited responses still go through retry and backoff.

  • A hung gh is killed after 120 seconds with a clear error
    (GITHUBDW_GH_DEADLINE_SECS changes the limit). gh now runs with
    GH_PROMPT_DISABLED=1 and without GH_DEBUG/DEBUG, so request headers
    never reach stored error text.

  • A permanent HTTP 403 (SAML, permissions, blocked repository) fails on the
    first attempt instead of seven. Only rate-limit 403s and specific
    transient network errors are retried.

  • GraphQL string variables are passed with -f, so a login or repository
    named 123, true or null reaches GitHub as a string and @x is never
    read as a file. Only variables the query declares Int or Boolean use
    -F.

  • sync: run-level errors (cancellation, a spent rate limit or quota reserve,
    an unusable gh, a failing database) now stop the repository and user walks
    at once instead of being recorded as a failure for every remaining item.
    Constraint errors on one item's rows are still recorded per item. Page size
    halves only for 502/504, timeout and resource-limit failures; any other
    error returns immediately.

  • sync: the per-entity sync lock is now an owned lease. Recording progress
    renews it, so a walk that runs past 30 minutes (search pacing, rate-limit
    sleeps) no longer lets a second process start the same sync. A run releases
    only the lock it holds, so a stale holder finishing cannot delete its
    successor's lock. A lock with an unparsable started_at is reclaimable
    instead of blocking forever, and a failure while recording the job outcome
    releases the lock and no longer replaces the sync's own error.

  • sync watch: the reported start time stays the job's real start instead of
    following lock renewals.

  • mcp: trigger_sync no longer blocks the server. It runs on a blocking
    thread with its own database connection, so other tool calls, pings and
    cancellation are answered while it works. A call processes at most 500
    pull requests and returns partial: true (status Partial) when it stops
    at that budget; calling again resumes. A rate-limit wait over 30 seconds
    is not slept: the call returns status RateLimited with
    rate_limited_until. The result also carries notes. Input is unchanged.

Removed

  • The unused live-tests Cargo feature.
  • storage::sync_state_repository::acquire_lock and release_lock; use
    SyncLease (or acquire_owned_lock).

v0.3.5

Choose a tag to compare

@github-actions github-actions released this 04 Nov 19:18
cc83ee5

Added

  • retention: a shared collection policy file
    ($XDG_CONFIG_HOME/adlio-collection/policy.json) re-read at every write.
    A valid file caps diff retention (none, transient, retain); an
    invalid file stores no new diff text; no file keeps the old behaviour.
    While a file exists, every sync path preserves stored payloads: an empty
    provider value never replaces a stored title, body, comment or patch, and
    no stored row is deleted.
  • collection: counts-first collection by warehouse day (collect_day)
    with per-day coverage, a review frontier for reviews on pull requests
    updated later, day_counts that returns None for days not collected,
    on-demand detail (fetch_pull_request_detail), in-memory diffs
    (fetch_pull_request_diff_live) and revision fingerprints.
  • GhClient cancellation (set_cancellation) and deferred rate-limit
    waits (set_defer_waits_over), reported as Error::Cancelled and
    Error::RateLimited.

Compatibility

  • The three new tables are created with CREATE TABLE IF NOT EXISTS on
    open, not by a numbered migration. user_version stays 8, so a 0.3.4
    binary still opens a warehouse 0.3.5 has used.

v0.3.4

Choose a tag to compare

@github-actions github-actions released this 04 Nov 16:23
8f56473

Fixed

  • Sync no longer slows down as the warehouse grows. The full-text triggers
    located a row's index entry with DELETE ... WHERE <key> = ... on an
    UNINDEXED FTS5 column, which scans the whole FTS table, so every upsert of a
    PR, issue or comment cost a full scan. At 259k issue comments one sync all
    ran past launchd's two-hour limit. Migration 8 rebuilds the four FTS tables
    keyed by the source rowid, makes the triggers delete by rowid, and skips the
    update trigger when no indexed column changed. On an 8.5 GB warehouse a
    comment upsert now takes about 8 ms, and the one-time rebuild took 6m49s.
    The rebuild runs when the first command opens the warehouse after the
    upgrade, so expect that first sync or search to take minutes on a large
    warehouse.

v0.3.3

Choose a tag to compare

@github-actions github-actions released this 02 Nov 04:49
4243529

Performance

  • Migration 7 adds fact_pull_requests(created_at DESC), so newest-first
    pull-request listings stop sorting the whole table: on a 16 GB test
    warehouse with nothing cached, the first page went from about 30 s to
    24 ms. The index is descending on purpose. Pull requests that share a
    created_at keep the order the old scan-and-sort returned.
  • It also adds fact_pull_requests(author_key, created_date_key, repo_key, title), so per-author work lists over a date window (repository and title)
    read only the index.

Upgrade notes

  • Migration 7 adds about 6 MB and builds in one transaction at first open.
    Binaries older than 0.3.3 refuse an upgraded warehouse.

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:58
6729ecb

Performance

  • Migration 6 adds covering indexes for per-author activity over a date
    window: pull requests opened (with additions, deletions and changed files),
    reviews submitted, and review comments written. Callers that count these
    per author (user metrics, leaderboards, or their own SQL over the
    warehouse) no longer read the full rows. On a 16 GB test warehouse, counts
    for a dozen authors went from seconds to milliseconds on a cold page cache.

Upgrade notes

  • Like migration 5, migration 6 builds its indexes in one transaction the
    first time a warehouse is opened (tens of seconds on a large warehouse)
    and adds about 16 MB there. Binaries older than 0.3.2 refuse an upgraded
    warehouse.

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 02 Nov 02:28
1ce02e9

Performance

  • Migration 5 adds covering indexes for the repository metrics and
    leaderboards: pull requests by repository and creation date, check-run
    outcomes, review and issue comments, and reviews per pull request; and
    per-author merged pull requests and pull-request conversation comments. On a
    warehouse whose pages are not cached, repo_metrics and repo_aggregations
    previously read every pull-request, comment and check-run row they touched,
    including the wide title and body columns; they now read index pages only. On a 16 GB test warehouse the
    slowest queries went from tens of seconds to under two seconds on a cold
    page cache, and the comment counts from about 1 s to under 0.2 s warm.
  • Repository comment counts and the top-commenters leaderboard restrict each
    side of the review/issue comment union to the repository's pull requests
    before combining them, instead of reading every comment in the warehouse.
    Results are unchanged.

Upgrade notes

  • Migration 5 builds the indexes the first time a warehouse is opened, which
    takes minutes on a large warehouse, followed by the one-time foreign key
    check every schema change triggers. The migration runs in one transaction:
    if interrupted, the warehouse stays at version 4 and the next open retries.
  • The indexes add about 1.6% to the database size, most of it check runs. As
    with every migration, a binary built before this release refuses to open a
    warehouse that has been upgraded.

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 27 Oct 05:57
fd09495

Breaking

  • Error gains GitRecovery and QuotaReserve variants; exhaustive matches
    on Error need a new arm.
  • New public fields break struct literals: fetch::issues::IssueData
    (pending_comments, pending_labels, pending_assignees),
    fetch::pull_requests::PullRequestData (node_id, pending,
    changed_files_reported, check_runs_truncated, ...), and
    sync::SyncSummary (partial).

Added

  • Nested-connection continuation, so heavy pull requests and issues land with
    every comment, review, thread and file instead of the first slice.
  • Git-backed recovery of pull-request file sets GitHub caps at 3,000 files.
  • sync targets, sync repair-plan, sync check-history and
    sync check-history-plan.
  • GithubDW::open_read_only.
  • query::PrFilters and PrState::parse: the filter set the CLI and the MCP
    query tool share.
  • MetricsEngine::group_metrics, storage::config_repository, and
    sync_state_repository::{active_syncs, recent_jobs}.

Changed

  • query --state with an unknown value now lists the accepted values.
  • Internal layout: sync, the CLI binary, check_history and
    fetch::git_files are split into submodules. Public paths are unchanged.

v0.2.4

Choose a tag to compare

@github-actions github-actions released this 17 Aug 04:50
d780b79

Added

  • sync user <login> and user coverage in sync all. monitor add-user has
    registered user sources since 0.1.0 and monitor list has shown them, but
    sync only ever served repositories — so a monitored user's last_sync_at
    never moved and no command could answer "what did this person do". This
    release makes sync serve them: for each enabled user it searches the pull
    requests they authored (author:) and the ones they reviewed
    (reviewed-by:), and upserts every result through the same entity, fact, and
    time-dimension pipeline sync repo uses. A PR reachable from both paths lands
    identically either way.
  • Coverage, locking, and job records for user sources under the user:<login>
    entity key, so sync watch, stale-lock recovery, and the recorded date-range
    merge all behave as they do for repositories. The two roles keep separate
    updated_at watermarks (user and user_reviews in sync_metadata) because
    they walk disjoint result sets — one shared cursor would let the busier side
    advance past items the other has not fetched. As on the repository path, a
    watermark only ever moves past an item that actually persisted, so a failed
    upsert is retried on the next run instead of becoming a permanent hole.
  • Honest handling of the two limits search imposes. GitHub serves at most 1,000
    results per query however many it reports matching, so a backfill is
    partitioned into calendar-month created: windows and any window still
    reporting more than the cap is bisected until each part fits — the over-cap
    query is abandoned before its results are spent, not truncated silently. When
    a window is already a single day and still over the cap, the run reports the
    shortfall rather than recording coverage it did not fetch. An incremental run
    is bounded by its watermark instead of by the window, so there the cap is only
    a problem if pagination runs out before the watermark is reached: that case is
    reported with the --days command that closes the gap, while a walk that
    reaches its watermark stays quiet no matter how many lifetime matches the
    query reports. Search's request budget is 30/minute, an order of magnitude
    tighter than the 5,000 points/hour the repository path spends, so search calls
    are paced on their own clock independent of the observed rateLimit block.

Changed

  • sync all now iterates every supported source type — repositories first, then
    users — and prints a line for each enabled source it will not serve. A source
    type this build does not implement, and a row that is present but disabled,
    are both named on stdout. Previously the source list was filtered to
    repositories and everything else disappeared without a word, which read as
    "there was nothing to do".
  • sync user covers pull requests and reviews. --issues-only has no
    user-scoped counterpart in this release; passing it reports that instead of
    returning zero, which would read as "this user has no issues".
  • Repositories discovered through a user sync are stored as dimensions but are
    not added to monitored_repos. Monitoring a person is a statement about
    that person, not an instruction to start tracking every repository they
    contributed to.

v0.2.3

Choose a tag to compare

@github-actions github-actions released this 17 Aug 01:30
ca34483

Fixed

  • Every command that names an author printed the warehouse's internal entity
    key (user:octocat, bot:dependabot) instead of the login GitHub uses.
    query in all four modes (table, json, csv, count-by-author), search --json, the metrics user header, and the query_pull_requests, search
    and get_metrics MCP tools were all affected, so the only githubdw output
    that showed a usable login was the metrics leaderboards. A value copied off
    any other surface could not be pasted into a GitHub URL or API call without
    knowing to strip a namespace first, and the field carrying it was already
    named author or login — the bare spelling the schema itself uses for
    dim_entities.login. Identity fields now hold the bare login everywhere, and
    the type that the namespace used to convey travels in its own field:
    author_type on PR rows and search hits, entity_type on a user report. The
    key remains available where a caller genuinely needs to join back to the star
    schema, under a name that says so: author_key on PR rows and entity_key
    on a user report.
  • A single display column could not tell a bot from the person who shares its
    login, since dropping the namespace drops that distinction. Bots are now
    marked visibly instead — dependabot [bot] in table output, in
    count-by-author group labels, and in the metrics user header — so the two
    identities stay distinguishable and remain separate groups in a breakdown.
  • A leaderboard row for an entity with no display name fell back to printing
    its raw key. It now falls back to the bare login, with the same bot marker.

Added

  • Schema v4 constrains dim_entities to the identity invariants the ingest
    code already upholds: login is non-empty and never namespaced,
    entity_key is exactly entity_type + : + login, and entity_type is
    one of the namespaces ingestion mints. These were enforced by code alone, so
    a writer that bypassed the normalizer could store a row that no bare-login
    lookup would ever match while the write reported success. The upgrade is a
    no-op on a warehouse whose rows already conform, and refuses to complete on
    one that carries a violating row rather than migrating the problem forward.

Changed

  • The csv output of query gained an author_type column, so the bare
    author and its type are both present without the namespaced key. Callers
    parsing CSV by column position need to account for the new column.