Engineering Year in Review Guide

For our team’s final 2025 meeting, I made a nice 2025 end-of-year report on our code entropy over the past year, with a focus on recognizing the contributions of our team. Sharing this guide for anyone who might want to do something similar.

It’s nice to have a snapshot of what a team accomplished in code form: code commits, PR reviews, cross-repo work, security patches, dependency updates - it all adds up to something worth celebrating.

What it produces

  • Markdown and HTML reports with contribution graphs
  • GitHub-style activity heatmaps
  • Tiered contributor rankings
  • Year-over-year trend analysis
  • Code review metrics via GitHub API
  • Cross-repo collaboration stats

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# Engineering Year in Review - Annual Report Generation Guide

**THIS DOCUMENT IS FOR AI CODING/RESEARCH AGENTS** - Follow these instructions exactly.

## MANDATORY REQUIREMENTS:
1. **NEVER ESTIMATE PR REVIEW STATISTICS** - Always use GitHub API for accurate data
2. **Install required packages FIRST** before attempting to generate reports
3. **Check for GitHub API token in .env or .bashrc** - Ask user for one if missing
4. **All statistics must be EXACT** - No rounding, no approximate numbers, no "~" or "+" symbols

## Before Starting:
> # Check if dependencies are installed
> which node && which python3 && which git || echo "Missing dependencies!"
>
> # Check for GitHub token
> grep GITHUB_TOKEN ~/acme-web/.env || echo "NO GITHUB TOKEN - ASK USER!"
>
> # Install Node packages if missing
> cd ~/acme-web && npm list @octokit/rest || npm install @octokit/rest @octokit/plugin-paginate-rest

## Overview
This guide provides step-by-step instructions for creating the annual engineering year-in-review report, including both markdown and HTML versions with contribution visualizations. All data must be fetched from actual sources - estimates are not acceptable.

## Prerequisites

### Required Software
- Access to all engineering repositories (web, mobile, legacy)
- Git command line tools
- Node.js 18+ for GitHub API interactions
- Bash scripting capabilities

### Required API Keys
- **GitHub Personal Access Token** with `repo` and `read:org` permissions
  - Required for accurate PR review statistics (NEVER use estimates)
  - Check `.bashrc` or `.env` for existing tokens first
  - Store in `.env` as `GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx`
  - Generate at: https://github.com/settings/tokens/new

### Installation Instructions for Future Agents

> # 1. Install required Node.js packages for GitHub API access
> cd ~/acme-web
> npm install @octokit/rest @octokit/plugin-paginate-rest
>
> # 2. Verify GitHub API access
> export GITHUB_TOKEN="your-github-token-here"
> curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user
>
> # 3. Clone all required repositories (if not already present)
> cd ~
> git clone https://github.com/AcmeCorp/acme-web.git
> git clone https://github.com/AcmeCorp/survey-web.git
> git clone https://github.com/AcmeCorp/web-legacy.git
> git clone https://github.com/AcmeCorp/mobile-android.git
> git clone https://github.com/AcmeCorp/mobile-ios.git

### Environment Configuration
Create or update `~/acme-web/.env` with:
> # GitHub API Access (REQUIRED - NEVER ESTIMATE PR REVIEWS)
> GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
> GITHUB_ORG=AcmeCorp
>
> # Repository names for analysis
> REPOS_TO_ANALYZE=acme-web,survey-web,web-legacy,mobile-android,mobile-ios

## Repository Setup

### 1. Ensure All Repositories Are Current
**CRITICAL**: Always pull latest changes before analysis
> # For each repository:
> cd ~/acme-web && git pull
> cd ~/survey-web && git pull
> cd ~/web-legacy && git pull
> cd ~/mobile-android && git pull
> cd ~/mobile-ios && git pull

## Data Collection Phase

### 2. Year-over-Year Trend Analysis

**IMPORTANT**: Always calculate and include YoY trends for major metrics.

#### gather_yoy_stats.sh
> #!/bin/bash
> # Gathers statistics for current and previous year for trend analysis
>
> CURRENT_YEAR=$(date +%Y)
> PREVIOUS_YEAR=$((CURRENT_YEAR - 1))
> REPOS=("acme-web" "survey-web" "web-legacy" "mobile-android" "mobile-ios")
>
> echo "=== Year-over-Year Statistics ==="
> for repo in "${REPOS[@]}"; do
>     if [ -d "~/$repo" ]; then
>         echo ""
>         echo "$repo:"
>         prev_commits=$(git -C "~/$repo" log --since="$PREVIOUS_YEAR-01-01" --until="$PREVIOUS_YEAR-12-31" --oneline 2>/dev/null | wc -l)
>         curr_commits=$(git -C "~/$repo" log --since="$CURRENT_YEAR-01-01" --until="$CURRENT_YEAR-12-31" --oneline 2>/dev/null | wc -l)
>
>         prev_contributors=$(git -C "~/$repo" log --since="$PREVIOUS_YEAR-01-01" --until="$PREVIOUS_YEAR-12-31" --format="%an" 2>/dev/null | sort -u | wc -l)
>         curr_contributors=$(git -C "~/$repo" log --since="$CURRENT_YEAR-01-01" --until="$CURRENT_YEAR-12-31" --format="%an" 2>/dev/null | sort -u | wc -l)
>
>         # Calculate percentage changes
>         commit_change=$(echo "scale=1; (($curr_commits - $prev_commits) * 100) / $prev_commits" | bc)
>         contributor_change=$(echo "scale=1; (($curr_contributors - $prev_contributors) * 100) / $prev_contributors" | bc)
>
>         echo "  Commits: $prev_commits → $curr_commits (${commit_change}%)"
>         echo "  Contributors: $prev_contributors → $curr_contributors (${contributor_change}%)"
>     fi
> done

**Key Metrics to Track YoY:**
- Total commits per repository
- Unique contributors
- Lines of code added/removed
- Files touched
- Average commits per contributor
- Mobile releases shipped
- Code velocity (lines changed per month)

### 3. Create Analysis Scripts

#### comprehensive_analyze.sh
> #!/bin/bash
> # Analyzes all repositories for the year
> YEAR=2026  # Update annually
> REPOS=("acme-web" "survey-web" "web-legacy" "mobile-android" "mobile-ios")
>
> for repo in "${REPOS[@]}"; do
>     echo "=== $repo ==="
>     cd ~/$repo
>     git log --since="$YEAR-01-01" --until="$YEAR-12-31" --format="%an" | sort | uniq -c | sort -rn
>     echo "Total commits: $(git log --since="$YEAR-01-01" --until="$YEAR-12-31" --oneline | wc -l)"
> done

#### generate_contribution_graph.py
Create a Python script to generate GitHub-style contribution graph data:
- Process daily commits across all repos
- Generate HTML with responsive tiles
- Use company brand colors (#3e90ed for Acme)
- Export to JSON for flexibility

### 3. Collect Key Metrics

#### Commits per Contributor
> # Get exact commit counts per person across all repos
> (
>   git -C acme-web log --since="2025-01-01" --until="2025-12-31" --format="%an"
>   git -C survey-web log --since="2025-01-01" --until="2025-12-31" --format="%an"
>   git -C web-legacy log --since="2025-01-01" --until="2025-12-31" --format="%an"
>   git -C mobile-android log --since="2025-01-01" --until="2025-12-31" --format="%an"
>   git -C mobile-ios log --since="2025-01-01" --until="2025-12-31" --format="%an"
> ) | sort | uniq -c | sort -rn > contributor_stats.txt

#### Repository-Specific Counts
> # Get per-repo breakdown for each contributor
> for contributor in "Jordan Chen" "Sarah Mitchell" "marcusw" "henriklars"; do
>   echo "$contributor:"
>   for repo in acme-web survey-web web-legacy; do
>     count=$(git -C $repo log --since="2025-01-01" --until="2025-12-31" \
>       --format="%an" | grep -c "^$contributor$")
>     echo "  $repo: $count"
>   done
> done

#### Name Mapping (CRITICAL)
Many contributors use git names different from display names:
- **marcusw** → Marcus Webb
- **henriklars** → Henrik Larsson
- **andersn** → Anders Nilsen
- **tbrooks** → Taylor Brooks
- **davidpark-acme** → David Park
- **christorres-acme** → Chris Torres
- **mellis96** → Morgan Ellis
- **lucasf/Lucas Fernandez** → Lucas Fernandez

Consolidate names where appropriate.

**Key Metrics to Collect:**
- **Total commits** per repository
- **Unique contributors** per repository
- **Cross-repository collaboration** (who worked on multiple repos)
- **Mobile releases** (count versions shipped)
- **Daily commit activity** for contribution graph
- **Monthly activity trends**

## Report Structure

### 4. Create Markdown Report Structure

> # 2026 Engineering Year in Review
>
> ## Executive Summary
> - Total commits across all repositories (with YoY % change)
> - Total unique contributors (with YoY % change)
> - Key achievements summary
> - Year-over-Year trends summary
>
> ## Year-over-Year Trend Analysis (NEW REQUIRED SECTION)
> - Overall metrics table (commits, contributors, productivity - both increases and decreases)
> - Repository-specific trends (each repo's YoY changes)
> - Productivity trends visualization
> - Engineering focus areas evolution (previous year vs current year)
>
> ## Repository Performance Overview
> - Table with commits, contributors, percentages
> - Monthly activity chart (ASCII art style)
>
> ## Complete Contributor Recognition
> ### Platform Champions (100+ commits)
> ### Core Contributors (50-99 commits)
> ### Valuable Contributors (10-49 commits)
> ### Supporting Contributors (1-9 commits)
>
> ## Cross-Repository Collaboration Excellence
> - List engineers working on 3+ repos
> - List engineers working on 2 repos
>
> ## Major Technical Achievements by Platform
> - Break down by repository
> - Include contributor attribution
> - Reference Jira tickets where applicable
>
> ## Code Review & Collaboration Excellence
> - Most active reviewers
> - Review pair collaborations
>
> ## The Unreasonable Effectiveness of One Hour per Week of Focused Time
> - Dependency management achievements
> - CVE fixes
> - Security updates
>
> ## Appendix: Data Collection Methodology

## Formatting Requirements

### 5. Contributor Recognition Rules
- **IMPORTANT**: Include ALL contributors, no matter how small their contribution
- Group by commit ranges for organization
- For each contributor include:
  - Name (with any medal/emoji if top contributor)
  - Commit count and repositories worked on
  - Specific achievements or focus areas
  - Latest commit date for active contributors

### 6. Name Corrections
Maintain a mapping of git names to display names:
- mellis96 → Morgan Ellis
- andersn → Anders Nilsen
- marcusw → Marcus Webb
- henriklars → Henrik Larsson
- christorres-acme → Chris Torres
- lucasf/Lucas Fernandez → Lucas Fernandez (consolidate)

### 7. Special Placement Rules
- Place Jordan Chen LAST in any top contributor list (no medals)

## HTML Version Requirements

### 8. HTML Styling Guidelines
- Use #3e90ed as primary brand color
- Create responsive grid layouts:
  - Desktop: 3 columns
  - Tablet: 2 columns
  - Mobile: 1 column
- No left-side borders on sections
- White text on blue backgrounds
- Compact layout with minimal spacing

### 9. GitHub-Style Contribution Graph
- Place ABOVE Executive Summary
- Full width responsive design
- Tiles scale with container
- Simple weekday labels (Sun at top, Sat at bottom)
- Tooltip with date and commit count
- Blue color gradient (#3e90ed based)

### 10. Card-Based Layouts
Use card grids for:
- Contributor recognition
- Weekly dependency review process
- Code review champions
- Any grouped information

## Content Guidelines

### 11. Technical Achievements
- Attribute features to specific contributors
- Reference Jira tickets (ACME-XXXXX)
- Group by platform/repository
- Include both shipped features and infrastructure improvements

### 12. Dependency Management Section
Title: "The Unreasonable Effectiveness of One Hour per Week of Focused Time"
- Emphasize weekly one-hour meetings
- Include CVE fixes with attribution
- Security achievements
- License compliance
- Technical debt prevention

### 13. Code Review Metrics - ACCURATE DATA REQUIRED

**CRITICAL**: NEVER use estimated PR review counts. Always fetch actual data from GitHub API.

#### Implementation Approach

**Method 1: GitHub Search API (More Efficient)**
Use the GitHub Search API to get review counts for known contributors:

> #!/usr/bin/env node
> const https = require('https');
>
> // GitHub token - check .bashrc or .env first
> const GITHUB_TOKEN = process.env.GITHUB_TOKEN || 'check-bashrc-for-token';
>
> // Repositories to analyze
> const REPOS = [
>   { owner: 'AcmeCorp', name: 'acme-web' },
>   { owner: 'AcmeCorp', name: 'survey-web' },
>   { owner: 'AcmeCorp', name: 'web-legacy' },
>   { owner: 'AcmeCorp', name: 'mobile-android' },
>   { owner: 'AcmeCorp', name: 'mobile-ios' }
> ];
>
> // Name mapping (CRITICAL - keep this updated)
> const NAME_MAP = {
>   'marcusw': 'Marcus Webb',
>   'henriklars': 'Henrik Larsson',
>   'andersn': 'Anders Nilsen',
>   'tbrooks': 'Taylor Brooks',
>   'davidpark-acme': 'David Park',
>   'christorres-acme': 'Chris Torres',
>   'jordanc': 'Jordan Chen',
>   'jchen': 'Jordan Chen',  // Same person, different account
>   'erodriguez-acme': 'Elena Rodriguez',
>   'jwilson': 'Jamie Wilson',
>   'jwilsondev': 'Jamie Wilson',
>   'rpatel-acme': 'Raj Patel',
>   'alexkim-acme': 'Alex Kim'
> };
>
> async function searchPRReviews() {
>   const reviewCounts = {};
>
>   // List of known contributors to check
>   const knownUsers = Object.keys(NAME_MAP);
>
>   // For each user, search for their PR reviews in the target year
>   for (const username of knownUsers) {
>     // Use GitHub Search API: reviewed-by:username created:YEAR-01-01..YEAR-12-31
>     const query = `org:AcmeCorp reviewed-by:${username} created:2025-01-01..2025-12-31`;
>     const searchPath = `/search/issues?q=${encodeURIComponent(query)}&type=pr&per_page=100`;
>
>     // Make API request and get total_count from search results
>     const result = await makeGitHubRequest(searchPath);
>
>     if (result.total_count > 0) {
>       reviewCounts[username] = result.total_count;
>     }
>
>     // Add delay to avoid rate limiting
>     await new Promise(resolve => setTimeout(resolve, 500));
>   }
>
>   return reviewCounts;
> }

**Method 2: Direct PR Review Fetching (More Thorough but Slower)**
> // Pseudocode for fetching all PR reviews:
> // 1. For each repository:
> //    a. Fetch all PRs from the target year
> //    b. For each PR:
> //       - Fetch all reviews for that PR
> //       - Count reviews by user
> // 2. Aggregate counts across all repos
> // 3. Map GitHub usernames to display names
> // 4. Sort by review count descending

#### Key Implementation Details

1. **Token Location**: Always check `.bashrc` first:
   > grep GITHUB_TOKEN ~/.bashrc
   > # Often tokens are stored as: export GITHUB_TOKEN="ghp_..."

2. **Efficient Searching**: Use GitHub Search API with query:
   > org:AcmeCorp reviewed-by:USERNAME created:YEAR-01-01..YEAR-12-31

3. **Name Mapping**: CRITICAL - Map GitHub usernames to real names

4. **Output Format**: Must be exact counts:
   > Jordan Chen: 843 PR Reviews
   > Marcus Webb: 558 PR Reviews
   > Henrik Larsson: 503 PR Reviews
   NEVER use "~843" or "550+" or "around 500"

5. **Rate Limiting**: Add delays between API calls (100-500ms)

#### Expected Output
> {
>   "reviewStats": [
>     {"name": "Jordan Chen", "count": 843},
>     {"name": "Marcus Webb", "count": 558},
>     {"name": "Henrik Larsson", "count": 503},
>     {"name": "Chris Torres", "count": 330},
>     {"name": "Taylor Brooks", "count": 186},
>     {"name": "David Park", "count": 119},
>     {"name": "Anders Nilsen", "count": 93}
>   ]
> }

**IMPORTANT REMINDERS**:
- NEVER estimate or approximate review counts
- Always check .bashrc for existing GitHub tokens before asking user
- Use exact counts from API, no rounding
- Include all reviewers, even those with 1 review
- Map GitHub usernames to real names consistently

## Quality Checks

### 14. Data Validation
- Cross-check contributor counts
- Ensure total commits match sum of individual repos
- Validate that ALL contributors are mentioned

### 15. Final Review Checklist
- [ ] All repositories pulled to latest
- [ ] Contribution graph visible and working
- [ ] All contributors recognized
- [ ] Names correctly formatted
- [ ] HTML is responsive
- [ ] Cards use company colors

## Avoiding Common Pitfalls

### 16. Things to AVOID
- Don't use "up from" or "down from" comparison language
- Don't include "Looking Forward to [Next Year]" section
- Don't create empty commits in git
- Don't miss mobile repositories (they have fewer commits but are important)
- Don't create infinite loops in contribution graph generation

### 17. Things to EMPHASIZE
- Every contributor matters
- Cross-repository collaboration
- Security and dependency management

## Output Files

### 18. Deliverables
1. `~/YEAR-full-review.md` - Complete markdown report
2. `~/YEAR-full-review.html` - Styled HTML version
3. `~/YEAR-review/contribution_data.json` - Graph data
4. `~/YEAR-review/daily_commits.json` - Daily activity data

---

**Remember**: The goal is to recognize EVERYONE's contribution while highlighting major achievements. Every commit counts, and every contributor should feel like their contributions are recognized in the final report.