generate-agenda.sh 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #!/bin/bash
  2. set -e
  3. # Configuration
  4. REPO="${GITHUB_REPOSITORY:-cashubtc/cdk}"
  5. DAYS_BACK="${DAYS_BACK:-7}"
  6. MEETING_LINK="https://meet.fulmo.org/cdk-dev"
  7. OUTPUT_DIR="meetings"
  8. # Calculate date range (last 7 days)
  9. SINCE_DATE=$(date -d "$DAYS_BACK days ago" -u +"%Y-%m-%dT%H:%M:%SZ")
  10. MEETING_DATE=$(date -u +"%b %d %Y 15:00 UTC")
  11. FILE_DATE=$(date -u +"%Y-%m-%d")
  12. echo "Generating meeting agenda for $MEETING_DATE"
  13. echo "Fetching data since $SINCE_DATE"
  14. # Function to format PR/issue list
  15. format_list() {
  16. local items="$1"
  17. if [ -z "$items" ]; then
  18. echo "- None"
  19. else
  20. echo "$items" | while IFS=$'\t' read -r number title url; do
  21. echo "- [#$number]($url) - $title"
  22. done
  23. fi
  24. }
  25. PR_TYPES=("feat" "fix" "refactor" "chore" "docs" "ci" "test" "backport")
  26. EXCLUDE_PATTERNS=(
  27. "^\\[Backport"
  28. "Weekly Meeting Agenda"
  29. )
  30. filter_all_types() {
  31. local prs="$1"
  32. local result=""
  33. local combined_regex=""
  34. for type in "${PR_TYPES[@]}"; do
  35. if [ "$type" = "backport" ]; then
  36. # backports are explicitly done in another section.
  37. # They still need to be filtered out of the the others grouping.
  38. regex="^\\[Backport"
  39. combined_regex+="^$type|"
  40. continue
  41. else
  42. regex="^$type"
  43. combined_regex+="^$type|"
  44. fi
  45. filtered=$(echo "$prs" | jq -r --arg regex "$regex" '
  46. .[] | select(.title | ltrimstr(" ") | rtrimstr(" ") | test($regex; "i")) | [.number, .title, .url] | @tsv
  47. ')
  48. if [[ -n "$filtered" ]]; then
  49. result+="$filtered"$'\n'
  50. fi
  51. done
  52. combined_regex="${combined_regex%|}"
  53. # Build exclusion regex from EXCLUDE_PATTERNS
  54. local exclude_regex=$(
  55. IFS="|"
  56. echo "${EXCLUDE_PATTERNS[*]}"
  57. )
  58. other=$(echo "$prs" | jq -r --arg combined_regex "$combined_regex" --arg exclude_regex "$exclude_regex" '
  59. .[] | select((.title | ltrimstr(" ") | rtrimstr(" ") | test($combined_regex; "i") | not) and (.title | ltrimstr(" ") | rtrimstr(" ") | test($exclude_regex; "i") | not)) | [.number, .title, .url] | @tsv
  60. ')
  61. # other=$(echo "$prs" | jq -r --arg combined_regex "$combined_regex" '
  62. # .[] | select(.title | test($combined_regex; "i") | not) | [.number, .title, .url] | @tsv
  63. # ')
  64. if [[ -n "$other" ]]; then
  65. result+="$other"$'\n'
  66. fi
  67. echo "$result"
  68. }
  69. # Fetch merged PRs
  70. echo "Fetching merged PRs..."
  71. MERGED_PRS=$(gh pr list \
  72. --repo "$REPO" \
  73. --state merged \
  74. --search "merged:>=$SINCE_DATE" \
  75. --json number,title,url \
  76. 2>/dev/null || echo "")
  77. MERGED_PRS_FILTERED=$(filter_all_types "$MERGED_PRS")
  78. BACKPORT_PRS=$(echo "$MERGED_PRS" | jq -r '.[] | select(.title | test("^\\[Backport"; "i")) | [.number, .title, .url] | @tsv')
  79. # Fetch recently active PRs (updated in last week, but not newly created)
  80. echo "Fetching recently active PRs..."
  81. RECENTLY_ACTIVE_PRS=$(gh pr list \
  82. --repo "$REPO" \
  83. --state open \
  84. --search "updated:>=$SINCE_DATE -created:>=$SINCE_DATE" \
  85. --json number,title,url \
  86. 2>/dev/null || echo "")
  87. RECENTLY_ACTIVE_PRS_FILTERED=$(filter_all_types "$RECENTLY_ACTIVE_PRS")
  88. # Fetch new PRs (opened in the last week)
  89. echo "Fetching new PRs..."
  90. NEW_PRS=$(gh pr list \
  91. --repo "$REPO" \
  92. --state open \
  93. --search "created:>=$SINCE_DATE" \
  94. --json number,title,url \
  95. 2>/dev/null || echo "")
  96. NEW_PRS_FILTERED=$(filter_all_types "$NEW_PRS")
  97. # Fetch new issues
  98. echo "Fetching new issues..."
  99. NEW_ISSUES=$(gh issue list \
  100. --repo "$REPO" \
  101. --state open \
  102. --search "created:>=$SINCE_DATE" \
  103. --json number,title,url \
  104. --jq '.[] | [.number, .title, .url] | @tsv' \
  105. 2>/dev/null || echo "")
  106. # Fetch discussion items (labeled with meeting-discussion)
  107. echo "Fetching discussion items..."
  108. DISCUSSION_PRS=$(gh pr list \
  109. --repo "$REPO" \
  110. --state open \
  111. --label "meeting-discussion" \
  112. --json number,title,url \
  113. --jq '.[] | [.number, .title, .url] | @tsv' \
  114. 2>/dev/null || echo "")
  115. DISCUSSION_ISSUES=$(gh issue list \
  116. --repo "$REPO" \
  117. --state open \
  118. --label "meeting-discussion" \
  119. --json number,title,url \
  120. --jq '.[] | [.number, .title, .url] | @tsv' \
  121. 2>/dev/null || echo "")
  122. # Combine discussion items (PRs and issues)
  123. DISCUSSION_ITEMS=$(printf "%s\n%s" "$DISCUSSION_PRS" "$DISCUSSION_ISSUES" | grep -v '^$' || echo "")
  124. echo "Fetching merged PRs from the nuts repo..."
  125. MERGED_NUTS=$(gh pr list \
  126. --repo cashubtc/nuts \
  127. --state merged \
  128. --search "merged:>=$SINCE_DATE" \
  129. --json number,title,url \
  130. --jq '.[] | [.number, .title, .url] | @tsv' \
  131. 2>/dev/null || echo "")
  132. # Generate markdown
  133. AGENDA=$(
  134. cat <<EOF
  135. # CDK Development Meeting
  136. $MEETING_DATE
  137. Meeting Link: $MEETING_LINK
  138. ## Merged
  139. $(format_list "$MERGED_PRS_FILTERED")
  140. ## New
  141. ### Issues
  142. $(format_list "$NEW_ISSUES")
  143. ### PRs
  144. $(format_list "$NEW_PRS_FILTERED")
  145. ## Recently Active
  146. $(format_list "$RECENTLY_ACTIVE_PRS_FILTERED")
  147. ## Merged NUTS
  148. $(format_list "$MERGED_NUTS")
  149. ## Backports
  150. $(format_list "$BACKPORT_PRS")
  151. ## Discussion
  152. $(format_list "$DISCUSSION_ITEMS")
  153. EOF
  154. )
  155. echo "$AGENDA"
  156. # Output to file if requested
  157. if [ "${OUTPUT_TO_FILE:-true}" = "true" ]; then
  158. mkdir -p "$OUTPUT_DIR"
  159. OUTPUT_FILE="$OUTPUT_DIR/$FILE_DATE-agenda.md"
  160. echo "$AGENDA" >"$OUTPUT_FILE"
  161. echo "Agenda saved to $OUTPUT_FILE"
  162. fi
  163. # Create GitHub Discussion if requested
  164. if [ "${CREATE_DISCUSSION:-false}" = "true" ]; then
  165. echo "Creating GitHub discussion..."
  166. DISCUSSION_TITLE="CDK Dev Meeting - $MEETING_DATE"
  167. # Note: gh CLI doesn't have direct discussion creation yet, so we'd need to use the API
  168. # For now, we'll just output instructions
  169. echo "To create discussion manually, use the GitHub web interface or API"
  170. echo "Title: $DISCUSSION_TITLE"
  171. fi
  172. # Output for GitHub Actions
  173. if [ -n "$GITHUB_OUTPUT" ]; then
  174. echo "agenda_file=$OUTPUT_FILE" >>"$GITHUB_OUTPUT"
  175. echo "meeting_date=$MEETING_DATE" >>"$GITHUB_OUTPUT"
  176. fi