CI Migration: Backport pkg/build (daggerbuild) and GHAs to release-12.0.3 (#107997)

* CI: move grafana-build into pkg/build (#105640)

* move grafana-build into pkg/build

* Update go.mod/go.sum files after cherry-pick build

- Updates from workspace sync after cherry-picking daggerbuild package
- Resolves dependency conflicts from pkg/build integration
- Required for successful build after CI migration backport

* CI Migration: Replace .github with main branch version

- Complete replacement of .github directory from main branch
- Includes updated workflows, actions, and configuration files
- Ensures all CI improvements from main are included
- Next step: fix branch-specific issues in separate commits

* Fix branch triggers: Update workflows to target release branches

- Update 8 workflows to trigger on release-* instead of main
- Ensures workflows run on pull requests to release branches
- Workflows updated: documentation-ci, pr-codeql-analysis-*, pr-dependabot-update-go-workspace, pr-go-workspace-check, pr-k8s-codegen-check, verify-kinds, codeowners-validator

* Fix branch triggers: Update workflows to target both main and release branches

- CORRECTED: Include both main and release-* branch patterns
- Ensures workflows run on both main branch (original functionality) and release branches (needed for backport)
- Previous commit incorrectly removed main branch support
- Workflows updated: documentation-ci, pr-codeql-analysis-*, pr-dependabot-update-go-workspace, pr-go-workspace-check, pr-k8s-codegen-check, verify-kinds, codeowners-validator

* CI Migration: Update .gitignore to allow OSS wire file to be committed

- Remove **/wire_gen.go (allow pkg/server/wire_gen.go to be committed)
- Add /pkg/server/enterprise_wire_gen.go (keep enterprise wire file ignored)
- This enables the new committed wire files architecture for CI

* CI Migration: Add enhanced wire tool with automatic build constraints

- Backport enhanced wire tool from main branch with -gen_tags flag
- This enables automatic regeneration with proper constraints to prevent conflicts
- Wire file contains all required functions: Initialize, InitializeDocumentBuilders, etc.
- Solves the missing wire functions issue causing CI failures
- Enhanced tool ensures build constraints persist on regeneration

* CI Migration: Update Makefile to use enhanced wire tool with build constraints

- Update gen-go target to use -gen_tags flag for automatic build constraints
- Ensures future engineers get proper build constraints when running 'make gen-go'
- Matches main branch approach for consistent wire file generation
- Removes dependency on WIRE_TAGS variable and GO_RACE_FLAG for simplicity

* Add gen-enterprise-go target to Makefile for release-12.0.3

- Backports gen-enterprise-go target from main branch
- Enables enterprise wire file generation in release branches
- Part of CI migration backport wire infrastructure fixes
- Resolves CI issues where enterprise wire functions were missing

* Fix wire tool golden file format for Drone CI compatibility

- Update all 43 golden test files to match main branch format
- Change go:generate command from github.com/google/wire/cmd/wire to ./pkg/build/wire/cmd/wire/main.go
- Remove legacy '// +build !wireinject' constraints
- Fixes Drone CI test failures that were blocking OSS PR merge
- All wire tests now pass successfully

This aligns the backport branch with the golden file format updates
that were made in main branch when the wire tool was enhanced.

* Update swagger specs to include enterprise APIs

- Regenerated api-enterprise-spec.json with enterprise API definitions
- Updated api-merged.json with merged OSS and enterprise specs
- Regenerated openapi3.json with complete API specifications
- Fixes enterprise CI swagger generation validation failures
- Enterprise APIs now properly detected and documented

* Fix OSS integration tests missing enterprise build tags in Drone CI

- Add -tags=enterprise to all integration test steps in lib.star
- Fixes test-backend-integration, postgres-integration-tests, and mysql-integration-tests
- Regenerate .drone.yml with proper enterprise build tags
- Resolves 'server could not find the requested resource' errors for enterprise APIs
- Ensures enterprise APIs (querylibrary, reporting, banners, scim) are registered during tests
- Aligns OSS Drone CI with GitHub Actions behavior and enterprise repository

* Fix CODEOWNERS for release-12.0.3 compatibility

- Remove 21 entries that reference files/directories not present in release branch
- Resolves File Exist Checker failures in codeowners-validator workflow
- Maintains team ownership assignments from main branch for existing files
- Lines removed: .air.toml, apps/secret/, apps/iam/, e2e-playwright/, packages/grafana-alerting/, etc.

* baldm0mma/ update releasefinder

* Add i18n-extract script for release branch compatibility

- Add 'i18n-extract': 'make i18n-extract' to package.json scripts
- Resolves i18n-verify workflow failure that expects this script
- The make target already exists and handles OSS + enterprise i18n extraction
- Maintains i18n verification functionality from main branch workflows
- Simple safe addition that calls existing make infrastructure

* Phase 4: Fix GitHub Actions workflow branch triggers

- Add release-*.*.* pattern to 8 workflows missing it
- Fix duplicate release branch patterns in 3 workflows
- Ensure consistent branch trigger format across all workflows
- Critical workflows now properly trigger on release branches

Fixes workflows: actionlint, backend-code-checks, go-lint, reject-gh-secrets,
run-schema-v2-e2e, shellcheck, swagger-gen, trivy-scan

* Fix: Backport E2E runner infrastructure for Enterprise CI

- Add e2e/main.go and e2e/internal/ directory from main branch
- Add urfave/cli/v3 dependency required by E2E runner
- Fixes Enterprise CI failure: 'Build E2E test runner' and 'Build & package Grafana for e2e tests'
- Root cause: E2E runner infrastructure was added to main after release-12.0.3 branch creation
- Solution: Backport missing E2E runner files to enable Enterprise CI completion

Resolves: no Go files in /opt/actions-runner/_work/grafana-enterprise/grafana-enterprise/grafana/e2e

* Fix: Update go.mod dependency classification for urfave/cli/v3

- Change urfave/cli/v3 from indirect to direct dependency
- Fixes Go Workspace Check failure in CI
- Required after adding E2E runner infrastructure that directly imports urfave/cli/v3
- Resolves: make update-workspace corrects dependency classification

* Fix: Add team ownership for urfave/cli/v3 dependency

- Assign @grafana/grafana-backend-group as owner for github.com/urfave/cli/v3@v3.3.8
- Follows existing pattern: urfave/cli v1 and v2 also owned by grafana-backend-group
- Resolves Backend Code Checks / Validate Backend Configs CI failure
- Required for E2E runner infrastructure dependency ownership compliance

Fixes: modowners check requiring team assignment for newly added dependencies

* Fix: Revert experimental E2E playwright infrastructure to stable version

- Revert pr-e2e-tests.yml to stable Cypress-based E2E testing
- Remove experimental storybook-verification-playwright.yml workflow
- Revert run-dashboard-search-e2e.yml and release-pr.yml to use e2e/test-plugins/
- Keep stable E2E runner infrastructure (e2e/main.go + e2e/internal/)
- Remove experimental playwright features per team recommendation

Team feedback: Playwright tests are experimental and shouldn't be backported to stable release branches

* Fix: Complete cleanup of experimental playwright dependencies

- Revert package.json to stable version (remove e2e-playwright scripts and path references)
- Revert playwright.config.ts to stable plugin-e2e configuration
- Remove all experimental playwright infrastructure dependencies
- Ensure clean stable E2E testing environment

All experimental features removed per team recommendation for stable release branches

* Fix: Restore working package.json configuration

- Revert package.json to version 12.0.3 (working release branch version)
- Fix workspace dependency resolution issues caused by incorrect revert to main branch version
- FE tests, betterer, and linting should now work correctly

Issue was caused by reverting package.json to main branch (12.1.0-pre) instead of keeping
the working release branch configuration (12.0.3)

* CI: mirror some CI dependencies (#106148)

* mirror some CI dependencies
* remove -v from go build

* Fix: Backport missing e2e/run-suite script for daggerbuild E2E system

The daggerbuild E2E system (used by OSS workflows) expects ./e2e/run-suite
to exist, but we only backported the new E2E runner infrastructure.

This script is needed for:
- OSS workflow: 'go run ./pkg/build/e2e --suite=dashboards-suite'
- Legacy Cypress configuration with video support
- Integration between daggerbuild and existing Cypress test suites

Resolves E2E test failures in OSS workflows where videos directory
cannot be found because run-suite script was missing.

* Fix: Resolve daggerbuild E2E path doubling issue

- Extract just suite name from full path using filepath.Base()
- Prevents doubled paths like './e2e/e2e/dashboards-suite/videos'
- Resolves 'no spec files found' and 'no such file or directory' errors
- GitHub Actions passes full paths like 'e2e/dashboards-suite' but run-suite script expects just 'dashboards-suite'

* Infrastructure: Wholesale copy pkg/build/ from main

COMPLETE DAGGERBUILD SYSTEM UPDATE:
- Modern E2E system with CLI framework and --flags support
- New accessibility testing system (a11y/)
- New Playwright E2E testing system (e2e-playwright/)
- External infrastructure improvements (musl.cc → dl.grafana.com/ci)
- Updated daggerbuild core components with latest fixes
- Updated Go dependencies and wire modules

ARCHITECTURAL COMPATIBILITY VERIFIED:
- Modern pkg/build calls: ./e2e-runner cypress --start-grafana=false --cypress-video
- Our e2e runner supports: All required parameters including --suite, --env flags
- GitHub Actions workflows: Pass compatible arguments
- Binary builds: Successfully creates working e2e-runner

RESOLVES ISSUES:
- Fixes --flags parameter compatibility with GitHub Actions
- Includes all follow-up infrastructure improvements
- Provides complete, tested system with modern CLI framework
- Eliminates external dependency failures (musl.cc timeouts)
- Removes need for path doubling workarounds (modern system handles full paths correctly)

Replaces incremental cherry-picking with complete, tested system from main.

* Dependencies: Update Go modules after pkg/build wholesale copy

DEPENDENCY UPDATES:
- Updated go.work.sum with new dependencies from modern pkg/build system
- Updated all workspace module dependencies (go.mod/go.sum files)
- Removed pkg/build/cmd/enterprise.go (enterprise-only file, gets copied during enterprise development)

ENTERPRISE INTEGRATION FIX:
- enterprise.go file doesn't belong in OSS repository
- Gets copied from grafana-enterprise during development mode
- Main branch doesn't have this file, explaining module compatibility

All Go modules now properly resolved and compatible with modern pkg/build architecture.

* Dependencies: Update workspace Go module checksums after pkg/build wholesale copy

- Synchronizes all go.sum files across workspace modules
- Adds missing .mod.h1 entries that were required after infrastructure update
- Resolves Go Workspace Check CI failures
- Updates 22 modules: .citools/, apps/, pkg/ subdirectories plus go.work.sum

Addresses CI error: 'Please run make update-workspace and commit the changes'

* Infrastructure: Revert to pre-Playwright E2E system for release branch compatibility

Strategic combination of modern daggerbuild with stable E2E infrastructure:

**Modern Daggerbuild (from main):**
- Latest CLI framework (github.com/urfave/cli/v3)
- External infrastructure fixes (musl.cc → dl.grafana.com/ci)
- Complete pkg/build/ system with all enhancements
- Updated dependencies and architecture improvements

**Stable E2E Infrastructure (pre-Playwright):**
- pkg/build/e2e/service.go: Reverted to version before commit b6580ccb10
- pkg/build/a11y/: Reverted to stable version compatible with existing infrastructure
- Removed experimental pkg/build/e2e-playwright/ system
- Removed experimental e2e-playwright/ test infrastructure

**Why This Approach:**
- GitHub Actions workflows call 'go run ./pkg/build/e2e' (modern system)
- Modern system now expects only standard e2e/ directory (compatible)
- Release branches have standard e2e/ infrastructure (dashboards-suite, various-suite, etc.)
- Eliminates dependency on experimental Playwright infrastructure

**Key Dependencies Met:**
- e2e/pa11yci.conf.js: Added for a11y test compatibility
- /src/e2e directory: Standard directory structure (no e2e-playwright needed)
- Existing test plugins: Uses stable e2e/test-plugins/

**Result:**
Best of both worlds - modern, reliable daggerbuild infrastructure with
proven E2E testing that works across all release branches without
requiring experimental dependencies.

* Fix: Remove unused embed.go file causing golangci-lint failure

- Removes pkg/build/daggerbuild/msi/embed.go with unused embed.FS variable
- MSI build process uses directory mounting instead of embedded filesystem
- Resolves 'var resources is unused (unused)' linting error

* Fix: Update Node.js version to match working E2E configuration

- Changes from v22.11.0 to v22.16.0 to match commit 17952d45e4
- Working commit had all E2E tests passing with same daggerbuild infrastructure
- Node.js version differences can affect frontend builds and UI rendering
- Ensures consistent environment between working reference and current branch

* Fix: Use conditional container base for E2E compatibility

- Alpine for OSS tests (better old arch dashboardScene=false compatibility)
- Ubuntu for Enterprise tests (when image renderer needed)
- Restores original release-12.0.3 Alpine behavior for OSS
- Should resolve old arch E2E test failures

* Fix: Go fmt formatting for conditional container logic

* Revert: Remove unnecessary Alpine/Ubuntu conditional logic

- Real issue was wrong environment variable name (dashboardScene vs DISABLE_SCENES)
- Keep Ubuntu base (original main branch behavior) for simplicity
- Container base was not the root cause of old arch failures

* Experiment: Copy scripts/ from pre-Playwright commit (ea0ddb3fc9)

- Copied scripts directory from commit ea0ddb3fc9 (just before Playwright migration)
- This overwrites some CI migration fixes but testing if it's actually needed
- Can revert back to b9b4602dbd if CI breaks

Test commit to see real impact on GitHub Actions workflows.

* trigger ci 01

* Fix: Copy .drone.star from main to match scripts structure

- Resolves Starlark evaluation error for missing integration_test_pipelines
- Aligns .drone.star with main branch scripts structure
- Same fix applied to both OSS and Enterprise repositories

* make drone

* Fix ARM/v7 Docker build failures by using dagger run for cross-compilation

- Change artifacts_cmd() in scripts/drone/steps/rgm.star to use 'dagger run go run' instead of 'go run'
- Add --max-execution-steps 100000 to make drone target in Makefile to properly regenerate .drone.yml
- This fixes CGO cross-compilation issues with SQLite for ARM/v7 Docker builds
- Matches the approach already used successfully in Enterprise builds

* Fix Docker base image references in rgm build steps

- Change from symbolic names (alpine-base, ubuntu-base) to actual Docker images
- alpine-base → alpine:3.21.3
- ubuntu-base → ubuntu:22.04
- Add ubuntu and alpine parameters to rgm_artifacts_step and rgm_build_docker_step functions
- Fixes Docker pull errors: 'repository does not exist or may require authorization'
- Aligns OSS configuration with Enterprise approach

---------

Co-authored-by: Kevin Minehart <5140827+kminehart@users.noreply.github.com>
This commit is contained in:
Jev Forsberg
2025-07-18 09:14:14 -06:00
committed by GitHub
co-authored by Kevin Minehart
parent aee6b20c7f
commit dc6bd2a20a
432 changed files with 24660 additions and 16787 deletions
+66
View File
@@ -0,0 +1,66 @@
{
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "GitHub Actions lint",
"version": {{ getVersion | json }},
"informationUri": "https://github.com/rhysd/actionlint",
"rules": [
{{$first := true}}
{{range $ := allKinds }}
{{if $first}}{{$first = false}}{{else}},{{end}}
{
"id": {{json $.Name}},
"name": {{$.Name | toPascalCase | json}},
"defaultConfiguration": {
"level": "error"
},
"properties": {
"description": {{json $.Description}},
"queryURI": "https://github.com/rhysd/actionlint/blob/main/docs/checks.md"
},
"fullDescription": {
"text": {{json $.Description}}
},
"helpUri": "https://github.com/rhysd/actionlint/blob/main/docs/checks.md"
}
{{end}}
]
}
},
"results": [
{{$first := true}}
{{range $ := .}}
{{if $first}}{{$first = false}}{{else}},{{end}}
{
"ruleId": {{json $.Kind}},
"message": {
"text": {{json $.Message}}
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": {{json $.Filepath}},
"uriBaseId": "%SRCROOT%"
},
"region": {
"startLine": {{$.Line}},
"startColumn": {{$.Column}},
"endColumn": {{$.EndColumn}},
"snippet": {
"text": {{json $.Snippet}}
}
}
}
}
]
}
{{end}}
]
}
]
}
+60
View File
@@ -0,0 +1,60 @@
# This workflow depends on the ./actionlint-format.txt file. It is MIT licensed (thanks, rhysd!): https://github.com/rhysd/actionlint/blob/2ab3a12c7848f6c15faca9a92612ef4261d0e370/testdata/format/sarif_template.txt
name: Actionlint
on:
push:
branches:
- main
- release-*.*.*
pull_request:
types:
- opened
- synchronize
- reopened
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
run-actionlint:
name: Lint GitHub Actions files
runs-on: ubuntu-latest
permissions:
contents: read # to check out the code
actions: read # to read the workflow files
security-events: write # for uploading the SARIF report
env:
ACTIONLINT_VERSION: 1.7.7
# curl -LXGET https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_checksums.txt | grep linux_amd64
CHECKSUM: 023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
persist-credentials: false
# GitHub Actions only runs x86_64. This will break if that assumption changes.
- name: Download Actionlint
run: |
set -euo pipefail
curl -OLXGET https://github.com/rhysd/actionlint/releases/download/v"${ACTIONLINT_VERSION}"/actionlint_"${ACTIONLINT_VERSION}"_linux_amd64.tar.gz
echo "${CHECKSUM} actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" | sha256sum -c -
tar xzf actionlint_"${ACTIONLINT_VERSION}"_linux_amd64.tar.gz
test -f actionlint
chmod +x actionlint
- name: Run Actionlint
run: ./actionlint -format "$(cat .github/workflows/actionlint-format.txt)" | tee results.sarif
- name: Upload to GitHub security events
if: success() || failure()
# If there are security problems, GitHub will automatically comment on the PR for us.
uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
with:
sarif_file: results.sarif
category: actionlint
+27 -18
View File
@@ -37,7 +37,7 @@ jobs:
id: current-commit
run: |
FROM_COMMIT=$(go list -m -json github.com/grafana/alerting | jq -r '.Version' | grep -oP '(?<=-)[a-f0-9]+$')
echo "from_commit=$FROM_COMMIT" >> $GITHUB_OUTPUT
echo "from_commit=$FROM_COMMIT" >> "$GITHUB_OUTPUT"
- name: Get current branch name
id: current-branch-name
@@ -47,14 +47,14 @@ jobs:
id: latest-commit
env:
GH_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.current-branch-name.outputs.name }}
run: |
BRANCH="${{ steps.current-branch-name.outputs.name }}"
TO_COMMIT=$(gh api repos/grafana/alerting/commits/$BRANCH --jq '.sha')
TO_COMMIT="$(gh api repos/grafana/alerting/commits/"$BRANCH" --jq '.sha')"
if [ -z "$TO_COMMIT" ]; then
echo "Branch $BRANCH not found in alerting repo, falling back to main branch"
exit 1
fi
echo "to_commit=$TO_COMMIT" >> $GITHUB_OUTPUT
echo "to_commit=$TO_COMMIT" >> "$GITHUB_OUTPUT"
- name: Compare commit hashes
run: |
@@ -74,26 +74,31 @@ jobs:
id: check-commits
env:
GH_TOKEN: ${{ github.token }}
FROM_COMMIT: ${{ steps.current-commit.outputs.from_commit }}
TO_COMMIT: ${{ steps.latest-commit.outputs.to_commit }}
run: |
# get all commits that contains 'Alerting:' in the message
ALERTING_COMMITS=$(gh api repos/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }} \
--jq '.commits[].commit.message | split("\n")[0]') || true
# get all commits that contains 'Alerting:' in the message
ALERTING_COMMITS="$(gh api repos/grafana/alerting/compare/"$FROM_COMMIT"..."$TO_COMMIT" \
--jq '.commits[].commit.message | split("\n")[0]')" || true
# Use printf instead of echo -e for better multiline handling
printf "%s\n" "$ALERTING_COMMITS"
# make the list for markdown and replace PR numbers with links
ALERTING_COMMITS_FORMATTED=$(echo "$ALERTING_COMMITS" | while read -r line; do echo "- $line" | sed -E 's/\(#([0-9]+)\)/[#\1](https:\/\/github.com\/grafana\/grafana\/pull\/\1)/g'; done)
echo "alerting_commits<<EOF" >> $GITHUB_OUTPUT
echo "$ALERTING_COMMITS_FORMATTED" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
ALERTING_COMMITS_FORMATTED="$(echo "$ALERTING_COMMITS" | while read -r line; do echo "- $line" | sed -E 's/\(#([0-9]+)\)/[#\1](https:\/\/github.com\/grafana\/grafana\/pull\/\1)/g'; done)"
{
echo "alerting_commits<<EOF"
echo "$ALERTING_COMMITS_FORMATTED"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Update alerting module
env:
GOSUMDB: off
PINNED_COMMIT: ${{ steps.latest-commit.outputs.to_commit }}
run: |
go get github.com/grafana/alerting@${{ steps.latest-commit.outputs.to_commit }}
go get github.com/grafana/alerting@"$PINNED_COMMIT"
make update-workspace
- id: get-secrets
@@ -124,7 +129,7 @@ jobs:
Compare changes: https://github.com/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }}
<details>
<summary>Commits</summary>
${{ steps.check-commits.outputs.alerting_commits }}
</details>
@@ -132,6 +137,10 @@ jobs:
Created by: [GitHub Action Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- name: Add PR URL to Summary
if: steps.create-pr.outputs.pull-request-url != ''
env:
PR_URL: ${{ steps.create-pr.outputs.pull-request-url }}
run: |
echo "## Pull Request Created" >> $GITHUB_STEP_SUMMARY
echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY
{
echo "## Pull Request Created"
echo "🔗 [View Pull Request]($PR_URL)"
} >> "$GITHUB_STEP_SUMMARY"
@@ -3,9 +3,13 @@ name: Analytics Events Report
on:
workflow_dispatch:
permissions: {}
jobs:
generate-report:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -9,6 +9,7 @@ on:
push:
branches:
- main
- release-*.*.*
paths-ignore:
- '*.md'
- 'docs/**'
+64 -13
View File
@@ -2,16 +2,10 @@ name: Backend Unit Tests
on:
pull_request:
paths-ignore:
- 'docs/**'
- '**/*.md'
push:
branches:
- main
- release-*.*.*
paths-ignore:
- 'docs/**'
- '**/*.md'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -20,10 +14,29 @@ concurrency:
permissions: {}
jobs:
detect-changes:
name: Detect whether code changed
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
changed: ${{ steps.detect-changes.outputs.backend }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: true # required to get more history in the changed-files action
fetch-depth: 2
- name: Detect changes
id: detect-changes
uses: ./.github/actions/change-detection
with:
self: .github/workflows/backend-unit-tests.yml
grafana:
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`,
# Run this workflow only for PRs from forks
# the `pr-backend-unit-tests-enterprise` workflow will run instead
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true
needs: detect-changes
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true && needs.detect-changes.outputs.changed == 'true'
strategy:
matrix:
shard: [
@@ -47,18 +60,18 @@ jobs:
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Generate Go code
run: make gen-go
- name: Run unit tests
env:
SHARD: ${{ matrix.shard }}
run: |
set -euo pipefail
readarray -t PACKAGES <<< "$(./scripts/ci/backend-tests/shard.sh -N"$SHARD")"
go test -short -timeout=30m "${PACKAGES[@]}"
grafana-enterprise:
# Run this workflow for non-PR events (like pushes to `main` or `release-*`) OR for internal PRs (PRs not from forks)
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
needs: detect-changes
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false && needs.detect-changes.outputs.changed == 'true'
strategy:
matrix:
shard: [
@@ -73,6 +86,7 @@ jobs:
contents: read
id-token: write
steps:
# Set up repository clone
- name: Checkout code
uses: actions/checkout@v4
with:
@@ -85,11 +99,48 @@ jobs:
uses: ./.github/actions/setup-enterprise
with:
github-app-name: 'grafana-ci-bot'
- name: Generate Go code
run: make gen-go
# Prepare what we need to upload test results
- run: echo "RESULTS_FILE=$(date --rfc-3339=seconds --utc | sed -s 's/ /-/g')_${SHARD/\//_}.xml" >> "$GITHUB_ENV"
env:
SHARD: ${{ matrix.shard }}
- run: go install github.com/jstemmer/go-junit-report/v2@85bf4716ac1f025f2925510a9f5e9f5bb347c009
# Run code
- name: Run unit tests
env:
SHARD: ${{ matrix.shard }}
run: |
set -euo pipefail
readarray -t PACKAGES <<< "$(./scripts/ci/backend-tests/shard.sh -N"$SHARD")"
# This tee requires pipefail to be set, otherwise `go test`'s exit code is thrown away.
# That means having no `-o pipefail` => failing tests => exit code 0, which is wrong.
go test -short -timeout=30m "${PACKAGES[@]}"
# This is the job that is actually required by rulesets.
# We need to require EITHER the OSS or the Enterprise job to pass.
# However, if one is skipped, GitHub won't flat-map the shards,
# so they won't be accepted by a ruleset.
required-backend-unit-tests:
needs:
- grafana
- grafana-enterprise
# always() is the best function here.
# success() || failure() will skip this function if any need is also skipped.
# That means conditional test suites will fail the entire requirement check.
if: always()
name: All backend unit tests complete
runs-on: ubuntu-latest
steps:
- name: Check test suites
env:
NEEDS: ${{ toJson(needs) }}
run: |
FAILURES="$(echo "$NEEDS" | jq 'with_entries(select(.value.result == "failure")) | map_values(.result)')"
echo "$FAILURES"
if [ "$(echo "$FAILURES" | jq '. | length')" != "0" ]; then
exit 1
fi
echo "All OK!"
+47
View File
@@ -0,0 +1,47 @@
# We need secrets to backport, but they're not available for actions ran by forks.
# So this workflow is used as a 'trigger', which the backport-workflow.yml will with
# via workflow_run
name: Backport (trigger)
on:
pull_request:
types:
- closed
- labeled
permissions: {}
jobs:
trigger:
# Only run this job if the PR has been merged and has a label containing "backport v"
if: |
github.repository == 'grafana/grafana' &&
github.event.pull_request.merged == true &&
contains(join(github.event.pull_request.labels.*.name, ','), 'backport v')
runs-on: ubuntu-latest
steps:
# TODO: save this as job summary instead?
- name: Trigger
run: |
echo "Triggering workflow"
echo "See https://github.com/${{ github.repository }}/actions/workflows/workflow_run.yml for progress"
# Create a JSON artifact with details of this PR to pass to the backport workflow.
# The { action: 'labelled', label: 'backport-1.23.x' } can only be determined from this event payload,
# and is needed to do a backport after a PR has been merged
#
# Important that we don't run *anything* from the PR which could modify the backport_data.json file
- name: Create action data
run: |
jq '{
action: .action,
label: .label.name,
pr_number: .number,
}' "$GITHUB_EVENT_PATH" > /tmp/pr_info.json
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pr_info
path: /tmp/pr_info.json
retention-days: 1
+88
View File
@@ -0,0 +1,88 @@
# Runs the actual backport, after being triggered by the backport-trigger.yml workflow.
name: Backport (workflow)
run-name: "Backport for ${{ github.event.workflow_run.head_branch }} #${{ github.event.workflow_run.run_number }}"
on:
workflow_run: # zizmor: ignore[dangerous-triggers] backport-trigger.yml does not run any user code
workflows: ["Backport (trigger)"]
types:
- completed
permissions: {}
jobs:
backport:
# Only run this job if the triggering workflow was not skipped (and on grafana repo)
if: github.repository == 'grafana/grafana' && github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
permissions:
id-token: write
actions: read
steps:
- name: Get vault secrets
id: secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
export_env: false
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ fromJSON(steps.secrets.outputs.secrets).APP_PEM }}
- name: Download PR info artifact
uses: actions/download-artifact@v4
id: download-pr-info
with:
github-token: ${{ github.token }}
run-id: ${{ github.event.workflow_run.id }}
name: pr_info
- name: Get PR info
id: pr-info
env:
PR_INFO_FILE: ${{ steps.download-pr-info.outputs.download-path }}/pr_info.json
# jq-magic to convert the JSON object into a list of key=value pairs for $GITHUB_OUTPUT
run:
jq -r 'to_entries[] | select(.value | type != "object") | "\(.key)=\(.value)"' "$PR_INFO_FILE" >> "$GITHUB_OUTPUT"
- name: Print PR info
env:
PR_ACTION: ${{ steps.pr-info.outputs.action }}
PR_LABEL: ${{ steps.pr-info.outputs.label }}
PR_NUMBER: ${{ steps.pr-info.outputs.pr_number }}
run: |
echo "PR action: $PR_ACTION"
echo "PR label: $PR_LABEL"
echo "PR number: $PR_NUMBER"
- name: Checkout Grafana
uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
fetch-depth: 2
fetch-tags: false
token: ${{ steps.generate_token.outputs.token }}
persist-credentials: true
- name: Configure git user
run: |
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local --add --bool push.autoSetupRemote true
- name: Run backport
uses: grafana/grafana-github-actions-go/backport@dev
with:
token: ${{ steps.generate_token.outputs.token }}
# If triggered by being labelled, only backport that label.
# Otherwise, the action will backport all labels.
pr_label: ${{ steps.pr-info.outputs.action == 'labeled' && steps.pr-info.outputs.label || '' }}
pr_number: ${{ steps.pr-info.outputs.pr_number }}
repo_owner: ${{ github.repository_owner }}
repo_name: ${{ github.event.repository.name }}
-32
View File
@@ -1,32 +0,0 @@
name: Backport PR Creator
on:
pull_request_target:
types:
- closed
- labeled
permissions:
contents: write
pull-requests: write
jobs:
main:
if: github.repository == 'grafana/grafana'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4 # 4.2.2
with:
persist-credentials: false
- run: git config --local user.name "github-actions[bot]"
- run: git config --local user.email "github-actions[bot]@users.noreply.github.com"
- run: git config --local --add --bool push.autoSetupRemote true
- name: Set remote URL
env:
GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git remote set-url origin "https://grafana-delivery-bot:$GIT_TOKEN@github.com/grafana/grafana.git"
- name: Run backport
uses: grafana/grafana-github-actions-go/backport@main # zizmor: ignore[unpinned-uses]
with:
token: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -44,4 +44,4 @@ jobs:
git add .
git commit -m "bump version ${VERSION}"
git push
gh pr create --dry-run=$DRY_RUN -l "type/ci" -l "no-changelog" -B "$REF_NAME" --title "Release: Bump version to ${VERSION}" --body "Updated version to ${VERSION}"
gh pr create --dry-run="$DRY_RUN" -l "type/ci" -l "no-changelog" -B "$REF_NAME" --title "Release: Bump version to ${VERSION}" --body "Updated version to ${VERSION}"
+54 -18
View File
@@ -22,11 +22,10 @@ on:
required: false
default: false
type: boolean
secrets:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
work_branch:
required: false
type: string
description: "Use specific branch for changelog"
workflow_dispatch:
inputs:
@@ -50,6 +49,10 @@ on:
required: false
default: false
type: boolean
work_branch:
required: false
type: string
description: "Use specific branch for changelog"
permissions: {}
@@ -67,25 +70,32 @@ jobs:
contents: write
pull-requests: write
steps:
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: "Checkout Grafana repo"
uses: "actions/checkout@v4"
with:
ref: main
sparse-checkout: |
.github/workflows
.github/actions
CHANGELOG.md
.nvmrc
.prettierignore
.prettierrc.js
fetch-depth: 0
fetch-tags: true
persist-credentials: false
- name: Setup nodejs environment
uses: actions/setup-node@v4
with:
@@ -96,7 +106,20 @@ jobs:
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local --add --bool push.autoSetupRemote true
- name: "Create branch"
run: git checkout -b "changelog/${RUN_ID}/${VERSION}"
run: |
if [[ "$WORK_BRANCH" == '' ]]; then
git switch -c "changelog/${RUN_ID}/${VERSION}"
exit 0
fi
# Checkout the changelog branch if exists, otherwise create a new one
if git show-ref --verify --quiet "refs/remotes/origin/$WORK_BRANCH"; then
git switch --track "origin/$WORK_BRANCH"
else
git switch -c "$WORK_BRANCH"
fi
env:
WORK_BRANCH: ${{ inputs.work_branch }}
- name: "Generate changelog"
id: changelog
uses: ./.github/actions/changelog
@@ -140,16 +163,29 @@ jobs:
- name: "Commit changelog changes"
run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md
- name: "git push"
if: ${{ inputs.dry_run }} != true
if: inputs.dry_run != true
run: git push
- name: "Create changelog PR"
run: >
gh pr create \
--dry-run=${DRY_RUN} \
--label "no-backport" \
--label "no-changelog" \
-B "${TARGET}" \
--title "Release: update changelog for ${VERSION}" \
--body "Changelog changes for release ${VERSION}"
run: |
if gh pr view &>/dev/null; then
echo "Changelog pr has already been created"
else
gh pr create \
--dry-run="${DRY_RUN}" \
--label "no-backport" \
--label "no-changelog" \
-B "${TARGET}" \
--title "Release: update changelog for ${TARGET}" \
--body "Changelog changes for release versions:"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Add release version to PR description"
if: inputs.dry_run != true
run: |
gh pr view --json body --jq .body > pr_body.md
echo " - ${VERSION}" >> pr_body.md
gh pr edit --body-file pr_body.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+7 -3
View File
@@ -2,11 +2,15 @@ name: "Codeowners Validator"
on:
pull_request:
branches: [ main ]
branches: [ main, release-* ]
permissions: {}
jobs:
codeowners-validator:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
# Checks-out your repository, which is validated in the next step
- uses: actions/checkout@v4
@@ -23,7 +27,7 @@ jobs:
# "The comma-separated list of experimental checks that should be executed. By default, all experimental checks are turned off. Possible values: notowned,avoid-shadowing"
experimental_checks: "notowned,avoid-shadowing"
# The repository path in which CODEOWNERS file should be validated."
repository_path: "."
@@ -37,4 +41,4 @@ jobs:
owner_checker_allow_unowned_patterns: "false"
# Specifies whether only teams are allowed as owners of files.
owner_checker_owners_must_be_teams: "false"
owner_checker_owners_must_be_teams: "false"
+3 -2
View File
@@ -33,8 +33,9 @@ jobs:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript', 'go', 'python']
# Supported options are listed here
# https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#changing-the-languages-that-are-analyzed
language: ['actions', 'javascript', 'go']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
+8 -8
View File
@@ -24,7 +24,7 @@ jobs:
id: check
shell: bash
run: |
if [ "${{ github.repository }}" == "grafana/grafana" ] && [ -n "${{ secrets.GRAFANA_MISC_STATS_API_KEY }}" ]; then
if [ "${{ github.repository }}" == "grafana/grafana" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
@@ -42,15 +42,15 @@ jobs:
with:
# Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot path in Vault
repo_secrets: |
GH_APP_ID=plugins_platform_issue_commands_github_bot:app_id
GH_APP_PEM=plugins_platform_issue_commands_github_bot:app_pem
GITHUB_APP_ID=grafana_pr_automation_app:app_id
GITHUB_APP_PRIVATE_KEY=grafana_pr_automation_app:app_pem
- name: "Generate token"
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app_id: ${{ env.GH_APP_ID }}
private_key: ${{ env.GH_APP_PEM }}
app-id: ${{ env.GITHUB_APP_ID }}
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- name: Checkout Actions
uses: actions/checkout@v4 # v4.2.2
@@ -65,6 +65,6 @@ jobs:
- name: Run Commands
uses: ./actions/commands
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
metricsWriteAPIKey: ""
token: ${{ steps.generate_token.outputs.token }}
configPath: commands
+11 -8
View File
@@ -11,11 +11,6 @@ on:
required: false
default: false
description: When enabled, this workflow will print a preview instead of creating an actual post.
secrets:
GRAFANA_MISC_STATS_API_KEY:
required: true
GRAFANABOT_FORUM_KEY:
required: true
workflow_dispatch:
inputs:
version:
@@ -30,17 +25,25 @@ on:
permissions:
contents: read
id-token: write
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/repo/grafana/grafana/community_release path in Vault
repo_secrets: |
GRAFANABOT_FORUM_KEY=community_release:GRAFANABOT_FORUM_KEY
- name: Run community-release (manually invoked)
uses: grafana/grafana-github-actions-go/community-release@main # zizmor: ignore[unpinned-uses]
uses: grafana/grafana-github-actions-go/community-release@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: ${{ inputs.version }}
metrics_api_key: ${{ secrets.GRAFANA_MISC_STATS_API_KEY }}
community_api_key: ${{ secrets.GRAFANABOT_FORUM_KEY }}
community_api_key: ${{ env.GRAFANABOT_FORUM_KEY }}
community_api_username: grafanabot
dry_run: ${{ inputs.dry_run }}
@@ -48,7 +48,7 @@ jobs:
persist-credentials: false
- name: Verify inputs
run: |
if [ -z $PLUGIN_ID ]; then echo "Missing plugin ID"; exit 1; fi
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:
@@ -72,13 +72,13 @@ jobs:
shell: bash
id: get_dir
run: |
dir=$(dirname \
$(egrep -lir --include=plugin.json --exclude-dir=dist \
'"id": "${PLUGIN_ID}"' \
dir="$(dirname \
"$(grep -Elir --include=plugin.json --exclude-dir=dist \
'"id": "'"${PLUGIN_ID}"'"' \
public/app/plugins \
) \
)
echo "dir=${dir}" >> $GITHUB_OUTPUT
)" \
)"
echo "dir=${dir}" >> "$GITHUB_OUTPUT"
- name: Install frontend dependencies
shell: bash
working-directory: ${{ steps.get_dir.outputs.dir }}
@@ -88,17 +88,17 @@ jobs:
shell: sh
working-directory: ${{ steps.get_dir.outputs.dir }}
run: |
[ ! -d ./bin ] && mkdir -pv ./bin || true
curl -fL -o ./bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v$GRABPL_VERSION/grabpl
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 egrep -qr --include=main.go 'datasource.Manage\("$PLUGIN_ID"' pkg/tsdb; then
echo "has_backend=true" >> $GITHUB_OUTPUT
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
echo "has_backend=false" >> "$GITHUB_OUTPUT"
fi
- name: Setup golang environment
uses: actions/setup-go@19bb51245e9c80abacb2e91cc42b33fa478b8639
@@ -149,6 +149,8 @@ jobs:
- 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
@@ -156,15 +158,15 @@ jobs:
command="plugin:build"
fi
yarn $command --scope="@grafana-plugins/$PLUGIN_ID"
version=$(cat ${{ steps.get_dir.outputs.dir }}/dist/plugin.json | jq -r .info.version)
echo "version=${version}" >> $GITHUB_OUTPUT
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
make build-plugin-go PLUGIN_ID="$PLUGIN_ID"
- name: package
working-directory: ${{ steps.get_dir.outputs.dir }}
run: |
@@ -177,16 +179,17 @@ jobs:
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" \
'${{ env.GCOM_API}}/api/plugins/$PLUGIN_ID?version=$VERSION' \
-H 'accept: application/json')
api_res_code=$(echo $api_res | jq -r .code)
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
echo "$api_res"
exit 1
fi
- name: store build artifacts
@@ -197,55 +200,46 @@ jobs:
- name: Publish release to Google Cloud Storage
working-directory: ${{ steps.get_dir.outputs.dir }}
env:
VERSION: ${{ steps.build_frontend.outputs.version }}
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://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/windows
gsutil -m cp -r ci/packages/*linux* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux
gsutil -m cp -r ci/packages/*darwin* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/darwin
gsutil -m cp -r ci/packages/*any* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/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}"
result=`curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" ${{ env.GCOM_API}}/api/plugins -d "{
\"url\": \"https://github.com/grafana/grafana/tree/main/${{ steps.get_dir.outputs.dir }}\",
\"download\": {
\"linux-amd64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux/$PLUGIN_ID-${VERSION}.linux_amd64.zip\",
\"md5\": \"$(cat ci/packages/info-linux_amd64.json | jq -r .plugin.md5)\"
},
\"linux-arm64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux/$PLUGIN_ID-${VERSION}.linux_arm64.zip\",
\"md5\": \"$(cat ci/packages/info-linux_arm64.json | jq -r .plugin.md5)\"
},
\"linux-arm\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux/$PLUGIN_ID-${VERSION}.linux_arm.zip\",
\"md5\": \"$(cat ci/packages/info-linux_arm.json | jq -r .plugin.md5)\"
},
\"windows-amd64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/windows/$PLUGIN_ID-${VERSION}.windows_amd64.zip\",
\"md5\": \"$(cat ci/packages/info-windows_amd64.json | jq -r .plugin.md5)\"
},
\"darwin-amd64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/darwin/$PLUGIN_ID-${VERSION}.darwin_amd64.zip\",
\"md5\": \"$(cat ci/packages/info-darwin_amd64.json | jq -r .plugin.md5)\"
},
\"darwin-arm64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/darwin/$PLUGIN_ID-${VERSION}.darwin_arm64.zip\",
\"md5\": \"$(cat ci/packages/info-darwin_arm64.json | jq -r .plugin.md5)\"
}
}
}"`
if [[ "$(echo $result | jq -r .version)" == "null" ]]; then
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
echo "$result"
exit 1
fi
- name: Publish new plugin version on grafana.com (frontend only)
@@ -254,20 +248,29 @@ jobs:
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}"
result=`curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" ${{ env.GCOM_API}}/api/plugins -d "{
\"url\": \"https://github.com/grafana/grafana/tree/main/${{ steps.get_dir.outputs.dir }}\",
\"download\": {
\"any\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/any/$PLUGIN_ID-${VERSION}.any.zip\",
\"md5\": \"$(cat ci/packages/info-any.json | jq -r .plugin.md5)\"
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
}
}
}"`
if [[ "$(echo $result | jq -r .version)" == "null" ]]; then
}' > 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
echo "$result"
exit 1
fi
@@ -10,11 +10,6 @@ on:
description: The release branch to increment (eg providing `release-11.2.3` will result in `release-11.2.4` being created)
type: string
required: true
secrets:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
outputs:
branch:
description: The new branch that was created
@@ -27,23 +22,32 @@ on:
description: The release branch to increment (eg providing `release-11.2.3` will result in `release-11.2.4` being created)
type: string
required: true
secrets:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
permissions:
contents: read
id-token: write
jobs:
main:
runs-on: ubuntu-latest
outputs:
branch: ${{ steps.branch.outputs.branch }}
steps:
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
repositories: "[\"grafana\", \"grafana-enterprise\"]"
permissions: "{\"contents\": \"write\", \"pull_requests\": \"write\", \"workflows\":\"write\"}"
- name: Create release branch
id: branch
uses: grafana/grafana-github-actions-go/bump-release@main # zizmor: ignore[unpinned-uses]
@@ -11,7 +11,7 @@ env:
ORGANIZATION: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
TARGET_PROJECT: 202
LABEL_IDs: "LA_kwDOAOaWjc8AAAABT38U-A"
LABEL_IDS: "LA_kwDOAOaWjc8AAAABT38U-A"
concurrency:
group: issue-label-when-in-project-${{ github.event.number }}
@@ -26,25 +26,26 @@ jobs:
with:
# Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot path in Vault
repo_secrets: |
GH_APP_ID=plugins_platform_issue_commands_github_bot:app_id
GH_APP_PEM=plugins_platform_issue_commands_github_bot:app_pem
GITHUB_APP_ID=grafana_pr_automation_app:app_id
GITHUB_APP_PRIVATE_KEY=grafana_pr_automation_app:app_pem
- name: "Generate token"
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app_id: ${{ env.GH_APP_ID }}
private_key: ${{ env.GH_APP_PEM }}
app-id: ${{ env.GITHUB_APP_ID }}
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- name: Check if issue is in target project
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
TARGET_PROJECT: ${{ env.TARGET_PROJECT }}
run: |
# shellcheck disable=SC2016 # we don't want the $s to be expanded
gh api graphql -f query='
query($org: String!, $repo: String!) {
query($org: String!, $repo: String!, $issueNumber: Int!) {
repository(name: $repo, owner: $org) {
issue (number: $ISSUE_NUMBER) {
issue (number: $issueNumber) {
id
projectItems(first:20) {
nodes {
@@ -55,15 +56,18 @@ jobs:
}
}
}
}' -f org=$ORGANIZATION -f repo=$REPO > projects_data.json
}' -f org="$ORGANIZATION" -f repo="$REPO" -F issueNumber="$ISSUE_NUMBER" > projects_data.json
echo 'IN_TARGET_PROJ='$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number=='"$TARGET_PROJECT"') | .project != null' projects_data.json) >> $GITHUB_ENV
echo 'ITEM_ID='$(jq '.data.repository.issue.id' projects_data.json) >> $GITHUB_ENV
{
echo "IN_TARGET_PROJ=$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number=='"$TARGET_PROJECT"') | .project != null' projects_data.json)"
echo "ITEM_ID=$(jq '.data.repository.issue.id' projects_data.json)"
} >> "$GITHUB_ENV"
- name: Set up label array
if: env.IN_TARGET_PROJ
env:
LABEL_IDS: ${{ env.LABEL_IDS }}
run: |
# shellcheck disable=SC2153 # we define the variable on the line above in 'read'
IFS=',' read -ra LABEL_IDs <<< "$LABEL_IDS"
for item in "${LABEL_IDs[@]}"; do
echo "Item: $item"
@@ -74,6 +78,7 @@ jobs:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
LABEL_IDS: ${{ env.LABEL_IDS }}
run: |
# shellcheck disable=SC2016 # we don't want the $s to be expanded
gh api graphql -f query='
mutation ($labelableId: ID!, $labelIds: [ID!]!) {
addLabelsToLabelable(
@@ -81,4 +86,4 @@ jobs:
) {
clientMutationId
}
}' -f labelableId=$ITEM_ID -f labelIds=$LABEL_IDS
}' -f labelableId="$ITEM_ID" -f labelIds="$LABEL_IDS"
+2
View File
@@ -9,6 +9,8 @@ on:
paths:
- "docs/sources/**"
permissions: {}
jobs:
deploy-pr-preview:
permissions:
@@ -0,0 +1,93 @@
name: Deploy Storybook preview
on:
pull_request:
paths:
- 'packages/grafana-ui/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
deploy-storybook-preview:
name: Deploy Storybook preview
runs-on: ubuntu-latest
# Don't run from forks for the moment. If we find this useful we can do the workflow_run dance
# to make it work for forks.
if: github.event.pull_request.head.repo.fork == false
permissions:
contents: read
id-token: write
env:
BUCKET_NAME: grafana-storybook-previews
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Cache node_modules
uses: actions/cache@v4
with:
path: |
node_modules
key: node_modules-${{ hashFiles('yarn.lock') }}
restore-keys: |
node_modules-
- name: Install dependencies
env:
# If the PR isn't from a fork then don't use the slower yarn checks
YARN_ENABLE_HARDENED_MODE: ${{ github.event.pull_request.head.repo.fork == false && '1' || '0' }}
run: yarn install --immutable
- name: Build storybook
run: yarn storybook:build
# Create the GCS folder name for the preview. Creates a consistent name for all deploys for the PR.
# Matches format of `pr_<PR_NUMBER>_<SANITIZED_BRANCH>`.
# Where `SANITIZED_BRANCH` is the branch name with only alphanumeric and hyphens, limited to 30 characters.
- name: Create deploy name
id: create-deploy-name
env:
BRANCH_NAME: ${{ github.event.pull_request.head.ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
# Convert branch name to only contain alphanumeric and hyphens
SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | tr -cs "[:alnum:]-" "-" | sed "s/^-//;s/-$//")
# Check if SANITIZED_BRANCH is empty and fail if it is
if [ -z "$SANITIZED_BRANCH" ]; then
echo "Error: Branch name resulted in empty string after sanitization"
exit 1
fi
echo "deploy-name=pr_${PR_NUMBER}_${SANITIZED_BRANCH:0:30}" >> "$GITHUB_OUTPUT"
- name: Upload Storybook
uses: grafana/shared-workflows/actions/push-to-gcs@main
with:
environment: prod
bucket: ${{ env.BUCKET_NAME }}
bucket_path: ${{ steps.create-deploy-name.outputs.deploy-name }}
path: packages/grafana-ui/dist/storybook
service_account: github-gf-storybook-preview@grafanalabs-workload-identity.iam.gserviceaccount.com
parent: false
- name: Write summary
env:
DEPLOY_NAME: ${{ steps.create-deploy-name.outputs.deploy-name }}
run: |
echo "## Storybook preview deployed! 🚀" >> $GITHUB_STEP_SUMMARY
echo "Check it out at https://storage.googleapis.com/${BUCKET_NAME}/${DEPLOY_NAME}/index.html" >> $GITHUB_STEP_SUMMARY
@@ -12,6 +12,8 @@ on:
pull_request:
paths:
- 'packages/**'
- '.nvmrc'
- '.github/workflows/detect-breaking-changes-levitate.yml'
branches:
- 'main'
@@ -31,9 +33,10 @@ jobs:
with:
path: './pr'
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 22.11.0
node-version-file: './pr/.nvmrc'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
@@ -81,10 +84,11 @@ jobs:
with:
path: './base'
ref: ${{ github.event.pull_request.base.ref }}
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 22.11.0
node-version-file: './base/.nvmrc'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
@@ -129,9 +133,12 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 22.11.0
node-version-file: '.nvmrc'
- name: Get built packages from pr
uses: actions/download-artifact@v4
@@ -151,13 +158,15 @@ jobs:
- id: 'auth'
uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f'
if: github.event.pull_request.head.repo.full_name == github.repository
with:
workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
service_account: ${{ secrets.LEVITATE_SA }}
workload_identity_provider: projects/304398677251/locations/global/workloadIdentityPools/github/providers/github-provider
service_account: github-plugins-data-levitate@grafanalabs-workload-identity.iam.gserviceaccount.com
project_id: 'grafanalabs-global'
- name: 'Set up Cloud SDK'
uses: 'google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a'
if: github.event.pull_request.head.repo.full_name == github.repository
with:
version: '>= 363.0.0'
project_id: 'grafanalabs-global'
@@ -168,11 +177,16 @@ jobs:
run: ./scripts/check-breaking-changes.sh
env:
FORCE_COLOR: 3
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }} # used in check-breaking-changes.sh and levitate-parse-json-report.js
- name: Persisting the check output
run: |
mkdir -p ./levitate
echo "{ \"exit_code\": ${{ steps.breaking-changes.outputs.is_breaking }}, \"message\": \"${{ steps.breaking-changes.outputs.message }}\", \"pr_number\": \"${{ github.event.pull_request.number }}\" }" > ./levitate/result.json
echo "{ \"exit_code\": ${IS_BREAKING}, \"message\": \"${MESSAGE}\", \"pr_number\": \"${PR_NUMBER}\" }" > ./levitate/result.json
env:
IS_BREAKING: ${{ steps.breaking-changes.outputs.is_breaking }}
MESSAGE: ${{ steps.breaking-changes.outputs.message }}
PR_NUMBER: ${{ github.event.pull_request.number }}
- name: Upload check output as artifact
uses: actions/upload-artifact@v4
@@ -188,16 +202,27 @@ jobs:
permissions:
contents: read
id-token: write
if: github.event.pull_request.head.repo.full_name == github.repository
steps:
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
- id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@28361cdb22223e5f1e34358c86c20908e7248760 # get-vault-secrets-v1.1.0
with:
app_id: ${{ secrets.GRAFANA_PR_AUTOMATION_APP_ID }}
private_key: ${{ secrets.GRAFANA_PR_AUTOMATION_APP_PEM }}
# Secrets placed in the ci/repo/grafana/grafana in vault
repo_secrets: |
GITHUB_APP_ID=grafana_pr_automation_app:app_id
GITHUB_APP_PRIVATE_KEY=grafana_pr_automation_app:app_pem
- name: Generate token
id: generate_token
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app-id: ${{ env.GITHUB_APP_ID }}
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: 'Download artifact'
uses: actions/download-artifact@v4
@@ -205,7 +230,7 @@ jobs:
name: levitate
- name: Parsing levitate result
uses: actions/github-script@v6
uses: actions/github-script@v7
id: levitate-run
with:
script: |
@@ -216,7 +241,7 @@ jobs:
# Check if label exists
- name: Check if "levitate breaking change" label exists
id: does-label-exist
uses: actions/github-script@v6
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
with:
@@ -295,7 +320,7 @@ jobs:
"fields": [
{
"type": "mrkdwn",
"text": "*PR:* <${{ github.event.pull_request.html_url }}|#${{ github.event.pull_request.number }}>"
"text": "*PR:* <${{ github.event.pull_request.html_url }}|#${{ github.event.pull_request.number }}>\n\nAuthor: ${{ github.event.pull_request.user.login }}"
},
{
"type": "mrkdwn",
@@ -309,7 +334,7 @@ jobs:
# Add the label
- name: Add "levitate breaking change" label
if: steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0
uses: actions/github-script@v6
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }}
with:
@@ -325,7 +350,7 @@ jobs:
# Remove label (no more breaking changes)
- name: Remove "levitate breaking change" label
if: steps.levitate-run.outputs.exit_code == 0 && steps.does-label-exist.outputs.result == 1
uses: actions/github-script@v6
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }}
with:
@@ -343,7 +368,7 @@ jobs:
# Related issue: https://github.com/renovatebot/renovate/issues/1908
- name: Add "grafana/plugins-platform-frontend" as a reviewer
if: steps.levitate-run.outputs.exit_code == 1
uses: actions/github-script@v6
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }}
with:
@@ -360,7 +385,7 @@ jobs:
# Remove reviewers (no more breaking changes)
- name: Remove "grafana/plugins-platform-frontend" from the list of reviewers
if: steps.levitate-run.outputs.exit_code == 0
uses: actions/github-script@v6
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }}
with:
@@ -376,9 +401,11 @@ jobs:
- name: Exit
run: |
if [ "${{ steps.levitate-run.outputs.exit_code }}" -ne 0 ]; then
if [ "${LV_EXIT_CODE}" -ne 0 ]; then
echo "Breaking changes detected. Please check the levitate report in your pull request. This workflow won't block merging."
fi
exit ${{ steps.levitate-run.outputs.exit_code }}
exit "${LV_EXIT_CODE}"
shell: bash
env:
LV_EXIT_CODE: ${{ steps.levitate-run.outputs.exit_code }}
+9 -2
View File
@@ -1,14 +1,21 @@
name: Documentation CI
on:
pull_request:
branches: ["main"]
branches: ["main", "release-*"]
paths: ["docs/sources/**"]
workflow_dispatch:
permissions: {}
jobs:
vale:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
security-events: write
container:
image: grafana/vale:latest
image: grafana/vale:latest # zizmor: ignore[unpinned-images]
steps:
- uses: actions/checkout@v4
with:
@@ -0,0 +1,42 @@
name: Run e2e for dashboardNewLayouts
on:
pull_request:
branches:
- '**'
paths:
- 'e2e/dashboard-new-layouts/**'
- 'public/app/features/dashboard-scene/**'
env:
ARCH: linux-amd64
jobs:
dashboard-new-layouts-e2e:
runs-on: ubuntu-latest
continue-on-error: true
if: github.event.pull_request.draft == false
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Pin Go version to mod file
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- run: go version
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Build grafana
run: make build
- name: Install Cypress dependencies
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f
with:
runTests: false
- name: Run dashboardNewLayouts e2e
run: yarn e2e:dashboard-new-layouts
@@ -1,47 +1,48 @@
name: 'Ephemeral instances'
name: "Ephemeral instances"
on:
issue_comment:
types: [created]
pull_request:
types: [closed]
jobs:
config:
runs-on: "ubuntu-latest"
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.EI_APP_ID != '' &&
secrets.EI_APP_PRIVATE_KEY != '' &&
secrets.EI_GCOM_HOST != '' &&
secrets.EI_GCOM_TOKEN != '' &&
secrets.EI_EPHEMERAL_INSTANCES_REGISTRY != '' &&
secrets.EI_GCP_SERVICE_ACCOUNT_KEY_BASE64 != '' &&
secrets.EI_EPHEMERAL_ORG_ID != ''
) || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
handle-pull-request-event:
needs: config
if: needs.config.outputs.has-secrets &&
${{ github.event.issue.pull_request && (startsWith(github.event.comment.body, '/deploy-to-hg') || github.event.action == 'closed') }}
permissions: {}
jobs:
handle-ephemeral-instances:
if: ${{ github.event.issue.pull_request && (startsWith(github.event.comment.body, '/deploy-to-hg') || github.event.action == 'closed') && github.repository_owner == 'grafana' }}
runs-on:
labels: ubuntu-latest-8-cores
labels: ubuntu-latest-16-cores
continue-on-error: true
permissions:
# For commenting.
pull-requests: write
# No contents permission is needed because we will impersonate an app to create the PR instead.
id-token: write # required for vault access
steps:
- name: Get vault secrets
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in ci/repo/grafana/grafana/
repo_secrets: |
APP_ID=ephemeral-instances-bot:app-id
APP_PEM=ephemeral-instances-bot:app-private-key
GCOM_HOST=ephemeral-instances-bot:gcom-host
GCOM_TOKEN=ephemeral-instances-bot:gcom-token
REGISTRY=ephemeral-instances-bot:registry
GCP_SA_ACCOUNT_KEY_BASE64=ephemeral-instances-bot:sa-key
- name: Generate a GitHub app installation token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 # v1.8.0
with:
app_id: ${{ secrets.EI_APP_ID }}
private_key: ${{ secrets.EI_APP_PRIVATE_KEY }}
app_id: ${{ env.APP_ID }}
private_key: ${{ env.APP_PEM }}
- name: Checkout ephemeral instances repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
repository: grafana/ephemeral-grafana-instances-github-action
token: ${{ steps.generate_token.outputs.token }}
@@ -52,11 +53,11 @@ jobs:
- name: build and deploy ephemeral instance
uses: ./ephemeral
with:
github-token: ${{ steps.generate_token.outputs.token }}
gcom-host: ${{ secrets.EI_GCOM_HOST }}
gcom-token: ${{ secrets.EI_GCOM_TOKEN }}
registry: "${{ secrets.EI_EPHEMERAL_INSTANCES_REGISTRY }}"
gcp-service-account-key: "${{ secrets.EI_GCP_SERVICE_ACCOUNT_KEY_BASE64 }}"
ephemeral-org-id: "${{ secrets.EI_EPHEMERAL_ORG_ID }}"
github-token: ${{ steps.generate_token.outputs.token }}
gcom-host: ${{ env.GCOM_HOST }}
gcom-token: ${{ env.GCOM_TOKEN }}
registry: "${{ env.REGISTRY }}"
gcp-service-account-key: ${{ env.GCP_SA_ACCOUNT_KEY_BASE64 }}
ephemeral-org-id: ephemeral
oss-or-enterprise: oss
verbose: true
+6
View File
@@ -7,9 +7,15 @@ on:
- 'pkg/services/featuremgmt/registry.go'
- 'docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md'
permissions: {}
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
+41 -33
View File
@@ -9,12 +9,35 @@ on:
permissions: {}
jobs:
lint-frontend-verify-i18n:
name: Verify i18n
detect-changes:
name: Detect whether code changed
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
changed: ${{ steps.detect-changes.outputs.frontend }}
prettier: ${{ steps.detect-changes.outputs.frontend == 'true' || steps.detect-changes.outputs.docs == 'true' }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: true # required to get more history in the changed-files action
fetch-depth: 2
- name: Detect changes
id: detect-changes
uses: ./.github/actions/change-detection
with:
self: .github/workflows/frontend-lint.yml
lint-frontend-prettier:
needs: detect-changes
permissions:
contents: read
id-token: write
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`,
# the `lint-frontend-prettier-enterprise` workflow will run instead
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true && needs.detect-changes.outputs.prettier == 'true'
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
@@ -25,46 +48,21 @@ jobs:
cache: 'yarn'
cache-dependency-path: 'yarn.lock'
- run: yarn install --immutable --check-cache
- run: |
extract_error_message='::error::Extraction failed. Make sure that you have no dynamic translation phrases, such as "t(`preferences.theme.{themeID}`, themeName)" and that no translation key is used twice. Search the output for '[warning]' to find the offending file.'
make i18n-extract || (echo "${extract_error_message}" && false)
- run: |
uncommited_error_message="::error::Translation extraction has not been committed. Please run 'make i18n-extract', commit the changes and push again."
file_diff=$(git diff --dirstat public/locales)
if [ -n "$file_diff" ]; then
echo $file_diff
echo "${uncommited_error_message}"
exit 1
fi
lint-frontend-prettier:
permissions:
contents: read
id-token: write
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`,
# the `lint-frontend-prettier-enterprise` workflow will run instead
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
cache-dependency-path: 'yarn.lock'
- run: yarn install --immutable --check-cache
- run: yarn run prettier:check
- run: yarn run lint
lint-frontend-prettier-enterprise:
needs: detect-changes
permissions:
contents: read
id-token: write
# Run this workflow for non-PR events (like pushes to `main` or `release-*`) OR for internal PRs (PRs not from forks)
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false && needs.detect-changes.outputs.prettier == 'true'
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@@ -78,16 +76,19 @@ jobs:
- run: yarn run prettier:check
- run: yarn run lint
lint-frontend-typecheck:
needs: detect-changes
permissions:
contents: read
id-token: write
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`,
# the `lint-frontend-typecheck-enterprise` workflow will run instead
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true && needs.detect-changes.outputs.changed == 'true'
name: Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@@ -96,15 +97,18 @@ jobs:
- run: yarn install --immutable --check-cache
- run: yarn run typecheck
lint-frontend-typecheck-enterprise:
needs: detect-changes
permissions:
contents: read
id-token: write
# Run this workflow for non-PR events (like pushes to `main` or `release-*`) OR for internal PRs (PRs not from forks)
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false && needs.detect-changes.outputs.changed == 'true'
name: Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@@ -117,13 +121,17 @@ jobs:
- run: yarn install --immutable --check-cache
- run: yarn run typecheck
lint-frontend-betterer:
needs: detect-changes
permissions:
contents: read
id-token: write
if: needs.detect-changes.outputs.changed == 'true'
name: Betterer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
+1 -1
View File
@@ -34,6 +34,7 @@ on:
permissions:
# contents: write allows the action(s) to create github releases
contents: write
id-token: write
jobs:
main:
@@ -44,6 +45,5 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: ${{ inputs.version }}
metrics_api_key: ${{ secrets.GRAFANA_MISC_STATS_API_KEY }}
latest: ${{ inputs.latest }}
dry_run: ${{ inputs.dry_run }}
+1 -1
View File
@@ -7,6 +7,7 @@ on:
- go.*
branches:
- main
- release-*.*.*
pull_request:
permissions:
@@ -22,7 +23,6 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
- run: make gen-go
- name: golangci-lint
uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd
with:
@@ -1,27 +1,13 @@
name: Crowdin Create Tasks
name: Crowdin automatic task management
on:
workflow_dispatch:
# schedule:
# - cron: "0 0 * * *"
# once a month on the first day of the month at midnight
schedule:
- cron: "0 0 1 * *"
jobs:
create-tasks-in-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- name: Create tasks
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
run: node ./.github/workflows/scripts/crowdin/create-tasks.js
uses: grafana/grafana-github-actions/.github/workflows/crowdin-create-tasks.yml@main
with:
crowdin_project_id: 5
+7 -150
View File
@@ -7,153 +7,10 @@ on:
jobs:
download-sources-from-crowdin:
runs-on: ubuntu-latest
permissions:
contents: write # needed to commit changes into the PR
pull-requests: write # needed to update PR description, labels, etc
id-token: write # needed to get vault secrets
steps:
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_PR_AUTOMATION_APP_ID }}
private_key: ${{ secrets.GRAFANA_PR_AUTOMATION_APP_PEM }}
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ steps.generate_token.outputs.token }}
persist-credentials: false
- name: Download sources
id: crowdin-download
uses: crowdin/github-action@b8012bd5491b8aa8578b73ab5b5f5e7c94aaa6e2
with:
upload_sources: false
upload_translations: false
download_sources: false
download_translations: true
export_only_approved: true
localization_branch_name: i18n_crowdin_translations
create_pull_request: true
pull_request_title: 'I18n: Download translations from Crowdin'
pull_request_body: |
:robot: Automatic download of translations from Crowdin.
This runs once per day and will merge automatically if all the required checks pass.
If there's a conflict, close the pull request and **delete the branch**.
You can then either wait for the schedule to trigger a new PR, or rerun the action manually.
pull_request_labels: 'area/frontend, area/internationalization, no-changelog, no-backport'
pull_request_base_branch_name: 'main'
base_url: 'https://grafana.api.crowdin.com'
config: 'crowdin.yml'
source: 'public/locales/en-US/grafana.json'
translation: 'public/locales/%locale%/%original_file_name%'
# Magic details of the github-actions bot user, to pass CLA checks
github_user_name: "github-actions[bot]"
github_user_email: "41898282+github-actions[bot]@users.noreply.github.com"
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
- name: Get pull request ID
if: steps.crowdin-download.outputs.pull_request_url
shell: bash
# Crowdin action returns us the URL of the pull request, but we need an ID for the GraphQL API
# that looks like 'PR_kwDOAOaWjc5mP_GU'
run: |
pr_id=$(gh pr view ${{ steps.crowdin-download.outputs.pull_request_url }} --json id -q .id)
echo "PULL_REQUEST_ID=$pr_id" >> "$GITHUB_ENV"
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
- name: Get project board ID
uses: octokit/graphql-action@51bf543c240dcd14761320e2efc625dc32ec0d32
id: get-project-id
if: steps.crowdin-download.outputs.pull_request_url
with:
# Frontend Platform project - https://github.com/orgs/grafana/projects/78
org: grafana
project_number: 78
query: |
query getProjectId($org: String!, $project_number: Int!){
organization(login: $org) {
projectV2(number: $project_number) {
title
id
}
}
}
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
- name: Add to project board
uses: octokit/graphql-action@51bf543c240dcd14761320e2efc625dc32ec0d32
if: steps.crowdin-download.outputs.pull_request_url
with:
projectid: ${{ fromJson(steps.get-project-id.outputs.data).organization.projectV2.id }}
prid: ${{ env.PULL_REQUEST_ID }}
query: |
mutation addPullRequestToProject($projectid: ID!, $prid: ID!){
addProjectV2ItemById(input: {projectId: $projectid, contentId: $prid}) {
item {
id
}
}
}
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
- name: Run auto-milestone
uses: grafana/grafana-github-actions-go/auto-milestone@main # zizmor: ignore[unpinned-uses]
if: steps.crowdin-download.outputs.pull_request_url
with:
pr: ${{ steps.crowdin-download.outputs.pull_request_number }}
token: ${{ steps.generate_token.outputs.token }}
- name: Get vault secrets
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main # zizmor: ignore[unpinned-uses]
with:
# Secrets placed in ci/repo/grafana/grafana/grafana-pr-approver
repo_secrets: |
GRAFANA_PR_APPROVER_APP_ID=grafana-pr-approver:app-id
GRAFANA_PR_APPROVER_APP_PEM=grafana-pr-approver:private-key
- name: Generate approver token
if: steps.crowdin-download.outputs.pull_request_url
id: generate_approver_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ env.GRAFANA_PR_APPROVER_APP_ID }}
private_key: ${{ env.GRAFANA_PR_APPROVER_APP_PEM }}
- name: Approve and automerge PR
if: steps.crowdin-download.outputs.pull_request_url
shell: bash
# Only approve if:
# - the PR does not modify files other than json files under the public/locales/ directory
# - the PR does not modify the en-US locale
run: |
filesChanged=$(gh pr diff --name-only ${{ steps.crowdin-download.outputs.pull_request_url }})
if [[ $(echo $filesChanged | grep -v 'public/locales/[a-zA-Z\-]*/grafana.json' | wc -l) -ne 0 ]]; then
echo "Non-i18n changes detected, not approving"
exit 1
fi
if [[ $(echo $filesChanged | grep "public/locales/en-US" | wc -l) -ne 0 ]]; then
echo "public/locales/en-US changes detected, not approving"
exit 1
fi
echo "Approving and enabling automerge"
gh pr review ${{ steps.crowdin-download.outputs.pull_request_url }} --approve
gh pr merge --auto --squash ${{ steps.crowdin-download.outputs.pull_request_url }}
env:
GITHUB_TOKEN: ${{ steps.generate_approver_token.outputs.token }}
if: github.repository == 'grafana/grafana'
uses: grafana/grafana-github-actions/.github/workflows/crowdin-download.yml@main
with:
crowdin_project_id: 5
pr_labels: 'area/frontend, area/internationalization, no-changelog, no-backport'
github_board_id: 78 # Frontend Platform project
en_paths: public/locales/en-US/grafana.json, public/app/plugins/datasource/azuremonitor/locales/en-US/grafana-azure-monitor-datasource.json, public/app/plugins/datasource/mssql/locales/en-US/mssql.json, packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json, packages/grafana-sql/src/locales/en-US/grafana-sql.json
+8 -23
View File
@@ -5,31 +5,16 @@ on:
push:
paths:
- 'public/locales/en-US/grafana.json'
- 'public/app/plugins/datasource/azuremonitor/locales/en-US/grafana-azure-monitor-datasource.json'
- 'public/app/plugins/datasource/mssql/locales/en-US/mssql.json'
- 'packages/grafana-sql/src/locales/en-US/grafana-sql.json'
- 'packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json'
branches:
- main
jobs:
upload-sources-to-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Upload sources
uses: crowdin/github-action@b8012bd5491b8aa8578b73ab5b5f5e7c94aaa6e2
with:
upload_sources: true
upload_sources_args: '--dest=public/locales/en-US/grafana.json'
upload_translations: false
download_translations: false
create_pull_request: false
base_url: 'https://grafana.api.crowdin.com'
config: 'crowdin.yml'
source: 'public/locales/en-US/grafana.json'
translation: 'public/locales/%locale%/%original_file_name%'
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
if: github.repository == 'grafana/grafana'
uses: grafana/grafana-github-actions/.github/workflows/crowdin-upload.yml@main
with:
crowdin_project_id: 5
+15
View File
@@ -0,0 +1,15 @@
name: Verify i18n
permissions:
contents: read
on:
pull_request:
push:
branches:
- main
- release-*.*.*
jobs:
verify-i18n:
uses: grafana/grafana-github-actions/.github/workflows/verify-i18n.yml@main
+14 -13
View File
@@ -43,20 +43,19 @@ jobs:
with:
# Secrets placed in the ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot path in Vault
repo_secrets: |
GH_APP_ID=plugins_platform_issue_commands_github_bot:app_id
GH_APP_PEM=plugins_platform_issue_commands_github_bot:app_pem
GITHUB_APP_ID=grafana_pr_automation_app:app_id
GITHUB_APP_PRIVATE_KEY=grafana_pr_automation_app:app_pem
- name: "Generate token"
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app_id: ${{ env.GH_APP_ID }}
private_key: ${{ env.GH_APP_PEM }}
app-id: ${{ env.GITHUB_APP_ID }}
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- name: Run Commands
uses: ./actions/commands
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{ steps.generate_token.outputs.token }}
configPath: "issue-opened"
@@ -77,18 +76,20 @@ jobs:
repo_secrets: |
AUTOTRIAGER_OPENAI_API_KEY=plugins_platform_issue_triager:AUTOTRIAGER_OPENAI_API_KEY
AUTOTRIAGER_SLACK_WEBHOOK_URL=plugins_platform_issue_triager:AUTOTRIAGER_SLACK_WEBHOOK_URL
GH_APP_ID=plugins_platform_issue_commands_github_bot:app_id
GH_APP_PEM=plugins_platform_issue_commands_github_bot:app_pem
GITHUB_APP_ID=plugins_platform_issue_triager_github_bot:app_id
GITHUB_APP_PRIVATE_KEY=plugins_platform_issue_triager_github_bot:app_pem
- name: "Generate token"
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app_id: ${{ env.GH_APP_ID }}
private_key: ${{ env.GH_APP_PEM }}
app-id: ${{ env.GITHUB_APP_ID }}
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@v4 # v4.2.2
with:
persist-credentials: false
- name: Send issue to the auto triager action
id: auto_triage
+12 -6
View File
@@ -16,10 +16,16 @@ on:
- 'packages/**/*.md'
- 'latest.json'
permissions: {}
jobs:
docs:
name: Build & Verify Docs
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -29,7 +35,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.11.0'
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
@@ -45,18 +51,18 @@ jobs:
run: |
# Create and start a container from the docs-base image in detached mode
docker run -d --name docs-builder grafana/docs-base:latest tail -f /dev/null
# Create the directory structure inside the container
docker exec docs-builder mkdir -p /hugo/content/docs/grafana/latest
# Create the _index.md file
docker exec docs-builder /bin/sh -c "echo -e '---\nredirectURL: /docs/grafana/latest/\ntype: redirect\nversioned: true\n---\n' > /hugo/content/docs/grafana/_index.md"
# Copy the docs sources from the host to the container
docker cp docs/sources/. docs-builder:/hugo/content/docs/grafana/latest/
# Run the make prod command inside the container
docker exec -w /hugo docs-builder make prod || echo "Build completed with warnings"
# Clean up the container
docker rm -f docs-builder
-54
View File
@@ -1,54 +0,0 @@
#
# When triggered by the cron job it will also collect metrics for:
# * number of issues without label
# * number of issues with "needs more info"
# * number of issues with "needs investigation"
# * number of issues with label type/bug
# * number of open issues in current milestone
#
# https://github.com/grafana/grafana-github-actions/blob/main/metrics-collector/index.ts
#
name: Github issue metrics collection
on:
schedule:
- cron: "*/10 * * * *"
issues:
types: [opened, closed]
permissions:
contents: read
jobs:
config:
runs-on: "ubuntu-latest"
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.GRAFANA_MISC_STATS_API_KEY != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
main:
needs: config
if: needs.config.outputs.has-secrets
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
uses: actions/checkout@v4 # v4.2.2
with:
repository: "grafana/grafana-github-actions"
path: ./actions
ref: main
persist-credentials: false
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run metrics collector
uses: ./actions/metrics-collector
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{secrets.GITHUB_TOKEN}}
configPath: "metrics-collector"
+14 -13
View File
@@ -15,11 +15,6 @@ on:
description: Owner/repo of the repository where the branch is created (e.g. 'grafana/grafana')
required: true
type: string
secrets:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
workflow_dispatch:
inputs:
from:
@@ -34,24 +29,30 @@ on:
description: Owner/repo of the repository where the branch is created (e.g. 'grafana/grafana')
required: true
type: string
secrets:
GRAFANA_DELIVERY_BOT_APP_ID:
required: true
GRAFANA_DELIVERY_BOT_APP_PEM:
required: true
permissions:
contents: read
id-token: write
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: Migrate PRs
uses: grafana/grafana-github-actions-go/migrate-open-prs@main # zizmor: ignore[unpinned-uses]
uses: grafana/grafana-github-actions-go/migrate-open-prs@main
with:
token: ${{ steps.generate_token.outputs.token }}
ownerRepo: ${{ inputs.ownerRepo }}
-71
View File
@@ -1,71 +0,0 @@
name: Coverage
on:
workflow_dispatch:
push:
branches:
- main
paths-ignore:
- 'docs/**'
- '**/*.md'
permissions:
contents: read
id-token: write
env:
EDITION: 'oss'
WIRE_TAGS: 'oss'
jobs:
main:
name: Backend Unit Tests
runs-on: ubuntu-latest-8-cores
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- 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
go install github.com/mfridman/tparse@c1754a1f484ac5cd422697b0fec635177ddc8507 # v0.17.0
- name: Generate Go code
run: make gen-go
- name: Run unit tests
run: COVER_OPTS="-coverprofile=be-unit.cov -coverpkg=github.com/grafana/grafana/..." GO_TEST_OUTPUT="/tmp/unit.log" make test-go-unit-cov
- 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'
- name: Install Grafana Bench
# We can't allow forks here, as we need secret access.
if: ${{ github.event_name != 'pull_request' }}
uses: ./.github/actions/setup-grafana-bench
- name: Process output for Bench
if: ${{ github.event_name != 'pull_request' }}
run: |
grafana-bench report \
--trigger pr-backend-unit-tests-oss \
--report-input go \
--report-output log \
--grafana-version "$(git rev-parse HEAD)" \
--suite-name grafana-oss-unit-tests \
/tmp/unit.log || true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
@@ -3,7 +3,7 @@ name: "CodeQL for PR / javascript"
on:
workflow_dispatch:
pull_request:
branches: [main]
branches: [main, release-*]
paths:
- '**/*.js'
- '**/*.ts'
@@ -3,7 +3,7 @@ name: "CodeQL for PR / python"
on:
workflow_dispatch:
pull_request:
branches: [main]
branches: [main, release-*]
paths:
- '**/*.py'
@@ -25,11 +25,24 @@ jobs:
fetch-depth: 2
persist-credentials: false
- name: Check for Python files
id: check-python
run: |
if [ -z "$(find . -name '*.py' -type f)" ]; then
echo "No Python files found, skipping analysis"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "Python files found, proceeding with analysis"
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
if: steps.check-python.outputs.skip != 'true'
uses: github/codeql-action/init@v3
with:
languages: "python"
- name: Perform CodeQL Analysis
if: steps.check-python.outputs.skip != 'true'
uses: github/codeql-action/analyze@v3
+5 -26
View File
@@ -5,28 +5,14 @@ on:
- labeled
- opened
- synchronize
permissions: {}
concurrency:
group: pr-commands-${{ github.event.number }}
jobs:
config:
runs-on: "ubuntu-latest"
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.GRAFANA_PR_AUTOMATION_APP_ID != '' &&
secrets.GRAFANA_PR_AUTOMATION_APP_PEM != '' &&
secrets.GRAFANA_MISC_STATS_API_KEY != ''
) || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
main:
needs: config
if: needs.config.outputs.has-secrets
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
@@ -38,15 +24,8 @@ jobs:
persist-credentials: false
- name: Install Actions
run: npm install --production --prefix ./actions
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_PR_AUTOMATION_APP_ID }}
private_key: ${{ secrets.GRAFANA_PR_AUTOMATION_APP_PEM }}
- name: Run Commands
uses: ./actions/commands
with:
metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{ steps.generate_token.outputs.token }}
token: ${{ secrets.GITHUB_TOKEN }}
configPath: pr-commands
@@ -1,7 +1,7 @@
name: "Update Go Workspace for Dependabot PRs"
on:
pull_request:
branches: [main]
branches: [main, release-*]
paths:
- .github/workflows/pr-dependabot-update-go-workspace.yml
- go.mod
@@ -65,5 +65,5 @@ jobs:
if ! git diff --exit-code --quiet; then
echo "Committing and pushing workspace changes"
git commit -a -m "update workspace"
git push origin $BRANCH_NAME
git push origin "$BRANCH_NAME"
fi
+177 -34
View File
@@ -11,27 +11,46 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
permissions: {}
jobs:
detect-changes:
name: Detect whether code changed
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
changed: ${{ steps.detect-changes.outputs.e2e }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: true # required to get more history in the changed-files action
fetch-depth: 2
- name: Detect changes
id: detect-changes
uses: ./.github/actions/change-detection
with:
self: .github/workflows/pr-e2e-tests.yml
build-grafana:
needs: detect-changes
if: needs.detect-changes.outputs.changed == 'true'
name: Build & Package Grafana
runs-on: ubuntu-latest-16-cores
permissions:
contents: read
outputs:
artifact: ${{ steps.artifact.outputs.artifact }}
steps:
- uses: actions/checkout@v4
with:
repository: 'grafana/grafana-build'
ref: 'main'
persist-credentials: false
- uses: actions/checkout@v4
with:
path: ./grafana
- run: echo "GRAFANA_GO_VERSION=$(grep "go 1." grafana/go.work | cut -d\ -f2)" >> "$GITHUB_ENV"
persist-credentials: false
- uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
verb: run
args: go run ./cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir=grafana --go-version=${GRAFANA_GO_VERSION} > out.txt
- run: mv $(cat out.txt) grafana.tar.gz
args: go -C grafana run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir="${PWD}/grafana" > out.txt
- run: mv "$(cat out.txt)" grafana.tar.gz
- run: echo "artifact=grafana-e2e-${{github.run_number}}" >> "$GITHUB_OUTPUT"
id: artifact
- uses: actions/upload-artifact@v4
@@ -40,33 +59,157 @@ jobs:
retention-days: 1
name: ${{ steps.artifact.outputs.artifact }}
path: grafana.tar.gz
e2e-matrix:
build-e2e-runner:
needs: detect-changes
if: needs.detect-changes.outputs.changed == 'true'
name: Build E2E test runner
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
artifact: ${{ steps.artifact.outputs.artifact }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: ${{ !github.event.pull_request.head.repo.fork }}
- name: Build E2E test runner
id: artifact
run: |
set -euo pipefail
# We want a static binary, so we need to set CGO_ENABLED=0
CGO_ENABLED=0 go build -o ./e2e-runner ./e2e/
echo "artifact=e2e-runner-${{github.run_number}}" >> "$GITHUB_OUTPUT"
- uses: actions/upload-artifact@v4
id: upload
with:
retention-days: 1
name: ${{ steps.artifact.outputs.artifact }}
path: e2e-runner
run-e2e-tests:
needs:
- build-grafana
- build-e2e-runner
strategy:
fail-fast: false
matrix:
include:
- suite: various-suite
path: e2e/various-suite
- suite: dashboards-suite
path: e2e/dashboards-suite
- suite: smoke-tests-suite
path: e2e/smoke-tests-suite
- suite: panels-suite
path: e2e/panels-suite
- suite: various-suite (old arch)
path: e2e/old-arch/various-suite
flags: --flags="--env DISABLE_SCENES=true"
- suite: dashboards-suite (old arch)
path: e2e/old-arch/dashboards-suite
flags: --flags="--env DISABLE_SCENES=true"
- suite: smoke-tests-suite (old arch)
path: e2e/old-arch/smoke-tests-suite
flags: --flags="--env DISABLE_SCENES=true"
- suite: panels-suite (old arch)
path: e2e/old-arch/panels-suite
flags: --flags="--env DISABLE_SCENES=true"
name: ${{ matrix.suite }}
strategy:
matrix:
suite:
- various-suite
- dashboards-suite
- smoke-tests-suite
- panels-suite
runs-on: ubuntu-latest-8-cores
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/download-artifact@v4
with:
name: ${{ needs.build-grafana.outputs.artifact }}
- uses: actions/download-artifact@v4
with:
name: ${{ needs.build-e2e-runner.outputs.artifact }}
- name: chmod +x
run: chmod +x ./e2e-runner
- name: Run E2E tests
uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
verb: run
args: go run ./pkg/build/e2e --package=grafana.tar.gz
--suite=${{ matrix.path }}
${{ matrix.flags }}
- name: Set suite name
id: set-suite-name
if: success() || failure()
env:
SUITE: ${{ matrix.path }}
run: |
set -euo pipefail
echo "suite=$(echo "$SUITE" | sed 's/\//-/g')" >> "$GITHUB_OUTPUT"
- uses: actions/upload-artifact@v4
if: success() || failure()
with:
name: ${{ steps.set-suite-name.outputs.suite }}-${{ github.run_number }}
path: videos
retention-days: 1
run-a11y-test:
needs:
- build-grafana
uses: ./.github/workflows/run-e2e-suite.yml
with:
package: ${{ needs.build-grafana.outputs.artifact }}
suite: ${{ matrix.suite }}
e2e-matrix-old-arch:
name: ${{ matrix.suite }} (old arch)
strategy:
matrix:
suite:
- old-arch/various-suite
- old-arch/dashboards-suite
- old-arch/smoke-tests-suite
- old-arch/panels-suite
name: A11y test
runs-on: ubuntu-latest-8-cores
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/download-artifact@v4
with:
name: ${{ needs.build-grafana.outputs.artifact }}
- name: Run PR a11y test
if: github.event_name == 'pull_request'
uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
verb: run
args: go run ./pkg/build/a11y --package=grafana.tar.gz
- name: Run non-PR a11y test
if: github.event_name != 'pull_request'
uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
verb: run
args: go run ./pkg/build/a11y --package=grafana.tar.gz --no-threshold-fail
# This is the job that is actually required by rulesets.
# We want to only require one job instead of all the individual tests.
# Future work also allows us to start skipping some tests based on changed files.
required-e2e-tests:
needs:
- build-grafana
uses: ./.github/workflows/run-e2e-suite.yml
with:
package: ${{ needs.build-grafana.outputs.artifact }}
suite: ${{ matrix.suite }}
- run-e2e-tests
# a11y test is not listed on purpose: it is not an important E2E test.
# It is also totally fine to fail right now.
# always() is the best function here.
# success() || failure() will skip this function if any need is also skipped.
# That means conditional test suites will fail the entire requirement check.
if: always()
name: All E2E tests complete
runs-on: ubuntu-latest
steps:
- name: Check test suites
env:
NEEDS: ${{ toJson(needs) }}
run: |
FAILURES="$(echo "$NEEDS" | jq 'with_entries(select(.value.result == "failure")) | map_values(.result)')"
echo "$FAILURES"
if [ "$(echo "$FAILURES" | jq '. | length')" != "0" ]; then
exit 1
fi
echo "All OK!"
@@ -0,0 +1,25 @@
name: External PR labelling
on:
# We need "write" permissions on the PR to be able to add a label.
pull_request_target: # zizmor: ignore[dangerous-triggers] We need this to have labelling permissions. There are no user inputs here, so we should be fine.
types:
- opened
permissions: {}
jobs:
label-if-external:
name: Add 'pr/external' label if the PR is external
if: github.event.pull_request.author_association != 'MEMBER' && github.event.pull_request.author_association != 'OWNER'
runs-on: ubuntu-latest
permissions:
pull-requests: write # to write the label
steps:
- name: Add the 'pr/external' label
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
echo "Adding 'pr/external' label to the PR"
gh pr edit "$PR_NUMBER" --add-label pr/external
+51 -2
View File
@@ -9,13 +9,32 @@ on:
permissions: {}
jobs:
detect-changes:
name: Detect whether code changed
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
changed: ${{ steps.detect-changes.outputs.frontend }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: true # required to get more history in the changed-files action
fetch-depth: 2
- name: Detect changes
id: detect-changes
uses: ./.github/actions/change-detection
with:
self: .github/workflows/pr-frontend-unit-tests.yml
frontend-unit-tests:
permissions:
contents: read
id-token: write
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`,
# the `frontend-unit-tests-enterprise` workflow will run instead
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true
needs: detect-changes
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true && needs.detect-changes.outputs.changed == 'true'
runs-on: ubuntu-latest-8-cores
name: "Unit tests (${{ matrix.chunk }} / 8)"
strategy:
@@ -43,7 +62,8 @@ jobs:
contents: read
id-token: write
# Run this workflow for non-PR events (like pushes to `main` or `release-*`) OR for internal PRs (PRs not from forks)
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
needs: detect-changes
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false && needs.detect-changes.outputs.changed == 'true'
runs-on: ubuntu-latest-8-cores
name: "Unit tests (${{ matrix.chunk }} / 8)"
strategy:
@@ -52,6 +72,8 @@ jobs:
chunk: [1, 2, 3, 4, 5, 6, 7, 8]
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
@@ -67,3 +89,30 @@ jobs:
TEST_MAX_WORKERS: 2
TEST_SHARD: ${{ matrix.chunk }}
TEST_SHARD_TOTAL: 8
# This is the job that is actually required by rulesets.
# We need to require EITHER the OSS or the Enterprise job to pass.
# However, if one is skipped, GitHub won't flat-map the shards,
# so they won't be accepted by a ruleset.
required-frontend-unit-tests:
needs:
- frontend-unit-tests
- frontend-unit-tests-enterprise
# always() is the best function here.
# success() || failure() will skip this function if any need is also skipped.
# That means conditional test suites will fail the entire requirement check.
if: always()
name: All frontend unit tests complete
runs-on: ubuntu-latest
steps:
- name: Check test suites
env:
NEEDS: ${{ toJson(needs) }}
run: |
FAILURES="$(echo "$NEEDS" | jq 'with_entries(select(.value.result == "failure")) | map_values(.result)')"
echo "$FAILURES"
if [ "$(echo "$FAILURES" | jq '. | length')" != "0" ]; then
exit 1
fi
echo "All OK!"
+1 -1
View File
@@ -3,7 +3,7 @@ name: "Go Workspace Check"
on:
workflow_dispatch:
pull_request:
branches: [main]
branches: [main, release-*]
paths:
- .github/workflows/pr-go-workspace-check.yml
- go.mod
+1 -1
View File
@@ -3,7 +3,7 @@ name: "K8s Codegen Check"
on:
workflow_dispatch:
pull_request:
branches: [main]
branches: [main, release-*]
paths:
- "pkg/apis/**"
- "pkg/aggregator/apis/**"
+12 -48
View File
@@ -1,63 +1,27 @@
# Owned by grafana-delivery-squad
# Intended to be dropped into the base repo Ex: grafana/grafana
name: Dispatch check for patch conflicts
run-name: dispatch-check-patch-conflicts-${{ github.base_ref }}-${{ github.head_ref }}
on:
pull_request_target:
pull_request:
types:
- opened
- reopened
- synchronize
branches:
- "main"
- "v*.*.*"
- "release-*"
permissions: {}
permissions:
id-token: write
contents: read
# Since this is run on a pull request, we want to apply the patches intended for the
# target branch onto the source branch, to verify compatibility before merging.
jobs:
dispatch-job:
permissions:
id-token: write
contents: read
actions: write
env:
HEAD_REF: ${{ github.head_ref }}
BASE_REF: ${{ github.base_ref }}
REPO: ${{ github.repository }}
SENDER: ${{ github.event.sender.login }}
SHA: ${{ github.sha }}
PR_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
runs-on: ubuntu-latest
steps:
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
# App needs Actions: Read/Write for the grafana/security-patch-actions repo
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: "Dispatch job"
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate_token.outputs.token }}
script: |
const {HEAD_REF, BASE_REF, REPO, SENDER, SHA, PR_COMMIT_SHA} = process.env;
await github.rest.actions.createWorkflowDispatch({
owner: 'grafana',
repo: 'security-patch-actions',
workflow_id: 'test-patches-event.yml',
ref: 'main',
inputs: {
src_repo: REPO,
src_ref: HEAD_REF,
src_merge_sha: SHA,
src_pr_commit_sha: PR_COMMIT_SHA,
patch_repo: REPO + '-security-patches',
patch_ref: BASE_REF,
triggering_github_handle: SENDER
}
})
uses: grafana/grafana/.github/workflows/pr-patch-check.yml@main
with:
head_ref: ${{ github.head_ref }}
base_ref: ${{ github.base_ref }}
repo: ${{ github.repository }}
sender_login: ${{ github.event.sender.login }}
sha: ${{ github.sha }}
pr_commit_sha: ${{ github.event.pull_request.head.sha }}
+78
View File
@@ -0,0 +1,78 @@
name: Dispatch check for patch conflicts
on:
workflow_call:
inputs:
head_ref:
type: string
required: true
base_ref:
type: string
required: true
repo:
type: string
required: true
sender_login:
type: string
required: true
sha:
type: string
required: true
pr_commit_sha:
type: string
required: true
permissions:
id-token: write
contents: read
# Since this is run on a pull request, we want to apply the patches intended for the
# target branch onto the source branch, to verify compatibility before merging.
jobs:
dispatch-job:
env:
HEAD_REF: ${{ inputs.head_ref }}
BASE_REF: ${{ github.base_ref }}
REPO: ${{ inputs.repo }}
SENDER: ${{ inputs.sender_login }}
SHA: ${{ inputs.sha }}
PR_COMMIT_SHA: ${{ inputs.pr_commit_sha }}
runs-on: ubuntu-latest
steps:
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
# App needs Actions: Read/Write for the grafana/security-patch-actions repo
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
permissions: "{\"actions\": \"write\", \"workflows\": \"write\"}"
repositories: "[\"security-patch-actions\"]"
- name: "Dispatch job"
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate_token.outputs.token }}
script: |
const {HEAD_REF, BASE_REF, REPO, SENDER, SHA, PR_COMMIT_SHA} = process.env;
await github.rest.actions.createWorkflowDispatch({
owner: 'grafana',
repo: 'security-patch-actions',
workflow_id: 'test-patches-event.yml',
ref: 'main',
inputs: {
src_repo: REPO,
src_ref: HEAD_REF,
src_merge_sha: SHA,
src_pr_commit_sha: PR_COMMIT_SHA,
patch_repo: REPO + '-security-patches',
patch_ref: BASE_REF,
triggering_github_handle: SENDER
}
})
+40 -6
View File
@@ -15,6 +15,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
permissions: {}
jobs:
sqlite:
strategy:
@@ -27,6 +29,8 @@ jobs:
name: Sqlite (${{ matrix.shard }})
runs-on: ubuntu-latest-8-cores
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -37,12 +41,11 @@ jobs:
with:
go-version-file: go.mod
cache: true
- name: Generate Go code
run: make gen-go
- name: Run tests
env:
SHARD: ${{ matrix.shard }}
run: |
set -euo pipefail
readarray -t PACKAGES <<< "$(./scripts/ci/backend-tests/pkgs-with-tests-named.sh -b TestIntegration | ./scripts/ci/backend-tests/shard.sh -N"$SHARD" -d-)"
go test -tags=sqlite -timeout=5m -run '^TestIntegration' "${PACKAGES[@]}"
mysql:
@@ -56,6 +59,8 @@ jobs:
name: MySQL (${{ matrix.shard }})
runs-on: ubuntu-latest-8-cores
permissions:
contents: read
env:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: 127.0.0.1
@@ -73,6 +78,8 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@v5
with:
@@ -80,12 +87,11 @@ jobs:
cache: true
- name: Setup MySQL devenv
run: mysql -h 127.0.0.1 -P 3306 -u root -prootpass < devenv/docker/blocks/mysql_tests/setup.sql
- name: Generate Go code
run: make gen-go
- name: Run tests
env:
SHARD: ${{ matrix.shard }}
run: |
set -euo pipefail
readarray -t PACKAGES <<< "$(./scripts/ci/backend-tests/pkgs-with-tests-named.sh -b TestIntegration | ./scripts/ci/backend-tests/shard.sh -N"$SHARD" -d-)"
go test -p=1 -tags=mysql -timeout=5m -run '^TestIntegration' "${PACKAGES[@]}"
postgres:
@@ -117,6 +123,8 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@v5
with:
@@ -124,11 +132,37 @@ jobs:
cache: true
- name: Setup Postgres devenv
run: psql -p 5432 -h 127.0.0.1 -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql
- name: Generate Go code
run: make gen-go
- name: Run tests
env:
SHARD: ${{ matrix.shard }}
run: |
set -euo pipefail
readarray -t PACKAGES <<< "$(./scripts/ci/backend-tests/pkgs-with-tests-named.sh -b TestIntegration | ./scripts/ci/backend-tests/shard.sh -N"$SHARD" -d-)"
go test -p=1 -tags=postgres -timeout=5m -run '^TestIntegration' "${PACKAGES[@]}"
# This is the job that is actually required by rulesets.
# We want to only require one job instead of all the individual tests and shards.
# Future work also allows us to start skipping some tests based on changed files.
required-backend-integration-tests:
needs:
- mysql
- postgres
- sqlite
# always() is the best function here.
# success() || failure() will skip this function if any need is also skipped.
# That means conditional test suites will fail the entire requirement check.
if: always()
name: All backend integration tests complete
runs-on: ubuntu-latest
steps:
- name: Check test suites
env:
NEEDS: ${{ toJson(needs) }}
run: |
FAILURES="$(echo "$NEEDS" | jq 'with_entries(select(.value.result == "failure")) | map_values(.result)')"
echo "$FAILURES"
if [ "$(echo "$FAILURES" | jq '. | length')" != "0" ]; then
exit 1
fi
echo "All OK!"
+68
View File
@@ -0,0 +1,68 @@
name: Publish artifacts to bucket
on:
workflow_call:
inputs:
pattern:
description: |
(From actinos/download-artifact) Glob pattern of artifacts (instead of `name`)
Be careful when using this option; the contents of the root of each artifact are coalesced, so ensure that they do not collide.
type: string
required: false
name:
description: (From actinos/download-artifact) Name of the GitHub artifact to upload (Ignored if `pattern` is set)
type: string
required: false
bucket:
description: Name of the GCS bucket
type: string
required: true
bucket-path:
description: Path in the GCS bucket
type: string
required: false
default: "."
environment:
description: "'prod' or 'dev'"
type: string
required: false
default: dev
run-id:
type: string
required: true
service-account:
type: string
required: false
default: github-prerelease-writer@grafanalabs-workload-identity.iam.gserviceaccount.com
jobs:
publish:
runs-on: github-hosted-ubuntu-x64-small
name: Publish
permissions:
id-token: write
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: ${{ inputs.name }}
pattern: ${{ inputs.pattern }}
run-id: ${{ inputs.run-id }}
path: ./artifact
- name: Log in to GCS
id: login-to-gcs
uses: grafana/shared-workflows/actions/login-to-gcs@login-to-gcs/v0.2.1
with:
environment: ${{ inputs.environment }}
service_account: ${{ inputs.service-account }}
- name: Coalesce artifacts
run: |
mkdir out
find ./artifact -mindepth 2 -maxdepth 2 -exec cp -r {} out/ \;
ls -al out
- name: Upload artifacts
uses: grafana/shared-workflows/actions/push-to-gcs@push-to-gcs-v0.2.0
with:
bucket: ${{ inputs.bucket }}
environment: ${{ inputs.environment }}
parent: false
path: out
bucket_path: ${{ inputs.bucket-path }}
service_account: ${{ inputs.service-account }}
+19 -19
View File
@@ -8,25 +8,17 @@ on:
- '**/*.cue'
workflow_dispatch:
jobs:
config:
runs-on: "ubuntu-latest"
if: github.repository == 'grafana/grafana'
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.GRAFANA_DELIVERY_BOT_APP_ID != '' &&secrets.GRAFANA_DELIVERY_BOT_APP_PEM != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
permissions: {}
jobs:
main:
needs: config
if: github.repository == 'grafana/grafana' && needs.config.outputs.has-secrets
if: github.repository == 'grafana/grafana'
runs-on: "ubuntu-latest"
permissions:
contents: read # cloning repo
actions: read # reading .github/workflows/ dir
id-token: write # reading vault secrets
steps:
- name: "Checkout Grafana repo"
uses: "actions/checkout@v4"
@@ -42,12 +34,20 @@ jobs:
- name: "Verify kinds"
run: go run .github/workflows/scripts/kinds/verify-kinds.go
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
# App needs Actions: Read/Write for the grafana/security-patch-actions repo
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: "Clone website-sync Action"
run: "git clone --single-branch --no-tags --depth 1 -b master https://grafana-delivery-bot:${{ steps.generate_token.outputs.token }}@github.com/grafana/website-sync ./.github/actions/website-sync"
+20 -19
View File
@@ -10,25 +10,17 @@ on:
- '**/*.cue'
workflow_dispatch:
jobs:
config:
runs-on: "ubuntu-latest"
if: github.repository == 'grafana/grafana'
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.GRAFANA_DELIVERY_BOT_APP_ID != '' && secrets.GRAFANA_DELIVERY_BOT_APP_PEM != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
permissions: {}
jobs:
main:
needs: config
if: github.repository == 'grafana/grafana' && needs.config.outputs.has-secrets
if: github.repository == 'grafana/grafana'
runs-on: "ubuntu-latest"
permissions:
contents: read # cloning repo
actions: read # reading .github/workflows/ dir
id-token: write # reading vault secrets
steps:
- name: "Checkout Grafana repo"
uses: "actions/checkout@v4"
@@ -50,6 +42,7 @@ jobs:
with:
repository: "grafana/grafana-github-actions"
path: "./actions"
persist-credentials: false
- name: "Install Actions from library"
run: "npm install --production --prefix ./actions"
@@ -62,12 +55,20 @@ jobs:
release_tag_regexp: "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
release_branch_regexp: "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.x$"
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
# Secrets placed in the ci/data/repo/grafana/grafana/delivery-bot-app path in Vault
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
# App needs Actions: Read/Write for the grafana/security-patch-actions repo
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
- name: "Clone website-sync Action"
if: "steps.has-matching-release-tag.outputs.bool == 'true'"
@@ -16,6 +16,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: grafana/writers-toolkit/publish-technical-documentation@publish-technical-documentation/v1 # zizmor: ignore[unpinned-uses]
with:
website_directory: content/docs/grafana/next
+31
View File
@@ -0,0 +1,31 @@
name: Reject GitHub secrets
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main
- release-*.*.*
permissions: {}
jobs:
reject-gh-secrets:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
persist-credentials: false
- name: Grep for secrets accesses
run: |
if grep -E '\$\{\{\s*secrets\s*\.\s*[a-zA-Z0-9_\-]+\s*\}\}' .github/workflows/*.yml | grep -vF 'secrets.GITHUB_TOKEN' | grep -vF '# nolint:reject-gh-secrets'; then
echo "Found secrets access in the codebase. Please remove it in favour of Vault secrets."
echo "If you are sure this is correct, add '# nolint:reject-gh-secrets' to the end of the line. Be VERY careful with this."
exit 1
fi
+190
View File
@@ -0,0 +1,190 @@
name: Build Release Packages
on:
workflow_dispatch:
push:
branches:
- release-*.*.*
- main
permissions:
contents: read
# Builds the following artifacts:
#
# npm:grafana
# storybook
# targz:grafana:linux/amd64
# targz:grafana:linux/arm64
# targz:grafana:linux/arm/v6
# targz:grafana:linux/arm/v7
# deb:grafana:linux/amd64
# deb:grafana:linux/arm64
# deb:grafana:linux/arm/v6
# deb:grafana:linux/arm/v7
# rpm:grafana:linux/amd64:sign
# rpm:grafana:linux/arm64:sign
# docker:grafana:linux/amd64
# docker:grafana:linux/arm64
# docker:grafana:linux/arm/v7
# docker:grafana:linux/amd64:ubuntu
# docker:grafana:linux/arm64:ubuntu
# docker:grafana:linux/arm/v7:ubuntu
# targz:grafana:windows/amd64
# targz:grafana:windows/arm64
# targz:grafana:darwin/amd64
# targz:grafana:darwin/arm64
# zip:grafana:windows/amd64
# msi:grafana:windows/amd64
jobs:
setup:
name: setup
runs-on: github-hosted-ubuntu-x64-small
if: github.repository == 'grafana/grafana'
outputs:
version: ${{ steps.output.outputs.version }}
grafana-commit: ${{ steps.output.outputs.grafana_commit }}
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up version (Release Branches)
if: startsWith(github.ref_name, 'release-')
run: echo "${REF_NAME#release-}" > VERSION
env:
REF_NAME: ${{ github.ref_name }}
- name: Set up version (Non-release branches)
if: ${{ !startsWith(github.ref_name, 'release-') }}
run: jq -r .version package.json | sed -s "s/pre/${BUILD_ID}/g" > VERSION
env:
REF_NAME: ${{ github.ref_name }}
BUILD_ID: ${{ github.run_id }}
- id: output
run: |
echo "version=$(cat VERSION)" >> "$GITHUB_OUTPUT"
echo "grafana_commit=$(git rev-parse HEAD)" | tee -a "$GITHUB_OUTPUT"
# Triggers the same workflow in `grafana-enterprise` on the same ref
downstream:
runs-on: github-hosted-ubuntu-x64-small
needs: [setup]
permissions:
contents: read
id-token: write
name: Dispatch grafana-enterprise build
steps:
- id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
repositories: '["grafana-enterprise"]'
permissions: '{"actions": "write"}'
- uses: actions/github-script@v7
env:
REF: ${{ github.ref_name }}
VERSION: ${{ needs.setup.outputs.version }}
BUILD_ID: ${{ github.run_id }}
BUCKET: grafana-prerelease
GRAFANA_COMMIT: ${{ needs.setup.outputs.grafana-commit }}
with:
github-token: ${{ steps.generate_token.outputs.token }}
script: |
const {REF, VERSION, BUILD_ID, BUCKET, GRAFANA_COMMIT} = process.env;
await github.rest.actions.createWorkflowDispatch({
owner: 'grafana',
repo: 'grafana-enterprise',
workflow_id: 'release-build.yml',
ref: REF,
inputs: {
"version": VERSION,
"build-id": String(BUILD_ID),
"bucket": BUCKET,
"grafana-commit": GRAFANA_COMMIT,
}
})
build:
runs-on: github-hosted-ubuntu-x64-large
needs: [setup]
permissions:
contents: read
id-token: write
name: ${{ needs.setup.outputs.version }} / ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
# The artifacts in these lists are grouped by their os+arch because the
# build process can reuse the binaries for each artifact.
# The downside to this is that the frontend will be built for each one when it could be reused for all of them.
# This could be a future improvement.
include:
- name: linux-amd64
artifacts: targz:grafana:linux/amd64,deb:grafana:linux/amd64,rpm:grafana:linux/amd64,docker:grafana:linux/amd64,docker:grafana:linux/amd64:ubuntu,npm:grafana,storybook
- name: linux-arm64
artifacts: targz:grafana:linux/arm64,deb:grafana:linux/arm64,rpm:grafana:linux/arm64,docker:grafana:linux/arm64,docker:grafana:linux/arm64:ubuntu
- name: linux-s390x
artifacts: targz:grafana:linux/s390x,deb:grafana:linux/s390x,rpm:grafana:linux/s390x,docker:grafana:linux/s390x,docker:grafana:linux/s390x:ubuntu
- name: linux-armv7
artifacts: targz:grafana:linux/arm/v7,deb:grafana:linux/arm/v7,docker:grafana:linux/arm/v7,docker:grafana:linux/arm/v7:ubuntu
- name: linux-armv6
artifacts: targz:grafana:linux/arm/v6,deb:grafana:linux/arm/v6
- name: windows-amd64
artifacts: targz:grafana:windows/amd64,zip:grafana:windows/amd64,msi:grafana:windows/amd64
- name: windows-arm64
artifacts: targz:grafana:windows/arm64,zip:grafana:windows/arm64
- name: darwin-amd64
artifacts: targz:grafana:darwin/amd64
- name: darwin-arm64
artifacts: targz:grafana:darwin/arm64
steps:
- uses: grafana/shared-workflows/actions/dockerhub-login@main
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
with:
image: docker.io/tonistiigi/binfmt:qemu-v7.0.0-28
- uses: ./.github/actions/build-package
id: build
with:
artifacts: ${{ matrix.artifacts }}
checksum: true
grafana-path: .
github-token: ${{ secrets.GITHUB_TOKEN }}
version: ${{ needs.setup.outputs.version }}
output: artifacts-${{ matrix.name }}.txt
verify: true
build-id: ${{ github.run_id }}
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: artifacts-list-${{ matrix.name }}
path: ${{ steps.build.outputs.file }}
retention-days: 1
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: artifacts-${{ matrix.name }}
path: ${{ steps.build.outputs.dist-dir }}
retention-days: 1
publish-artifacts:
name: Upload artifacts
uses: grafana/grafana/.github/workflows/publish-artifact.yml@main
permissions:
id-token: write
needs:
- setup
- build
with:
bucket: grafana-prerelease
pattern: artifacts-*
run-id: ${{ github.run_id }}
bucket-path: ${{ needs.setup.outputs.version }}_${{ github.run_id }}
environment: prod
+26 -30
View File
@@ -21,6 +21,11 @@ on:
- 'main'
- 'release-*.*.*'
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
setup:
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/')) }}
@@ -30,6 +35,8 @@ jobs:
release_branch: ${{ steps.output.outputs.release_branch }}
dry_run: ${{ steps.output.outputs.dry_run }}
latest: ${{ steps.output.outputs.latest }}
private_key: ${{ steps.output.outputs.delivery_bot_pem }}
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
env:
HEAD_REF: ${{ github.head_ref }}
DRY_RUN: ${{ inputs.dry_run }}
@@ -39,36 +46,34 @@ jobs:
steps:
- if: ${{ github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/') }}
run: |
echo "VERSION=$(echo ${HEAD_REF} | sed -e 's/release\/.*\//v/g')" >> $GITHUB_ENV
echo "DRY_RUN=${{ contains(github.event.pull_request.labels.*.name, 'release/dry-run') }}" >> $GITHUB_ENV
echo "LATEST=${{ contains(github.event.pull_request.labels.*.name, 'release/latest') && '1' || '0' }}" >> $GITHUB_ENV
{
echo "VERSION=$(echo "${HEAD_REF}" | sed -e 's/release\/.*\//v/g')"
echo "DRY_RUN=${{ contains(github.event.pull_request.labels.*.name, 'release/dry-run') }}"
echo "LATEST=${{ contains(github.event.pull_request.labels.*.name, 'release/latest') && '1' || '0' }}"
} >> "$GITHUB_ENV"
- id: output
run: |
echo "dry_run: $DRY_RUN"
echo "latest: $LATEST"
echo "version: $VERSION"
echo "release_branch=$(echo $VERSION | sed -s 's/^v/release-/g')" >> "$GITHUB_OUTPUT"
echo "dry_run=$DRY_RUN" >> "$GITHUB_OUTPUT"
echo "latest=$LATEST" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
{
echo "release_branch=$(echo "$VERSION" | sed -s 's/^v/release-/g')"
echo "dry_run=$DRY_RUN"
echo "latest=$LATEST"
echo "version=$VERSION"
} >> "$GITHUB_OUTPUT"
create_next_release_branch_grafana:
name: Create next release branch (Grafana)
needs: setup
uses: ./.github/workflows/create-next-release-branch.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
uses: grafana/grafana/.github/workflows/create-next-release-branch.yml@main
with:
ownerRepo: 'grafana/grafana'
source: ${{ needs.setup.outputs.release_branch }}
create_next_release_branch_enterprise:
name: Create next release branch (Grafana Enterprise)
needs: setup
uses: ./.github/workflows/create-next-release-branch.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
uses: grafana/grafana/.github/workflows/create-next-release-branch.yml@main
with:
ownerRepo: 'grafana/grafana-enterprise'
source: ${{ needs.setup.outputs.release_branch }}
@@ -92,10 +97,7 @@ jobs:
needs:
- setup
- create_next_release_branch_grafana
uses: ./.github/workflows/migrate-prs.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
uses: grafana/grafana/.github/workflows/migrate-prs.yml@main
with:
ownerRepo: 'grafana/grafana'
from: ${{ needs.setup.outputs.release_branch }}
@@ -104,20 +106,14 @@ jobs:
needs:
- setup
- create_next_release_branch_enterprise
uses: ./.github/workflows/migrate-prs.yml
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
uses: grafana/grafana/.github/workflows/migrate-prs.yml@main
with:
ownerRepo: 'grafana/grafana-enterprise'
from: ${{ needs.setup.outputs.release_branch }}
to: ${{ needs.create_next_release_branch_enterprise.outputs.branch }}
post_changelog_on_forum:
needs: setup
uses: ./.github/workflows/community-release.yml
secrets:
GRAFANA_MISC_STATS_API_KEY: ${{ secrets.GRAFANA_MISC_STATS_API_KEY }}
GRAFANABOT_FORUM_KEY: ${{ secrets.GRAFANABOT_FORUM_KEY }}
uses: grafana/grafana/.github/workflows/community-release.yml@main
with:
version: ${{ needs.setup.outputs.version }}
dry_run: ${{ needs.setup.outputs.dry_run == 'true' }}
@@ -126,7 +122,7 @@ jobs:
# The github-release action retrieves the changelog using the /repos/grafana/grafana/contents/CHANGELOG.md API
# endpoint.
needs: setup
uses: ./.github/workflows/github-release.yml
uses: grafana/grafana/.github/workflows/github-release.yml@main
with:
version: ${{ needs.setup.outputs.version }}
dry_run: ${{ needs.setup.outputs.dry_run == 'true' }}
@@ -139,5 +135,5 @@ jobs:
VERSION: ${{ needs.setup.outputs.version }}
steps:
- run: |
echo announce on slack that $VERSION has been released
echo dry run: $DRY_RUN
echo announce on slack that "$VERSION" has been released
echo dry run: "$DRY_RUN"
+94 -64
View File
@@ -15,15 +15,19 @@ on:
version:
required: true
type: string
description: The version of Grafana that is being released
description: The version of Grafana that is being released (without the `v` prefix)`
target:
required: true
type: string
description: The release branch pattern (eg v9.5.x) that these changes are being merged into
backport:
required: false
type: string
description: Branch to backport these changes to
description: 'Unused: left here for backwards compatibility'
changelog:
required: false
type: boolean
default: true
bump:
required: false
type: boolean
default: true
dry_run:
required: false
default: false
@@ -32,29 +36,63 @@ on:
required: false
default: false
type: boolean
release_date:
required: false
type: string
description: "Release date in format YYYY-MM-DD"
permissions: {}
permissions:
contents: read
jobs:
capture-date:
runs-on: ubuntu-latest
outputs:
release_date: ${{ steps.set_release_date.outputs.release_date }}
steps:
- name: compute_release_date
run: |
if [ -n "$DATE" ]; then
echo "release_date=$DATE" >> "$GITHUB_ENV"
exit 0
fi
echo "Fetching workflow run creation date..."
created_at=$(gh run view "$GITHUB_RUN_ID" --repo "$GH_REPO" --json createdAt -q .createdAt)
formatted_date=$(date -d "$created_at" +%Y-%m-%d)
echo "release_date=$formatted_date" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
DATE: ${{ inputs.release_date }}
- id: set_release_date
run: echo "release_date=$release_date" >> "$GITHUB_OUTPUT"
push-changelog-to-main:
needs: capture-date
permissions:
contents: write
id-token: write
pull-requests: write
name: Create PR to main to update the changelog
uses: ./.github/workflows/changelog.yml
concurrency:
group: grafana-release-pr-update-changelog-main
cancel-in-progress: false
with:
previous_version: ${{inputs.previous_version}}
version: ${{ inputs.version }}
latest: ${{ inputs.latest }}
dry_run: ${{ inputs.dry_run }}
target: main
secrets:
GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
work_branch: changelog/update-changelog-${{ needs.capture-date.outputs.release_date }}
create-prs:
permissions:
contents: write
id-token: write
pull-requests: write
name: Create Release PR
runs-on: ubuntu-latest
@@ -64,55 +102,62 @@ jobs:
LATEST: ${{ inputs.latest }}
DRY_RUN: ${{ inputs.dry_run }}
steps:
- name: Get release branch
id: branch
uses: grafana/grafana-github-actions-go/latest-release-branch@main # zizmor: ignore[unpinned-uses]
- name: "Get vault secrets"
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
ownerRepo: 'grafana/grafana'
pattern: ${{ inputs.target }}
repo_secrets: |
GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY
- name: Generate token
id: generate_changelog_token
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a
with:
app_id: ${{ vars.DELIVERY_BOT_APP_ID }}
private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }}
repositories: "[\"grafana\", \"grafana-enterprise\"]"
permissions: "{\"contents\": \"write\", \"pull_requests\": \"write\", \"workflows\":\"write\"}"
- run: echo "RELEASE_BRANCH=release-${VERSION}" >> "$GITHUB_ENV"
- name: Checkout Grafana
uses: actions/checkout@v4
with:
ref: ${{ steps.branch.outputs.branch }}
token: ${{ steps.generate_changelog_token.outputs.token }}
ref: ${{ env.RELEASE_BRANCH }}
fetch-tags: true
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
- name: Checkout Grafana (main)
uses: actions/checkout@v4
with:
token: ${{ steps.generate_changelog_token.outputs.token }}
ref: main
fetch-depth: '0'
fetch-tags: 'false'
path: .grafana-main
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false
- name: Setup nodejs environment
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Configure git user
run: |
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "grafana-delivery-bot[bot]"
git config --local user.email "grafana-delivery-bot[bot]@users.noreply.github.com"
git config --local --add --bool push.autoSetupRemote true
- name: Create branch
run: git checkout -b "release/${{ github.run_id }}/$VERSION"
- name: Generate changelog token
id: generate_changelog_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
run: git checkout -b "release/${{ github.run_number }}/$VERSION"
- name: Generate changelog
id: changelog
if: ${{ inputs.changelog == true || inputs.changelog == 'true' }}
uses: ./.grafana-main/.github/actions/changelog
with:
previous: ${{inputs.previous_version}}
github_token: ${{ steps.generate_changelog_token.outputs.token }}
target: v${{ env.VERSION }}
output_file: changelog_items.md
- name: Patch CHANGELOG.md
if: ${{ inputs.changelog == true || inputs.changelog == 'true' }}
run: |
# Prepare CHANGELOG.md content with version delimiters
(
@@ -144,58 +189,43 @@ jobs:
git diff CHANGELOG.md
- name: "Prettify CHANGELOG.md"
if: ${{ inputs.changelog == true || inputs.changelog == 'true' }}
run: npx prettier --write CHANGELOG.md
- name: Commit CHANGELOG.md changes
if: ${{ inputs.changelog == true || inputs.changelog == 'true' }}
run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md
- name: Update package.json versions
uses: ./.grafana-main/pkg/build/actions/bump-version
- name: Bump versions
if: ${{ inputs.bump == true || inputs.bump == 'true' }}
uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
version: 'patch'
verb: run
args: go run -C .grafana-main ./pkg/build/actions/bump-version -version="patch"
- name: make gen-cue
shell: bash
run: make gen-cue
- name: Add package.json changes
if: ${{ inputs.bump == true || inputs.bump == 'true' }}
run: |
git add package.json lerna.json yarn.lock packages public
test -e e2e/test-plugins && git add e2e/test-plugins
git commit -m "Update version to $VERSION"
- name: Git push
if: ${{ inputs.dry_run }} != true
run: git push --set-upstream origin "release/${{ github.run_id }}/$VERSION"
- name: Create PR without backports
if: "${{ inputs.backport == '' }}"
run: git push
- name: Create PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: ${{ steps.branch.outputs.branch }}
DRY_RUN: ${{ inputs.dry_run }}
run: |
LATEST_FLAG=""
LATEST_FLAG=()
if [ "$LATEST" = "true" ]; then
LATEST_FLAG='-l "release/latest"'
LATEST_FLAG=(-l "release/latest")
fi
gh pr create \
$LATEST_FLAG \
"${LATEST_FLAG[@]}" \
-l "no-changelog" \
--dry-run="$DRY_RUN" \
-B "$BRANCH" \
--title "Release: $VERSION" \
--body "These code changes must be merged after a release is complete"
- name: Create PR with backports
if: "${{ inputs.backport != '' }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: ${{ steps.branch.outputs.branch }}
run: |
LATEST_FLAG=""
if [ "$LATEST" = "true" ]; then
LATEST_FLAG='-l "release/latest"'
fi
gh pr create \
$LATEST_FLAG \
-l "product-approved" \
-l "no-changelog" \
--dry-run="$DRY_RUN" \
-B "$BRANCH" \
-B "${RELEASE_BRANCH}" \
--title "Release: $VERSION" \
--body "These code changes must be merged after a release is complete"
+33
View File
@@ -0,0 +1,33 @@
name: Relyance Compliance Inspection
on:
schedule:
- cron: '0 0 * * *' # Run daily at 00:00 UTC
workflow_dispatch: # Allow for manual trigger
jobs:
relyance-compliance-inspector:
permissions:
contents: read
id-token: write # Needed for Vault access
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Get API key
id: vault-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@5d7e361bc7e0a183cde8afe9899fb7b596d2659b # get-vault-secrets-v1.2.0
with:
repo_secrets: |
API_KEY=relyance:API_KEY
- name: Run Relyance scan
env:
API_KEY: "${{ fromJSON(steps.vault-secrets.outputs.secrets).API_KEY }}"
run: |
docker pull gcr.io/relyance-ext/compliance_inspector:release && \
docker run --rm -v ${{ github.workspace }}:/repo --env "API_KEY=${{ env.API_KEY }}" gcr.io/relyance-ext/compliance_inspector:release
+16 -11
View File
@@ -2,7 +2,7 @@ name: run-dashboard-search-e2e
on:
workflow_run:
workflows:
workflows:
- trigger-dashboard-search-e2e
types:
- completed
@@ -36,11 +36,11 @@ jobs:
- run: go version
- uses: actions/setup-node@v4
with:
node-version: 20
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Cache Node Modules
id: cache-node-modules
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
node_modules
@@ -56,7 +56,7 @@ jobs:
runTests: false
- name: Cache Grafana Build and Dependencies
id: cache-grafana
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
bin/
@@ -74,9 +74,11 @@ jobs:
- name: Get list of .ini files
id: get_files
env:
WORKSPACE: ${{ github.workspace }}
run: |
INI_FILES=$(ls ${{ github.workspace }}/e2e/dashboards-search-suite/*.ini | jq -R -s -c 'split("\n")[:-1]')
echo "ini_files=$INI_FILES" >> $GITHUB_OUTPUT
INI_FILES="$(find "$WORKSPACE"/e2e/dashboards-search-suite/ -type f -name '*.ini' | jq -R -s -c 'split("\n")[:-1]')"
echo "ini_files=$INI_FILES" >> "$GITHUB_OUTPUT"
shell: bash
run_tests:
@@ -95,8 +97,10 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Restore Cached Node Modules
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
node_modules
@@ -104,7 +108,7 @@ jobs:
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
- name: Restore Cached Grafana Build and Dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
bin/
@@ -120,11 +124,12 @@ jobs:
env:
INI_NAME: ${{ matrix.ini_file }}
run: |
FILE_NAME=$(basename "$env.INI_NAME" .ini)
echo "FILE_NAME=$FILE_NAME" >> $GITHUB_OUTPUT
FILE_NAME="$(basename "$INI_NAME" .ini)"
echo "FILE_NAME=$FILE_NAME" >> "$GITHUB_OUTPUT"
- name: Run tests for ${{ steps.set_file_name.outputs.FILE_NAME }}
env:
INI_NAME: ${{ matrix.ini_file }}
WORKSPACE: ${{ github.workspace }}
run: |
cp -rf $INI_NAME ${{ github.workspace }}/scripts/grafana-server/custom.ini
cp -rf "$INI_NAME" "$WORKSPACE"/scripts/grafana-server/custom.ini
yarn e2e:dashboards-search || echo "Test failed but marking as success since unified search is behind a feature flag and should not block PRs"
-39
View File
@@ -1,39 +0,0 @@
name: e2e suite
on:
workflow_call:
inputs:
package:
type: string
required: true
suite:
type: string
required: true
jobs:
main:
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/download-artifact@v4
with:
name: ${{ inputs.package }}
- uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e
with:
verb: run
args: go run ./pkg/build/e2e --package=grafana.tar.gz --suite=${{ inputs.suite }}
- name: Set suite name
id: set-suite-name
if: always()
env:
SUITE: ${{ inputs.suite }}
run: |
echo "suite=$(echo $SUITE | sed 's/\//-/g')" >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@v4
if: always()
with:
name: e2e-${{ steps.set-suite-name.outputs.suite }}-${{github.run_number}}
path: videos
retention-days: 1
+4 -3
View File
@@ -4,9 +4,10 @@ on:
push:
branches:
- main
- release-*.*.*
pull_request:
branches:
- '**'
- '**'
env:
ARCH: linux-amd64
@@ -28,7 +29,7 @@ jobs:
- run: go version
- uses: actions/setup-node@v4
with:
node-version: 20
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
@@ -40,7 +41,7 @@ jobs:
runTests: false
- name: Run dashboard scenes e2e
run: yarn e2e:schema-v2 || echo "Test failed but marking as success since schema V2 is behind a feature flag and should not block PRs"
- name: Always succeed # This is a workaround to make the job pass even if the previous step fails
if: failure()
run: exit 0
@@ -1,84 +0,0 @@
const crowdin = require('@crowdin/crowdin-api-client');
const TRANSLATED_CONNECTOR_DESCRIPTION = '{{tos_service_type: premium}}';
const API_TOKEN = process.env.CROWDIN_PERSONAL_TOKEN;
if (!API_TOKEN) {
console.error('Error: CROWDIN_PERSONAL_TOKEN environment variable is not set');
process.exit(1);
}
const PROJECT_ID = process.env.CROWDIN_PROJECT_ID;
if (!PROJECT_ID) {
console.error('Error: CROWDIN_PROJECT_ID environment variable is not set');
process.exit(1);
}
const { tasksApi, projectsGroupsApi, sourceFilesApi } = new crowdin.default({
token: API_TOKEN,
organization: 'grafana'
});
const languages = await getLanguages();
const fileIds = await getFileIds();
console.log('Languages: ', languages);
console.log('File IDs: ', fileIds);
// for (const language of languages) {
// const { name, id } = language;
// await createTask(`Translate to ${name}`, id, fileIds);
// }
async function getLanguages() {
try {
const project = await projectsGroupsApi.getProject(PROJECT_ID);
const languages = project.data.targetLanguages;
return languages;
} catch (error) {
console.error('Failed to fetch languages: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
async function getFileIds() {
try {
const response = await sourceFilesApi.listProjectFiles(PROJECT_ID);
const files = response.data;
const fileIds = files.map(file => file.data.id);
return fileIds;
} catch (error) {
console.error('Failed to fetch file IDs: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
async function createTask(title, languageId, fileIds) {
try {
const taskParams = {
title,
description: TRANSLATED_CONNECTOR_DESCRIPTION,
languageId,
type: 2, // Translation by vendor
workflowStepId: 78, // Translation step ID
skipAssignedStrings: true,
fileIds,
};
console.log(`Creating Crowdin task: "${title}" for language ${languageId}`);
const response = await tasksApi.addTask(PROJECT_ID, taskParams);
console.log(`Task created successfully! Task ID: ${response.data.id}`);
return response.data;
} catch (error) {
console.error('Failed to create Crowdin task: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
@@ -0,0 +1,110 @@
import crowdinImport from '@crowdin/crowdin-api-client';
const TRANSLATED_CONNECTOR_DESCRIPTION = '{{tos_service_type: premium}}';
const TRANSLATE_BY_VENDOR_WORKFLOW_TYPE = 'TranslateByVendor'
// TODO Remove this type assertion when https://github.com/crowdin/crowdin-api-client-js/issues/508 is fixed
// @ts-expect-error
const crowdin = crowdinImport.default as typeof crowdinImport;
const API_TOKEN = process.env.CROWDIN_PERSONAL_TOKEN;
if (!API_TOKEN) {
console.error('Error: CROWDIN_PERSONAL_TOKEN environment variable is not set');
process.exit(1);
}
const PROJECT_ID = process.env.CROWDIN_PROJECT_ID ? parseInt(process.env.CROWDIN_PROJECT_ID, 10) : undefined;
if (!PROJECT_ID) {
console.error('Error: CROWDIN_PROJECT_ID environment variable is not set');
process.exit(1);
}
const credentials = {
token: API_TOKEN,
organization: 'grafana'
};
const { tasksApi, projectsGroupsApi, sourceFilesApi, workflowsApi } = new crowdin(credentials);
const languages = await getLanguages(PROJECT_ID);
const fileIds = await getFileIds(PROJECT_ID);
const workflowStepId = await getWorkflowStepId(PROJECT_ID);
for (const language of languages) {
const { name, id } = language;
await createTask(PROJECT_ID, `Translate to ${name}`, id, fileIds, workflowStepId);
}
async function getLanguages(projectId: number) {
try {
const project = await projectsGroupsApi.getProject(projectId);
const languages = project.data.targetLanguages;
console.log('Fetched languages successfully!');
return languages;
} catch (error) {
console.error('Failed to fetch languages: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
async function getFileIds(projectId: number) {
try {
const response = await sourceFilesApi.listProjectFiles(projectId);
const files = response.data;
const fileIds = files.map(file => file.data.id);
console.log('Fetched file ids successfully!');
return fileIds;
} catch (error) {
console.error('Failed to fetch file IDs: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
async function getWorkflowStepId(projectId: number) {
try {
const response = await workflowsApi.listWorkflowSteps(projectId);
const workflowSteps = response.data;
const workflowStepId = workflowSteps.find(step => step.data.type === TRANSLATE_BY_VENDOR_WORKFLOW_TYPE)?.data.id;
if (!workflowStepId) {
throw new Error(`Workflow step with type "${TRANSLATE_BY_VENDOR_WORKFLOW_TYPE}" not found`);
}
console.log('Fetched workflow step ID successfully!');
return workflowStepId;
} catch (error) {
console.error('Failed to fetch workflow step ID: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
async function createTask(projectId: number, title: string, languageId: string, fileIds: number[], workflowStepId: number) {
try {
const taskParams = {
title,
description: TRANSLATED_CONNECTOR_DESCRIPTION,
languageId,
workflowStepId,
skipAssignedStrings: true,
fileIds,
};
console.log(`Creating Crowdin task: "${title}" for language ${languageId}`);
const response = await tasksApi.addTask(projectId, taskParams);
console.log(`Task created successfully! Task ID: ${response.data.id}`);
return response.data;
} catch (error) {
console.error('Failed to create Crowdin task: ', error.message);
if (error.response && error.response.data) {
console.error('Error details: ', JSON.stringify(error.response.data, null, 2));
}
process.exit(1);
}
}
+29
View File
@@ -0,0 +1,29 @@
name: Shellcheck
on:
push:
branches:
- main
- release-*.*.*
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
shellcheck:
name: Shellcheck scripts
runs-on: ubuntu-latest
permissions:
contents: read # clone the repository
steps:
- name: Clone repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Run Shellcheck
run: find scripts/ -name '*.sh' -type f -exec shellcheck -e SC1071 -e SC2162 '{}' +
+10 -20
View File
@@ -1,15 +1,15 @@
name: Add issues and PRs to Skye project board
name: Add issues to Skye project board
on:
workflow_dispatch:
inputs:
manual_issue_number:
description: 'Issue/PR number to add to project'
description: 'Issue to add to project'
required: false
type: number
# Ideally we could trigger this for PRs as well, but getting the secrets on that is tricky
# so we just won't bother for now
issues:
types: [opened]
pull_request:
types: [opened]
permissions:
contents: read
@@ -47,26 +47,16 @@ jobs:
app_id: ${{ env.GH_APP_ID }}
private_key: ${{ env.GH_APP_PEM }}
# Check if the user is in the list from the secret
# We do the check in the Github Actions expression and then export it to the output
# to reuse it
- name: Check if user is allowed
id: check_user
env:
ALLOWED_USERS: ${{ env.ALLOWED_USERS }}
USERNAME: ${{ github.event.sender.login }}
USER_IS_ALLOWED: ${{ contains(fromJSON(env.ALLOWED_USERS), github.event.sender.login) }}
run: |
# Convert the comma-separated list to an array
IFS=',' read -ra ALLOWED_USERS <<< "$ALLOWED_USERS"
echo "user_allowed=${USER_IS_ALLOWED}" >> "$GITHUB_OUTPUT"
# Check if user is in the allowed list
for allowed_user in "${ALLOWED_USERS[@]}"; do
if [ "$allowed_user" = "$USERNAME" ]; then
echo "user_allowed=true" >> $GITHUB_OUTPUT
exit 0
fi
done
echo "user_allowed=false" >> $GITHUB_OUTPUT
# Convert the issue/PR number to a node ID for the GraphQL API
# Convert the issue to a node ID for the GraphQL API
- name: Get node ID for item
if: steps.check_user.outputs.user_allowed == 'true'
id: get_node_id
@@ -88,7 +78,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
# Finally, add the issue/PR to the project board
# Finally, add the issue to the project board
- name: Add to project board
if: steps.check_user.outputs.user_allowed == 'true'
uses: octokit/graphql-action@51bf543c240dcd14761320e2efc625dc32ec0d32
+9 -5
View File
@@ -14,26 +14,30 @@ on:
- '!docs/**'
- '!*.md'
permissions: {}
jobs:
verify-storybook:
name: Verify Storybook
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: 'package.json'
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run Storybook and E2E tests
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f
with:
+51
View File
@@ -0,0 +1,51 @@
name: Swagger generated code
on:
push:
branches:
- main
- release-*.*.*
pull_request:
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
verify:
name: Verify committed API specs match
runs-on: ubuntu-latest
if: ${{ github.repository == 'grafana/grafana' }}
permissions:
contents: read # clone the repository
id-token: write # required for Vault access
steps:
# Set up repository clone
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Setup Enterprise
if: ${{ github.event.pull_request.head.repo.fork == false }}
uses: ./.github/actions/setup-enterprise
with:
github-app-name: 'grafana-ci-bot'
- name: Generate Swagger specs
run: make swagger-clean && make openapi3-gen
- name: Check for changes
run: |
git add -f public/api-merged.json public/openapi3.json
if [ -z "$(git diff --name-only --cached)" ]; then
echo "No changes detected in API specs."
else
echo "Changes detected in API specs. Please review the changes."
echo "You can regenerate them locally with: make swagger-clean && make openapi3-gen"
exit 1
fi
+1
View File
@@ -8,6 +8,7 @@ on:
push:
branches:
- main
- release-*.*.*
paths:
- go.*
- .github/workflows/trivy-scan.yml
+35
View File
@@ -0,0 +1,35 @@
name: Trufflehog
on:
pull_request:
types:
- opened
- synchronize
- reopened
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
trufflehog:
name: Run Trufflehog
runs-on: ubuntu-latest
permissions:
contents: read # clone the repo
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.head_ref }}
- name: Trufflehog
uses: trufflesecurity/trufflehog@90190deac64289cb10bb694894be8db9ead8790b # v3.88.29
with:
base: ${{ github.event.pull_request.base.sha }}
head: ${{ github.event.pull_request.head.sha }}
extra_args: --results=verified
+1 -1
View File
@@ -2,7 +2,7 @@ name: "verify-kinds"
on:
pull_request:
branches: [ main ]
branches: [ main, release-* ]
paths:
- '**/*.cue'