From aaf685670e9fa8efb0a5a9f842ef1fe58b46a9a3 Mon Sep 17 00:00:00 2001 From: "Catalin I. Tomai" Date: Wed, 15 Jul 2026 15:19:34 +0200 Subject: [PATCH] improve CI gates: drift checks, coverage, CodeQL, PR analysis --- .github/codeql/codeql-config.yml | 13 ++ .github/workflows/ci.yml | 203 +++++++++++++++++- .github/workflows/codeql-analysis.yml | 41 ++++ .../workflows/pr-test-analysis-override.yml | 32 +++ .github/workflows/pr-test-analysis.yml | 46 ++++ 5 files changed, 331 insertions(+), 4 deletions(-) create mode 100644 .github/codeql/codeql-config.yml create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/pr-test-analysis-override.yml create mode 100644 .github/workflows/pr-test-analysis.yml diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000..4d9fa7b --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,13 @@ +name: "CodeQL config" + +query-filters: + - exclude: + problem.severity: + - warning + - recommendation + - exclude: + id: go/log-injection + +paths-ignore: + - '**/*_test.go' + - '**/*.test.*' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 270f2ed..a9e07ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,9 +11,204 @@ on: permissions: contents: read - id-token: write jobs: - plugin-ci: - uses: mattermost/actions-workflows/.github/workflows/plugin-ci.yml@main - secrets: inherit + lint: + if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }} + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: ci/setup + uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be + with: + go-version-file: go.mod + + - name: ci/lint + uses: mattermost/actions/plugin-ci/lint@0256d363493a1e6b9e361ea788c62a0a73bc00be + + - name: ci/check-go-mod-tidy + run: | + go mod tidy + git diff --exit-code go.mod go.sum + + - name: ci/check-manifest-drift + run: | + make apply + git diff --exit-code + + - name: ci/check-i18n-drift + run: | + make i18n-extract + git diff --exit-code assets/i18n/en.json webapp/i18n/en.json + + test: + if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }} + runs-on: ubuntu-latest + permissions: + contents: read + # The store and service tests require a real Postgres (PG14+ for the + # hierarchy CYCLE clause) and never skip; the default test DSN is + # postgres://mmuser:mostest@localhost:5432/mattermost_test. + services: + postgres: + image: postgres:14 + env: + POSTGRES_USER: mmuser + POSTGRES_PASSWORD: mostest + POSTGRES_DB: mattermost_test + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: ci/setup + uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be + with: + go-version-file: go.mod + + - name: ci/test + uses: mattermost/actions/plugin-ci/test@0256d363493a1e6b9e361ea788c62a0a73bc00be + + build: + if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }} + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: ci/setup + uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be + with: + go-version-file: go.mod + + - name: ci/build + uses: mattermost/actions/plugin-ci/build@0256d363493a1e6b9e361ea788c62a0a73bc00be + + coverage: + if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }} + runs-on: ubuntu-latest + permissions: + contents: read + services: + postgres: + image: postgres:14 + env: + POSTGRES_USER: mmuser + POSTGRES_PASSWORD: mostest + POSTGRES_DB: mattermost_test + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - name: Checkout repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: ci/setup + uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be + with: + go-version-file: go.mod + + - name: ci/test-coverage + env: + TEST_DATABASE_POSTGRESQL_DSN: "postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable" + run: go test -coverprofile=server/coverage.txt ./server/... + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + files: ./server/coverage.txt + disable_search: true + + delivery: + if: ${{ github.repository_owner == 'mattermost' && github.event_name != 'schedule' && github.ref_name == 'master' }} + runs-on: ubuntu-latest + needs: [lint, test, build] + permissions: + contents: read + id-token: write + steps: + - name: ci/download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: dist + path: dist + + - name: ci/prepare-artifact + run: mv *.tar.gz ${GITHUB_REPOSITORY#*/}-ci.tar.gz + working-directory: dist + + - name: ci/aws-configure + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + with: + aws-region: us-east-1 + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_RELEASE }}:role/mattermost-release-plugin-store-role + + - name: ci/artifact-upload + shell: bash + run: | + aws s3 cp *.tar.gz s3://mattermost-plugins-delivery/ci/ --acl public-read --cache-control no-cache + working-directory: dist + + release: + if: ${{ startsWith(github.ref, 'refs/tags/v') && github.repository_owner == 'mattermost' }} + runs-on: ubuntu-latest + needs: [lint, test, build] + permissions: + contents: read + id-token: write + steps: + - name: ci/download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: dist + path: dist + + - name: ci/prepare-artifact + env: + REF_NAME: ${{ github.ref_name }} + run: mv *.tar.gz ${GITHUB_REPOSITORY#*/}-${REF_NAME}.tar.gz + working-directory: dist + + - name: ci/aws-configure + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + with: + aws-region: us-east-1 + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_RELEASE }}:role/mattermost-release-plugin-store-role + + - name: ci/artifact-upload + shell: bash + run: | + aws s3 cp *.tar.gz s3://mattermost-plugins-delivery/release/ --acl public-read --cache-control no-cache + working-directory: dist diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..3438d3e --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,41 @@ +name: "CodeQL" + +on: + push: + branches: [master, 'release-*'] + pull_request: + branches: [master, 'release-*'] + schedule: + - cron: '30 4 * * 0' + +permissions: + contents: read + +jobs: + analyze: + permissions: + security-events: write + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: ['go', 'javascript'] + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3.28.9 + with: + languages: ${{ matrix.language }} + debug: false + config-file: ./.github/codeql/codeql-config.yml + + - name: Autobuild + uses: github/codeql-action/autobuild@v3.28.9 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3.28.9 diff --git a/.github/workflows/pr-test-analysis-override.yml b/.github/workflows/pr-test-analysis-override.yml new file mode 100644 index 0000000..6d89775 --- /dev/null +++ b/.github/workflows/pr-test-analysis-override.yml @@ -0,0 +1,32 @@ +name: PR Test Analysis Override + +on: + issue_comment: + types: [created] + +concurrency: + group: test-analyzer-${{ github.event.issue.number }} + cancel-in-progress: false + +jobs: + override: + permissions: + statuses: write + pull-requests: read + contents: read + issues: write + if: >- + github.repository == 'mattermost/mattermost-plugin-docs' && + github.event.issue.pull_request && + startsWith(github.event.comment.body, '/test-analysis-override') && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association) + uses: mattermost/mattermost-test-automation-toolkit/.github/workflows/pr-test-analysis-override.yml@main + with: + pr_number: ${{ github.event.issue.number }} + target_repo: mattermost/mattermost-plugin-docs + comment_body: ${{ github.event.comment.body }} + comment_id: ${{ github.event.comment.id }} + sender: ${{ github.event.comment.user.login }} + secrets: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + WEBHOOK_URL: ${{ secrets.WEBHOOK_URL_TEST_PR_ANALYSIS_HUB }} diff --git a/.github/workflows/pr-test-analysis.yml b/.github/workflows/pr-test-analysis.yml new file mode 100644 index 0000000..a76bbc0 --- /dev/null +++ b/.github/workflows/pr-test-analysis.yml @@ -0,0 +1,46 @@ +name: PR Test Analysis + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: + - master + - 'release-*' + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to analyze' + required: true + type: number + claude_model: + description: 'Claude model to use (default: claude-sonnet-4-6)' + required: false + type: string + +concurrency: + group: test-analyzer-${{ github.event.pull_request.number || inputs.pr_number }} + cancel-in-progress: true + +jobs: + analyze: + permissions: + contents: read + pull-requests: write + statuses: write + id-token: write + # pull_request: skip drafts and forks (drafts are not ready for analysis; + # fork runs do not receive this repo's Actions secrets). + # workflow_dispatch: always allowed — runs in this repo with secrets, so you can pass a fork PR number manually. + if: >- + github.event_name == 'workflow_dispatch' || + (github.event.pull_request.draft == false && + github.event.pull_request.head.repo.full_name == 'mattermost/mattermost-plugin-docs') + uses: mattermost/mattermost-test-automation-toolkit/.github/workflows/pr-test-analysis.yml@main + with: + pr_number: ${{ github.event.pull_request.number || inputs.pr_number }} + target_repo: mattermost/mattermost-plugin-docs + claude_model: ${{ inputs.claude_model || vars.CLAUDE_MODEL || 'claude-sonnet-4-6' }} + secrets: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + WEBHOOK_URL: ${{ secrets.WEBHOOK_URL_TEST_PR_ANALYSIS_HUB }}