sonar.yaml 5.7 KB

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