diff --git a/.github/workflows/example-consumer.yaml b/.github/workflows/example-consumer.yaml index dcfdd85..23fed87 100644 --- a/.github/workflows/example-consumer.yaml +++ b/.github/workflows/example-consumer.yaml @@ -1,6 +1,9 @@ # Example: how a repo would use the published action. # Copy this to your repo as .github/workflows/cef-github-tracker.yaml -# and set repository secrets: WALLET_URI, NOTION_API_KEY. +# and set repository secrets: WALLET_URI, NOTION_API_KEY for legacy mode. +# Central sender mode does not require per-repo CEF wallet secrets once +# this action is released with central_sender_url defaulting to the +# CEF-owned sender endpoint. # # If the action lives in the same org (cef-ai/cef-github-tracker-action): # uses: cef-ai/cef-github-tracker-action@v1 @@ -19,13 +22,19 @@ on: jobs: send: runs-on: ubuntu-latest + env: + # These can come from organization-level secrets/variables granted + # to this repository. + WALLET_URI: ${{ secrets.WALLET_URI }} + NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }} + GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} + CEF_DDC_BASE_URL: ${{ vars.CEF_DDC_BASE_URL }} + CEF_GAR_URL: ${{ vars.CEF_GAR_URL }} + CEF_AGENT_SERVICE: ${{ vars.CEF_AGENT_SERVICE }} + CEF_WORKSPACE: ${{ vars.CEF_WORKSPACE }} + CEF_STREAM: ${{ vars.CEF_STREAM }} steps: - uses: cef-ai/cef-github-tracker-action@v1 with: - wallet_uri: ${{ secrets.WALLET_URI }} - notion_api_key: ${{ secrets.NOTION_API_KEY }} github_token: ${{ secrets.GITHUB_TOKEN }} - agent_service: '0x2bc3e8a0d6b12e660f519c74697f0929b9b815afc51544bdef08535a5d1c2d4f' - workspace: '2199' - stream: 'stream-fd9b5419' wiki_check_branches: 'main,master' diff --git a/README.md b/README.md index ed5ee3b..7a2e53c 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,84 @@ # CEF GitHub Tracker Action -Reusable GitHub Action that sends PR, review, and push events to the [CEF Project Tazz](https://github.com/cef-ai/Project-Tazz-Execution-Log-Tracker) execution log tracker. One workflow file in any repo, no copy-paste of payload logic. +Reusable GitHub Action that sends PR, review, and push events to the CEF Vault GitHub agent. + +This action is Vault-only. It reads the raw GitHub webhook payload from `GITHUB_EVENT_PATH`, adds a few CEF fields, and delegates to `cef-ai/Cef-Send-Event-Action`. ## Usage -Create `.github/workflows/cef-github-tracker.yaml` in your repo: +Create `.github/workflows/cef-github-tracker.yaml`: ```yaml name: CEF GitHub Tracker on: pull_request: - types: [opened, closed, reopened] + types: [opened, closed, reopened, synchronize] pull_request_review: types: [submitted] push: - branches: ['**'] + branches: ["**"] jobs: - send: + send-github-event: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + env: + CEF_AGENT_ID: ${{ vars.CEF_AGENT_ID }} + CEF_VAULT_WALLET_KEYSTORE_B64: ${{ secrets.CEF_VAULT_WALLET_KEYSTORE_B64 }} + CEF_VAULT_WALLET_KEYSTORE_PASSWORD: ${{ secrets.CEF_VAULT_WALLET_KEYSTORE_PASSWORD }} + GITHUB_TOKEN: ${{ github.token }} steps: - uses: cef-ai/cef-github-tracker-action@v1 - with: - wallet_uri: ${{ secrets.WALLET_URI }} - notion_api_key: ${{ secrets.NOTION_API_KEY }} - github_token: ${{ secrets.GITHUB_TOKEN }} - agent_service: '0x2bc3e8a0d6b12e660f519c74697f0929b9b815afc51544bdef08535a5d1c2d4f' - workspace: '2199' - stream: 'stream-fd9b5419' - # Optional: - wiki_check_branches: 'main,master' - # ddc_base_url defaults to https://compute-1.devnet.ddc-dragon.com ``` -## Required secrets +For the current test Vault, `Cef-Send-Event-Action` already defaults these values: -| Secret | Description | -|--------|-------------| -| `WALLET_URI` | CEF wallet URI for DDC authentication | -| `NOTION_API_KEY` | Notion internal integration token | +```text +CEF_VAULT_URL=https://vault-api.compute.test.ddcdragon.com +CEF_GAR_URL=https://gar.compute.test.ddcdragon.com +CEF_MARKETPLACE_URL=https://agent-marketplace.compute.test.ddcdragon.com +CEF_S3_GATEWAY_AUTH_INFO_URL=https://ddc-s3-gateway.compute.test.ddcdragon.com/auth/info +CEF_SCOPE=default +CEF_AGENT_ALIAS=productivity-agent +CEF_CUBBY_ALIAS=productivity_store +``` -`GITHUB_TOKEN` is provided by GitHub Actions; pass it as `github_token` so the action can include it in the payload for the CEF agent. +Set them as repo/org variables only when the repo needs a different Vault environment or target. ## Inputs | Input | Required | Default | Description | -|-------|----------|---------|-------------| -| `wallet_uri` | Yes | — | CEF wallet URI | -| `notion_api_key` | Yes | — | Notion API key | -| `github_token` | Yes | — | e.g. `${{ secrets.GITHUB_TOKEN }}` | -| `agent_service` | Yes | — | CEF agent service ID | -| `workspace` | Yes | — | CEF workspace ID | -| `stream` | Yes | — | CEF event stream ID | +| --- | --- | --- | --- | +| `notion_api_key` | No | `""` | Optional Notion token included in the payload | +| `github_token` | No | `""` | GitHub token for agent-side enrichment. Falls back to `GITHUB_TOKEN` or `CEF_GITHUB_TOKEN` env. | +| `gemini_api_key` | No | `""` | Optional Gemini API key included in the payload | | `wiki_check_branches` | No | `main,master` | Branches that trigger wiki staleness checks | -| `ddc_base_url` | No | `https://compute-1.devnet.ddc-dragon.com` | DDC compute base URL | -## Pinning a version +## Payload -Use a tag (e.g. `@v1`, `@v1.0.1`) instead of `@main` so updates are intentional: +The payload sent to Vault is the raw GitHub webhook JSON plus: -```yaml -- uses: cef-ai/cef-github-tracker-action@v1 +```json +{ + "event_type": "GITHUB_ACTION_PR_EVENT", + "github_event_name": "pull_request", + "delivery_id": "github-run-id-run-attempt", + "notion_api_key": "...", + "github_token": "...", + "gemini_api_key": "...", + "wiki_check_branches": "main,master" +} ``` -## Turning this into a repo +`Cef-Send-Event-Action` fills `repo`, `branch`, `pr_number`, and `head_sha` before publishing to Vault. + +## Version Pinning -1. Create a new repo (e.g. `cef-ai/cef-github-tracker-action`). -2. Copy the contents of this folder (at least `action.yml` and this README) into the repo root. -3. Commit, push, and create a tag (e.g. `v1`) so others can use `@v1`. -4. In consuming repos, use `uses: cef-ai/cef-github-tracker-action@v1` (replace with your org/repo and tag). -# cef-github-tracker-action +Use a tag such as `@v1` after release: + +```yaml +- uses: cef-ai/cef-github-tracker-action@v1 +``` diff --git a/action.yml b/action.yml index 4b533a2..dad938b 100644 --- a/action.yml +++ b/action.yml @@ -1,179 +1,81 @@ -name: 'CEF GitHub Tracker' -description: 'Send GitHub events (PRs, reviews, pushes) to CEF execution log tracker (Project Tazz)' +name: "CEF GitHub Tracker" +description: "Send GitHub PR, review, and push events to the CEF Vault GitHub agent" + inputs: - wallet_uri: - required: true - description: 'CEF wallet URI for DDC authentication' notion_api_key: - required: true - description: 'Notion internal integration token' + required: false + description: "Optional Notion token to include in the Vault payload" + default: "" github_token: - required: true - description: 'GitHub token (e.g. secrets.GITHUB_TOKEN) for API access in the payload' + required: false + description: "GitHub token for agent-side GitHub API enrichment" + default: "" gemini_api_key: - required: true - description: 'Google Gemini API key for AI operations' - agent_service: - required: true - description: 'CEF agent service ID' - workspace: - required: true - description: 'CEF workspace ID' - stream: - required: true - description: 'CEF event stream ID' + required: false + description: "Optional Gemini API key to include in the Vault payload" + default: "" wiki_check_branches: - description: 'Comma-separated branches that trigger wiki staleness checks' - default: 'main,master' - ddc_base_url: - description: 'DDC compute base URL' - default: 'https://compute-1.devnet.ddc-dragon.com' + required: false + description: "Comma-separated branches that trigger wiki staleness checks" + default: "main,master" + runs: - using: 'composite' + using: "composite" steps: - id: payload env: - NOTION_API_KEY: ${{ inputs.notion_api_key }} - GITHUB_TOKEN: ${{ inputs.github_token }} - GEMINI_API_KEY: ${{ inputs.gemini_api_key }} - WIKI_CHECK_BRANCHES: ${{ inputs.wiki_check_branches }} + INPUT_NOTION_API_KEY: ${{ inputs.notion_api_key }} + INPUT_GITHUB_TOKEN: ${{ inputs.github_token }} + INPUT_GEMINI_API_KEY: ${{ inputs.gemini_api_key }} + INPUT_WIKI_CHECK_BRANCHES: ${{ inputs.wiki_check_branches }} shell: bash run: | - set -e + set -euo pipefail + case "${{ github.event_name }}" in - pull_request) - jq -n \ - --argjson e "$(cat $GITHUB_EVENT_PATH)" \ - --arg notion "$NOTION_API_KEY" \ - --arg token "$GITHUB_TOKEN" \ - --arg gemini "$GEMINI_API_KEY" \ - --arg wiki_branches "$WIKI_CHECK_BRANCHES" \ - '{ - event_type: "GITHUB_ACTION_PR_EVENT", - action: $e.action, - merged: ($e.pull_request.merged // false), - pr_number: $e.number, - pr_title: $e.pull_request.title, - pr_url: $e.pull_request.html_url, - pr_body: ($e.pull_request.body // ""), - repo: $e.repository.full_name, - author: $e.pull_request.user.login, - merged_by: ($e.pull_request.merged_by.login // null), - merged_at: ($e.pull_request.merged_at // null), - base_branch: ($e.pull_request.base.ref // null), - branch: ($e.pull_request.head.ref // null), - before: ($e.before // null), - after: ($e.after // null), - timestamp: ($e.pull_request.updated_at // $e.pull_request.created_at // ""), - notion_api_key: $notion, - github_token: $token, - gemini_api_key: $gemini, - wiki_check_branches: $wiki_branches - }' > payload.json - ;; - pull_request_review) - jq -n \ - --argjson e "$(cat $GITHUB_EVENT_PATH)" \ - --arg notion "$NOTION_API_KEY" \ - --arg token "$GITHUB_TOKEN" \ - --arg gemini "$GEMINI_API_KEY" \ - --arg wiki_branches "$WIKI_CHECK_BRANCHES" \ - '{ - event_type: "GITHUB_ACTION_PR_EVENT", - action: ( - if $e.review.state == "approved" then "review_approved" - elif $e.review.state == "changes_requested" then "review_changes_requested" - else "review_commented" - end - ), - merged: false, - pr_number: $e.pull_request.number, - pr_title: $e.pull_request.title, - pr_url: $e.pull_request.html_url, - pr_body: ($e.pull_request.body // ""), - repo: $e.repository.full_name, - author: $e.pull_request.user.login, - reviewer: $e.review.user.login, - merged_by: null, - merged_at: null, - base_branch: ($e.pull_request.base.ref // null), - branch: ($e.pull_request.head.ref // null), - before: null, - after: null, - timestamp: ($e.review.submitted_at // ""), - notion_api_key: $notion, - github_token: $token, - gemini_api_key: $gemini, - wiki_check_branches: $wiki_branches - }' > payload.json - ;; - push) - jq -n \ - --argjson e "$(cat $GITHUB_EVENT_PATH)" \ - --arg notion "$NOTION_API_KEY" \ - --arg token "$GITHUB_TOKEN" \ - --arg gemini "$GEMINI_API_KEY" \ - --arg wiki_branches "$WIKI_CHECK_BRANCHES" \ - ' - $e.ref as $ref | - ($e.repository.default_branch // "main") as $default | - (if $ref == ("refs/heads/" + $default) then $default else ($ref | split("refs/heads/")[1]) end) as $branch | - ($e.commits | length) as $n | - ($e.commits[0].message // "") as $first_msg | - ($e.after // "") as $after | - (if $n == 0 then true - elif ($ref == ("refs/heads/" + $default)) and ($n == 1) and ($first_msg | test("^Merge "; "i")) then true - else false end) as $skip_log | - { - event_type: "GITHUB_ACTION_PR_EVENT", - action: "branch_push", - merged: false, - is_branch_push: true, - branch: $branch, - head_sha: $after, - commit_messages: [$e.commits[].message], - repo: $e.repository.full_name, - author: ($e.pusher.login // $e.commits[0].author.username // "unknown"), - pr_number: 0, - pr_title: ("Branch: " + $branch), - pr_url: ("https://github.com/" + $e.repository.full_name + "/commit/" + $after), - pr_body: "", - merged_by: null, - merged_at: null, - base_branch: null, - before: $e.before, - after: $after, - timestamp: ($e.head_commit.timestamp // $e.repository.updated_at // ""), - notion_api_key: $notion, - github_token: $token, - gemini_api_key: $gemini, - skip_log: $skip_log, - wiki_check_branches: $wiki_branches - } - ' > payload.json + pull_request|pull_request_review|push) ;; *) - echo "Unsupported event: ${{ github.event_name }}" + echo "::error::Unsupported event: ${{ github.event_name }}" exit 1 ;; esac - echo "payload<> $GITHUB_OUTPUT - cat payload.json >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - uses: cef-ai/Cef-Send-Event-Action@main + notion_api_key="${INPUT_NOTION_API_KEY:-${CEF_NOTION_API_KEY:-${NOTION_API_KEY:-}}}" + github_token="${INPUT_GITHUB_TOKEN:-${GITHUB_TOKEN:-${CEF_GITHUB_TOKEN:-}}}" + gemini_api_key="${INPUT_GEMINI_API_KEY:-${CEF_GEMINI_API_KEY:-${GEMINI_API_KEY:-}}}" + wiki_check_branches="${INPUT_WIKI_CHECK_BRANCHES:-${CEF_GITHUB_TRACKER_WIKI_CHECK_BRANCHES:-main,master}}" + delivery_id="${GITHUB_RUN_ID:-local}-${GITHUB_RUN_ATTEMPT:-1}" + + jq \ + --arg event_type "GITHUB_ACTION_PR_EVENT" \ + --arg github_event_name "${{ github.event_name }}" \ + --arg notion "$notion_api_key" \ + --arg token "$github_token" \ + --arg gemini "$gemini_api_key" \ + --arg wiki_branches "$wiki_check_branches" \ + --arg delivery "$delivery_id" \ + '. + { + event_type: $event_type, + github_event_name: $github_event_name, + notion_api_key: $notion, + github_token: $token, + gemini_api_key: $gemini, + wiki_check_branches: $wiki_branches, + delivery_id: (.delivery_id // $delivery) + }' "$GITHUB_EVENT_PATH" > payload.json + + echo "payload<> "$GITHUB_OUTPUT" + cat payload.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + - uses: cef-ai/Cef-Send-Event-Action@awei/central-sender-mode with: - wallet_uri: ${{ inputs.wallet_uri }} - ddc_base_url: ${{ inputs.ddc_base_url }} - agent_service: ${{ inputs.agent_service }} - workspace: ${{ inputs.workspace }} - stream: ${{ inputs.stream }} event_type: GITHUB_ACTION_PR_EVENT event_payload: ${{ steps.payload.outputs.payload }} - # Keep the job (and therefore GITHUB_TOKEN) alive long enough for CEF - # to process the event. Without this, GITHUB_TOKEN is revoked when the - # job ends — often before CEF's fetch-code task pulls PR data. + # Keep the job (and therefore GITHUB_TOKEN) alive long enough for the + # agent to enrich the event before GitHub revokes the token. - name: Keep GITHUB_TOKEN alive for CEF processing shell: bash run: sleep 30