diff --git a/.github/workflows/README_CI_RESULTS.md b/.github/workflows/README_CI_RESULTS.md deleted file mode 100644 index f3bcd2b7a64..00000000000 --- a/.github/workflows/README_CI_RESULTS.md +++ /dev/null @@ -1,139 +0,0 @@ -# CI Results Comment Workflow - -## Overview / 概述 - -This feature automatically posts CI test results as comments on Pull Requests, making it easier for contributors and reviewers to see the status of all CI checks at a glance. - -此功能自动将 CI 测试结果作为评论发布到 Pull Request 中,使贡献者和审阅者更容易一目了然地看到所有 CI 检查的状态。 - -## Implementation / 实现方式 - -The feature uses **two complementary approaches** to ensure CI results are always visible: -该功能使用**两种互补方法**来确保 CI 结果始终可见: - -### 1. Direct Workflow Integration (Immediate) / 直接工作流集成(立即生效) - -Each main CI workflow includes a `post-ci-status` job that: -每个主要 CI 工作流都包含一个 `post-ci-status` 作业,它: - -- ✅ Works immediately on PR branches (no merge required) / 立即在 PR 分支上生效(无需合并) -- 📝 Updates a single comment with workflow status / 使用工作流状态更新单个评论 -- 🔄 Runs after each workflow completes / 在每个工作流完成后运行 - -**Modified Workflows:** -- `bsp_buildings.yml` -- `static_code_analysis.yml` -- `format_check.yml` -- `utest_auto_run.yml` - -### 2. Workflow Run Trigger (After Merge) / 工作流运行触发器(合并后) - -The `ci_results_comment.yml` workflow: -`ci_results_comment.yml` 工作流: - -- ⏰ Triggers when CI workflows complete / 在 CI 工作流完成时触发 -- 📊 Provides comprehensive summary of all workflows / 提供所有工作流的全面摘要 -- 🔍 Shows detailed job-level information / 显示详细的作业级信息 -- ⚠️ **Only works after merged to master** / **仅在合并到 master 后才有效** - -## Features / 功能特性 - -1. **Automatic Updates / 自动更新**: The comment is automatically created when CI workflows complete and updated as new workflows finish. - / 当 CI 工作流完成时自动创建评论,并在新工作流完成时更新。 - -2. **Comprehensive Summary / 全面总结**: Shows the status of all major CI workflows including: - / 显示所有主要 CI 工作流的状态,包括: - - RT-Thread BSP Static Build Check / BSP 静态构建检查 - - Static code analysis / 静态代码分析 - - Check File Format and License / 文件格式和许可证检查 - - utest_auto_run / 单元测试自动运行 - -3. **Status Indicators / 状态指示器**: - - ✅ Success / 成功 - - ❌ Failure / 失败 - - 🟠 Queued / 排队中 - - 🟡 In Progress / 进行中 - - ⏭️ Skipped / 已跳过 - -4. **Detailed Information / 详细信息**: Expandable sections show individual job results within each workflow. - / 可展开的部分显示每个工作流中的各个作业结果。 - -## How It Works / 工作原理 - -1. The workflow is triggered when any of the monitored CI workflows complete. - / 当任何受监控的 CI 工作流完成时,将触发此工作流。 - -2. It collects the status of all workflows and jobs for the associated Pull Request. - / 它收集关联 Pull Request 的所有工作流和作业的状态。 - -3. A formatted comment is posted (or updated if one already exists) with the current CI status. - / 发布(或更新已存在的)格式化评论,显示当前 CI 状态。 - -## Comment Format / 评论格式 - -The comment includes: -评论包括: - -- **Overall Summary / 总体摘要**: Quick statistics showing count of passed, failed, queued, in-progress, and skipped workflows. - / 快速统计数据,显示通过、失败、排队、进行中和跳过的工作流数量。 - -- **Detailed Results / 详细结果**: Collapsible sections for each workflow with links to individual jobs. - / 每个工作流的可折叠部分,包含指向各个作业的链接。 - -## Benefits / 优势 - -1. **Visibility / 可见性**: Contributors can immediately see which CI checks have passed or failed without navigating to the Actions tab. - / 贡献者无需导航到 Actions 选项卡即可立即查看哪些 CI 检查通过或失败。 - -2. **Efficiency / 效率**: Reviewers can quickly assess the CI status before reviewing the code. - / 审阅者可以在审查代码之前快速评估 CI 状态。 - -3. **Transparency / 透明度**: All stakeholders have a clear view of the PR's CI status. - / 所有利益相关者都可以清楚地了解 PR 的 CI 状态。 - -## Permissions Required / 所需权限 - -The workflow requires the following permissions: -工作流需要以下权限: - -- `pull-requests: write` - To create and update comments / 创建和更新评论 -- `issues: write` - To post comments on PR issues / 在 PR 问题上发布评论 -- `actions: read` - To read workflow run status / 读取工作流运行状态 -- `checks: read` - To read check run status / 读取检查运行状态 - -## Configuration / 配置 - -The workflow monitors the following workflows by default: -工作流默认监控以下工作流: - -```yaml -workflows: - - "RT-Thread BSP Static Build Check" - - "Static code analysis" - - "Check File Format and License" - - "utest_auto_run" -``` - -To add more workflows to monitor, edit the `.github/workflows/ci_results_comment.yml` file and add workflow names to the `workflows` list. - -要监控更多工作流,请编辑 `.github/workflows/ci_results_comment.yml` 文件并将工作流名称添加到 `workflows` 列表中。 - -## Troubleshooting / 故障排除 - -### Comment not appearing / 评论未出现 - -1. Ensure the workflow has the required permissions / 确保工作流具有所需权限 -2. Check that the PR is from a branch in the repository (not a fork) / 检查 PR 是否来自存储库中的分支(而非分支) -3. Verify the workflow is enabled in the repository settings / 验证工作流在存储库设置中已启用 - -### Comment not updating / 评论未更新 - -1. The comment updates when a monitored workflow completes / 当受监控的工作流完成时,评论会更新 -2. Check the Actions tab to see if the workflow is running / 检查 Actions 选项卡以查看工作流是否正在运行 -3. Look for errors in the workflow logs / 在工作流日志中查找错误 - -## Contributing / 贡献 - -Contributions to improve this workflow are welcome! Please follow the standard contribution process outlined in the CONTRIBUTING.md file. - -欢迎改进此工作流的贡献!请遵循 CONTRIBUTING.md 文件中概述的标准贡献流程。 diff --git a/.github/workflows/bsp_buildings.yml b/.github/workflows/bsp_buildings.yml index 47647aaff13..65dc02638a8 100644 --- a/.github/workflows/bsp_buildings.yml +++ b/.github/workflows/bsp_buildings.yml @@ -13,6 +13,9 @@ name: RT-Thread BSP Static Build Check # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the RT-Thread organization master branch on: + # Runs at 16:00 UTC (BeiJing 00:00) every day + schedule: + - cron: '0 16 * * *' push: branches: - master @@ -43,12 +46,6 @@ on: types: - online-pkgs-static-building-trigger-event workflow_dispatch: - inputs: - trigger_type: - description: '触发类型' - required: false - default: 'manual' - type: string concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -291,17 +288,4 @@ jobs: uses: actions/upload-artifact@main with: name: 00_all_bsp_output_${{ github.sha }} - path: output/ - - # Post CI status to PR comment - post-ci-status: - needs: build - if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread' - uses: ./.github/workflows/post_ci_status.yml - with: - workflow_name: "RT-Thread BSP Static Build Check" - workflow_status: ${{ needs.build.result }} - pr_number: ${{ github.event.pull_request.number }} - permissions: - pull-requests: write - issues: write \ No newline at end of file + path: output/ \ No newline at end of file diff --git a/.github/workflows/ci_results_comment.yml b/.github/workflows/ci_results_comment.yml deleted file mode 100644 index 3e811229849..00000000000 --- a/.github/workflows/ci_results_comment.yml +++ /dev/null @@ -1,303 +0,0 @@ -# -# Copyright (c) 2025, RT-Thread Development Team -# -# SPDX-License-Identifier: Apache-2.0 -# -# Change Logs: -# Date Author Notes -# 2025-10-27 GitHub Copilot Post CI results to PR comments - -name: CI Results Comment - -on: - workflow_run: - workflows: - - "RT-Thread BSP Static Build Check" - - "Static code analysis" - - "Check File Format and License" - - "utest_auto_run" - - "ToolsCI" - - "pkgs_test" - types: - - completed - -permissions: - pull-requests: write - issues: write - actions: read - checks: read - -jobs: - comment-ci-results: - runs-on: ubuntu-22.04 - if: github.event.workflow_run.event == 'pull_request' && github.repository_owner == 'RT-Thread' - steps: - - name: Get PR number - id: get-pr - uses: actions/github-script@v7 - with: - script: | - // Get PR number from workflow_run - const prNumber = context.payload.workflow_run.pull_requests[0]?.number; - if (!prNumber) { - console.log('No PR found in workflow_run'); - // Fallback: search for PR by branch - const pulls = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}` - }); - - if (pulls.data.length === 0) { - console.log('No open PR found for this branch'); - return null; - } - - const pr = pulls.data[0]; - console.log(`Found PR #${pr.number}`); - return pr.number; - } - - console.log(`Found PR #${prNumber}`); - return prNumber; - - - name: Get workflow run details - if: steps.get-pr.outputs.result != 'null' - id: workflow-details - uses: actions/github-script@v7 - with: - script: | - const prNumber = ${{ steps.get-pr.outputs.result }}; - if (!prNumber) { - return { success: false, message: 'No PR found' }; - } - - // Get all workflow runs for this PR - const workflowRuns = await github.rest.actions.listWorkflowRunsForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - event: 'pull_request', - per_page: 100 - }); - - // Filter runs for this specific PR - const prRuns = workflowRuns.data.workflow_runs.filter(run => { - return run.pull_requests.some(pr => pr.number === prNumber); - }); - - // Get the latest run for each workflow - const workflowMap = new Map(); - for (const run of prRuns) { - const existing = workflowMap.get(run.name); - if (!existing || new Date(run.created_at) > new Date(existing.created_at)) { - workflowMap.set(run.name, run); - } - } - - // Prepare results summary - const results = []; - for (const [name, run] of workflowMap) { - let status = '🟡'; - let statusText = 'In Progress'; - - if (run.status === 'completed') { - if (run.conclusion === 'success') { - status = '✅'; - statusText = 'Success'; - } else if (run.conclusion === 'failure') { - status = '❌'; - statusText = 'Failure'; - } else if (run.conclusion === 'cancelled') { - status = '⏭️'; - statusText = 'Cancelled'; - } else if (run.conclusion === 'skipped') { - status = '⏭️'; - statusText = 'Skipped'; - } - } else if (run.status === 'queued') { - status = '🟠'; - statusText = 'Queued'; - } - - results.push({ - name: name, - status: status, - statusText: statusText, - url: run.html_url, - conclusion: run.conclusion, - runId: run.id - }); - } - - return { - success: true, - results: results, - prNumber: prNumber - }; - - - name: Get job details - if: steps.get-pr.outputs.result != 'null' - id: job-details - uses: actions/github-script@v7 - with: - script: | - const workflowDetails = ${{ steps.workflow-details.outputs.result }}; - if (!workflowDetails || !workflowDetails.success) { - return { jobs: [] }; - } - - const allJobs = []; - - for (const result of workflowDetails.results) { - try { - const jobs = await github.rest.actions.listJobsForWorkflowRun({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: result.runId, - per_page: 100 - }); - - for (const job of jobs.data.jobs) { - let jobStatus = '⌛'; - if (job.status === 'completed') { - if (job.conclusion === 'success') { - jobStatus = '✅'; - } else if (job.conclusion === 'failure') { - jobStatus = '❌'; - } else if (job.conclusion === 'skipped') { - jobStatus = '⏭️'; - } - } else if (job.status === 'in_progress') { - jobStatus = '🔄'; - } else if (job.status === 'queued') { - jobStatus = '🟠'; - } - - allJobs.push({ - workflow: result.name, - name: job.name, - status: jobStatus, - conclusion: job.conclusion || job.status, - url: job.html_url - }); - } - } catch (error) { - console.log(`Error getting jobs for workflow ${result.name}: ${error.message}`); - } - } - - return { jobs: allJobs }; - - - name: Post or update comment - if: steps.get-pr.outputs.result != 'null' - uses: actions/github-script@v7 - with: - script: | - const prNumber = ${{ steps.get-pr.outputs.result }}; - const workflowDetails = ${{ steps.workflow-details.outputs.result }}; - const jobDetails = ${{ steps.job-details.outputs.result }}; - - if (!workflowDetails || !workflowDetails.success) { - console.log('No workflow details available'); - return; - } - - // Prepare comment body - const now = new Date(); - const timestamp = now.toISOString(); - const results = workflowDetails.results; - const jobs = jobDetails.jobs || []; - - let commentBody = '\n'; - commentBody += '## 🤖 CI Test Results\n\n'; - commentBody += `**Last Updated:** ${timestamp}\n\n`; - commentBody += '### Test Spec & Results:\n\n'; - commentBody += '✅ Success | ❌ Failure | 🟠 Queued | 🟡 Progress | ⏭️ Skipped | ⚠️ Quarantine\n\n'; - - // Group jobs by workflow - const jobsByWorkflow = new Map(); - for (const job of jobs) { - if (!jobsByWorkflow.has(job.workflow)) { - jobsByWorkflow.set(job.workflow, []); - } - jobsByWorkflow.get(job.workflow).push(job); - } - - // Calculate overall statistics - let totalSuccess = 0; - let totalFailure = 0; - let totalQueued = 0; - let totalProgress = 0; - let totalSkipped = 0; - - for (const result of results) { - if (result.conclusion === 'success') totalSuccess++; - else if (result.conclusion === 'failure') totalFailure++; - else if (result.statusText === 'Queued') totalQueued++; - else if (result.statusText === 'In Progress') totalProgress++; - else if (result.conclusion === 'skipped' || result.conclusion === 'cancelled') totalSkipped++; - } - - // Summary line - commentBody += '#### Overall Summary\n\n'; - commentBody += `- ✅ **Success:** ${totalSuccess}\n`; - commentBody += `- ❌ **Failure:** ${totalFailure}\n`; - commentBody += `- 🟠 **Queued:** ${totalQueued}\n`; - commentBody += `- 🟡 **In Progress:** ${totalProgress}\n`; - commentBody += `- ⏭️ **Skipped:** ${totalSkipped}\n\n`; - - commentBody += '---\n\n'; - commentBody += '### Detailed Results\n\n'; - - // Build detailed results - for (const result of results) { - commentBody += `
\n`; - commentBody += `${result.status} ${result.name} - ${result.statusText}\n\n`; - commentBody += `**Workflow:** [${result.name}](${result.url})\n\n`; - - // Show jobs for this workflow - const workflowJobs = jobsByWorkflow.get(result.name) || []; - if (workflowJobs.length > 0) { - commentBody += '**Jobs:**\n\n'; - for (const job of workflowJobs) { - commentBody += `- ${job.status} [${job.name}](${job.url})\n`; - } - } - commentBody += '\n
\n\n'; - } - - commentBody += '\n---\n'; - commentBody += '*🤖 This comment is automatically generated and updated by the CI system.*\n'; - - // Check if comment already exists - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber - }); - - const existingComment = comments.data.find(comment => - comment.user.login === 'github-actions[bot]' && - comment.body.includes('') - ); - - if (existingComment) { - // Update existing comment - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existingComment.id, - body: commentBody - }); - console.log(`Updated comment ${existingComment.id} on PR #${prNumber}`); - } else { - // Create new comment - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: commentBody - }); - console.log(`Created new comment on PR #${prNumber}`); - } diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml index c9779bd1e60..5c40a91a16d 100644 --- a/.github/workflows/format_check.yml +++ b/.github/workflows/format_check.yml @@ -29,17 +29,4 @@ jobs: shell: bash run: | pip install click chardet PyYaml - python tools/ci/file_check.py check 'https://github.com/RT-Thread/rt-thread' 'master' - - # Post CI status to PR comment - post-ci-status: - needs: scancode_job - if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread' - uses: ./.github/workflows/post_ci_status.yml - with: - workflow_name: "Check File Format and License" - workflow_status: ${{ needs.scancode_job.result }} - pr_number: ${{ github.event.pull_request.number }} - permissions: - pull-requests: write - issues: write \ No newline at end of file + python tools/ci/file_check.py check 'https://github.com/RT-Thread/rt-thread' 'master' \ No newline at end of file diff --git a/.github/workflows/post_ci_status.yml b/.github/workflows/post_ci_status.yml deleted file mode 100644 index 717180aa6c9..00000000000 --- a/.github/workflows/post_ci_status.yml +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright (c) 2025, RT-Thread Development Team -# -# SPDX-License-Identifier: Apache-2.0 -# -# Change Logs: -# Date Author Notes -# 2025-10-27 GitHub Copilot Reusable workflow to post CI status - -name: Post CI Status Comment - -on: - workflow_call: - inputs: - workflow_name: - description: 'Name of the workflow' - required: true - type: string - workflow_status: - description: 'Status of the workflow (success/failure)' - required: true - type: string - pr_number: - description: 'Pull request number' - required: true - type: number - -permissions: - pull-requests: write - issues: write - -jobs: - post-comment: - runs-on: ubuntu-22.04 - if: github.repository_owner == 'RT-Thread' - steps: - - name: Post or update CI status comment - uses: actions/github-script@v7 - with: - script: | - const prNumber = ${{ inputs.pr_number }}; - const workflowName = '${{ inputs.workflow_name }}'; - const workflowStatus = '${{ inputs.workflow_status }}'; - - // Status emoji mapping - const statusEmoji = workflowStatus === 'success' ? '✅' : '❌'; - const timestamp = new Date().toISOString(); - - // Try to find existing comment - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber - }); - - const botComment = comments.data.find(comment => - comment.user.login === 'github-actions[bot]' && - comment.body.includes('') - ); - - // Get all workflow runs for this PR to build comprehensive status - let allStatuses = {}; - - if (botComment) { - // Parse existing statuses from comment - const statusRegex = /- (✅|❌|🟡) \*\*(.+?)\*\*/g; - let match; - while ((match = statusRegex.exec(botComment.body)) !== null) { - allStatuses[match[2]] = match[1]; - } - } - - // Update current workflow status - allStatuses[workflowName] = statusEmoji; - - // Build comment body - let commentBody = '\n'; - commentBody += '## 🤖 CI Test Results\n\n'; - commentBody += `**Last Updated:** ${timestamp}\n\n`; - commentBody += '### Workflow Status:\n\n'; - - for (const [name, emoji] of Object.entries(allStatuses)) { - commentBody += `- ${emoji} **${name}**\n`; - } - - commentBody += '\n---\n'; - commentBody += '✅ Success | ❌ Failure | 🟡 In Progress\n\n'; - commentBody += '*This comment is automatically updated as CI workflows complete.*\n'; - - if (botComment) { - // Update existing comment - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: botComment.id, - body: commentBody - }); - console.log(`Updated comment ${botComment.id} on PR #${prNumber}`); - } else { - // Create new comment - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: commentBody - }); - console.log(`Created new comment on PR #${prNumber}`); - } diff --git a/.github/workflows/static_code_analysis.yml b/.github/workflows/static_code_analysis.yml index f517a309d5c..3a5fdb34f54 100644 --- a/.github/workflows/static_code_analysis.yml +++ b/.github/workflows/static_code_analysis.yml @@ -54,17 +54,4 @@ jobs: sudo make install FILESDIR=/usr/local/share/Cppcheck cppcheck --version cd .. - python tools/ci/cpp_check.py check - - # Post CI status to PR comment - post-ci-status: - needs: scancode_job - if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread' - uses: ./.github/workflows/post_ci_status.yml - with: - workflow_name: "Static code analysis" - workflow_status: ${{ needs.scancode_job.result }} - pr_number: ${{ github.event.pull_request.number }} - permissions: - pull-requests: write - issues: write \ No newline at end of file + python tools/ci/cpp_check.py check \ No newline at end of file diff --git a/.github/workflows/utest_auto_run.yml b/.github/workflows/utest_auto_run.yml index 824caffcbac..107b1b3fe6c 100644 --- a/.github/workflows/utest_auto_run.yml +++ b/.github/workflows/utest_auto_run.yml @@ -18,13 +18,6 @@ on: - documentation/** - '**/README.md' - '**/README_zh.md' - workflow_dispatch: - inputs: - trigger_type: - description: '触发类型' - required: false - default: 'manual' - type: string concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -304,16 +297,4 @@ jobs: echo "==========================================================================================" break fi - done - # Post CI status to PR comment - post-ci-status: - needs: test - if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread' - uses: ./.github/workflows/post_ci_status.yml - with: - workflow_name: "utest_auto_run" - workflow_status: ${{ needs.test.result }} - pr_number: ${{ github.event.pull_request.number }} - permissions: - pull-requests: write - issues: write + done \ No newline at end of file