sonar.yaml 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. checks: write
  14. contents: read
  15. actions: read
  16. steps:
  17. - uses: LouisBrunner/checks-action@v2.0.0
  18. if: always()
  19. with:
  20. token: ${{ secrets.GITHUB_TOKEN }}
  21. name: Quality Gate
  22. status: in_progress
  23. sha: ${{ github.event.workflow_run.head_sha }}
  24. - uses: actions/checkout@v4
  25. with:
  26. repository: ${{ github.event.workflow_run.head_repository.full_name }}
  27. ref: ${{ github.event.workflow_run.head_branch }}
  28. fetch-depth: 0
  29. - name: Download coverage artifacts
  30. uses: actions/download-artifact@v4
  31. with:
  32. name: code-coverage
  33. run-id: ${{ github.event.workflow_run.id }}
  34. github-token: ${{ github.token }}
  35. path: pr-artifact
  36. - name: Validate Coverage Vars
  37. id: validate-vars
  38. if: github.event.workflow_run.head_branch != 'develop'
  39. shell: bash
  40. run: |
  41. # check the PR number
  42. pr_content=$(cat pr-artifact/pr_num.txt | tr -d '\n' | tr -d ' ')
  43. # Check if the content matches a single number
  44. if [[ "$pr_content" =~ ^[0-9]+$ ]]; then
  45. echo "The file 'pr_num.txt' contains a single number: $pr_content"
  46. else
  47. echo "The file 'pr_num.txt' does not contain a single number."
  48. exit 1
  49. fi
  50. base_content=$(cat pr-artifact/base.txt | tr -d '\n' | tr -d ' ')
  51. if git check-ref-format --allow-onelevel "$base_content"; then
  52. echo "The file 'base.txt' contains a valid git ref: $base_content"
  53. else
  54. echo "The file 'base.txt' does not contain a valid git ref: $base_content"
  55. exit 1
  56. fi
  57. head_content=$(cat pr-artifact/head.txt | tr -d '\n' | tr -d ' ')
  58. if git check-ref-format --allow-onelevel "$head_content"; then
  59. echo "The file 'head.txt' contains a valid git ref: $head_content"
  60. else
  61. echo "The file 'head.txt' does not contain a valid git ref: $head_content"
  62. exit 1
  63. fi
  64. - name: set vars
  65. id: set-vars
  66. run: |
  67. echo "SONAR_PR_NUM=$(cat pr-artifact/pr_num.txt | tr -d '\n' | tr -d ' ')" >> $GITHUB_OUTPUT
  68. echo "SONAR_BASE=$(cat pr-artifact/base.txt | tr -d '\n' | tr -d ' ')" >> $GITHUB_OUTPUT
  69. echo "SONAR_HEAD=$(cat pr-artifact/head.txt | tr -d '\n' | tr -d ' ')" >> $GITHUB_OUTPUT
  70. # move coverage file to root where sonar properties file is expecting it
  71. cp pr-artifact/coverage.out coverage.out
  72. # on develop branch, only run a baseline scan
  73. - name: SonarCloud Scan (Baseline)
  74. uses: sonarsource/sonarcloud-github-action@master
  75. if: github.event.workflow_run.head_branch == 'develop'
  76. env:
  77. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  78. SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  79. with:
  80. args: >
  81. -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }}
  82. -Dsonar.projectKey=opencost_opencost
  83. -Dsonar.organization=opencost
  84. -Dsonar.branch.name=develop
  85. - name: SonarCloud Scan (PR)
  86. uses: sonarsource/sonarcloud-github-action@master
  87. if: github.event.workflow_run.head_branch != 'develop'
  88. env:
  89. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  90. SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  91. with:
  92. args: >
  93. -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }}
  94. -Dsonar.pullrequest.key=${{ steps.set-vars.outputs.SONAR_PR_NUM }}
  95. -Dsonar.pullrequest.branch="${{ steps.set-vars.outputs.SONAR_HEAD }}"
  96. -Dsonar.pullrequest.base="${{ steps.set-vars.outputs.SONAR_BASE }}"
  97. -Dsonar.projectKey=opencost_opencost
  98. -Dsonar.organization=opencost
  99. - name: SonarQube Quality Gate check
  100. id: sonarqube-quality-gate-check
  101. continue-on-error: true
  102. uses: sonarsource/sonarqube-quality-gate-action@master
  103. # fail step after specific time.
  104. timeout-minutes: 5
  105. env:
  106. SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
  107. SONAR_HOST_URL: "https://sonarcloud.io"
  108. - uses: LouisBrunner/checks-action@v2.0.0
  109. id: fail-quality-gate
  110. if: steps.sonarqube-quality-gate-check.outputs.quality-gate-status != 'PASSED'
  111. with:
  112. token: ${{ secrets.GITHUB_TOKEN }}
  113. name: Quality Gate
  114. status: completed
  115. conclusion: failure
  116. sha: ${{ github.event.workflow_run.head_sha }}
  117. output: |
  118. {"summary":"Failed - see https://sonarcloud.io/summary/new_code?id=opencost_opencostl&pullRequest=${{ steps.set-vars.outputs.SONAR_PR_NUM }}","text_description":"Quality Gate failed. Check the [SonarCloud Dashboard](https://sonarcloud.io/dashboard?id=opencost_opencost&pullRequest=${{ steps.set-vars.outputs.SONAR_PR_NUM }}) for more details."}
  119. - uses: LouisBrunner/checks-action@v2.0.0
  120. id: pass-quality-gate
  121. if: steps.sonarqube-quality-gate-check.outputs.quality-gate-status == 'PASSED'
  122. with:
  123. token: ${{ secrets.GITHUB_TOKEN }}
  124. name: Quality Gate
  125. status: completed
  126. conclusion: success
  127. sha: ${{ github.event.workflow_run.head_sha }}
  128. output: |
  129. {"summary":"Passed","text_description":"Quality Gate passed. Check the [SonarCloud Dashboard](https://sonarcloud.io/dashboard?id=opencost_opencost&pullRequest=${{ steps.set-vars.outputs.SONAR_PR_NUM }}) for more details."}