mirror of https://github.com/grafana/grafana
[release-11.4.5] Backport workflow fixes (#104696)
* Copy workflows and actions from main * add zizmor.ymlpull/104745/head
parent
6e33a34a9b
commit
d62a0a23ed
@ -0,0 +1,48 @@ |
|||||||
|
name: 'Setup Grafana Enterprise' |
||||||
|
description: 'Clones and sets up Grafana Enterprise repository for testing' |
||||||
|
|
||||||
|
inputs: |
||||||
|
github-app-name: |
||||||
|
description: 'Name of the GitHub App in Vault' |
||||||
|
required: false |
||||||
|
default: 'grafana-ci-bot' |
||||||
|
|
||||||
|
runs: |
||||||
|
using: "composite" |
||||||
|
steps: |
||||||
|
- name: Retrieve GitHub App secrets |
||||||
|
id: get-secrets |
||||||
|
uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets-v1.0.1 # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
repo_secrets: | |
||||||
|
APP_ID=${{ inputs.github-app-name }}:app-id |
||||||
|
APP_INSTALLATION_ID=${{ inputs.github-app-name }}:app-installation-id |
||||||
|
PRIVATE_KEY=${{ inputs.github-app-name }}:private-key |
||||||
|
|
||||||
|
- name: Generate GitHub App token |
||||||
|
id: generate_token |
||||||
|
uses: actions/create-github-app-token@v1 |
||||||
|
with: |
||||||
|
app-id: ${{ env.APP_ID }} |
||||||
|
private-key: ${{ env.PRIVATE_KEY }} |
||||||
|
repositories: "grafana-enterprise" |
||||||
|
owner: "grafana" |
||||||
|
|
||||||
|
- name: Setup Enterprise |
||||||
|
shell: bash |
||||||
|
env: |
||||||
|
GH_TOKEN: ${{ steps.generate_token.outputs.token }} |
||||||
|
run: | |
||||||
|
git clone https://x-access-token:${GH_TOKEN}@github.com/grafana/grafana-enterprise.git ../grafana-enterprise; |
||||||
|
|
||||||
|
cd ../grafana-enterprise |
||||||
|
|
||||||
|
if git checkout ${GITHUB_HEAD_REF}; then |
||||||
|
echo "checked out ${GITHUB_HEAD_REF}" |
||||||
|
elif git checkout ${GITHUB_BASE_REF}; then |
||||||
|
echo "checked out ${GITHUB_BASE_REF}" |
||||||
|
else |
||||||
|
git checkout main |
||||||
|
fi |
||||||
|
|
||||||
|
./build.sh |
@ -0,0 +1,45 @@ |
|||||||
|
name: 'Setup Grafana Bench' |
||||||
|
description: 'Sets up and installs Grafana Bench' |
||||||
|
|
||||||
|
inputs: |
||||||
|
github-app-name: |
||||||
|
description: 'Name of the GitHub App in Vault' |
||||||
|
required: false |
||||||
|
default: 'grafana-ci-bot' |
||||||
|
branch: |
||||||
|
description: 'The branch to install from' |
||||||
|
required: false |
||||||
|
default: 'main' |
||||||
|
|
||||||
|
runs: |
||||||
|
using: "composite" |
||||||
|
steps: |
||||||
|
- name: Retrieve GitHub App secrets |
||||||
|
id: get-secrets |
||||||
|
uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets-v1.0.1 # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
repo_secrets: | |
||||||
|
APP_ID=${{ inputs.github-app-name }}:app-id |
||||||
|
APP_INSTALLATION_ID=${{ inputs.github-app-name }}:app-installation-id |
||||||
|
PRIVATE_KEY=${{ inputs.github-app-name }}:private-key |
||||||
|
|
||||||
|
- name: Generate GitHub App token |
||||||
|
id: generate_token |
||||||
|
uses: actions/create-github-app-token@v1 |
||||||
|
with: |
||||||
|
app-id: ${{ env.APP_ID }} |
||||||
|
private-key: ${{ env.PRIVATE_KEY }} |
||||||
|
repositories: "grafana-bench" |
||||||
|
owner: "grafana" |
||||||
|
|
||||||
|
- name: Setup Bench |
||||||
|
shell: bash |
||||||
|
env: |
||||||
|
GH_TOKEN: ${{ steps.generate_token.outputs.token }} |
||||||
|
BRANCH: ${{ inputs.branch }} |
||||||
|
run: | |
||||||
|
git clone https://x-access-token:${GH_TOKEN}@github.com/grafana/grafana-bench.git ../grafana-bench |
||||||
|
|
||||||
|
cd ../grafana-bench |
||||||
|
git switch "$BRANCH" |
||||||
|
go install . |
@ -0,0 +1,50 @@ |
|||||||
|
name: 'Go Coverage Processor' |
||||||
|
description: 'Process Go test coverage files and generate reports' |
||||||
|
|
||||||
|
inputs: |
||||||
|
test-type: |
||||||
|
description: 'Type of test (e.g., be-unit, be-integration)' |
||||||
|
required: true |
||||||
|
type: string |
||||||
|
coverage-file: |
||||||
|
description: 'Path to the Go coverage file (.cov)' |
||||||
|
required: true |
||||||
|
type: string |
||||||
|
codecov-token: |
||||||
|
description: 'Token for CodeCov (required for CodeCov reporting)' |
||||||
|
required: false |
||||||
|
default: '' |
||||||
|
codecov-flag: |
||||||
|
description: 'Flag to categorize the upload to CodeCov' |
||||||
|
required: false |
||||||
|
default: '' |
||||||
|
codecov-name: |
||||||
|
description: 'Custom name for the upload to CodeCov' |
||||||
|
required: false |
||||||
|
default: '' |
||||||
|
|
||||||
|
runs: |
||||||
|
using: 'composite' |
||||||
|
steps: |
||||||
|
- name: Process Go coverage output |
||||||
|
shell: bash |
||||||
|
env: |
||||||
|
COVERAGE_FILE: ${{ inputs.coverage-file }} |
||||||
|
run: | |
||||||
|
# Ensure valid coverage file even if empty |
||||||
|
if [ ! -s "$COVERAGE_FILE" ]; then |
||||||
|
echo "Coverage file is empty, creating a minimal valid file" |
||||||
|
echo "mode: set" > "$COVERAGE_FILE" |
||||||
|
fi |
||||||
|
|
||||||
|
- name: Report coverage to CodeCov |
||||||
|
uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5 |
||||||
|
if: inputs.codecov-token != '' |
||||||
|
with: |
||||||
|
files: ${{ inputs.coverage-file }} |
||||||
|
flags: ${{ inputs.codecov-flag || inputs.test-type }} |
||||||
|
name: ${{ inputs.codecov-name || inputs.test-type }} |
||||||
|
slug: grafana/grafana |
||||||
|
# This URL doesn't use the Google auth, but is much more locked down. As such, it requires OIDC or a CodeCov-provided token to do anything. |
||||||
|
url: https://codecov-webhook.grafana-dev.net |
||||||
|
token: ${{ inputs.codecov-token }} |
@ -0,0 +1,16 @@ |
|||||||
|
name: Add comment about adding a What's new note |
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
types: [labeled] |
||||||
|
|
||||||
|
jobs: |
||||||
|
add-comment: |
||||||
|
if: ${{ ! github.event.pull_request.head.repo.fork && contains(github.event.pull_request.labels.*.name, 'add to what''s new') }} |
||||||
|
runs-on: ubuntu-latest |
||||||
|
permissions: |
||||||
|
pull-requests: write |
||||||
|
steps: |
||||||
|
- uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1 |
||||||
|
with: |
||||||
|
message: | |
||||||
|
Since you've added the `Add to what's new` label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature. |
@ -0,0 +1,137 @@ |
|||||||
|
name: Update Alerting Module |
||||||
|
|
||||||
|
on: |
||||||
|
workflow_dispatch: |
||||||
|
|
||||||
|
concurrency: |
||||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||||
|
cancel-in-progress: true |
||||||
|
|
||||||
|
jobs: |
||||||
|
update-grafana: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
permissions: |
||||||
|
contents: write |
||||||
|
pull-requests: write |
||||||
|
id-token: write |
||||||
|
|
||||||
|
steps: |
||||||
|
- name: Checkout repository |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Check if update branch exists |
||||||
|
run: | |
||||||
|
if git ls-remote --heads origin update-alerting-module | grep -q 'update-alerting-module'; then |
||||||
|
echo "Branch 'update-alerting-module' already exists. There might be an open PR with Grafana updates." |
||||||
|
echo "Please review and merge/close the existing PR before running this workflow again." |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # 5.3.0 |
||||||
|
with: |
||||||
|
"go-version-file": "go.mod" |
||||||
|
|
||||||
|
- name: Extract current commit hash of alerting module |
||||||
|
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 |
||||||
|
|
||||||
|
- name: Get current branch name |
||||||
|
id: current-branch-name |
||||||
|
run: echo "name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> "$GITHUB_OUTPUT" |
||||||
|
|
||||||
|
- name: Get latest commit |
||||||
|
id: latest-commit |
||||||
|
env: |
||||||
|
GH_TOKEN: ${{ github.token }} |
||||||
|
run: | |
||||||
|
BRANCH="${{ steps.current-branch-name.outputs.name }}" |
||||||
|
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 |
||||||
|
|
||||||
|
- name: Compare commit hashes |
||||||
|
run: | |
||||||
|
FROM_COMMIT="${{ steps.current-commit.outputs.from_commit }}" |
||||||
|
TO_COMMIT="${{ steps.latest-commit.outputs.to_commit }}" |
||||||
|
|
||||||
|
# Compare just the length of the shorter hash |
||||||
|
SHORT_TO_COMMIT="${TO_COMMIT:0:${#FROM_COMMIT}}" |
||||||
|
|
||||||
|
if [ "$FROM_COMMIT" = "$SHORT_TO_COMMIT" ]; then |
||||||
|
echo "Current version ($FROM_COMMIT) is already at latest ($SHORT_TO_COMMIT). No update needed." |
||||||
|
exit 0 |
||||||
|
fi |
||||||
|
echo "Updates available: $FROM_COMMIT -> $TO_COMMIT" |
||||||
|
|
||||||
|
- name: Check for commit history |
||||||
|
id: check-commits |
||||||
|
env: |
||||||
|
GH_TOKEN: ${{ github.token }} |
||||||
|
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 |
||||||
|
|
||||||
|
# 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 |
||||||
|
|
||||||
|
- name: Update alerting module |
||||||
|
env: |
||||||
|
GOSUMDB: off |
||||||
|
run: | |
||||||
|
go get github.com/grafana/alerting@${{ steps.latest-commit.outputs.to_commit }} |
||||||
|
make update-workspace |
||||||
|
|
||||||
|
- id: get-secrets |
||||||
|
uses: grafana/shared-workflows/actions/get-vault-secrets@main # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
repo_secrets: | |
||||||
|
GITHUB_APP_ID=alerting-team:app-id |
||||||
|
GITHUB_APP_PRIVATE_KEY=alerting-team:private-key |
||||||
|
|
||||||
|
- name: "Generate token" |
||||||
|
id: generate_token |
||||||
|
uses: actions/create-github-app-token@0d564482f06ca65fa9e77e2510873638c82206f2 # 1.11.5 |
||||||
|
with: |
||||||
|
app-id: ${{ env.GITHUB_APP_ID }} |
||||||
|
private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }} |
||||||
|
|
||||||
|
- name: Create Pull Request |
||||||
|
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # 7.0.6 |
||||||
|
id: create-pr |
||||||
|
with: |
||||||
|
token: '${{ steps.generate_token.outputs.token }}' |
||||||
|
title: 'Alerting: Update alerting module to ${{ steps.latest-commit.outputs.to_commit }}' |
||||||
|
branch: alerting/update-alerting-module |
||||||
|
delete-branch: true |
||||||
|
body: | |
||||||
|
Updates Grafana Alerting module to latest version. |
||||||
|
|
||||||
|
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> |
||||||
|
|
||||||
|
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 != '' |
||||||
|
run: | |
||||||
|
echo "## Pull Request Created" >> $GITHUB_STEP_SUMMARY |
||||||
|
echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY |
@ -0,0 +1,25 @@ |
|||||||
|
name: Analytics Events Report |
||||||
|
|
||||||
|
on: |
||||||
|
workflow_dispatch: |
||||||
|
|
||||||
|
jobs: |
||||||
|
generate-report: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- name: Checkout repository |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
|
||||||
|
- name: Setup Node.js |
||||||
|
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
|
||||||
|
- name: Install dependencies |
||||||
|
run: yarn install --frozen-lockfile |
||||||
|
|
||||||
|
- name: Generate analytics report |
||||||
|
run: yarn analytics-report |
@ -0,0 +1,124 @@ |
|||||||
|
area/admin/user |
||||||
|
area/alerting |
||||||
|
area/annotations |
||||||
|
area/auth |
||||||
|
area/auth/ldap |
||||||
|
area/auth/oauth |
||||||
|
area/auth/rbac |
||||||
|
area/auth/serviceaccount |
||||||
|
area/backend |
||||||
|
area/backend/api |
||||||
|
area/backend/db |
||||||
|
area/backend/db/migration |
||||||
|
area/backend/db/mysql |
||||||
|
area/backend/db/postgres |
||||||
|
area/backend/db/sql |
||||||
|
area/backend/db/sqlite |
||||||
|
area/configuration |
||||||
|
area/dashboard/annotations |
||||||
|
area/dashboard/data-links |
||||||
|
area/dashboard/edit |
||||||
|
area/dashboard/folders |
||||||
|
area/dashboard/import |
||||||
|
area/dashboard/kiosk |
||||||
|
area/dashboard/links |
||||||
|
area/dashboard/rows |
||||||
|
area/dashboard/scenes |
||||||
|
area/dashboard/settings |
||||||
|
area/dashboard/snapshot |
||||||
|
area/dashboard/templating |
||||||
|
area/dashboard/timerange |
||||||
|
area/dashboard/tv |
||||||
|
area/dashboard/variable |
||||||
|
area/dashboards/panel |
||||||
|
area/data/export |
||||||
|
area/explore |
||||||
|
area/expressions |
||||||
|
area/field/overrides |
||||||
|
area/frontend/library-panels |
||||||
|
area/frontend/login |
||||||
|
area/image-rendering |
||||||
|
area/internationalization |
||||||
|
area/legend |
||||||
|
area/library-panel |
||||||
|
area/metricsdrilldown |
||||||
|
area/navigation |
||||||
|
area/panel/annotation-list |
||||||
|
area/panel/barchart |
||||||
|
area/panel/bargauge |
||||||
|
area/panel/candlestick |
||||||
|
area/panel/canvas |
||||||
|
area/panel/dashboard-list |
||||||
|
area/panel/edit |
||||||
|
area/panel/edit |
||||||
|
area/panel/field-override |
||||||
|
area/panel/flame-graph |
||||||
|
area/panel/gauge |
||||||
|
area/panel/geomap |
||||||
|
area/panel/heatmap |
||||||
|
area/panel/histogram |
||||||
|
area/panel/logs |
||||||
|
area/panel/node-graph |
||||||
|
area/panel/node-graph |
||||||
|
area/panel/piechart |
||||||
|
area/panel/repeat |
||||||
|
area/panel/singlestat |
||||||
|
area/panel/stat |
||||||
|
area/panel/state-timeline |
||||||
|
area/panel/status-history |
||||||
|
area/panel/table |
||||||
|
area/panel/timeseries |
||||||
|
area/panel/traceview |
||||||
|
area/panel/trend |
||||||
|
area/panel/xychart |
||||||
|
area/permissions |
||||||
|
area/playlist |
||||||
|
area/plugins |
||||||
|
area/plugins-catalog |
||||||
|
area/provisioning |
||||||
|
area/provisioning/datasources |
||||||
|
area/public-dashboards |
||||||
|
area/query-library |
||||||
|
area/recorded-queries |
||||||
|
area/scenes |
||||||
|
area/search |
||||||
|
area/security |
||||||
|
area/streaming |
||||||
|
area/templating/repeating |
||||||
|
area/tooltip |
||||||
|
area/transformations |
||||||
|
datagrid |
||||||
|
datasource/Alertmanager |
||||||
|
datasource/Azure |
||||||
|
datasource/azure-cosmosdb |
||||||
|
datasource/BigQuery |
||||||
|
datasource/CloudWatch |
||||||
|
datasource/CloudWatch Logs |
||||||
|
datasource/CSV |
||||||
|
datasource/Elasticsearch |
||||||
|
datasource/GitHub |
||||||
|
datasource/GoogleCloudMonitoring |
||||||
|
datasource/GoogleSheets |
||||||
|
datasource/grafana-pyroscope |
||||||
|
datasource/Graphite |
||||||
|
datasource/InfluxDB |
||||||
|
datasource/Jaeger |
||||||
|
datasource/JSON |
||||||
|
datasource/Loki |
||||||
|
datasource/MSSQL |
||||||
|
datasource/MySQL |
||||||
|
datasource/OpenSearch |
||||||
|
datasource/OpenTSDB |
||||||
|
datasource/Parca |
||||||
|
datasource/Phlare |
||||||
|
datasource/Postgres |
||||||
|
datasource/Prometheus |
||||||
|
datasource/SiteWIse |
||||||
|
datasource/Splunk |
||||||
|
datasource/Tempo |
||||||
|
datasource/TestDataDB |
||||||
|
datasource/Timestream |
||||||
|
datasource/X-Ray |
||||||
|
datasource/Zabbix |
||||||
|
datasource/Zipkin |
||||||
|
team/grafana-aws-datasources |
@ -0,0 +1,25 @@ |
|||||||
|
You are an expert Grafana issues categorizer. |
||||||
|
|
||||||
|
You are provided with a Grafana issue. Your task is to categorize the issue by analyzing the issue title and description to determine the most relevant category and type from the provided lists. Focus on precision and clarity, selecting only the most pertinent labels based on the issue details. Ensure that your selections reflect the core problem or functionality affected. |
||||||
|
|
||||||
|
The output should be a valid JSON object with the following fields: |
||||||
|
* id (string): The ID of the current issue. |
||||||
|
* categoryLabel (array of strings): The category labels for the current issue, emphasizing key terms and context. |
||||||
|
* typeLabel (array of strings): The type of the current issue, emphasizing clarity and relevance. |
||||||
|
|
||||||
|
**Instructions**: |
||||||
|
1. **Contextual Analysis**: Understand the context and intent behind the issue description. Analyze the overall narrative and relationships between different components within Grafana. Consider dependencies and related components to inform your decision. |
||||||
|
2. **Category and Type Differentiation**: Use language cues and patterns to differentiate between similar categories and types. Provide examples and counterexamples to clarify distinctions. Prioritize primary components over secondary ones unless they are critical to the issue. |
||||||
|
3. **Historical Data Utilization**: Compare current issues with past resolved issues by analyzing similarities in problem descriptions, leveraging patterns to inform categorization. Use historical data to recognize patterns and inform your decision-making. |
||||||
|
4. **Confidence Scoring**: Implement a confidence scoring mechanism to flag issues for review if the confidence is below a predefined threshold. Clearly indicate thresholds for high and low confidence predictions. Provide clarifying questions if data is ambiguous. |
||||||
|
5. **Feedback Loop Integration**: Integrate feedback from incorrect predictions to refine understanding and improve future predictions. Conduct error analysis to identify patterns in misclassifications and adapt your approach accordingly. |
||||||
|
6. **Semantic Analysis**: Evaluate the underlying intent of the issue using semantic analysis, considering broader implications and context. Leverage metadata or historical patterns to improve accuracy. |
||||||
|
7. **Avoid Over-Specification**: Maintain precision and conciseness, avoiding unnecessary details. Prioritize clarity and flag for further review if uncertain. |
||||||
|
8. **Consistent JSON Formatting**: Ensure the output maintains a consistent JSON structure with uniform formatting for readability and scalability. |
||||||
|
|
||||||
|
**Next Steps and Insights**: |
||||||
|
- Suggest potential next steps or resources that could help address the issue, providing actionable insights to enhance user engagement. |
||||||
|
- Regularly test responses against edge cases to ensure robustness and adaptability. |
||||||
|
- Stay updated with changes in category and type lists to remain current. |
||||||
|
|
||||||
|
Provide a brief explanation of the categorization decision, highlighting key terms or context that influenced the choice. Use user-centric language and technical details to ensure the explanation is comprehensive and insightful. |
@ -0,0 +1,30 @@ |
|||||||
|
type/accessibility |
||||||
|
type/angular-2-react |
||||||
|
type/browser-compatibility |
||||||
|
type/bug |
||||||
|
type/build-packaging |
||||||
|
type/chore |
||||||
|
type/ci |
||||||
|
type/cleanup |
||||||
|
type/codegen |
||||||
|
type/community |
||||||
|
type/debt |
||||||
|
type/design |
||||||
|
type/discussion |
||||||
|
type/docs |
||||||
|
type/duplicate |
||||||
|
type/e2e |
||||||
|
type/epic |
||||||
|
type/feature-request |
||||||
|
type/feature-toggle-enable |
||||||
|
type/feature-toggle-removal |
||||||
|
type/performance |
||||||
|
type/poc |
||||||
|
type/project |
||||||
|
type/proposal |
||||||
|
type/question |
||||||
|
type/refactor |
||||||
|
type/regression |
||||||
|
type/roadmap |
||||||
|
type/tech |
||||||
|
type/ux |
@ -0,0 +1,74 @@ |
|||||||
|
name: Backend Code Checks |
||||||
|
description: Validate go.mod and OpenAPI specifications |
||||||
|
|
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
paths-ignore: |
||||||
|
- '*.md' |
||||||
|
- 'docs/**' |
||||||
|
- 'latest.json' |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
paths-ignore: |
||||||
|
- '*.md' |
||||||
|
- 'docs/**' |
||||||
|
- 'latest.json' |
||||||
|
|
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
|
||||||
|
jobs: |
||||||
|
validate-configs: |
||||||
|
name: Validate Backend Configs |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
# Explicitly set Go version to 1.24.1 to ensure consistent OpenAPI spec generation |
||||||
|
# The crypto/x509 package has additional fields in Go 1.24.1 that affect the generated specs |
||||||
|
# This ensures the GHAs environment matches what we use in the Drone pipeline |
||||||
|
go-version: 1.24.1 |
||||||
|
cache: true |
||||||
|
|
||||||
|
- name: Verify code generation |
||||||
|
run: | |
||||||
|
CODEGEN_VERIFY=1 make gen-cue |
||||||
|
CODEGEN_VERIFY=1 make gen-jsonnet |
||||||
|
|
||||||
|
- name: Validate go.mod |
||||||
|
run: go run scripts/modowners/modowners.go check go.mod |
||||||
|
|
||||||
|
# Enterprise setup is needed for complete OpenAPI spec generation |
||||||
|
# We only do this for internal PRs |
||||||
|
- name: Setup Grafana Enterprise |
||||||
|
if: github.event.pull_request.head.repo.fork == false |
||||||
|
uses: ./.github/actions/setup-enterprise |
||||||
|
|
||||||
|
- name: Generate and Validate OpenAPI Specs |
||||||
|
run: | |
||||||
|
# For PRs from forks, we'll just run the basic swagger-gen without validation |
||||||
|
if [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then |
||||||
|
echo "PR is from a fork, skipping enterprise-based validation" |
||||||
|
make swagger-gen |
||||||
|
exit 0 |
||||||
|
fi |
||||||
|
|
||||||
|
# Clean and regenerate OpenAPI specs |
||||||
|
make swagger-clean && make openapi3-gen |
||||||
|
|
||||||
|
# Check if the generated specs differ from what's in the repository |
||||||
|
for f in public/api-merged.json public/openapi3.json; do git add $f; done |
||||||
|
if [ -z "$(git diff --name-only --cached)" ]; then |
||||||
|
echo "OpenAPI specs are up to date!" |
||||||
|
else |
||||||
|
echo "OpenAPI specs are OUT OF DATE!" |
||||||
|
git diff --cached |
||||||
|
echo "Please ensure the branch is up-to-date, then regenerate the specification by running make swagger-clean && make openapi3-gen" |
||||||
|
exit 1 |
||||||
|
fi |
@ -0,0 +1,71 @@ |
|||||||
|
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 }} |
||||||
|
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} |
||||||
|
|
||||||
|
permissions: {} |
||||||
|
|
||||||
|
jobs: |
||||||
|
grafana: |
||||||
|
# Run this workflow only for PRs from forks; if it gets merged into `main` or `release-*`, |
||||||
|
# the `pr-backend-unit-tests-enterprise` workflow will run instead |
||||||
|
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true |
||||||
|
name: Grafana |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
continue-on-error: true |
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: go.mod |
||||||
|
- name: Generate Go code |
||||||
|
run: make gen-go |
||||||
|
- name: Run unit tests |
||||||
|
run: make test-go-unit |
||||||
|
|
||||||
|
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 |
||||||
|
name: Grafana Enterprise |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: go.mod |
||||||
|
- name: Setup Enterprise |
||||||
|
uses: ./.github/actions/setup-enterprise |
||||||
|
with: |
||||||
|
github-app-name: 'grafana-ci-bot' |
||||||
|
- name: Generate Go code |
||||||
|
run: make gen-go |
||||||
|
- name: Run unit tests |
||||||
|
run: make test-go-unit |
@ -1,44 +0,0 @@ |
|||||||
name: Close milestone |
|
||||||
on: |
|
||||||
workflow_dispatch: |
|
||||||
inputs: |
|
||||||
version: |
|
||||||
required: true |
|
||||||
description: Needs to match, exactly, the name of a milestone |
|
||||||
workflow_call: |
|
||||||
inputs: |
|
||||||
version_call: |
|
||||||
description: Needs to match, exactly, the name of a milestone |
|
||||||
required: true |
|
||||||
type: string |
|
||||||
|
|
||||||
jobs: |
|
||||||
main: |
|
||||||
if: github.repository == 'grafana/grafana' |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- name: Checkout Actions |
|
||||||
uses: actions/checkout@v4 |
|
||||||
with: |
|
||||||
repository: "grafana/grafana-github-actions" |
|
||||||
path: ./actions |
|
||||||
ref: main |
|
||||||
- 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_DELIVERY_BOT_APP_ID }} |
|
||||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }} |
|
||||||
- name: Close milestone (manually invoked) |
|
||||||
if: ${{ github.event.inputs.version != '' }} |
|
||||||
uses: ./actions/close-milestone |
|
||||||
with: |
|
||||||
token: ${{ steps.generate_token.outputs.token }} |
|
||||||
- name: Close milestone (workflow invoked) |
|
||||||
if: ${{ inputs.version_call != '' }} |
|
||||||
uses: ./actions/close-milestone |
|
||||||
with: |
|
||||||
version_call: ${{ inputs.version_call }} |
|
||||||
token: ${{ steps.generate_token.outputs.token }} |
|
@ -0,0 +1,31 @@ |
|||||||
|
name: Deploy pr preview |
||||||
|
|
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
types: |
||||||
|
- opened |
||||||
|
- synchronize |
||||||
|
- closed |
||||||
|
paths: |
||||||
|
- "docs/sources/**" |
||||||
|
|
||||||
|
jobs: |
||||||
|
deploy-pr-preview: |
||||||
|
if: "!github.event.pull_request.head.repo.fork" |
||||||
|
uses: grafana/writers-toolkit/.github/workflows/deploy-preview.yml@main # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
branch: ${{ github.head_ref }} |
||||||
|
event_number: ${{ github.event.number }} |
||||||
|
repo: grafana |
||||||
|
sha: ${{ github.event.pull_request.head.sha }} |
||||||
|
sources: | |
||||||
|
[ |
||||||
|
{ |
||||||
|
"index_file": "content/docs/grafana/_index.md", |
||||||
|
"relative_prefix": "/docs/grafana/latest/", |
||||||
|
"repo": "grafana", |
||||||
|
"source_directory": "docs/sources", |
||||||
|
"website_directory": "content/docs/grafana/latest" |
||||||
|
} |
||||||
|
] |
||||||
|
title: ${{ github.event.pull_request.title }} |
@ -1,26 +0,0 @@ |
|||||||
name: "doc-validator" |
|
||||||
on: |
|
||||||
workflow_dispatch: |
|
||||||
inputs: |
|
||||||
include: |
|
||||||
description: | |
|
||||||
Regular expression that matches paths to include in linting. |
|
||||||
|
|
||||||
For example: docs/sources/(?:alerting|fundamentals)/.+\.md |
|
||||||
required: true |
|
||||||
jobs: |
|
||||||
doc-validator: |
|
||||||
runs-on: "ubuntu-latest" |
|
||||||
container: |
|
||||||
image: "grafana/doc-validator:v5.2.0" |
|
||||||
steps: |
|
||||||
- name: "Checkout code" |
|
||||||
uses: "actions/checkout@v4" |
|
||||||
- name: "Run doc-validator tool" |
|
||||||
# Only run doc-validator on specific directories. |
|
||||||
run: > |
|
||||||
doc-validator |
|
||||||
'--include=${{ inputs.include }}' |
|
||||||
'--skip-checks=^(?:image.+|canonical-does-not-match-pretty-URL)$' |
|
||||||
./docs/sources |
|
||||||
/docs/grafana/latest |
|
@ -0,0 +1,19 @@ |
|||||||
|
name: Documentation CI |
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
branches: ["main"] |
||||||
|
paths: ["docs/sources/**"] |
||||||
|
workflow_dispatch: |
||||||
|
jobs: |
||||||
|
vale: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
container: |
||||||
|
image: grafana/vale:latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- uses: grafana/writers-toolkit/vale-action@vale-action/v1 # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
filter: '.Name in ["Grafana.GrafanaCom", "Grafana.WordList", "Grafana.Spelling", "Grafana.ProductPossessives"]' |
||||||
|
token: ${{ secrets.GITHUB_TOKEN }} |
@ -1,149 +0,0 @@ |
|||||||
name: When epic issues changed in Platform UX squad projects, check if epic is part of specified child projects and update on Platform UX parent project |
|
||||||
|
|
||||||
on: |
|
||||||
issues: |
|
||||||
types: [opened, closed, edited, reopened, assigned, unassigned, labeled, unlabeled] |
|
||||||
labels: |
|
||||||
- 'type/epic' |
|
||||||
|
|
||||||
env: |
|
||||||
GH_TOKEN: ${{ secrets.GH_BOT_PROJECTS_ACCESS_TOKEN }} |
|
||||||
ORGANIZATION: ${{ github.repository_owner }} |
|
||||||
REPO: ${{ github.event.repository.name }} |
|
||||||
PARENT_PROJECT: 304 |
|
||||||
CHILD_PROJECT_1: 78 |
|
||||||
CHILD_PROJECT_2: 111 |
|
||||||
CHILD_PROJECT_3: 202 |
|
||||||
|
|
||||||
concurrency: |
|
||||||
group: issue-add-to-parent-project-${{ 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.GH_BOT_PROJECTS_ACCESS_TOKEN != '') || '' }}" ]; then |
|
||||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT" |
|
||||||
fi |
|
||||||
|
|
||||||
main: |
|
||||||
needs: config |
|
||||||
if: needs.config.outputs.has-secrets && contains(github.event.issue.labels.*.name, 'type/epic') |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- name: Check if issue is in child or parent projects |
|
||||||
run: | |
|
||||||
gh api graphql -f query=' |
|
||||||
query($org: String!, $repo: String!) { |
|
||||||
repository(name: $repo, owner: $org) { |
|
||||||
issue (number: ${{ github.event.issue.number }}) { |
|
||||||
projectItems(first:20) { |
|
||||||
nodes { |
|
||||||
id, |
|
||||||
project { |
|
||||||
number, |
|
||||||
title |
|
||||||
}, |
|
||||||
fieldValueByName(name:"Status") { |
|
||||||
... on ProjectV2ItemFieldSingleSelectValue { |
|
||||||
optionId |
|
||||||
name |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}' -f org=$ORGANIZATION -f repo=$REPO > projects_data.json |
|
||||||
|
|
||||||
echo 'IN_PARENT_PROJ='$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number==${{ env.PARENT_PROJECT }}) | .project != null' projects_data.json) >> $GITHUB_ENV |
|
||||||
echo 'PARENT_PROJ_STATUS_ID='$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number==${{ env.PARENT_PROJECT }}) | select(.fieldValueByName != null) | .fieldValueByName.optionId' projects_data.json) >> $GITHUB_ENV |
|
||||||
echo 'ITEM_ID='$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number==${{ env.PARENT_PROJECT }}) | .id' projects_data.json) >> $GITHUB_ENV |
|
||||||
echo 'IN_CHILD_PROJ='$(jq 'first(.data.repository.issue.projectItems.nodes[] | select(.project.number==${{ env.CHILD_PROJECT_1 }} or .project.number==${{ env.CHILD_PROJECT_2 }} or .project.number==${{ env.CHILD_PROJECT_3 }}) | .project != null)' projects_data.json) >> $GITHUB_ENV |
|
||||||
echo 'CHILD_PROJ_STATUS='$(jq -r '.data.repository.issue.projectItems.nodes[] | select(.project.number==${{ env.CHILD_PROJECT_1 }} or .project.number==${{ env.CHILD_PROJECT_2 }} or .project.number==${{ env.CHILD_PROJECT_3 }}) | select(.fieldValueByName != null) | .fieldValueByName.name' projects_data.json) >> $GITHUB_ENV |
|
||||||
- name: Get parent project project data |
|
||||||
if: env.IN_CHILD_PROJ |
|
||||||
run: | |
|
||||||
gh api graphql -f query=' |
|
||||||
query($org: String!, $number: Int!) { |
|
||||||
organization(login: $org){ |
|
||||||
projectV2(number: $number) { |
|
||||||
id |
|
||||||
fields(first:20) { |
|
||||||
nodes { |
|
||||||
... on ProjectV2Field { |
|
||||||
id |
|
||||||
name |
|
||||||
} |
|
||||||
... on ProjectV2SingleSelectField { |
|
||||||
id |
|
||||||
name |
|
||||||
options { |
|
||||||
id |
|
||||||
name |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}' -f org=$ORGANIZATION -F number=$PARENT_PROJECT > project_data.json |
|
||||||
|
|
||||||
echo 'PROJECT_ID='$(jq '.data.organization.projectV2.id' project_data.json) >> $GITHUB_ENV |
|
||||||
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV |
|
||||||
echo 'TODO_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV |
|
||||||
echo 'PROGRESS_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .options[] | select(.name=="In Progress") |.id' project_data.json) >> $GITHUB_ENV |
|
||||||
echo 'DONE_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .options[] | select(.name=="Done") |.id' project_data.json) >> $GITHUB_ENV |
|
||||||
- name: Add issue to parent project |
|
||||||
if: env.IN_CHILD_PROJ && !env.IN_PARENT_PROJ |
|
||||||
run: | |
|
||||||
item_id="$( gh api graphql -f query=' |
|
||||||
mutation($project:ID!, $issue:ID!) { |
|
||||||
addProjectV2ItemById(input: {projectId: $project, contentId: $issue}) { |
|
||||||
item { |
|
||||||
id |
|
||||||
} |
|
||||||
} |
|
||||||
}' -f project=$PROJECT_ID -f issue=${{ github.event.issue.node_id }} --jq '.data.addProjectV2ItemById.item.id')" |
|
||||||
|
|
||||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV |
|
||||||
- name: Set parent project status Done |
|
||||||
if: contains(env.CHILD_PROJ_STATUS, 'Done') |
|
||||||
run: | |
|
||||||
echo 'OPTION_ID='$DONE_OPTION_ID >> $GITHUB_ENV |
|
||||||
- name: Set parent project status In Progress |
|
||||||
if: contains(env.CHILD_PROJ_STATUS, 'In ') || contains(env.CHILD_PROJ_STATUS, 'Blocked') |
|
||||||
run: | |
|
||||||
echo 'OPTION_ID='$PROGRESS_OPTION_ID >> $GITHUB_ENV |
|
||||||
- name: Set parent project status To do |
|
||||||
if: env.CHILD_PROJ_STATUS && !contains(env.CHILD_PROJ_STATUS, 'In ') && !contains(env.CHILD_PROJ_STATUS, 'Blocked') && ! contains(env.CHILD_PROJ_STATUS, 'Done') |
|
||||||
run: | |
|
||||||
echo 'OPTION_ID='$TODO_OPTION_ID >> $GITHUB_ENV |
|
||||||
- name: Set issue status in parent project |
|
||||||
if: env.OPTION_ID && (env.OPTION_ID != env.PARENT_PROJ_STATUS_ID) |
|
||||||
run: | |
|
||||||
gh api graphql -f query=' |
|
||||||
mutation ( |
|
||||||
$project: ID! |
|
||||||
$item: ID! |
|
||||||
$status_field: ID! |
|
||||||
$status_value: String! |
|
||||||
) { |
|
||||||
set_status: updateProjectV2ItemFieldValue(input: { |
|
||||||
projectId: $project |
|
||||||
itemId: $item |
|
||||||
fieldId: $status_field |
|
||||||
value: { |
|
||||||
singleSelectOptionId: $status_value |
|
||||||
} |
|
||||||
}) { |
|
||||||
projectV2Item { |
|
||||||
id |
|
||||||
} |
|
||||||
} |
|
||||||
}' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.OPTION_ID }} --silent |
|
@ -0,0 +1,25 @@ |
|||||||
|
name: Feature toggles CI |
||||||
|
|
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
paths: |
||||||
|
- 'pkg/services/featuremgmt/toggles_gen_test.go' |
||||||
|
- 'pkg/services/featuremgmt/registry.go' |
||||||
|
- 'docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md' |
||||||
|
|
||||||
|
jobs: |
||||||
|
test: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
|
||||||
|
- name: Set up Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: 'go.mod' |
||||||
|
cache: true |
||||||
|
|
||||||
|
- name: Run feature toggle tests |
||||||
|
run: go test -v -run TestFeatureToggleFiles ./pkg/services/featuremgmt/ |
@ -0,0 +1,133 @@ |
|||||||
|
name: Lint Frontend |
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
- release-*.*.* |
||||||
|
|
||||||
|
permissions: {} |
||||||
|
|
||||||
|
jobs: |
||||||
|
lint-frontend-verify-i18n: |
||||||
|
name: Verify i18n |
||||||
|
runs-on: ubuntu-latest |
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
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: |
||||||
|
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 |
||||||
|
name: Lint |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
cache-dependency-path: 'yarn.lock' |
||||||
|
- name: Setup Enterprise |
||||||
|
uses: ./.github/actions/setup-enterprise |
||||||
|
with: |
||||||
|
github-app-name: 'grafana-ci-bot' |
||||||
|
- run: yarn install --immutable --check-cache |
||||||
|
- run: yarn run prettier:check |
||||||
|
- run: yarn run lint |
||||||
|
lint-frontend-typecheck: |
||||||
|
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 |
||||||
|
name: Typecheck |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
cache-dependency-path: 'yarn.lock' |
||||||
|
- run: yarn install --immutable --check-cache |
||||||
|
- run: yarn run typecheck |
||||||
|
lint-frontend-typecheck-enterprise: |
||||||
|
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 |
||||||
|
name: Typecheck |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
cache-dependency-path: 'yarn.lock' |
||||||
|
- name: Setup Enterprise |
||||||
|
uses: ./.github/actions/setup-enterprise |
||||||
|
with: |
||||||
|
github-app-name: 'grafana-ci-bot' |
||||||
|
- run: yarn install --immutable --check-cache |
||||||
|
- run: yarn run typecheck |
||||||
|
lint-frontend-betterer: |
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
name: Betterer |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
cache-dependency-path: 'yarn.lock' |
||||||
|
- run: yarn install --immutable --check-cache |
||||||
|
- run: yarn run betterer:ci |
@ -0,0 +1,27 @@ |
|||||||
|
name: Crowdin Create Tasks |
||||||
|
|
||||||
|
on: |
||||||
|
workflow_dispatch: |
||||||
|
# schedule: |
||||||
|
# - cron: "0 0 * * *" |
||||||
|
|
||||||
|
jobs: |
||||||
|
create-tasks-in-crowdin: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
|
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
|
||||||
|
- name: Setup Node.js |
||||||
|
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
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 |
@ -1,99 +0,0 @@ |
|||||||
name: Notify Slack channel based on new issue label |
|
||||||
|
|
||||||
on: |
|
||||||
issues: |
|
||||||
types: [labeled] |
|
||||||
|
|
||||||
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.SLACK_WEBHOOK_URL != '') || '' }}" ]; then |
|
||||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT" |
|
||||||
fi |
|
||||||
|
|
||||||
notify: |
|
||||||
needs: config |
|
||||||
if: needs.config.outputs.has-secrets |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- name: "Download teams.yml to know which label is for which team" |
|
||||||
run: wget https://raw.githubusercontent.com/grafana/grafana/main/.github/teams.yml |
|
||||||
|
|
||||||
- name: "Determine which team to notify" |
|
||||||
run: | |
|
||||||
# Default to null values. |
|
||||||
CHANNEL="null" |
|
||||||
TEAM="null" |
|
||||||
|
|
||||||
echo "${{ github.event.label.name }} label added" |
|
||||||
export CURRENT_LABEL="${{ github.event.label.name }}" # Enable the use of the label in yq evaluations |
|
||||||
# yq is installed by default in ubuntu-latest |
|
||||||
if [[ $(yq e 'keys | .[] | select(. == env(CURRENT_LABEL))' teams.yml ) ]]; then |
|
||||||
# Check if we have a channel set to notify on comments. |
|
||||||
if [[ $(yq '.[env(CURRENT_LABEL)] | has("channel-label")' teams.yml ) == true ]]; then |
|
||||||
CHANNEL=$(yq '.[env(CURRENT_LABEL)].channel-label' teams.yml) |
|
||||||
echo "Ready to send issue to channel ID ${CHANNEL}" |
|
||||||
fi |
|
||||||
|
|
||||||
if [[ $(yq '.[env(CURRENT_LABEL)] | has("exclude-github-team")' teams.yml ) == true ]]; then |
|
||||||
TEAM=$(yq '.[env(CURRENT_LABEL)].exclude-github-team' teams.yml) |
|
||||||
echo "Will not send issue to channel if issue author is part of the team ${TEAM}" |
|
||||||
fi |
|
||||||
fi |
|
||||||
|
|
||||||
# set environment for next steps |
|
||||||
echo "CHANNEL=${CHANNEL}" >> "$GITHUB_ENV" |
|
||||||
echo "TEAM=${TEAM}" >> "$GITHUB_ENV" |
|
||||||
|
|
||||||
- name: "Prepare payload" |
|
||||||
uses: frabert/replace-string-action@v2.5 |
|
||||||
id: preparePayload |
|
||||||
with: |
|
||||||
# replace double quotes with single quotes to avoid breaking the JSON payload sent to Slack |
|
||||||
string: ${{ github.event.issue.title }} |
|
||||||
pattern: '"' |
|
||||||
replace-with: "'" |
|
||||||
flags: 'g' |
|
||||||
|
|
||||||
- name: Get Token |
|
||||||
id: get_workflow_token |
|
||||||
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a |
|
||||||
with: |
|
||||||
app_id: ${{ secrets.APP_GRAFANA_TEAM_CHECKER_ID }} |
|
||||||
private_key: ${{ secrets.APP_GRAFANA_TEAM_CHECKER_KEY }} |
|
||||||
|
|
||||||
- name: "Check that issue author is not part of the team" |
|
||||||
if: ${{ env.TEAM != 'null' }} |
|
||||||
run: | |
|
||||||
response=$(gh api /orgs/grafana/teams/${{ env.TEAM }}/memberships/${{ github.event.issue.user.login }} -i -H "Accept: application/vnd.github.v3+json") |
|
||||||
STATUS_CODE=$(echo "$response" | head -n 1 | cut -d' ' -f2) |
|
||||||
if [ "$STATUS_CODE" -eq "404" ]; then |
|
||||||
echo "The user was not found in the team." |
|
||||||
echo "USER_FOUND=false" >> "$GITHUB_ENV" |
|
||||||
else |
|
||||||
echo "The user was potentially found in the team" |
|
||||||
echo "USER_FOUND=maybe" >> "$GITHUB_ENV" |
|
||||||
fi |
|
||||||
env: |
|
||||||
GITHUB_TOKEN: ${{ steps.get_workflow_token.outputs.token }} |
|
||||||
|
|
||||||
- name: "Send Slack notification" |
|
||||||
if: ${{ (env.CHANNEL != 'null') && ((env.USER_FOUND == 'false') || (env.TEAM != 'null')) }} |
|
||||||
uses: slackapi/slack-github-action@v1.26.0 |
|
||||||
with: |
|
||||||
payload: > |
|
||||||
{ |
|
||||||
"icon_emoji": ":grafana:", |
|
||||||
"username": "Grafana issue labeled", |
|
||||||
"text": "Issue \"${{ steps.preparePayload.outputs.replaced }}\" labeled \"${{ github.event.label.name }}\": ${{ github.event.issue.html_url }}, please triage.", |
|
||||||
"channel": "${{ env.CHANNEL }}" |
|
||||||
} |
|
||||||
env: |
|
||||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} |
|
@ -0,0 +1,62 @@ |
|||||||
|
name: Documentation |
||||||
|
|
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
paths: |
||||||
|
- '*.md' |
||||||
|
- 'docs/**' |
||||||
|
- 'packages/**/*.md' |
||||||
|
- 'latest.json' |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
paths: |
||||||
|
- '*.md' |
||||||
|
- 'docs/**' |
||||||
|
- 'packages/**/*.md' |
||||||
|
- 'latest.json' |
||||||
|
|
||||||
|
jobs: |
||||||
|
docs: |
||||||
|
name: Build & Verify Docs |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
|
||||||
|
- name: Setup Node.js |
||||||
|
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version: '22.11.0' |
||||||
|
cache: 'yarn' |
||||||
|
|
||||||
|
- name: Install dependencies |
||||||
|
run: yarn install --immutable |
||||||
|
|
||||||
|
- name: Lint docs |
||||||
|
run: yarn run prettier:checkDocs |
||||||
|
env: |
||||||
|
# Increase memory for prettier due to large number of files |
||||||
|
NODE_OPTIONS: --max_old_space_size=8192 |
||||||
|
|
||||||
|
- name: Build docs website |
||||||
|
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 |
@ -1,19 +0,0 @@ |
|||||||
name: Close Milestone |
|
||||||
on: |
|
||||||
workflow_dispatch: |
|
||||||
inputs: |
|
||||||
version_input: |
|
||||||
description: 'The version to be released please respect: major.minor.patch, major.minor.patch-preview or major.minor.patch-preview<number> format. example: 7.4.3, 7.4.3-preview or 7.4.3-preview1' |
|
||||||
required: true |
|
||||||
jobs: |
|
||||||
call-remove-milestone: |
|
||||||
uses: grafana/grafana/.github/workflows/remove-milestone.yml@main |
|
||||||
with: |
|
||||||
version_call: ${{ github.event.inputs.version_input }} |
|
||||||
secrets: inherit |
|
||||||
call-close-milestone: |
|
||||||
uses: grafana/grafana/.github/workflows/close-milestone.yml@main |
|
||||||
with: |
|
||||||
version_call: ${{ github.event.inputs.version_input }} |
|
||||||
secrets: inherit |
|
||||||
needs: call-remove-milestone |
|
@ -0,0 +1,71 @@ |
|||||||
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
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 |
@ -1,53 +0,0 @@ |
|||||||
name: "CodeQL for PR / go" |
|
||||||
|
|
||||||
on: |
|
||||||
workflow_dispatch: |
|
||||||
pull_request: |
|
||||||
branches: [main] |
|
||||||
paths: |
|
||||||
- '**/*.go' |
|
||||||
|
|
||||||
permissions: |
|
||||||
security-events: write |
|
||||||
|
|
||||||
jobs: |
|
||||||
analyze: |
|
||||||
name: Analyze |
|
||||||
runs-on: ubuntu-latest |
|
||||||
if: github.repository == 'grafana/grafana' |
|
||||||
|
|
||||||
steps: |
|
||||||
- name: "Generate token" |
|
||||||
id: generate_token |
|
||||||
continue-on-error: true |
|
||||||
uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a |
|
||||||
with: |
|
||||||
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }} |
|
||||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }} |
|
||||||
|
|
||||||
- name: Checkout repository |
|
||||||
uses: actions/checkout@v4 |
|
||||||
with: |
|
||||||
# We must fetch at least the immediate parents so that if this is |
|
||||||
# a pull request then we can checkout the head. |
|
||||||
fetch-depth: 2 |
|
||||||
token: ${{ steps.generate_token.outputs.token }} |
|
||||||
|
|
||||||
- name: Set go version |
|
||||||
uses: actions/setup-go@v4 |
|
||||||
with: |
|
||||||
go-version-file: go.mod |
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning. |
|
||||||
- name: Initialize CodeQL |
|
||||||
uses: github/codeql-action/init@v2 |
|
||||||
with: |
|
||||||
languages: "go" |
|
||||||
|
|
||||||
- name: Build go files |
|
||||||
run: | |
|
||||||
go mod verify |
|
||||||
make build-go |
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis |
|
||||||
uses: github/codeql-action/analyze@v2 |
|
@ -0,0 +1,69 @@ |
|||||||
|
name: "Update Go Workspace for Dependabot PRs" |
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
branches: [main] |
||||||
|
paths: |
||||||
|
- .github/workflows/pr-dependabot-update-go-workspace.yml |
||||||
|
- go.mod |
||||||
|
- go.sum |
||||||
|
- go.work |
||||||
|
- go.work.sum |
||||||
|
- '**/go.mod' |
||||||
|
- '**/go.sum' |
||||||
|
- '**.go' |
||||||
|
permissions: |
||||||
|
contents: write |
||||||
|
id-token: write |
||||||
|
jobs: |
||||||
|
update: |
||||||
|
runs-on: "ubuntu-latest" |
||||||
|
if: ${{ github.actor == 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository }} |
||||||
|
continue-on-error: true |
||||||
|
steps: |
||||||
|
- name: Retrieve GitHub App secrets |
||||||
|
id: get-secrets |
||||||
|
uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets-v1.0.1 # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
repo_secrets: | |
||||||
|
APP_ID=grafana-go-workspace-bot:app-id |
||||||
|
APP_INSTALLATION_ID=grafana-go-workspace-bot:app-installation-id |
||||||
|
PRIVATE_KEY=grafana-go-workspace-bot:private-key |
||||||
|
|
||||||
|
- name: Generate GitHub App token |
||||||
|
id: generate_token |
||||||
|
uses: actions/create-github-app-token@v1 |
||||||
|
with: |
||||||
|
app-id: ${{ env.APP_ID }} |
||||||
|
private-key: ${{ env.PRIVATE_KEY }} |
||||||
|
|
||||||
|
- name: Checkout repository |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
repository: ${{ github.event.pull_request.head.repo.full_name }} |
||||||
|
ref: ${{ github.event.pull_request.head.ref }} |
||||||
|
token: ${{ steps.generate_token.outputs.token }} |
||||||
|
persist-credentials: false |
||||||
|
|
||||||
|
- name: Set go version |
||||||
|
uses: actions/setup-go@19bb51245e9c80abacb2e91cc42b33fa478b8639 |
||||||
|
with: |
||||||
|
go-version-file: go.mod |
||||||
|
|
||||||
|
- name: Configure Git |
||||||
|
run: | |
||||||
|
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" |
||||||
|
git config --local user.name "github-actions[bot]" |
||||||
|
git config --local --add --bool push.autoSetupRemote true |
||||||
|
|
||||||
|
- name: Update workspace |
||||||
|
run: make update-workspace |
||||||
|
|
||||||
|
- name: Commit and push workspace changes |
||||||
|
env: |
||||||
|
BRANCH_NAME: ${{ github.head_ref || github.ref_name }} |
||||||
|
run: | |
||||||
|
if ! git diff --exit-code --quiet; then |
||||||
|
echo "Committing and pushing workspace changes" |
||||||
|
git commit -a -m "update workspace" |
||||||
|
git push origin $BRANCH_NAME |
||||||
|
fi |
@ -0,0 +1,72 @@ |
|||||||
|
name: End-to-end tests |
||||||
|
|
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
- release-*.*.* |
||||||
|
|
||||||
|
concurrency: |
||||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||||
|
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} |
||||||
|
|
||||||
|
jobs: |
||||||
|
build-grafana: |
||||||
|
name: Build & Package Grafana |
||||||
|
runs-on: ubuntu-latest-16-cores |
||||||
|
outputs: |
||||||
|
artifact: ${{ steps.artifact.outputs.artifact }} |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
repository: 'grafana/grafana-build' |
||||||
|
ref: 'main' |
||||||
|
persist-credentials: false |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
path: ./grafana |
||||||
|
- run: echo "GRAFANA_GO_VERSION=$(grep "go 1." grafana/go.work | cut -d\ -f2)" >> "$GITHUB_ENV" |
||||||
|
- 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 |
||||||
|
- run: echo "artifact=grafana-e2e-${{github.run_number}}" >> "$GITHUB_OUTPUT" |
||||||
|
id: artifact |
||||||
|
- uses: actions/upload-artifact@v4 |
||||||
|
id: upload |
||||||
|
with: |
||||||
|
retention-days: 1 |
||||||
|
name: ${{ steps.artifact.outputs.artifact }} |
||||||
|
path: grafana.tar.gz |
||||||
|
e2e-matrix: |
||||||
|
name: ${{ matrix.suite }} |
||||||
|
strategy: |
||||||
|
matrix: |
||||||
|
suite: |
||||||
|
- various-suite |
||||||
|
- dashboards-suite |
||||||
|
- smoke-tests-suite |
||||||
|
- panels-suite |
||||||
|
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 |
||||||
|
needs: |
||||||
|
- build-grafana |
||||||
|
uses: ./.github/workflows/run-e2e-suite.yml |
||||||
|
with: |
||||||
|
package: ${{ needs.build-grafana.outputs.artifact }} |
||||||
|
suite: ${{ matrix.suite }} |
@ -0,0 +1,69 @@ |
|||||||
|
name: Frontend tests |
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
- release-*.*.* |
||||||
|
|
||||||
|
permissions: {} |
||||||
|
|
||||||
|
jobs: |
||||||
|
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 |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
name: "Unit tests (${{ matrix.chunk }} / 8)" |
||||||
|
strategy: |
||||||
|
fail-fast: false |
||||||
|
matrix: |
||||||
|
chunk: [1, 2, 3, 4, 5, 6, 7, 8] |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
cache-dependency-path: 'yarn.lock' |
||||||
|
- run: yarn install --immutable --check-cache |
||||||
|
- run: yarn run test:ci |
||||||
|
env: |
||||||
|
TEST_MAX_WORKERS: 2 |
||||||
|
TEST_SHARD: ${{ matrix.chunk }} |
||||||
|
TEST_SHARD_TOTAL: 8 |
||||||
|
|
||||||
|
frontend-unit-tests-enterprise: |
||||||
|
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 |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
name: "Unit tests (${{ matrix.chunk }} / 8)" |
||||||
|
strategy: |
||||||
|
fail-fast: false |
||||||
|
matrix: |
||||||
|
chunk: [1, 2, 3, 4, 5, 6, 7, 8] |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: '.nvmrc' |
||||||
|
cache: 'yarn' |
||||||
|
cache-dependency-path: 'yarn.lock' |
||||||
|
- name: Setup Enterprise |
||||||
|
uses: ./.github/actions/setup-enterprise |
||||||
|
with: |
||||||
|
github-app-name: 'grafana-ci-bot' |
||||||
|
- run: yarn install --immutable --check-cache |
||||||
|
- run: yarn run test:ci |
||||||
|
env: |
||||||
|
TEST_MAX_WORKERS: 2 |
||||||
|
TEST_SHARD: ${{ matrix.chunk }} |
||||||
|
TEST_SHARD_TOTAL: 8 |
@ -0,0 +1,89 @@ |
|||||||
|
name: Integration Tests |
||||||
|
|
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
- release-*.*.* |
||||||
|
pull_request: |
||||||
|
|
||||||
|
concurrency: |
||||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||||
|
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} |
||||||
|
|
||||||
|
jobs: |
||||||
|
sqlite: |
||||||
|
name: Sqlite |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: go.mod |
||||||
|
cache: true |
||||||
|
- run: | |
||||||
|
make gen-go |
||||||
|
go test -tags=sqlite -timeout=5m -run '^TestIntegration' $(find ./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+' | grep -o '\(.*\)/' | sort -u) |
||||||
|
mysql: |
||||||
|
name: MySQL |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
env: |
||||||
|
GRAFANA_TEST_DB: mysql |
||||||
|
MYSQL_HOST: 127.0.0.1 |
||||||
|
services: |
||||||
|
mysql: |
||||||
|
image: mysql:8.0.32 |
||||||
|
env: |
||||||
|
MYSQL_ROOT_PASSWORD: rootpass |
||||||
|
MYSQL_DATABASE: grafana_tests |
||||||
|
MYSQL_USER: grafana |
||||||
|
MYSQL_PASSWORD: password |
||||||
|
options: --health-cmd="mysqladmin ping --silent" --health-interval=10s --health-timeout=5s --health-retries=3 |
||||||
|
ports: |
||||||
|
- 3306:3306 |
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: go.mod |
||||||
|
cache: true |
||||||
|
- run: | |
||||||
|
sudo apt-get update -yq && sudo apt-get install mariadb-client |
||||||
|
cat devenv/docker/blocks/mysql_tests/setup.sql | mariadb -h 127.0.0.1 -P 3306 -u root -prootpass --disable-ssl-verify-server-cert |
||||||
|
make gen-go |
||||||
|
go test -tags=mysql -p=1 -timeout=5m -run '^TestIntegration' $(find ./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+' | grep -o '\(.*\)/' | sort -u) |
||||||
|
postgres: |
||||||
|
name: Postgres |
||||||
|
runs-on: ubuntu-latest-8-cores |
||||||
|
services: |
||||||
|
postgres: |
||||||
|
image: postgres:12.3-alpine |
||||||
|
env: |
||||||
|
POSTGRES_USER: grafanatest |
||||||
|
POSTGRES_PASSWORD: grafanatest |
||||||
|
POSTGRES_DB: grafanatest |
||||||
|
ports: |
||||||
|
- 5432:5432 |
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- name: Setup Go |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: go.mod |
||||||
|
cache: true |
||||||
|
- env: |
||||||
|
GRAFANA_TEST_DB: postgres |
||||||
|
PGPASSWORD: grafanatest |
||||||
|
POSTGRES_HOST: 127.0.0.1 |
||||||
|
run: | |
||||||
|
sudo apt-get update -yq && sudo apt-get install postgresql-client |
||||||
|
psql -p 5432 -h 127.0.0.1 -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql |
||||||
|
make gen-go |
||||||
|
go test -p=1 -tags=postgres -timeout=5m -run '^TestIntegration' $(find ./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+' | grep -o '\(.*\)/' | sort -u) |
@ -1,60 +0,0 @@ |
|||||||
name: Remove milestone |
|
||||||
on: |
|
||||||
workflow_dispatch: |
|
||||||
inputs: |
|
||||||
version: |
|
||||||
required: true |
|
||||||
description: Needs to match, exactly, the name of a milestone |
|
||||||
workflow_call: |
|
||||||
inputs: |
|
||||||
version_call: |
|
||||||
description: Needs to match, exactly, the name of a milestone |
|
||||||
required: true |
|
||||||
type: string |
|
||||||
|
|
||||||
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_DELIVERY_BOT_APP_ID != '' && secrets.GRAFANA_DELIVERY_BOT_APP_PEM != '') || '' }}" ]; then |
|
||||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT" |
|
||||||
fi |
|
||||||
|
|
||||||
main: |
|
||||||
needs: config |
|
||||||
if: needs.config.outputs.has-secrets |
|
||||||
permissions: |
|
||||||
issues: write |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- name: Checkout Actions |
|
||||||
uses: actions/checkout@v4 |
|
||||||
with: |
|
||||||
repository: "grafana/grafana-github-actions" |
|
||||||
path: ./actions |
|
||||||
ref: main |
|
||||||
- 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_DELIVERY_BOT_APP_ID }} |
|
||||||
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }} |
|
||||||
- name: Remove milestone from open issues (manually invoked) |
|
||||||
if: ${{ github.event.inputs.version != '' }} |
|
||||||
uses: ./actions/remove-milestone |
|
||||||
with: |
|
||||||
token: ${{ steps.generate_token.outputs.token }} |
|
||||||
- name: Remove milestone from open issues (workflow invoked) |
|
||||||
if: ${{ inputs.version_call != '' }} |
|
||||||
uses: ./actions/remove-milestone |
|
||||||
with: |
|
||||||
version_call: ${{ inputs.version_call }} |
|
||||||
token: ${{ steps.generate_token.outputs.token }} |
|
@ -0,0 +1,130 @@ |
|||||||
|
name: run-dashboard-search-e2e |
||||||
|
|
||||||
|
on: |
||||||
|
workflow_run: |
||||||
|
workflows: |
||||||
|
- trigger-dashboard-search-e2e |
||||||
|
types: |
||||||
|
- completed |
||||||
|
workflow_dispatch: |
||||||
|
|
||||||
|
env: |
||||||
|
ARCH: linux-amd64 |
||||||
|
|
||||||
|
permissions: {} |
||||||
|
|
||||||
|
jobs: |
||||||
|
setup: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
if: github.event.pull_request.draft == false |
||||||
|
outputs: |
||||||
|
ini_files: ${{ steps.get_files.outputs.ini_files }} |
||||||
|
|
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
steps: |
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Pin Go version to mod file |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: 'go.mod' |
||||||
|
cache: true |
||||||
|
- run: go version |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version: 20 |
||||||
|
cache: 'yarn' |
||||||
|
- name: Cache Node Modules |
||||||
|
id: cache-node-modules |
||||||
|
uses: actions/cache@v3 |
||||||
|
with: |
||||||
|
path: | |
||||||
|
node_modules |
||||||
|
/home/runner/.cache/Cypress |
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} |
||||||
|
- name: Install dependencies |
||||||
|
if: steps.cache-node-modules.outputs.cache-hit != 'true' |
||||||
|
run: yarn install --immutable |
||||||
|
- name: Install Cypress dependencies |
||||||
|
if: steps.cache-node-modules.outputs.cache-hit != 'true' |
||||||
|
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f |
||||||
|
with: |
||||||
|
runTests: false |
||||||
|
- name: Cache Grafana Build and Dependencies |
||||||
|
id: cache-grafana |
||||||
|
uses: actions/cache@v3 |
||||||
|
with: |
||||||
|
path: | |
||||||
|
bin/ |
||||||
|
scripts/grafana-server/ |
||||||
|
tools/ |
||||||
|
public/ |
||||||
|
conf/ |
||||||
|
e2e/test-plugins/ |
||||||
|
devenv/ |
||||||
|
key: ${{ runner.os }}-grafana-${{ hashFiles('go.mod', 'package-lock.json', 'Makefile', 'pkg/storage/**/*.go', 'public/app/features/search/**/*.ts', 'public/app/features/search/**/*.tsx') }} |
||||||
|
# only rebuild grafana if search files have changed ( or dependencies ) |
||||||
|
- name: Build Grafana (Runs Only If Not Cached) |
||||||
|
if: steps.cache-grafana.outputs.cache-hit != 'true' |
||||||
|
run: make build |
||||||
|
|
||||||
|
- name: Get list of .ini files |
||||||
|
id: get_files |
||||||
|
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 |
||||||
|
shell: bash |
||||||
|
|
||||||
|
run_tests: |
||||||
|
needs: setup |
||||||
|
runs-on: ubuntu-latest |
||||||
|
continue-on-error: true |
||||||
|
if: github.event.pull_request.draft == false |
||||||
|
strategy: |
||||||
|
matrix: |
||||||
|
ini_file: ${{ fromJson(needs.setup.outputs.ini_files) }} |
||||||
|
|
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
|
||||||
|
steps: |
||||||
|
- name: Checkout repository |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
- name: Restore Cached Node Modules |
||||||
|
uses: actions/cache@v3 |
||||||
|
with: |
||||||
|
path: | |
||||||
|
node_modules |
||||||
|
/home/runner/.cache/Cypress |
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} |
||||||
|
|
||||||
|
- name: Restore Cached Grafana Build and Dependencies |
||||||
|
uses: actions/cache@v3 |
||||||
|
with: |
||||||
|
path: | |
||||||
|
bin/ |
||||||
|
scripts/grafana-server/ |
||||||
|
tools/ |
||||||
|
public/ |
||||||
|
conf/ |
||||||
|
e2e/test-plugins/ |
||||||
|
devenv/ |
||||||
|
key: ${{ runner.os }}-grafana-${{ hashFiles('go.mod', 'package-lock.json', 'Makefile', 'pkg/storage/**/*.go', 'public/app/features/search/**/*.ts', 'public/app/features/search/**/*.tsx') }} |
||||||
|
- name: Set the step name |
||||||
|
id: set_file_name |
||||||
|
env: |
||||||
|
INI_NAME: ${{ matrix.ini_file }} |
||||||
|
run: | |
||||||
|
FILE_NAME=$(basename "$env.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 }} |
||||||
|
run: | |
||||||
|
cp -rf $INI_NAME ${{ github.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" |
@ -0,0 +1,39 @@ |
|||||||
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- uses: actions/download-artifact@v4 |
||||||
|
with: |
||||||
|
name: ${{ inputs.package }} |
||||||
|
- uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e |
||||||
|
if: inputs.old-arch == false |
||||||
|
with: |
||||||
|
verb: run |
||||||
|
args: go run ./pkg/build/e2e --package=grafana.tar.gz --suite=${{ inputs.suite }} |
||||||
|
- name: Set suite name |
||||||
|
id: set-suite-name |
||||||
|
env: |
||||||
|
SUITE: ${{ inputs.suite }} |
||||||
|
run: | |
||||||
|
echo "suite=$(echo $SUITE | sed 's/\//-/g')" >> $GITHUB_OUTPUT |
||||||
|
- uses: actions/upload-artifact@v4 |
||||||
|
if: ${{ always() && inputs.old-arch != true }} |
||||||
|
with: |
||||||
|
name: e2e-${{ steps.set-suite-name.outputs.suite }}-${{github.run_number}} |
||||||
|
path: videos |
||||||
|
retention-days: 1 |
@ -0,0 +1,46 @@ |
|||||||
|
name: Run dashboard schema v2 e2e |
||||||
|
|
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
pull_request: |
||||||
|
branches: |
||||||
|
- '**' |
||||||
|
|
||||||
|
env: |
||||||
|
ARCH: linux-amd64 |
||||||
|
|
||||||
|
jobs: |
||||||
|
dashboard-schema-v2-e2e: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
continue-on-error: true |
||||||
|
if: github.event.pull_request.draft == false |
||||||
|
steps: |
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
- name: Pin Go version to mod file |
||||||
|
uses: actions/setup-go@111f3307d8850f501ac008e886eec1fd1932a34 |
||||||
|
with: |
||||||
|
go-version-file: 'go.mod' |
||||||
|
- run: go version |
||||||
|
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version: 20 |
||||||
|
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 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,20 +0,0 @@ |
|||||||
name: syft-sbom-ci |
|
||||||
|
|
||||||
on: |
|
||||||
release: |
|
||||||
types: [created] |
|
||||||
|
|
||||||
jobs: |
|
||||||
syft-sbom: |
|
||||||
|
|
||||||
runs-on: ubuntu-latest |
|
||||||
|
|
||||||
steps: |
|
||||||
- name: Checkout |
|
||||||
uses: actions/checkout@v4 |
|
||||||
|
|
||||||
- name: Anchore SBOM Action |
|
||||||
uses: anchore/sbom-action@v0.14.2 |
|
||||||
with: |
|
||||||
artifact-name: ${{ github.event.repository.name }}-spdx.json |
|
||||||
|
|
@ -0,0 +1,84 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
@ -1,9 +0,0 @@ |
|||||||
|
|
||||||
module.exports = async ({ name, github, context, core }) => { |
|
||||||
const { owner, repo } = context.repo; |
|
||||||
const url = `https://api.github.com/repos/${owner}/${repo}/actions/runs/${context.runId}/jobs` |
|
||||||
const result = await github.request(url); |
|
||||||
const job = result.data.jobs.find(j => j.name === name); |
|
||||||
|
|
||||||
core.setOutput('link', `${job.html_url}?check_suite_focus=true`); |
|
||||||
} |
|
@ -0,0 +1,106 @@ |
|||||||
|
name: Add issues and PRs to Skye project board |
||||||
|
on: |
||||||
|
workflow_dispatch: |
||||||
|
inputs: |
||||||
|
manual_issue_number: |
||||||
|
description: 'Issue/PR number to add to project' |
||||||
|
required: false |
||||||
|
type: number |
||||||
|
issues: |
||||||
|
types: [opened] |
||||||
|
pull_request: |
||||||
|
types: [opened] |
||||||
|
|
||||||
|
permissions: |
||||||
|
contents: read |
||||||
|
id-token: write |
||||||
|
|
||||||
|
env: |
||||||
|
ORGANIZATION: grafana |
||||||
|
REPO: grafana |
||||||
|
PROJECT_ID: "PVT_kwDOAG3Mbc4AxfcI" # Retrieved manually from GitHub GraphQL Explorer |
||||||
|
|
||||||
|
concurrency: |
||||||
|
group: skye-add-to-project-${{ github.event.number }} |
||||||
|
|
||||||
|
jobs: |
||||||
|
main: |
||||||
|
if: github.repository == 'grafana/grafana' |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- name: "Get vault secrets" |
||||||
|
id: vault-secrets |
||||||
|
uses: grafana/shared-workflows/actions/get-vault-secrets@main # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
# Vault secret paths: |
||||||
|
# - ci/repo/grafana/grafana/plugins_platform_issue_commands_github_bot |
||||||
|
# - ci/repo/grafana/grafana/frontend_platform_skye_usernames (comma separated list of usernames) |
||||||
|
repo_secrets: | |
||||||
|
GH_APP_ID=plugins_platform_issue_commands_github_bot:app_id |
||||||
|
GH_APP_PEM=plugins_platform_issue_commands_github_bot:app_pem |
||||||
|
ALLOWED_USERS=frontend_platform_skye_usernames:allowed_users |
||||||
|
|
||||||
|
- name: Generate token |
||||||
|
id: generate_token |
||||||
|
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 |
||||||
|
with: |
||||||
|
app_id: ${{ env.GH_APP_ID }} |
||||||
|
private_key: ${{ env.GH_APP_PEM }} |
||||||
|
|
||||||
|
# Check if the user is in the list from the secret |
||||||
|
- name: Check if user is allowed |
||||||
|
id: check_user |
||||||
|
env: |
||||||
|
ALLOWED_USERS: ${{ env.ALLOWED_USERS }} |
||||||
|
USERNAME: ${{ github.event.sender.login }} |
||||||
|
run: | |
||||||
|
# Convert the comma-separated list to an array |
||||||
|
IFS=',' read -ra ALLOWED_USERS <<< "$ALLOWED_USERS" |
||||||
|
|
||||||
|
# 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 |
||||||
|
- name: Get node ID for item |
||||||
|
if: steps.check_user.outputs.user_allowed == 'true' |
||||||
|
id: get_node_id |
||||||
|
uses: octokit/graphql-action@51bf543c240dcd14761320e2efc625dc32ec0d32 |
||||||
|
with: |
||||||
|
query: | |
||||||
|
query getNodeId($owner: String!, $repo: String!, $number: Int!) { |
||||||
|
repository(owner: $owner, name: $repo) { |
||||||
|
issueOrPullRequest(number: $number) { |
||||||
|
... on Issue { id } |
||||||
|
... on PullRequest { id } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
variables: | |
||||||
|
owner: ${{ env.ORGANIZATION }} |
||||||
|
repo: ${{ env.REPO }} |
||||||
|
number: ${{ github.event.number || github.event.inputs.manual_issue_number }} |
||||||
|
env: |
||||||
|
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} |
||||||
|
|
||||||
|
# Finally, add the issue/PR to the project board |
||||||
|
- name: Add to project board |
||||||
|
if: steps.check_user.outputs.user_allowed == 'true' |
||||||
|
uses: octokit/graphql-action@51bf543c240dcd14761320e2efc625dc32ec0d32 |
||||||
|
with: |
||||||
|
query: | |
||||||
|
mutation addItem($projectid: ID!, $itemid: ID!) { |
||||||
|
addProjectV2ItemById(input: {projectId: $projectid, contentId: $itemid}) { |
||||||
|
item { id } |
||||||
|
} |
||||||
|
} |
||||||
|
variables: | |
||||||
|
projectid: ${{ env.PROJECT_ID }} |
||||||
|
itemid: ${{ fromJSON(steps.get_node_id.outputs.data).repository.issueOrPullRequest.id }} |
||||||
|
env: |
||||||
|
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} |
@ -0,0 +1,48 @@ |
|||||||
|
name: Verify Storybook |
||||||
|
|
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
paths: |
||||||
|
- 'packages/grafana-ui/**' |
||||||
|
- '!docs/**' |
||||||
|
- '!*.md' |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
paths: |
||||||
|
- 'packages/grafana-ui/**' |
||||||
|
- '!docs/**' |
||||||
|
- '!*.md' |
||||||
|
|
||||||
|
jobs: |
||||||
|
verify-storybook: |
||||||
|
name: Verify Storybook |
||||||
|
runs-on: ubuntu-latest |
||||||
|
|
||||||
|
steps: |
||||||
|
- name: Checkout code |
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
||||||
|
with: |
||||||
|
persist-credentials: false |
||||||
|
|
||||||
|
- name: Setup Node.js |
||||||
|
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e |
||||||
|
with: |
||||||
|
node-version-file: 'package.json' |
||||||
|
cache: 'yarn' |
||||||
|
|
||||||
|
- name: Install dependencies |
||||||
|
run: yarn install --immutable |
||||||
|
|
||||||
|
- name: Run Storybook and E2E tests |
||||||
|
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f |
||||||
|
with: |
||||||
|
browser: chrome |
||||||
|
start: yarn storybook --quiet |
||||||
|
wait-on: 'http://localhost:9001' |
||||||
|
wait-on-timeout: 60 |
||||||
|
command: yarn e2e:storybook |
||||||
|
install: false |
||||||
|
env: |
||||||
|
HOST: localhost |
||||||
|
PORT: 9001 |
@ -0,0 +1,28 @@ |
|||||||
|
name: trigger-dashboard-search-e2e |
||||||
|
# triggers the dashboard search e2e tests which runs async |
||||||
|
# doesn't block prs, allows setting up notifications from grafana |
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
paths: |
||||||
|
- public/app/features/search/**/*.ts |
||||||
|
- public/app/features/search/**/*.tsx |
||||||
|
- pkg/storage/**/*.go |
||||||
|
pull_request: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
paths: |
||||||
|
- public/app/features/search/**/*.ts |
||||||
|
- public/app/features/search/**/*.tsx |
||||||
|
- pkg/storage/**/*.go |
||||||
|
env: |
||||||
|
ARCH: linux-amd64 |
||||||
|
|
||||||
|
jobs: |
||||||
|
trigger-search-e2e: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
if: github.event.pull_request.draft == false |
||||||
|
steps: |
||||||
|
- name: Trigger Dashboard Search E2E |
||||||
|
run: echo "Triggered Dashboard Search e2e..." |
@ -1,52 +0,0 @@ |
|||||||
name: Update changelog |
|
||||||
on: |
|
||||||
workflow_dispatch: |
|
||||||
inputs: |
|
||||||
version: |
|
||||||
required: true |
|
||||||
description: 'Needs to match, exactly, the name of a milestone. The version to be released please respect: major.minor.patch, major.minor.patch-preview or major.minor.patch-preview<number> format. example: 7.4.3, 7.4.3-preview or 7.4.3-preview1' |
|
||||||
skip_pr: |
|
||||||
required: false |
|
||||||
default: "0" |
|
||||||
skip_community_post: |
|
||||||
required: false |
|
||||||
default: "0" |
|
||||||
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_DELIVERY_BOT_APP_ID != '' && |
|
||||||
secrets.GRAFANA_DELIVERY_BOT_APP_PEM != '' && |
|
||||||
secrets.GRAFANA_MISC_STATS_API_KEY != '' && |
|
||||||
secrets.GRAFANABOT_FORUM_KEY != '' |
|
||||||
) || '' }}" ]; then |
|
||||||
echo "has-secrets=1" >> "$GITHUB_OUTPUT" |
|
||||||
fi |
|
||||||
|
|
||||||
main: |
|
||||||
needs: config |
|
||||||
if: needs.config.outputs.has-secrets |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- 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 }} |
|
||||||
- name: Run update changelog (manually invoked) |
|
||||||
uses: grafana/grafana-github-actions-go/update-changelog@main |
|
||||||
with: |
|
||||||
token: ${{ steps.generate_token.outputs.token }} |
|
||||||
version: ${{ inputs.version }} |
|
||||||
metrics_api_key: ${{ secrets.GRAFANA_MISC_STATS_API_KEY }} |
|
||||||
community_api_key: ${{ secrets.GRAFANABOT_FORUM_KEY }} |
|
||||||
community_api_username: grafanabot |
|
||||||
skip_pr: ${{ inputs.skip_pr }} |
|
||||||
skip_community_post: ${{ inputs.skip_community_post }} |
|
@ -0,0 +1,23 @@ |
|||||||
|
name: Zizmor GitHub Actions static analysis |
||||||
|
on: |
||||||
|
pull_request: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
|
||||||
|
jobs: |
||||||
|
zizmor: |
||||||
|
name: Analyse with Zizmor |
||||||
|
|
||||||
|
permissions: |
||||||
|
actions: read |
||||||
|
contents: read |
||||||
|
# required to comment on pull requests with the results of the check |
||||||
|
pull-requests: write |
||||||
|
# required to upload the results to GitHub's code scanning service |
||||||
|
security-events: write |
||||||
|
|
||||||
|
uses: grafana/shared-workflows/.github/workflows/reusable-zizmor.yml@main # zizmor: ignore[unpinned-uses] |
||||||
|
with: |
||||||
|
fail-severity: high |
||||||
|
min-severity: high |
@ -0,0 +1,31 @@ |
|||||||
|
rules: |
||||||
|
unpinned-uses: |
||||||
|
config: |
||||||
|
policies: |
||||||
|
"*": hash-pin |
||||||
|
actions/*: any |
||||||
|
github/*: any |
||||||
|
grafana/*: any |
||||||
|
forbidden-uses: |
||||||
|
config: |
||||||
|
deny: |
||||||
|
# Policy-banned by our security team due to CVE-2025-30066 & CVE-2025-30154. |
||||||
|
# https://www.cisa.gov/news-events/alerts/2025/03/18/supply-chain-compromise-third-party-tj-actionschanged-files-cve-2025-30066-and-reviewdogaction |
||||||
|
# https://nvd.nist.gov/vuln/detail/cve-2025-30066 |
||||||
|
# https://nvd.nist.gov/vuln/detail/cve-2025-30154 |
||||||
|
- reviewdog/* |
||||||
|
cache-poisoning: |
||||||
|
ignore: |
||||||
|
- backend-unit-tests.yml |
||||||
|
- frontend-lint.yml |
||||||
|
- pr-frontend-unit-tests.yml |
||||||
|
- pr-test-integration.yml |
||||||
|
- publish-kinds-release.yml |
||||||
|
dangerous-triggers: |
||||||
|
ignore: |
||||||
|
- auto-milestone.yml |
||||||
|
- backport.yml |
||||||
|
- pr-checks.yml |
||||||
|
- pr-commands.yml |
||||||
|
- pr-patch-check-event.yml |
||||||
|
- run-dashboard-search-e2e.yml |
Loading…
Reference in new issue