integration tests #1765
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: integration tests | |
on: | |
pull_request: | |
schedule: | |
- cron: "0 11 * * *" #once a day at 11 UTC | |
concurrency: | |
group: integration-tests-${{ github.ref }} | |
cancel-in-progress: true | |
permissions: | |
contents: read | |
id-token: write | |
jobs: | |
setup-matrix: | |
runs-on: ubuntu-latest | |
timeout-minutes: 30 | |
outputs: | |
pluginDirs: ${{ steps.set-plugin-dirs.outputs.pluginDirs }} | |
canaryVersion: ${{ steps.npm-canary-version.outputs.version }} | |
canaryDockerTag: ${{ steps.docker-canary-tag.outputs.result }} | |
latestVersion: ${{ steps.npm-latest-version.outputs.version }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup plugin dir variable | |
id: set-plugin-dirs | |
run: echo "pluginDirs=$(find ./examples -type d -name "src" -not -path "*/node_modules*" -maxdepth 3 -exec test -e "{}/plugin.json" \; -print | sed "s/\/src$//" | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT | |
- name: Setup NPM canary version variable | |
id: npm-canary-version | |
run: echo "version=$(npm view @grafana/ui dist-tags.canary)" >> $GITHUB_OUTPUT | |
- name: Setup docker canary tag variable | |
id: docker-canary-tag | |
uses: actions/github-script@v7 | |
env: | |
INPUT_NPM-TAG: ${{ steps.npm-canary-version.outputs.version }} | |
with: | |
result-encoding: string | |
script: | | |
const script = require('./.github/workflows/scripts/npm-to-docker-image.js'); | |
return await script({ core }); | |
- name: Setup NPM latest version variable | |
id: npm-latest-version | |
run: echo "version=$(npm view @grafana/ui dist-tags.latest)" >> $GITHUB_OUTPUT | |
run-integration-tests: | |
needs: setup-matrix | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
pluginDir: ${{ fromJson(needs.setup-matrix.outputs.pluginDirs) }} | |
fail-fast: false | |
env: | |
GF_AUTH_ANONYMOUS_ENABLED: "true" | |
GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin" | |
GF_AUTH_BASIC_ENABLED: "false" | |
GF_DEFAULT_APP_MODE: "development" | |
GF_INSTALL_PLUGINS: "marcusolsson-static-datasource" | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set the name of the plugin-example to be tested | |
id: example-name | |
run: | | |
echo "PLUGIN_NAME=$(basename ${{ matrix.pluginDir }})" >> $GITHUB_OUTPUT | |
- name: Setup node version | |
uses: actions/setup-node@v4 | |
with: | |
node-version: "20" | |
registry-url: "https://registry.npmjs.org" | |
cache: "npm" | |
- name: Install dependencies | |
run: | | |
npm ci | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Run frontend tests | |
run: | | |
npm run test:ci | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Build plugin frontend | |
run: | | |
npm run build | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Check for backend Mage file | |
id: backend-check | |
run: | | |
echo "MAGEFILE_EXISTS=$(test -f ./Magefile.go && echo true || echo false)" >> $GITHUB_OUTPUT | |
working-directory: ${{ matrix.pluginDir }} | |
- uses: actions/setup-go@v5 | |
with: | |
go-version: "~1.22" | |
check-latest: true | |
cache-dependency-path: ${{ matrix.pluginDir }}/go.sum | |
if: steps.backend-check.outputs.MAGEFILE_EXISTS == 'true' | |
- name: Test plugin backend | |
uses: magefile/mage-action@v3 | |
with: | |
version: latest | |
args: -v test | |
workdir: ${{ matrix.pluginDir }} | |
if: steps.backend-check.outputs.MAGEFILE_EXISTS == 'true' | |
- name: Build plugin backend | |
uses: magefile/mage-action@v3 | |
with: | |
version: latest | |
args: -v build:linux | |
workdir: ${{ matrix.pluginDir }} | |
if: steps.backend-check.outputs.MAGEFILE_EXISTS == 'true' | |
## CANARY_VERSION has to use NPM as we only publish the packages on changes | |
- name: Set environment vars for testing | |
run: | | |
echo "PLUGIN_ID=$(cat src/plugin.json | jq -r '.id')" >> $GITHUB_ENV | |
echo "EXPECTED_GRAFANA_VERSION=$(npx semver@latest $(cat src/plugin.json | jq -r '.dependencies.grafanaDependency') -c)" >> $GITHUB_ENV | |
echo "CANARY_VERSION=${{ needs.setup-matrix.outputs.canaryVersion }}" >> $GITHUB_ENV | |
echo "CANARY_DOCKER_TAG=${{ needs.setup-matrix.outputs.canaryDockerTag }}" >> $GITHUB_ENV | |
echo "LATEST_STABLE_VERSION=${{ needs.setup-matrix.outputs.latestVersion }}" >> $GITHUB_ENV | |
if [ -f "${PWD}/.env" ]; then | |
echo "ENV_FILE_OPTION=--env-file ${PWD}/.env" >> $GITHUB_ENV | |
fi | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Has Integration Tests | |
id: has-integration-tests | |
continue-on-error: true | |
run: | | |
echo "DIR=$($(test -f ./playwright.config.ts) && echo "true" || echo "false")" >> $GITHUB_OUTPUT | |
working-directory: ${{ matrix.pluginDir }} | |
## If we're creating examples for new features that are only found in canary versions the grafanaDependency | |
## will be greater than any stable release of Grafana and so will not be available on docker. | |
- name: Should run tests against expected and latest | |
id: should-run-expected-latest-tests | |
continue-on-error: true | |
run: | | |
npm exec --package semver-compare-cli --call 'semver-compare $LATEST_STABLE_VERSION ge $EXPECTED_GRAFANA_VERSION' | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Check if mockserver is defined | |
id: mockserver-check | |
run: | | |
echo $(docker compose config --services) | |
if docker compose config --services | grep -wq mockserver; then | |
echo "MOCKSERVER_DEFINED=true" >> $GITHUB_OUTPUT | |
else | |
echo "MOCKSERVER_DEFINED=false" >> $GITHUB_OUTPUT | |
fi | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Run mock server | |
if: steps.mockserver-check.outputs.MOCKSERVER_DEFINED == 'true' | |
run: docker compose up -d mockserver | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Setup playwright browser | |
if: steps.has-integration-tests.outputs.DIR == 'true' | |
run: npx playwright install --with-deps chromium | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Expected version - Start Grafana | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
run: | | |
docker run -d -p 3000:3000 --add-host=host.docker.internal:host-gateway --name $PLUGIN_ID -v ${PWD}/dist:/var/lib/grafana/plugins/$PLUGIN_ID -v ${PWD}/provisioning:/etc/grafana/provisioning -e GF_DEFAULT_APP_MODE -e GF_INSTALL_PLUGINS -e GF_AUTH_ANONYMOUS_ORG_ROLE -e GF_AUTH_ANONYMOUS_ENABLED -e GF_AUTH_BASIC_ENABLED $ENV_FILE_OPTION grafana/grafana:$EXPECTED_GRAFANA_VERSION | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Expected - Wait for Grafana to start | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
uses: nev7n/wait_for_response@v1 | |
with: | |
url: "http://localhost:3000/" | |
responseCode: 200 | |
timeout: 60000 | |
interval: 500 | |
- name: Expected - Run Playwright tests | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
id: expected-version-tests | |
continue-on-error: true | |
run: npm run e2e --prefix ${{ matrix.pluginDir }} | |
- name: Expected - Publish report to GCS | |
if: ${{ always() && steps.expected-version-tests.outcome == 'failure' }} | |
uses: grafana/plugin-actions/publish-report@main | |
with: | |
grafana-version: ${{ env.EXPECTED_GRAFANA_VERSION }} | |
path: ${{ matrix.pluginDir }}/playwright-report/ | |
- name: Expected - Failing build due to test failures | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.expected-version-tests.outcome != 'success' && steps.should-run-expected-latest-tests.outcome == 'success' | |
run: exit 1 | |
- name: Expected - Stop and remove Docker container | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
run: | | |
docker stop $PLUGIN_ID && docker rm $PLUGIN_ID | |
working-directory: ${{ matrix.pluginDir }} | |
# Latest Version Tests | |
# Runs the plugin tests against the latest stable version of Grafana. | |
# Only run if should-run-expected-latest-tests so we can build examples of new features without failing tests. | |
- name: Latest - Start Grafana | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
run: | | |
docker run -d -p 3000:3000 --add-host=host.docker.internal:host-gateway --name $PLUGIN_ID -v ${PWD}/dist:/var/lib/grafana/plugins/$PLUGIN_ID -v ${PWD}/provisioning:/etc/grafana/provisioning -e GF_DEFAULT_APP_MODE -e GF_INSTALL_PLUGINS -e GF_AUTH_ANONYMOUS_ORG_ROLE -e GF_AUTH_ANONYMOUS_ENABLED -e GF_AUTH_BASIC_ENABLED $ENV_FILE_OPTION grafana/grafana:latest | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Latest - Wait for Grafana to start | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
uses: nev7n/wait_for_response@v1 | |
with: | |
url: "http://localhost:3000/" | |
responseCode: 200 | |
timeout: 60000 | |
interval: 500 | |
- name: Latest - Run Playwright tests | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
id: latest-version-tests | |
continue-on-error: true | |
run: npm run e2e --prefix ${{ matrix.pluginDir }} | |
- name: Latest - Publish report to GCS | |
if: ${{ always() && steps.latest-version-tests.outcome == 'failure' }} | |
uses: grafana/plugin-actions/publish-report@main | |
with: | |
grafana-version: ${{ env.LATEST_STABLE_VERSION }} | |
path: ${{ matrix.pluginDir }}/playwright-report/ | |
- name: Latest - Failing build due to test failures (latest version of Grafana) | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.latest-version-tests.outcome != 'success' && steps.should-run-expected-latest-tests.outcome == 'success' | |
run: exit 1 | |
- name: Latest - Stop and remove Docker container | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.should-run-expected-latest-tests.outcome == 'success' | |
run: | | |
docker stop $PLUGIN_ID && docker rm $PLUGIN_ID | |
working-directory: ${{ matrix.pluginDir }} | |
## Canary Version Tests | |
## Runs the plugin tests against the latest build of Grafana main branch. | |
- name: Canary - Upgrade @grafana packages using canary_version | |
run: | | |
npm install --legacy-peer-deps $(echo $(cat package.json | jq -r --arg version $CANARY_VERSION '["@grafana/eslint-config", "@grafana/tsconfig", "@grafana/scenes", "@grafana/experimental", "@grafana/plugin-e2e", "@grafana/plugin-meta-extractor"] as $blacklist | [(.devDependencies,.dependencies) | keys] | flatten | unique | map(select ( test("^@grafana") ) ) as $deps | $deps - $blacklist | map("\(.)@\($version)") | join(" ")') ) | |
npm install --force --save-optional @swc/core @swc/core-linux-arm-gnueabihf @swc/core-linux-arm64-gnu @swc/core-linux-arm64-musl @swc/core-linux-x64-gnu @swc/core-linux-x64-musl | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Canary - Run frontend tests | |
run: | | |
npm run test:ci | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Canary - Build plugin with grafana dependencies | |
run: | | |
npm run build | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Canary - Build plugin backend | |
uses: magefile/mage-action@v3 | |
with: | |
version: latest | |
args: -v build:linux | |
workdir: ${{ matrix.pluginDir }} | |
if: steps.backend-check.outputs.MAGEFILE_EXISTS == 'true' | |
# Canary versions live at grafana/grafana-dev | |
- name: Canary - Start Grafana dev image | |
if: steps.has-integration-tests.outputs.DIR == 'true' | |
run: | | |
docker run -d -p 3000:3000 --add-host=host.docker.internal:host-gateway --name $PLUGIN_ID -v ${PWD}/dist:/var/lib/grafana/plugins/$PLUGIN_ID -v ${PWD}/provisioning:/etc/grafana/provisioning -e GF_DEFAULT_APP_MODE -e GF_INSTALL_PLUGINS -e GF_AUTH_ANONYMOUS_ORG_ROLE -e GF_AUTH_ANONYMOUS_ENABLED -e GF_AUTH_BASIC_ENABLED $ENV_FILE_OPTION grafana/grafana-dev:$CANARY_DOCKER_TAG | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Canary - Wait for Grafana to start | |
if: steps.has-integration-tests.outputs.DIR == 'true' | |
uses: nev7n/wait_for_response@v1 | |
with: | |
url: "http://localhost:3000/" | |
responseCode: 200 | |
timeout: 60000 | |
interval: 500 | |
- name: Canary - Run Playwright tests | |
if: steps.has-integration-tests.outputs.DIR == 'true' | |
id: canary-version-tests | |
continue-on-error: true | |
run: npm run e2e --prefix ${{ matrix.pluginDir }} | |
- name: Canary - Publish report to GCS | |
if: ${{ always() && steps.canary-version-tests.outcome == 'failure' }} | |
uses: grafana/plugin-actions/publish-report@main | |
with: | |
grafana-version: ${{ env.CANARY_DOCKER_TAG }} | |
path: ${{ matrix.pluginDir }}/playwright-report/ | |
- name: Canary - Failing build due to test failures (canary versions) | |
if: steps.has-integration-tests.outputs.DIR == 'true' && steps.canary-version-tests.outcome != 'success' | |
run: exit 1 | |
- name: Canary - Stop and remove Docker container | |
if: steps.has-integration-tests.outputs.DIR == 'true' | |
run: | | |
docker stop $PLUGIN_ID && docker rm $PLUGIN_ID | |
working-directory: ${{ matrix.pluginDir }} | |
- name: Stop mockserver if running | |
if: steps.mockserver-check.outputs.MOCKSERVER_DEFINED == 'true' | |
run: docker compose down mockserver | |
working-directory: ${{ matrix.pluginDir }} | |
notify: | |
if: ${{ (always() && github.event_name == 'schedule') }} | |
runs-on: ubuntu-latest | |
needs: [run-integration-tests] | |
steps: | |
- name: Send GitHub Action trigger data to Slack workflow | |
id: slack | |
uses: slackapi/[email protected] | |
if: contains(fromJson('["failure"]'), needs.run-integration-tests.result) | |
with: | |
channel-id: ${{ secrets.SLACK_CHANNEL_ID }} | |
payload: | | |
{ | |
"blocks": [ | |
{ | |
"type": "section", | |
"text": { | |
"type": "mrkdwn", | |
"text": ":blob-sad: <${{ github.server_url }}/${{ github.repository }}|Plugin Examples> Integration Test `${{ needs.run-integration-tests.result }}`" | |
} | |
}, | |
{ | |
"type": "actions", | |
"elements": [ | |
{ | |
"type": "button", | |
"text": { | |
"type": "plain_text", | |
"text": ":octocat: Open Job", | |
"emoji": true | |
}, | |
"url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}", | |
"action_id": "actionId-0" | |
} | |
] | |
}, | |
{ | |
"type": "divider" | |
}, | |
{ | |
"type": "context", | |
"elements": [ | |
{ | |
"type": "mrkdwn", | |
"text": "*Commit*: <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*Event*: ${{ github.event_name }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*Branch*: `${{ github.head_ref || github.ref_name }}`" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*PR Number*: `${{ github.event.pull_request.number || 'Not triggered by a PR' }}`" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github. run_id }}?pr=${{ github.event.number }}|See Playwright reports>" | |
} | |
] | |
} | |
] | |
} | |
env: | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK |