Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 11 additions & 84 deletions .github/workflows/actions-fleet-monitor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,90 +74,6 @@ jobs:
GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }}
run: bash scripts/fleet_monitor.sh

- name: Summarize token usage by workflow
env:
GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }}
REPO: petry-projects/.github-private
LOOKBACK_DAYS: ${{ env.LOOKBACK_DAYS }}
run: |
set -euo pipefail

workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT
jsonl_dir="$workdir/jsonl"
artifacts_file="$workdir/token-artifacts.base64"
mkdir -p "$jsonl_dir"

cutoff_epoch="$(date -u -d "-${LOOKBACK_DAYS} days" +%s)"
artifact_count=0

gh api "repos/$REPO/actions/artifacts" --paginate \
--jq '.artifacts[] | select(.name | startswith("token-usage-")) | @base64' \
> "$artifacts_file"

while IFS= read -r encoded; do
[ -n "$encoded" ] || continue
item="$(printf '%s' "$encoded" | base64 -d)"
id="$(printf '%s' "$item" | jq -r '.id')"
created_at="$(printf '%s' "$item" | jq -r '.created_at')"
expired="$(printf '%s' "$item" | jq -r '.expired')"
created_epoch="$(date -u -d "$created_at" +%s)"

if [ "$expired" = "true" ] || [ "$created_epoch" -lt "$cutoff_epoch" ]; then
continue
fi

zip_file="$workdir/artifact-$id.zip"
unzip_dir="$workdir/unzip-$id"
mkdir -p "$unzip_dir"
gh api "repos/$REPO/actions/artifacts/$id/zip" > "$zip_file"
unzip -q -o "$zip_file" -d "$unzip_dir"

found_any=false
while IFS= read -r f; do
found_any=true
cp "$f" "$jsonl_dir/${id}-$(basename "$f")"
done < <(find "$unzip_dir" -type f -name '*.jsonl' -print)

if [ "$found_any" = true ]; then
artifact_count=$((artifact_count + 1))
fi
done < "$artifacts_file"

if ! find "$jsonl_dir" -type f -name '*.jsonl' | grep -q .; then
{
echo "## Token usage (${LOOKBACK_DAYS} day lookback)"
echo
echo "No token-usage artifacts found in the lookback window."
} >> "$GITHUB_STEP_SUMMARY"
exit 0
fi

aggregate="$workdir/token-usage-summary.json"
jq -s '
sort_by(.workflow) |
group_by(.workflow) |
map({
workflow: (.[0].workflow // "unknown"),
calls: length,
input_tokens: (map(.input_tokens // 0) | add),
cache_read_tokens: (map(.cache_read_tokens // 0) | add),
output_tokens: (map(.output_tokens // 0) | add),
et: (map(.et // 0) | add)
}) |
sort_by(.et) | reverse
' "$jsonl_dir"/*.jsonl > "$aggregate"

{
echo "## Token usage (${LOOKBACK_DAYS} day lookback)"
echo
echo "Processed ${artifact_count} token-usage artifact(s)."
echo
echo "| Workflow | Calls | Input Tokens | Cache Read Tokens | Output Tokens | Total ET |"
echo "|---|---:|---:|---:|---:|---:|"
jq -r '.[] | "| \(.workflow) | \(.calls) | \(.input_tokens) | \(.cache_read_tokens) | \(.output_tokens) | \(.et | tostring) |"' "$aggregate"
} >> "$GITHUB_STEP_SUMMARY"

- name: Create issue with findings
if: env.HAS_FAILURES == 'true' && hashFiles('fleet_monitor_report.md') != ''
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
Expand Down Expand Up @@ -367,6 +283,17 @@ jobs:
{"event_type":"dev-lead-ci-failure","client_payload":{"source":"fleet-monitor","count":"${{ env.HIGH_FAILURE_COUNT }}"}}
EOF

- name: Summarize token usage (org-wide)
# Runs after all alerting steps so a token-report failure or timeout does
# not prevent monitoring findings from being created or dispatched.
# continue-on-error keeps this informational step non-blocking.
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }}
ORG: ${{ env.ORG }}
LOOKBACK_DAYS: ${{ env.LOOKBACK_DAYS }}
run: bash scripts/token_report.sh >> "$GITHUB_STEP_SUMMARY"

- name: Annotate clean run
if: env.HAS_FAILURES != 'true'
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: shellcheck
# --severity=warning: SC2016 (info) fires on printf '`%s`' where backticks
# are literal markdown, not shell expressions — suppress info-level noise.
run: shellcheck --severity=warning scripts/fleet_monitor.sh scripts/fleet_report.sh
run: shellcheck --severity=warning scripts/fleet_monitor.sh scripts/fleet_report.sh scripts/token_report.sh scripts/lib/model-pricing.sh

bats:
runs-on: ubuntu-latest
Expand All @@ -34,7 +34,7 @@ jobs:
run: sudo apt-get install -y bats

- name: Run tests
run: bats tests/fleet_report.bats
run: bats tests/fleet_report.bats tests/token_report.bats tests/model_pricing.bats

validate-agent-profiles:
runs-on: ubuntu-latest
Expand Down
119 changes: 119 additions & 0 deletions .github/workflows/token-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# ─────────────────────────────────────────────────────────────────────────────
# SOURCE OF TRUTH: petry-projects/.github-private/.github/workflows/token-report.yml
Comment thread
don-petry marked this conversation as resolved.
#
# AGENTS — READ BEFORE EDITING:
# • Weekly Token Cost Observatory report. The org-wide collection + aggregation
# logic lives in scripts/token_report.sh (unit-tested in tests/token_report.bats).
# • The script reads token-usage artifacts from EVERY non-archived repo in the org,
# so it needs GH_PAT_WORKFLOWS (cross-org actions:read) — github.token cannot read
# other repos' artifacts.
# • The report is posted as a comment on a single pinned tracking issue
# (label: token-report) in .github-private, so github.token suffices for the
# comment step.
# • Do NOT change checkout ref from 'main'.
# ─────────────────────────────────────────────────────────────────────────────
name: Token Cost Report

on:
schedule:
# Mondays at 08:00 UTC — weekly cost rollup before the work week
- cron: '0 8 * * 1'
workflow_dispatch:
inputs:
org:
description: "GitHub org to scan"
required: false
default: "petry-projects"
type: string
lookback_days:
description: "Days of token-usage history to include"
required: false
default: "7"
type: string

permissions:
contents: read
issues: write

Comment thread
coderabbitai[bot] marked this conversation as resolved.
concurrency:
group: token-report-${{ inputs.org || 'petry-projects' }}
cancel-in-progress: true

jobs:
report:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
ORG: ${{ inputs.org || 'petry-projects' }}
LOOKBACK_DAYS: ${{ inputs.lookback_days || '7' }}

steps:
- name: Checkout agent repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: petry-projects/.github-private
ref: main
token: ${{ secrets.GH_PAT_WORKFLOWS }}

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Generate org-wide token report
env:
GH_TOKEN: ${{ secrets.GH_PAT_WORKFLOWS }}
TOKEN_REPORT_OUT: token_report.md
run: |
bash scripts/token_report.sh >> "$GITHUB_STEP_SUMMARY"

- name: Post report to tracking issue
if: hashFiles('token_report.md') != ''
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ github.token }}
script: |
const fs = require('fs');
const MAX = 65000;
let report = fs.readFileSync('token_report.md', 'utf8');
if (!report.trim()) { core.setFailed('Report file is empty'); return; }

const runUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
if (report.length > MAX) {
report = report.slice(0, MAX) +
`\n\n---\n_Report truncated — full output in the [workflow run summary](${runUrl})._`;
}

const LABEL = 'token-report';
const TITLE = '📊 Token Cost Observatory — Weekly Report';

// Ensure the tracking label exists.
try {
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: LABEL });
} catch (e) {
await github.rest.issues.createLabel({
owner: context.repo.owner, repo: context.repo.repo,
name: LABEL, color: '5319e7',
description: 'Weekly Token Cost Observatory report',
});
}

// Find-or-create the single pinned tracking issue.
const existing = await github.paginate(github.rest.issues.listForRepo, {
owner: context.repo.owner, repo: context.repo.repo,
labels: LABEL, state: 'open', per_page: 100,
});

let issue = existing.find(i => i.title === TITLE);
if (!issue) {
const created = await github.rest.issues.create({
owner: context.repo.owner, repo: context.repo.repo,
title: TITLE, labels: [LABEL],
body: 'Tracking issue for the weekly Token Cost Observatory report. ' +
'Each run posts a new comment below with org-wide Effective Tokens (ET) usage.\n\n' +
'Source: `scripts/token_report.sh` · `.github/workflows/token-report.yml`',
});
issue = created.data;
core.notice(`Created tracking issue #${issue.number}: ${issue.html_url}`);
}

const comment = await github.rest.issues.createComment({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: issue.number, body: report,
});
core.notice(`Posted weekly token report: ${comment.data.html_url}`);
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ This is the `.github-private` org infrastructure repo for `petry-projects`. It c
agentic workflow compilation. It is not covered by the org template and must not be removed by template
syncs. If the org template gains a `gh-aw-compile` equivalent, remove this exception and defer to the
template instead.
- **Exception:** `token-report.yml` (weekly Token Cost Observatory report) is a documented repo-specific
workflow with no corresponding org template in `standards/workflows/`. It must not be removed by template
syncs. If the org template gains a token-report equivalent, remove this exception and defer to the
template instead.

### Agent Profiles (`agents/*.md`)

Expand Down
1 change: 1 addition & 0 deletions docs/actions-fleet-monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The fleet summary table is sorted by severity so the worst performers appear fir

- **Step Summary** — fleet table written on every run; visible in the Actions UI without leaving GitHub.
- **GitHub Issue** — opened when any workflow has failed runs; see [Issue destination](#issue-destination) below.
- **Token usage (org-wide)** — each run also appends an Effective Tokens (ET) rollup to the Step Summary via `scripts/token_report.sh`, scanning token-usage artifacts across every repo. The weekly digest is delivered as a tracking-issue comment by `token-report.yml` — see [docs/token-report.md](token-report.md).

## Usage

Expand Down
Loading
Loading