Skip to content
Open
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
3 changes: 3 additions & 0 deletions community-dashboard/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cdk/cdk.out
cdk/node_modules
.git
14 changes: 14 additions & 0 deletions community-dashboard/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SQLite database with metrics data (generated by strands-metrics)
metrics.db

# Rust build artifacts
strands-metrics/target/

# CDK
cdk/node_modules/
cdk/cdk.out/
cdk/dist/
cdk/.env

# Docker local data
docker/data/
130 changes: 130 additions & 0 deletions community-dashboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# community-dashboard

GitHub metrics collection and Grafana dashboards for the [strands-agents](https://github.com/strands-agents) organization.

A unified Docker container syncs GitHub data (issues, PRs, stars, commits, CI runs, reviews, comments) into a local SQLite database on a daily cron schedule, and serves pre-built Grafana dashboards for org-wide health and triage visibility.


## Directory Structure

```
community-dashboard/
├── README.md ← you are here
├── docker/
│ ├── Dockerfile ← unified Grafana + metrics-sync image
│ ├── entrypoint.sh ← initial backfill, cron, then Grafana
│ └── docker-compose.local.yaml ← local dev compose
├── provisioning/ ← Grafana auto-provisioning
│ ├── datasources/
│ │ └── automatic.yaml ← SQLite datasource
│ └── dashboards/
│ ├── dashboards.yaml ← dashboard provider config
│ ├── health.json ← org health dashboard
│ └── triage.json ← triage dashboard
├── strands-metrics/ ← Rust CLI (syncs GitHub → SQLite)
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs
│ ├── client.rs
│ ├── db.rs
│ └── aggregates.rs
└── cdk/ ← AWS CDK deployment
├── bin/app.ts
├── lib/community-dashboard-stack.ts
├── package.json
├── tsconfig.json
├── cdk.json
└── .env.example
```

## Prerequisites

| Tool | Purpose |
|------|---------|
| **Docker** + **Docker Compose** | Build & run the unified container |
| **GitHub PAT** | Token with read access to the `strands-agents` org (public repos) |
| **Node.js** ≥ 18 | CDK CLI (AWS deployment only) |
| **AWS CDK CLI** | `npm install -g aws-cdk` (AWS deployment only) |
| **Rust toolchain** | Only needed if building strands-metrics locally outside Docker |

## Local Development

Build and run the unified container locally:

```bash
cd community-dashboard
GITHUB_TOKEN=ghp_your_token docker compose -f docker/docker-compose.local.yaml up --build
```

On first start the container will:
1. Run a full GitHub sync (this takes a few minutes)
2. Start a daily cron job (06:00 UTC) for incremental syncs
3. Launch Grafana

Open [http://localhost:3000](http://localhost:3000) — no login required (anonymous read-only).

The SQLite database is persisted in `docker/data/` on the host so subsequent restarts skip the initial backfill.

### Running strands-metrics standalone

If you prefer to run the Rust CLI directly (without Docker):

```bash
cd strands-metrics
GITHUB_TOKEN=ghp_xxx cargo run --release -- sync # full/incremental sync
GITHUB_TOKEN=ghp_xxx cargo run --release -- sweep # reconcile stale open items
cargo run --release -- query "SELECT date, stars FROM daily_metrics WHERE repo='sdk-python' ORDER BY date DESC LIMIT 10"
```

By default the CLI writes to `../metrics.db` (the `community-dashboard/` root).

## AWS Deployment

The CDK stack deploys everything to AWS as a single Fargate service with EFS-backed persistent storage:

```
CloudFront (HTTPS) → ALB (HTTP:80) → ECS Fargate → unified Docker image → EFS (metrics.db)
```

### 1. Create the GitHub token secret

```bash
aws secretsmanager create-secret \
--name strands-grafana/github-token \
--secret-string "ghp_your_token" \
--region us-west-2
```

### 2. Configure and deploy

```bash
cd cdk
cp .env.example .env
# Edit .env — set GITHUB_SECRET_ARN to the ARN from step 1

npm install
npx cdk deploy
```

The stack creates:
- **VPC** (2 AZs, 1 NAT gateway)
- **EFS** file system with access point at `/grafana-data` (RETAIN policy)
- **ECS Fargate** service (0.5 vCPU, 1 GB RAM)
- **ALB** on port 80 with health check at `/api/health`
- **CloudFront** distribution for HTTPS access

The Grafana URL (HTTPS) is printed in the stack outputs.

### Tear down

```bash
cd cdk
npx cdk destroy
```

> **Note:** The EFS file system has a RETAIN removal policy — delete it manually if you want to remove the data.

## Dashboards

- **Health** — org-wide metrics: stars, open issues & PRs, merge times (internal vs external), CI health, code churn, time-to-first-response
- **Triage** — focused view for issue/PR triage workflows
3 changes: 3 additions & 0 deletions community-dashboard/cdk/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ARN of the Secrets Manager secret holding the GitHub personal access token.
# The secret value should be a plain-text token (not JSON).
GITHUB_SECRET_ARN=arn:aws:secretsmanager:us-west-2:ACCOUNT:secret:strands-grafana/github-token
24 changes: 24 additions & 0 deletions community-dashboard/cdk/bin/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env node
import "source-map-support/register";
import * as dotenv from "dotenv";
import * as cdk from "aws-cdk-lib";
import { CommunityDashboardStack } from "../lib/community-dashboard-stack";

// Load environment variables from .env file (if present)
dotenv.config();

const app = new cdk.App();

const env = {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION ?? process.env.AWS_REGION ?? "us-west-2",
};

new CommunityDashboardStack(app, "CommunityDashboardStack", {
env,
description:
"Community Dashboard — GitHub metrics collection and dashboards for strands-agents org",
tags: {
Project: "community-dashboard",
},
});
26 changes: 26 additions & 0 deletions community-dashboard/cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"app": "npx ts-node --prefer-ts-exts bin/app.ts",
"watch": {
"include": ["**"],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": ["aws"],
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false
}
}
Loading