Skip to content

Contribution event tracker v1: CloudEvents capture, APICURON delivery and backfill - #19

Merged
Mehdi-SK merged 71 commits into
mainfrom
dev
Oct 8, 2026
Merged

Mehdi-SK merged 71 commits into
mainfrom
dev

Conversation

@Mehdi-SK

@Mehdi-SK Mehdi-SK commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Turns the TypeScript Action template on main into the contribution event
tracker. When a pull request is merged, the Action builds one CloudEvents 1.0
event describing who did what and sends it to APICURON, so contributors can be
credited. A backfill script produces the same events for past pull requests.

This is the first release. Partner repositories will reference the Action at
@main.

How it works

  1. Trigger. The workflow runs on pull_request_target (types: [closed])
    for merged pull requests.
  2. Snapshot. The PR object from the webhook payload is reused; reviews,
    conversation comments, review comments and closing issues are fetched
    through the GitHub API (REST and GraphQL).
  3. Build. A pure builder turns the snapshot into one event. Live capture
    and backfill share it.
  4. Send. The event is posted to APICURON, or only logged in dry-run.

The event

  • CloudEvents 1.0 envelope, type
    it.unipd.biocomputingup.github.pull_request.merged.
  • source github:repository:{numeric id}, subject
    pull_request/{number}, dataschema a w3id URI.
  • Deterministic UUIDv5 id derived from repository id, PR number, event type
    and closed_at, so re-sending or backfilling the same PR gives the same id.
  • data contains:
    • repository and pull_request metadata;
    • activities[]: opened, reviewed (with state), commented (conversation or
      review thread, with review_object_id), merged;
    • relationships[]: issues the PR closes;
    • capture: tool, version, mode (live or backfill), observed time.
  • Metadata only: no comment bodies, diffs or code.
  • Bots are dropped, activity after closed_at is excluded, and activities,
    relationships and labels are sorted so output is reproducible.

Main parts

Area Location
Entry point and input handling src/main.ts
Event processors (strategy per GitHub event, handler per action) src/processors/
GitHub client and snapshot fetching src/client/github/
Event builder and id generation src/builders/
APICURON client src/client/apicuron-client/
Backfill script and batch sender src/scripts/
Event and snapshot types src/types/
Generated JSON Schemas schemas/

Action inputs

Input Default Purpose
apicuron-token none Token of a user managing the linked resource. Required unless dry-run
apicuron-url https://apicuron.org/api API base URL
dry-run false Build and log the event without sending
github-token workflow token Reads the pull request

There is deliberately no resource id input: the repository-to-resource link
lives in APICURON.

Delivery

  • POST /tracker-events for one event, /tracker-events/batch for several.
  • A missing token fails the run unless dry-run is true.
  • No retry logic. Maintainers re-run a failed job; re-sent events are
    recognised as duplicates.

Backfill

yarn backfill <owner> <repo> [outFile] walks all merged pull requests, writes
every event to backfill-{owner}-{repo}-{timestamp}.jsonl, and, when
APICURON_TOKEN is set, sends them in batches packed by size (about 900 KB,
max 500 events) with split-and-retry on 413.

Also in this branch

  • JSON Schemas generated from the TypeScript types (yarn schema).
  • Unit tests for the builder, including a pinned event id that protects events
    already stored in APICURON.
  • Partner-facing README (setup, inputs, dry-run, backfill, troubleshooting,
    draft contributor notice) and an example workflow.
  • Template material removed and project metadata set; CI switched to yarn.

Testing

  • Type-check, lint and format check pass.
  • Builder tests pass (9).
  • dist/ is built from the final source.
  • Backfill run against BioComputingUP/disprot.

Notes for reviewers

  • pull_request_target is used so pull requests from forks can access the
    secret. It is safe here because the Action only reads PR metadata through
    the API and never checks out or runs PR code.
  • The dataschema URI does not resolve yet; the w3id redirect will be
    requested after this merge.
  • The contributor notice in the README is a draft pending data-protection
    review.
  • Only merged pull requests are tracked. Closed-unmerged pull requests are a
    known follow-up.

After merging

  • Open the w3id pull request for the schema URIs.
  • Link the first partner repository in APICURON and verify one live event.

🤖 Generated with Claude Code

Mehdi-SK added 30 commits May 22, 2026 11:52
- Introduces the IEventProcessorStrategy interface to define methods
  for handling events and processing payloads.
- Adds PushStrategy class implementing IEventProcessorStrategy
- Defines canHandle method to identify 'push' events
- Implements process method to transform TPushEventPayload into ContributionPayload[]
…sses

- Added PRStrategy class to handle pull request events.
- Introduced PRMergedEventHandler to process merged pull request actions.
- Defined PRActionHandler interface for consistent event handling.
- Implemented creditAuthors function to process pull request authors.
- Implemented creditReviewers function to process pull request reviewers.
- Both functions currently throw an error indicating they are not implemented.
- Added the run function to handle GitHub event processing.
- Utilizes the processors to determine the appropriate strategy based on the event type.
- Logs the processed tracked events for further analysis.
…class

- Added IExternalClient interface for sending contribution payloads.
- Implemented ApicuronClient class that adheres to IExternalClient.
- Prepared sendPayload method for future implementation of payload handling.
Extract User login, review state, and submission date to use as timestamp with fallback of date.now()
- TPushEventPayload -> GHPushEventPayload to indicate it's the GH produced payload not the action one.
- Implements functionality to fetch closed PRs from GitHub.
- Sends PR data as payload to a specified server endpoint.
- Supports optional parameters for limiting results and dry runs.
- Saves server responses to a JSON file.
- Deleted wait.ts and main.test.ts as they are no longer needed.
- Cleaned up the test suite by removing unused test cases.
…amline user null check in process PR merge method

- Ensures consistency in the payload structure by requiring a valid github_login.
- This change may affect how the application handles user authentication and contributions.
- Moved the null check for pull request user to the top of the process method for better readability.
- Ensures that the error is thrown immediately if the user is null, preventing further execution.
- Moved try-catch block to encompass the entire run logic.
- Ensured that errors during client initialization and processing are caught and handled properly.
…on dependancies

- Previously relied on @github/local-action to pull them in as a dev dependency,
Mehdi-SK and others added 28 commits October 2, 2026 12:29
- Introduced fetchPullRequestSnapshot function to encapsulate logic for fetching pull request details.
- Utilizes helper functions to transform data into the required snapshot format.
- Reduces API calls by allowing prefetched data to be used when available.
- Introduced a new function to create unique event IDs for pull requests.
- Utilizes UUID v5 for consistent ID generation based on repository and event details.
…ities

- Adds functionality to build a pull request event with detailed activities.
- Integrates helper functions to determine user types and account details.
- Supports tracking of comments, reviews, and merges by human users.
- Introduced captureInfo function to encapsulate event tracking information.
- Utilizes TRACKER_VERSION for versioning and formats observed_at for GitHub compatibility.
…plementation

- moved IEventProcessorStrategy and IPRActionHandler interfaces.
- Removed outdated PRStrategy and PREventHandler implementations to replace with new ones in the following commits.
- Streamlined event handling structure for better maintainability.
- Added PRMergedEventHandler class to handle events for merged pull requests.
- Integrated fetching of pull request snapshots and building event data.
- Updated capture mode constants to use uppercase for consistency.
- Removed unused import from strategies.
- Added GitHubClient and processors imports for clarity.
- Changed trackedEvents initialization to default to an empty array.
- Implements a new script to list closed pull requests and capture events.
- Utilizes GitHubClient to fetch closed PRs and their details.
- Writes captured events to a specified output file in JSONL format.
- Enhanced TPullRequestActivity to include review_object_id for better tracking of review comments.
- Updated fetchPullRequestSnapshot to map review_id correctly.
- Adjusted TCommentSnapshot to accommodate optional review_id.
…er extraction

- Deleted PRMergedEventHandler as it is no longer needed.
- Removed getPullRequestReviewers function due to redundancy.
- Eliminated extractAuthors function which was not implemented.
… schema

- Updated version in package.json and version.ts to 0.3.1
- Introduced review_object_id in pull request schema for better tracking
- Added envelope.json schema for event envelope structure
- Created pull_request.strict.json for stricter validation of pull request data
…ling

- Added `sendEvent` and `sendBatch` methods to handle event submissions.
- Introduced `ApicuronRequestError` class for better error management.
- Removed unused `IExternalClient` interface and related code.
- Created `apicuron.types.ts` for type definitions related to API responses.
- Introduced apicuron-url and apicuron-token inputs for better API management.
- Added dry-run option to allow event logging without sending to the API.
- Introduced dry-run validation to ensure apicuron-token is provided unless dry-run is true.
- Simplified event handling by directly processing tracked events.
- Improved logging for dry-run scenarios to enhance debugging.
…tion

- Introduced BatchSender class to manage event queuing and sending to APICURON.
- Updated backfill script to read APICURON configuration from environment variables.
- Enhanced error handling for batch sending, including handling of oversized batches.
…events

- Added stats parameter to track skipped events during processing.
- Increment skipped count when an event is not yielded.
Format sources and action.yml, ignore generated schemas in prettier, and suppress the empty-interface rule on the two types used as schema sources.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handler list was empty, so every run ended with no event to send. Also type the strategy payload as unknown instead of any.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main.ts reads github-token, but the input was dropped from action.yml. It now defaults to the workflow token. The CI self-test has no APICURON token, so it runs with dry-run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the unused flat payload types, the unused context and push payload types, and the Python sender for the old payload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Set the real package name, author, repository links, code owner and licence holder. Remove the Copilot prompts, the licensed workflow and cache, and the coverage badge. Add rimraf as a dev dependency, drop unused ones, and list the real inputs in .env.example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Explain why the event id inputs must not change, why activity after close is excluded, and that the action must never check out PR code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the template README with partner setup, inputs, dry-run, backfill, troubleshooting and a draft contributor notice. Update the example to the current inputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Implement tests to validate the behavior of buildPullRequestEvent.
- Ensure correct handling of merged and unmerged pull requests.
- Verify exclusion of bot activities and proper sorting of events.
- Test deep equality of events built from the same snapshot.
- Introduced a new snapshot file for pull request events.
- Added functions to create snapshots, reviews, and comments.
- Removed redundant code from tests by importing from the new snapshot.
@Mehdi-SK Mehdi-SK added the enhancement New feature or request label Oct 8, 2026
@Mehdi-SK
Mehdi-SK merged commit fa112ed into main Oct 8, 2026
20 of 25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant