diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f10b2da8efe..7d2f7a23cd0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -754,9 +754,7 @@ embed.go @grafana/grafana-as-code /.github/pr-checks.json @tolzhabayev /.github/pr-commands.json @tolzhabayev /.github/renovate.json5 @grafana/frontend-ops -/.github/actions/report-coverage @grafana/grafana-backend-group -/.github/actions/run-backend-tests @grafana/grafana-backend-group -/.github/actions/setup-enterprise @grafana/grafana-backend-group +/.github/actions/test-coverage-processor/action.yml @grafana/grafana-backend-group /.github/workflows/add-to-whats-new.yml @grafana/docs-tooling /.github/workflows/auto-triager/ @grafana/plugins-platform-frontend /.github/workflows/alerting-swagger-gen.yml @grafana/alerting-backend @@ -790,7 +788,7 @@ embed.go @grafana/grafana-as-code /.github/workflows/pr-codeql-analysis-python.yml @DanCech /.github/workflows/pr-commands.yml @tolzhabayev /.github/workflows/pr-patch-check.yml @grafana/grafana-developer-enablement-squad -/.github/workflows/pr-test-backend.yml @grafana/grafana-backend-group +/.github/workflows/pr-backend-unit-tests.yml @grafana/grafana-backend-group /.github/workflows/sync-mirror.yml @grafana/grafana-developer-enablement-squad /.github/workflows/publish-technical-documentation-next.yml @grafana/docs-tooling /.github/workflows/publish-technical-documentation-release.yml @grafana/docs-tooling diff --git a/.github/actions/report-coverage/action.yml b/.github/actions/report-coverage/action.yml deleted file mode 100644 index 58ccfb23bd0..00000000000 --- a/.github/actions/report-coverage/action.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: 'Report Coverage' -description: 'Processes and uploads coverage reports from Go tests' - -inputs: - unit-cov-path: - description: 'Path to unit test coverage file' - required: true - integration-cov-path: - description: 'Path to integration test coverage file' - required: true - codecov-token: - description: 'Token for CodeCov' - required: true - -runs: - using: "composite" - steps: - - name: Join coverage outputs - shell: bash - run: | - cp ${{ inputs.unit-cov-path }} backend.cov - tail -n+2 ${{ inputs.integration-cov-path }} >> backend.cov - - - name: Convert coverage info to per-func stats - shell: bash - run: go tool cover -func backend.cov > backend-funcs.log - - - name: Convert coverage info to HTML - shell: bash - run: go tool cover -html backend.cov -o backend.html - - - name: Upload coverage file - uses: actions/upload-artifact@v4 - with: - name: backend-cov - path: | - backend.cov - backend-funcs.log - backend.html - retention-days: 30 - compression-level: 9 - - - name: Set summary to total coverage - shell: bash - run: | - echo '# Coverage' >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - grep 'total:' backend-funcs.log | tr '\t' ' ' >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - - - name: Report coverage to CodeCov - uses: codecov/codecov-action@v5 - with: - files: backend.cov - flags: unified-backend - name: backend - slug: grafana/grafana - # This URL doesn't use the Google auth, but is much more locked down. As such, it requires OIDC or a CodeCov-provided token to do anything. - url: https://codecov-webhook.grafana-dev.net - token: ${{ inputs.codecov-token }} diff --git a/.github/actions/run-backend-tests/action.yml b/.github/actions/run-backend-tests/action.yml deleted file mode 100644 index 6ae930fa489..00000000000 --- a/.github/actions/run-backend-tests/action.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: 'Run Backend Tests' -description: 'Runs Grafana backend test suites' - -inputs: - coverage-opts: - description: 'Coverage options to pass to the test command (empty for no coverage)' - required: false - default: '' - test-command: - description: 'The test command to run' - required: false - default: 'make gen-go test-go-unit' - -runs: - using: "composite" - steps: - - name: Run tests - shell: bash - run: | - if [ -n "${{ inputs.coverage-opts }}" ]; then - COVER_OPTS="${{ inputs.coverage-opts }}" ${{ inputs.test-command }} - else - ${{ inputs.test-command }} - fi diff --git a/.github/actions/setup-enterprise/action.yml b/.github/actions/setup-enterprise/action.yml deleted file mode 100644 index e87d3d7bae9..00000000000 --- a/.github/actions/setup-enterprise/action.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: 'Setup Grafana Enterprise' -description: 'Clones and sets up Grafana Enterprise repository for testing' - -inputs: - github-app-name: - description: 'Name of the GitHub App in Vault' - required: false - default: 'grafana-ci-bot' - -runs: - using: "composite" - steps: - - name: Retrieve GitHub App secrets - id: get-secrets - uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets-v1.0.1 - with: - repo_secrets: | - APP_ID=${{ inputs.github-app-name }}:app-id - APP_INSTALLATION_ID=${{ inputs.github-app-name }}:app-installation-id - PRIVATE_KEY=${{ inputs.github-app-name }}:private-key - - - name: Generate GitHub App token - id: generate_token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ env.APP_ID }} - private-key: ${{ env.PRIVATE_KEY }} - repositories: "grafana-enterprise" - owner: "grafana" - - - name: Setup Enterprise - shell: bash - env: - GH_TOKEN: ${{ steps.generate_token.outputs.token }} - run: | - git clone https://x-access-token:${GH_TOKEN}@github.com/grafana/grafana-enterprise.git ../grafana-enterprise; - - cd ../grafana-enterprise - - if git checkout ${GITHUB_HEAD_REF}; then - echo "checked out ${GITHUB_HEAD_REF}" - elif git checkout ${GITHUB_BASE_REF}; then - echo "checked out ${GITHUB_BASE_REF}" - else - git checkout main - fi - - ./build.sh diff --git a/.github/actions/test-coverage-processor/action.yml b/.github/actions/test-coverage-processor/action.yml new file mode 100644 index 00000000000..7560031e846 --- /dev/null +++ b/.github/actions/test-coverage-processor/action.yml @@ -0,0 +1,48 @@ +name: 'Go Coverage Processor' +description: 'Process Go test coverage files and generate reports' + +inputs: + test-type: + description: 'Type of test (e.g., be-unit, be-integration)' + required: true + type: string + coverage-file: + description: 'Path to the Go coverage file (.cov)' + required: true + type: string + codecov-token: + description: 'Token for CodeCov (required for CodeCov reporting)' + required: false + default: '' + codecov-flag: + description: 'Flag to categorize the upload to CodeCov' + required: false + default: '' + codecov-name: + description: 'Custom name for the upload to CodeCov' + required: false + default: '' + +runs: + using: 'composite' + steps: + - name: Process Go coverage output + shell: bash + run: | + # Ensure valid coverage file even if empty + if [ ! -s ${{ inputs.coverage-file }} ]; then + echo "Coverage file is empty, creating a minimal valid file" + echo "mode: set" > ${{ inputs.coverage-file }} + fi + + - name: Report coverage to CodeCov + uses: codecov/codecov-action@v5 + if: inputs.codecov-token != '' + with: + files: ${{ inputs.coverage-file }} + flags: ${{ inputs.codecov-flag || inputs.test-type }} + name: ${{ inputs.codecov-name || inputs.test-type }} + slug: grafana/grafana + # This URL doesn't use the Google auth, but is much more locked down. As such, it requires OIDC or a CodeCov-provided token to do anything. + url: https://codecov-webhook.grafana-dev.net + token: ${{ inputs.codecov-token }} diff --git a/.github/workflows/pr-backend-unit-tests.yml b/.github/workflows/pr-backend-unit-tests.yml new file mode 100644 index 00000000000..4b264547957 --- /dev/null +++ b/.github/workflows/pr-backend-unit-tests.yml @@ -0,0 +1,66 @@ +name: Backend Unit Tests + +on: + workflow_dispatch: + push: + branches: + - main + paths-ignore: + - 'docs/**' + - '**/*.md' + pull_request: + paths-ignore: + - 'docs/**' + - '**/*.md' + +permissions: + contents: read + id-token: write + +env: + EDITION: 'oss' + WIRE_TAGS: 'oss' + +jobs: + backend-testing-coverage: + name: Backend Testing & Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential shared-mime-info + + - name: Verify code generation + run: | + CODEGEN_VERIFY=1 make gen-cue + CODEGEN_VERIFY=1 make gen-jsonnet + + - name: Generate Go code + run: make gen-go + + - name: Run unit tests + run: COVER_OPTS="-coverprofile=be-unit.cov -coverpkg=github.com/grafana/grafana/..." make test-go-unit + + - name: Process and upload coverage + uses: ./.github/actions/test-coverage-processor + with: + test-type: 'be-unit' + # Needs to be named 'unit.cov' based on the Makefile command `make test-go-unit` + coverage-file: 'unit.cov' + codecov-token: ${{ secrets.CODECOV_TOKEN }} + codecov-flag: 'be-unit' + codecov-name: 'be-unit' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true diff --git a/.github/workflows/pr-test-backend.yml b/.github/workflows/pr-test-backend.yml deleted file mode 100644 index e86c20c387a..00000000000 --- a/.github/workflows/pr-test-backend.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Test Backend - -on: - workflow_dispatch: - push: - branches: - - main - paths-ignore: - - 'docs/**' - - '**/*.md' - pull_request: - paths-ignore: - - 'docs/**' - - '**/*.md' - -permissions: - contents: read - id-token: write - -env: - EDITION: 'oss' - -jobs: - test-backend: - name: Test Backend - runs-on: ubuntu-latest - continue-on-error: true - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.7' - cache: true - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y build-essential shared-mime-info make - - - name: Get runner name - run: echo ${{ runner.name }} - - - name: Setup Enterprise (PR only) - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false - uses: ./.github/actions/setup-enterprise - - - name: Verify CUE generation - run: CODEGEN_VERIFY=1 make gen-cue - - - name: Verify Jsonnet generation - run: CODEGEN_VERIFY=1 make gen-jsonnet - - - name: Check if coverage should be generated - id: check-coverage - env: - GH_TOKEN: ${{ github.token }} - run: | - echo "Event: ${{ github.event_name }}" - echo "Ref: ${{ github.ref }}" - - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - echo "PR changed files:" - files=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --jq '.[].filename') - echo "$files" - if echo "$files" | grep -E "(pkg/|go\.)"; then - echo "Coverage will be generated: true (PR changes)" - echo "generate=true" >> $GITHUB_OUTPUT - else - echo "Coverage will be generated: false" - echo "generate=false" >> $GITHUB_OUTPUT - fi - elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]] && \ - [[ "${{ github.event.head_commit.modified }}" =~ (pkg/|go\.|\.github/workflows/pr-test-backend\.yml) ]]; then - echo "Coverage will be generated: true (push to main)" - echo "generate=true" >> $GITHUB_OUTPUT - else - echo "Coverage will be generated: false" - echo "generate=false" >> $GITHUB_OUTPUT - fi - - - name: Run backend tests - uses: ./.github/actions/run-backend-tests - with: - coverage-opts: ${{ steps.check-coverage.outputs.generate == 'true' && '-coverprofile=unit.cov -coverpkg=github.com/grafana/grafana/...' || '' }} - test-command: 'make gen-go test-go-unit' - - - name: Run backend integration tests - uses: ./.github/actions/run-backend-tests - with: - coverage-opts: ${{ steps.check-coverage.outputs.generate == 'true' && '-coverprofile=integration.cov -coverpkg=github.com/grafana/grafana/...' || '' }} - test-command: 'make gen-go test-go-integration' - - - name: Generate Coverage Report - if: steps.check-coverage.outputs.generate == 'true' - uses: ./.github/actions/report-coverage - with: - unit-cov-path: unit.cov - integration-cov-path: integration.cov - codecov-token: ${{ secrets.CODECOV_TOKEN }} - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true