sonar.yaml 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. name: Sonar
  2. on:
  3. workflow_run:
  4. workflows: ["Build/Test"]
  5. types: [completed]
  6. permissions: {}
  7. jobs:
  8. sonar:
  9. name: Sonar
  10. runs-on: ubuntu-latest
  11. if: github.event.workflow_run.conclusion == 'success'
  12. permissions:
  13. statuses: write
  14. contents: read
  15. actions: read
  16. steps:
  17. - name: Set Quality Gate status (pending)
  18. if: always()
  19. uses: guibranco/github-status-action-v2@v1.1.14
  20. with:
  21. authToken: ${{ secrets.GITHUB_TOKEN }}
  22. state: 'pending'
  23. context: 'Quality Gate'
  24. description: 'Quality Gate check in progress...'
  25. sha: ${{ github.event.workflow_run.head_sha }}
  26. target_url: 'https://sonarcloud.io/dashboard?id=opencost_opencost'
  27. - name: Checkout upstream repository
  28. uses: actions/checkout@v4
  29. with:
  30. repository: opencost/opencost
  31. ref: develop
  32. fetch-depth: 0
  33. - name: Fetch PR branch from fork
  34. if: github.event.workflow_run.head_branch != 'develop' || github.event.workflow_run.head_repository.full_name != 'opencost/opencost'
  35. env:
  36. HEAD_REPO_FULL_NAME: ${{ github.event.workflow_run.head_repository.full_name }}
  37. HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
  38. HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
  39. run: |
  40. git remote add fork "https://github.com/$HEAD_REPO_FULL_NAME.git"
  41. if [ "$HEAD_BRANCH" = "develop" ]; then
  42. # For fork's develop branch, fetch and checkout by SHA to avoid refspec conflict
  43. git fetch fork "$HEAD_BRANCH"
  44. git checkout "$HEAD_SHA"
  45. else
  46. # For feature branches, fetch and checkout normally
  47. git fetch fork "$HEAD_BRANCH:$HEAD_BRANCH"
  48. git checkout "$HEAD_BRANCH"
  49. fi
  50. - name: Checkout develop branch at specific SHA
  51. if: github.event.workflow_run.head_branch == 'develop' && github.event.workflow_run.head_repository.full_name == 'opencost/opencost'
  52. run: |
  53. git checkout ${{ github.event.workflow_run.head_sha }}
  54. - name: Download coverage artifacts
  55. uses: actions/download-artifact@v4
  56. with:
  57. name: code-coverage
  58. run-id: ${{ github.event.workflow_run.id }}
  59. github-token: ${{ github.token }}
  60. path: pr-artifact
  61. - name: Validate Coverage Vars
  62. id: validate-vars
  63. if: github.event.workflow_run.head_branch != 'develop'
  64. shell: bash
  65. run: |
  66. # check the PR number
  67. pr_content=$(cat pr-artifact/pr_num.txt | tr -d '\n' | tr -d ' ')
  68. # Check if the content matches a single number
  69. if [[ "$pr_content" =~ ^[0-9]+$ ]]; then
  70. echo "The file 'pr_num.txt' contains a single number: $pr_content"
  71. else
  72. echo "The file 'pr_num.txt' does not contain a single number."
  73. exit 1
  74. fi
  75. base_content=$(cat pr-artifact/base.txt | tr -d '\n' | tr -d ' ')
  76. if git check-ref-format --allow-onelevel "$base_content"; then
  77. echo "The file 'base.txt' contains a valid git ref: $base_content"
  78. else
  79. echo "The file 'base.txt' does not contain a valid git ref: $base_content"
  80. exit 1
  81. fi
  82. head_content=$(cat pr-artifact/head.txt | tr -d '\n' | tr -d ' ')
  83. if git check-ref-format --allow-onelevel "$head_content"; then
  84. echo "The file 'head.txt' contains a valid git ref: $head_content"
  85. else
  86. echo "The file 'head.txt' does not contain a valid git ref: $head_content"
  87. exit 1
  88. fi
  89. - name: set vars
  90. id: set-vars
  91. run: |
  92. echo "SONAR_PR_NUM=$(cat pr-artifact/pr_num.txt | tr -d '\n' | tr -d ' ')" >> $GITHUB_OUTPUT
  93. echo "SONAR_BASE=$(cat pr-artifact/base.txt | tr -d '\n' | tr -d ' ')" >> $GITHUB_OUTPUT
  94. echo "SONAR_HEAD=$(cat pr-artifact/head.txt | tr -d '\n' | tr -d ' ')" >> $GITHUB_OUTPUT
  95. # move coverage file to root where sonar properties file is expecting it
  96. cp pr-artifact/coverage.out coverage.out
  97. # on develop branch, only run a baseline scan
  98. - name: SonarCloud Scan (Baseline)
  99. uses: sonarsource/sonarcloud-github-action@master
  100. if: github.event.workflow_run.head_branch == 'develop'
  101. env:
  102. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  103. SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  104. with:
  105. args: >
  106. -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }}
  107. -Dsonar.projectKey=opencost_opencost
  108. -Dsonar.organization=opencost
  109. -Dsonar.branch.name=develop
  110. - name: SonarCloud Scan (PR)
  111. uses: sonarsource/sonarcloud-github-action@master
  112. if: github.event.workflow_run.head_branch != 'develop'
  113. env:
  114. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  115. SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  116. with:
  117. args: >
  118. -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }}
  119. -Dsonar.pullrequest.key=${{ steps.set-vars.outputs.SONAR_PR_NUM }}
  120. -Dsonar.pullrequest.branch=${{ steps.set-vars.outputs.SONAR_HEAD }}
  121. -Dsonar.pullrequest.base=${{ steps.set-vars.outputs.SONAR_BASE }}
  122. -Dsonar.projectKey=opencost_opencost
  123. -Dsonar.organization=opencost
  124. - name: SonarQube Quality Gate check
  125. id: sonarqube-quality-gate-check
  126. continue-on-error: true
  127. uses: sonarsource/sonarqube-quality-gate-action@master
  128. # fail step after specific time.
  129. timeout-minutes: 5
  130. env:
  131. SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  132. SONAR_HOST_URL: "https://sonarcloud.io"
  133. - name: Set Quality Gate status (failed - PR)
  134. id: fail-quality-gate-pr
  135. if: steps.sonarqube-quality-gate-check.outputs.quality-gate-status != 'PASSED' && steps.set-vars.outputs.SONAR_PR_NUM != ''
  136. uses: guibranco/github-status-action-v2@v1.1.14
  137. with:
  138. authToken: ${{ secrets.GITHUB_TOKEN }}
  139. state: 'failure'
  140. context: 'Quality Gate'
  141. description: 'Quality Gate failed. Check the SonarCloud Dashboard for PR #${{ steps.set-vars.outputs.SONAR_PR_NUM }}'
  142. sha: ${{ github.event.workflow_run.head_sha }}
  143. target_url: 'https://sonarcloud.io/dashboard?id=opencost_opencost&pullRequest=${{ steps.set-vars.outputs.SONAR_PR_NUM }}'
  144. - name: Set Quality Gate status (failed - develop)
  145. id: fail-quality-gate-develop
  146. if: steps.sonarqube-quality-gate-check.outputs.quality-gate-status != 'PASSED' && steps.set-vars.outputs.SONAR_PR_NUM == ''
  147. uses: guibranco/github-status-action-v2@v1.1.14
  148. with:
  149. authToken: ${{ secrets.GITHUB_TOKEN }}
  150. state: 'failure'
  151. context: 'Quality Gate'
  152. description: 'Quality Gate failed. Check the SonarCloud Dashboard for more details.'
  153. sha: ${{ github.event.workflow_run.head_sha }}
  154. target_url: 'https://sonarcloud.io/dashboard?id=opencost_opencost'
  155. - name: Set Quality Gate status (passed - PR)
  156. id: pass-quality-gate-pr
  157. if: steps.sonarqube-quality-gate-check.outputs.quality-gate-status == 'PASSED' && steps.set-vars.outputs.SONAR_PR_NUM != ''
  158. uses: guibranco/github-status-action-v2@v1.1.14
  159. with:
  160. authToken: ${{ secrets.GITHUB_TOKEN }}
  161. state: 'success'
  162. context: 'Quality Gate'
  163. description: 'Quality Gate passed. Check the SonarCloud Dashboard for PR #${{ steps.set-vars.outputs.SONAR_PR_NUM }}'
  164. sha: ${{ github.event.workflow_run.head_sha }}
  165. target_url: 'https://sonarcloud.io/dashboard?id=opencost_opencost&pullRequest=${{ steps.set-vars.outputs.SONAR_PR_NUM }}'
  166. - name: Set Quality Gate status (passed - develop)
  167. id: pass-quality-gate-develop
  168. if: steps.sonarqube-quality-gate-check.outputs.quality-gate-status == 'PASSED' && steps.set-vars.outputs.SONAR_PR_NUM == ''
  169. uses: guibranco/github-status-action-v2@v1.1.14
  170. with:
  171. authToken: ${{ secrets.GITHUB_TOKEN }}
  172. state: 'success'
  173. context: 'Quality Gate'
  174. description: 'Quality Gate passed. Check the SonarCloud Dashboard for more details.'
  175. sha: ${{ github.event.workflow_run.head_sha }}
  176. target_url: 'https://sonarcloud.io/dashboard?id=opencost_opencost'