name: Build and release core plugins on: workflow_dispatch: inputs: plugin_id: description: "ID of the plugin you want to publish" required: true type: choice options: - grafana-azure-monitor-datasource - grafana-pyroscope-datasource - grafana-testdata-datasource - jaeger - parca - stackdriver - tempo - zipkin concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}-${{ inputs.plugin_id }} cancel-in-progress: true env: GRABPL_VERSION: 3.0.44 GCP_BUCKET: integration-artifacts # Dev: plugins-community-staging GCOM_API: https://grafana.com # Dev: https://grafana-dev.com # These permissions are needed to assume roles from Github's OIDC. permissions: contents: read id-token: write jobs: build-and-publish: env: PLUGIN_ID: ${{ inputs.plugin_id }} name: Build and publish ${{ inputs.plugin_id }} runs-on: ubuntu-latest outputs: type: ${{ steps.get_dir.outputs.dir }} has_backend: ${{ steps.check_backend.outputs.has_backend }} version: ${{ steps.build_frontend.outputs.version }} steps: - name: checkout uses: actions/checkout@v5 with: persist-credentials: false - name: Verify inputs run: | if [ -z "$PLUGIN_ID" ]; then echo "Missing plugin ID"; exit 1; fi - id: get-secrets uses: grafana/shared-workflows/actions/get-vault-secrets@main # zizmor: ignore[unpinned-uses] with: # Secrets placed in the ci/repo/grafana// path in Vault repo_secrets: | PLUGINS_GOOGLE_CREDENTIALS=core-plugins-build-and-release:PLUGINS_GOOGLE_CREDENTIALS PLUGINS_GRAFANA_API_KEY=core-plugins-build-and-release:PLUGINS_GRAFANA_API_KEY PLUGINS_GCOM_TOKEN=core-plugins-build-and-release:PLUGINS_GCOM_TOKEN - name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' with: credentials_json: '${{ env.PLUGINS_GOOGLE_CREDENTIALS }}' - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db' - name: Setup nodejs environment uses: actions/setup-node@v4 with: node-version-file: .nvmrc cache: yarn - name: Find plugin directory shell: bash id: get_dir run: | dir="$(dirname \ "$(grep -Elir --include=plugin.json --exclude-dir=dist \ '"id": "'"${PLUGIN_ID}"'"' \ public/app/plugins \ )" \ )" echo "dir=${dir}" >> "$GITHUB_OUTPUT" - name: Install frontend dependencies shell: bash working-directory: ${{ steps.get_dir.outputs.dir }} run: | yarn install --immutable - name: Download grabpl executable shell: sh working-directory: ${{ steps.get_dir.outputs.dir }} run: | mkdir -pv ./bin curl -fL -o ./bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v"$GRABPL_VERSION"/grabpl chmod 0755 ./bin/grabpl - name: Check backend id: check_backend shell: bash run: | if grep -Eqr --include=main.go 'datasource.Manage\('"$PLUGIN_ID" pkg/tsdb; then echo "has_backend=true" >> "$GITHUB_OUTPUT" else echo "has_backend=false" >> "$GITHUB_OUTPUT" fi - name: Setup golang environment uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 if: steps.check_backend.outputs.has_backend == 'true' with: go-version-file: go.mod - name: Install Mage shell: bash if: steps.check_backend.outputs.has_backend == 'true' run: | go install github.com/magefile/mage - name: Check tools shell: bash working-directory: ${{ steps.get_dir.outputs.dir }} run: | echo "=======================================" echo " Frontend tools" echo "=======================================" echo "-------- node version -----" node --version echo "-------- npm version -----" npm --version echo "-------- yarn version -----" yarn --version echo "=======================================" echo " Misc tools" echo "=======================================" echo "-------- docker version -----" docker --version echo "-------- jq version -----" jq --version echo "-------- grabpl version -----" ./bin/grabpl --version echo "=======================================" - name: Check backend tools shell: bash if: steps.check_backend.outputs.has_backend == 'true' working-directory: ${{ steps.get_dir.outputs.dir }} run: | echo "=======================================" echo " Backend tools" echo "=======================================" echo "-------- go version -----" go version echo "-------- mage version -----" mage --version echo "=======================================" - name: build:frontend shell: bash id: build_frontend env: OUTPUT_DIR: ${{ steps.get_dir.outputs.dir }} run: | command="plugin:build:commit" if [ "$GITHUB_REF" != "refs/heads/main" ]; then # Release branch, do not add commit hash to version command="plugin:build" fi yarn $command --scope="@grafana-plugins/$PLUGIN_ID" version="$(jq -r .info.version "$OUTPUT_DIR"/dist/plugin.json)" echo "version=${version}" >> "$GITHUB_OUTPUT" - name: build:backend if: steps.check_backend.outputs.has_backend == 'true' shell: bash env: VERSION: ${{ steps.build_frontend.outputs.version }} run: | make build-plugin-go PLUGIN_ID="$PLUGIN_ID" - name: package working-directory: ${{ steps.get_dir.outputs.dir }} run: | mkdir -p ci/jobs/package bin/grabpl plugin package env: GRAFANA_API_KEY: ${{ env.PLUGINS_GRAFANA_API_KEY }} PLUGIN_SIGNATURE_TYPE: grafana - name: Check existing release env: GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }} VERSION: ${{ steps.build_frontend.outputs.version }} GCOM_API: ${{ env.GCOM_API }} run: | api_res="$(curl -X 'GET' -H "Authorization: Bearer $GCOM_TOKEN" \ "$GCOM_API/api/plugins/$PLUGIN_ID?version=$VERSION" \ -H 'accept: application/json')" api_res_code="$(echo "$api_res" | jq -r .code)" if [ "$api_res_code" = "NotFound" ]; then echo "No existing release found" else echo "Expecting a missing release, got:" echo "$api_res" exit 1 fi - name: store build artifacts uses: actions/upload-artifact@v4 with: name: build-artifacts path: ${{ steps.get_dir.outputs.dir }}/ci/packages/*.zip - name: Publish release to Google Cloud Storage working-directory: ${{ steps.get_dir.outputs.dir }} env: VERSION: ${{ steps.build_frontend.outputs.version }} GCP_BUCKET: ${{ env.GCP_BUCKET }} run: | echo "Publish release to Google Cloud Storage:" set -x touch ci/packages/windows ci/packages/darwin ci/packages/linux ci/packages/any gsutil -m cp -r ci/packages/*windows* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/windows" gsutil -m cp -r ci/packages/*linux* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/linux" gsutil -m cp -r ci/packages/*darwin* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/darwin" gsutil -m cp -r ci/packages/*any* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/any" - name: Publish new plugin version on grafana.com if: steps.check_backend.outputs.has_backend == 'true' working-directory: ${{ steps.get_dir.outputs.dir }} env: GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }} VERSION: ${{ steps.build_frontend.outputs.version }} GCP_BUCKET: ${{ env.GCP_BUCKET }} OUTPUT_DIR: ${{ steps.get_dir.outputs.dir }} GCOM_API: ${{ env.GCOM_API }} run: | echo "Publish new plugin version on grafana.com:" echo "Plugin version: ${VERSION}" OUTPUT_URL="https://github.com/grafana/grafana/tree/$OUTPUT_DIR" \ jq -n '{"url": env.OUTPUT_URL}' > body.json osarchs=(linux_amd64 linux_arm64 linux_arm windows_amd64 darwin_amd64 darwin_arm64) for osarch in "${osarchs[@]}"; do echo "Processing $osarch" KEY="${osarch//_/-}" \ OSARCH="$osarch" \ jq -s '. as $i | .[0] | .download[env.KEY] = { "url": "https://storage.googleapis.com/\(env.GCP_BUCKET)/\(env.PLUGIN_ID)/release/\(env.VERSION)/linux/\(env.PLUGIN_ID)-\(env.VERSION).\(env.OSARCH).zip", "md5": $i[1].plugin.md5 }' body.json ci/packages/info-"$osarch".json > tmp.json && mv tmp.json body.json done result="$(curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" "$GCOM_API"/api/plugins --data-binary '@body.json')" if [[ "$(echo "$result" | jq -r .version)" == "null" ]]; then echo "Failed to publish plugin version. Got:" echo "$result" exit 1 fi - name: Publish new plugin version on grafana.com (frontend only) if: steps.check_backend.outputs.has_backend == 'false' working-directory: ${{ steps.get_dir.outputs.dir }} env: GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }} VERSION: ${{ steps.build_frontend.outputs.version }} GCOM_API: ${{ env.GCOM_API }} OUTPUT_DIR: ${{ steps.get_dir.outputs.dir }} GCP_BUCKET: ${{ env.GCP_BUCKET }} run: | echo "Publish new plugin version on grafana.com:" echo "Plugin version: ${VERSION}" OUTPUT_URL="https://github.com/grafana/grafana/tree/$OUTPUT_DIR" \ DOWNLOAD_URL="https://storage.googleapis.com/$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/any/$PLUGIN_ID-${VERSION}.any.zip" \ MD5_CHECKSUM="$(jq -r '.plugin.md5' ci/packages/info-any.json)" \ jq -rn '{ "url": env.OUTPUT_URL, "download": { "any": { "url": env.DOWNLOAD_URL, "md5": env.MD5_CHECKSUM } } }' > body.json result="$(curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" "$GCOM_API"/api/plugins --data-binary '@body.json')" if [[ "$(echo "$result" | jq -r .version)" == "null" ]]; then echo "Failed to publish plugin version. Got:" echo "$result" exit 1 fi