scheduled-ci-trigger.yml 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. name: Weekly CI Scheduler
  2. on:
  3. # Runs at 08:00 Beijing time every day
  4. schedule:
  5. - cron: '0 0 * * *'
  6. workflow_dispatch:
  7. inputs:
  8. debug:
  9. description: 'Debug mode'
  10. required: false
  11. default: 'false'
  12. env:
  13. TARGET_WORKFLOWS: '["RT-Thread BSP Static Build Check", "utest_auto_run"]'
  14. DISCUSSION_CATEGORY: "Github Action Exception Reports"
  15. jobs:
  16. trigger-and-monitor:
  17. name: Trigger and Monitor CIs
  18. runs-on: ubuntu-latest
  19. outputs:
  20. failed_workflows: ${{ steps.collect-results.outputs.failed_workflows }}
  21. total_workflows: ${{ steps.collect-results.outputs.total_workflows }}
  22. has_results: ${{ steps.collect-results.outputs.has_results }}
  23. steps:
  24. - name: Checkout repository
  25. uses: actions/checkout@v4
  26. - name: Install Python dependencies
  27. run: |
  28. python -m pip install --upgrade pip
  29. pip install requests
  30. - name: Record start time
  31. id: start-time
  32. run: |
  33. echo "start_time=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
  34. echo "Start time: $(date -u +'%Y-%m-%dT%H:%M:%SZ')"
  35. - name: Trigger CI workflows directly
  36. id: trigger-ci
  37. run: |
  38. python tools/ci/scheduled-ci-trigger/trigger_workflows_direct.py
  39. env:
  40. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  41. TARGET_WORKFLOWS: ${{ env.TARGET_WORKFLOWS }}
  42. - name: Wait for workflows to appear
  43. id: wait-for-workflows
  44. run: |
  45. echo "Waiting for workflows to appear in API..."
  46. python tools/ci/scheduled-ci-trigger/wait_for_workflows.py "${{ steps.start-time.outputs.start_time }}"
  47. env:
  48. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  49. TARGET_WORKFLOWS: ${{ env.TARGET_WORKFLOWS }}
  50. - name: Monitor CI workflows
  51. id: monitor-ci
  52. run: |
  53. python tools/ci/scheduled-ci-trigger/monitor_workflows.py "${{ steps.start-time.outputs.start_time }}"
  54. env:
  55. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  56. TARGET_WORKFLOWS: ${{ env.TARGET_WORKFLOWS }}
  57. - name: Collect monitoring results
  58. id: collect-results
  59. run: |
  60. echo "Checking for monitoring results..."
  61. if [ -f "monitoring_results.json" ]; then
  62. echo "monitoring_results.json found"
  63. FAILED_COUNT=$(python -c "import json; data=json.load(open('monitoring_results.json')); print(len([w for w in data if w.get('conclusion') == 'failure']))")
  64. TOTAL_COUNT=$(python -c "import json; data=json.load(open('monitoring_results.json')); print(len(data))")
  65. echo "failed_workflows=$FAILED_COUNT" >> $GITHUB_OUTPUT
  66. echo "total_workflows=$TOTAL_COUNT" >> $GITHUB_OUTPUT
  67. echo "has_results=true" >> $GITHUB_OUTPUT
  68. echo "Results: $FAILED_COUNT failed out of $TOTAL_COUNT total"
  69. else
  70. echo "monitoring_results.json not found"
  71. echo "failed_workflows=0" >> $GITHUB_OUTPUT
  72. echo "total_workflows=0" >> $GITHUB_OUTPUT
  73. echo "has_results=false" >> $GITHUB_OUTPUT
  74. fi
  75. - name: Generate detailed report
  76. if: steps.collect-results.outputs.has_results == 'true' && steps.collect-results.outputs.failed_workflows != '0'
  77. id: generate-report
  78. run: |
  79. echo "Generating detailed report..."
  80. python tools/ci/scheduled-ci-trigger/generate_report.py
  81. echo "Report generation completed"
  82. - name: Upload report artifact
  83. if: steps.collect-results.outputs.has_results == 'true' && steps.collect-results.outputs.failed_workflows != '0'
  84. uses: actions/upload-artifact@v4
  85. with:
  86. name: ci-failure-report
  87. path: |
  88. monitoring_results.json
  89. failure_details.md
  90. retention-days: 7
  91. create-discussion:
  92. name: Create Discussion Report
  93. needs: trigger-and-monitor
  94. if: needs.trigger-and-monitor.outputs.has_results == 'true' && needs.trigger-and-monitor.outputs.failed_workflows != '0'
  95. runs-on: ubuntu-latest
  96. steps:
  97. - name: Checkout repository
  98. uses: actions/checkout@v4
  99. - name: Download report artifact
  100. uses: actions/download-artifact@v4
  101. with:
  102. name: ci-failure-report
  103. - name: Create Discussion
  104. uses: actions/github-script@v6
  105. env:
  106. DISCUSSION_CATEGORY: ${{ env.DISCUSSION_CATEGORY }}
  107. with:
  108. script: |
  109. const fs = require('fs');
  110. const reportPath = './failure_details.md';
  111. let reportContent = fs.readFileSync(reportPath, 'utf8');
  112. // 提取日期从第一行: # YYYYMMDD_ci_integration-failed-report
  113. const lines = reportContent.split('\n');
  114. const firstLine = lines[0].trim();
  115. const dateMatch = firstLine.match(/# (\d{8})_ci_integration-failed-report/);
  116. if (!dateMatch) {
  117. console.error('Failed to extract date from first line:', firstLine);
  118. process.exit(1);
  119. }
  120. const dateString = dateMatch[1];
  121. const discussionTitle = `${dateString}_ci_integration-failed-report`;
  122. // === 关键修复:移除第一行(用于提取的隐藏行) ===
  123. reportContent = lines.slice(1).join('\n').trim();
  124. // 获取仓库ID和分类ID
  125. const getRepoQuery = `
  126. query($owner: String!, $repo: String!) {
  127. repository(owner: $owner, name: $repo) {
  128. id
  129. discussionCategories(first: 20) {
  130. nodes {
  131. id
  132. name
  133. }
  134. }
  135. }
  136. }
  137. `;
  138. const repoData = await github.graphql(getRepoQuery, {
  139. owner: context.repo.owner,
  140. repo: context.repo.repo
  141. });
  142. const repositoryId = repoData.repository.id;
  143. const categories = repoData.repository.discussionCategories.nodes;
  144. const targetCategory = categories.find(cat => cat.name === process.env.DISCUSSION_CATEGORY);
  145. if (!targetCategory) {
  146. console.error('Category not found:', process.env.DISCUSSION_CATEGORY);
  147. process.exit(1);
  148. }
  149. const createDiscussionMutation = `
  150. mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!) {
  151. createDiscussion(input: {
  152. repositoryId: $repositoryId
  153. categoryId: $categoryId
  154. title: $title
  155. body: $body
  156. }) {
  157. discussion {
  158. id
  159. title
  160. url
  161. }
  162. }
  163. }
  164. `;
  165. const result = await github.graphql(createDiscussionMutation, {
  166. repositoryId: repositoryId,
  167. categoryId: targetCategory.id,
  168. title: discussionTitle,
  169. body: reportContent // 使用清理后的内容(无第一行)
  170. });
  171. console.log('Discussion created successfully:', result.createDiscussion.discussion.url);