Actions: Introduce actionlint (#105224)

This commit is contained in:
Mariell Hoversholm
2025-05-13 08:23:59 +02:00
committed by GitHub
parent 99273f15eb
commit c92ff0ca75
20 changed files with 304 additions and 131 deletions

2
.github/CODEOWNERS vendored
View File

@ -758,6 +758,8 @@ embed.go @grafana/grafana-as-code
/.github/renovate.json5 @grafana/frontend-ops /.github/renovate.json5 @grafana/frontend-ops
/.github/actions/setup-enterprise/action.yml @grafana/grafana-backend-group /.github/actions/setup-enterprise/action.yml @grafana/grafana-backend-group
/.github/actions/setup-grafana-bench/ @Proximyst /.github/actions/setup-grafana-bench/ @Proximyst
/.github/workflows/actionlint-format.txt @Proximyst
/.github/workflows/actionlint.yml @Proximyst
/.github/workflows/add-to-whats-new.yml @grafana/docs-tooling /.github/workflows/add-to-whats-new.yml @grafana/docs-tooling
/.github/workflows/auto-triager/ @grafana/plugins-platform-frontend /.github/workflows/auto-triager/ @grafana/plugins-platform-frontend
/.github/workflows/alerting-swagger-gen.yml @grafana/alerting-backend /.github/workflows/alerting-swagger-gen.yml @grafana/alerting-backend

66
.github/workflows/actionlint-format.txt vendored Normal file
View File

@ -0,0 +1,66 @@
{
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "GitHub Actions lint",
"version": {{ getVersion | json }},
"informationUri": "https://github.com/rhysd/actionlint",
"rules": [
{{$first := true}}
{{range $ := allKinds }}
{{if $first}}{{$first = false}}{{else}},{{end}}
{
"id": {{json $.Name}},
"name": {{$.Name | toPascalCase | json}},
"defaultConfiguration": {
"level": "error"
},
"properties": {
"description": {{json $.Description}},
"queryURI": "https://github.com/rhysd/actionlint/blob/main/docs/checks.md"
},
"fullDescription": {
"text": {{json $.Description}}
},
"helpUri": "https://github.com/rhysd/actionlint/blob/main/docs/checks.md"
}
{{end}}
]
}
},
"results": [
{{$first := true}}
{{range $ := .}}
{{if $first}}{{$first = false}}{{else}},{{end}}
{
"ruleId": {{json $.Kind}},
"message": {
"text": {{json $.Message}}
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": {{json $.Filepath}},
"uriBaseId": "%SRCROOT%"
},
"region": {
"startLine": {{$.Line}},
"startColumn": {{$.Column}},
"endColumn": {{$.EndColumn}},
"snippet": {
"text": {{json $.Snippet}}
}
}
}
}
]
}
{{end}}
]
}
]
}

60
.github/workflows/actionlint.yml vendored Normal file
View File

@ -0,0 +1,60 @@
# This workflow depends on the ./actionlint-format.txt file. It is MIT licensed (thanks, rhysd!): https://github.com/rhysd/actionlint/blob/2ab3a12c7848f6c15faca9a92612ef4261d0e370/testdata/format/sarif_template.txt
name: Actionlint
on:
push:
branches:
- main
- release-*
pull_request:
types:
- opened
- synchronize
- reopened
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
run-actionlint:
name: Lint GitHub Actions files
runs-on: ubuntu-latest
permissions:
contents: read # to check out the code
actions: read # to read the workflow files
security-events: write # for uploading the SARIF report
env:
ACTIONLINT_VERSION: 1.7.7
# curl -LXGET https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_checksums.txt | grep linux_amd64
CHECKSUM: 023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
persist-credentials: false
# GitHub Actions only runs x86_64. This will break if that assumption changes.
- name: Download Actionlint
run: |
set -euo pipefail
curl -OLXGET https://github.com/rhysd/actionlint/releases/download/v"${ACTIONLINT_VERSION}"/actionlint_"${ACTIONLINT_VERSION}"_linux_amd64.tar.gz
echo "${CHECKSUM} actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" | sha256sum -c -
tar xzf actionlint_"${ACTIONLINT_VERSION}"_linux_amd64.tar.gz
test -f actionlint
chmod +x actionlint
- name: Run Actionlint
run: ./actionlint -format "$(cat .github/workflows/actionlint-format.txt)" | tee results.sarif
- name: Upload to GitHub security events
if: success() || failure()
# If there are security problems, GitHub will automatically comment on the PR for us.
uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
with:
sarif_file: results.sarif
category: actionlint

View File

@ -37,7 +37,7 @@ jobs:
id: current-commit id: current-commit
run: | run: |
FROM_COMMIT=$(go list -m -json github.com/grafana/alerting | jq -r '.Version' | grep -oP '(?<=-)[a-f0-9]+$') FROM_COMMIT=$(go list -m -json github.com/grafana/alerting | jq -r '.Version' | grep -oP '(?<=-)[a-f0-9]+$')
echo "from_commit=$FROM_COMMIT" >> $GITHUB_OUTPUT echo "from_commit=$FROM_COMMIT" >> "$GITHUB_OUTPUT"
- name: Get current branch name - name: Get current branch name
id: current-branch-name id: current-branch-name
@ -47,14 +47,14 @@ jobs:
id: latest-commit id: latest-commit
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.current-branch-name.outputs.name }}
run: | run: |
BRANCH="${{ steps.current-branch-name.outputs.name }}" TO_COMMIT="$(gh api repos/grafana/alerting/commits/"$BRANCH" --jq '.sha')"
TO_COMMIT=$(gh api repos/grafana/alerting/commits/$BRANCH --jq '.sha')
if [ -z "$TO_COMMIT" ]; then if [ -z "$TO_COMMIT" ]; then
echo "Branch $BRANCH not found in alerting repo, falling back to main branch" echo "Branch $BRANCH not found in alerting repo, falling back to main branch"
exit 1 exit 1
fi fi
echo "to_commit=$TO_COMMIT" >> $GITHUB_OUTPUT echo "to_commit=$TO_COMMIT" >> "$GITHUB_OUTPUT"
- name: Compare commit hashes - name: Compare commit hashes
run: | run: |
@ -74,26 +74,31 @@ jobs:
id: check-commits id: check-commits
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
FROM_COMMIT: ${{ steps.current-commit.outputs.from_commit }}
TO_COMMIT: ${{ steps.latest-commit.outputs.to_commit }}
run: | run: |
# get all commits that contains 'Alerting:' in the message # 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 }} \ ALERTING_COMMITS="$(gh api repos/grafana/alerting/compare/"$FROM_COMMIT"..."$TO_COMMIT" \
--jq '.commits[].commit.message | split("\n")[0]') || true --jq '.commits[].commit.message | split("\n")[0]')" || true
# Use printf instead of echo -e for better multiline handling # Use printf instead of echo -e for better multiline handling
printf "%s\n" "$ALERTING_COMMITS" printf "%s\n" "$ALERTING_COMMITS"
# make the list for markdown and replace PR numbers with links # 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) 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 "alerting_commits<<EOF"
echo "EOF" >> $GITHUB_OUTPUT echo "$ALERTING_COMMITS_FORMATTED"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Update alerting module - name: Update alerting module
env: env:
GOSUMDB: off GOSUMDB: off
PINNED_COMMIT: ${{ steps.latest-commit.outputs.to_commit }}
run: | run: |
go get github.com/grafana/alerting@${{ steps.latest-commit.outputs.to_commit }} go get github.com/grafana/alerting@"$PINNED_COMMIT"
make update-workspace make update-workspace
- id: get-secrets - id: get-secrets
@ -124,7 +129,7 @@ jobs:
Compare changes: https://github.com/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }} Compare changes: https://github.com/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }}
<details> <details>
<summary>Commits</summary> <summary>Commits</summary>
${{ steps.check-commits.outputs.alerting_commits }} ${{ steps.check-commits.outputs.alerting_commits }}
</details> </details>
@ -132,6 +137,10 @@ jobs:
Created by: [GitHub Action Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) Created by: [GitHub Action Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- name: Add PR URL to Summary - name: Add PR URL to Summary
if: steps.create-pr.outputs.pull-request-url != '' if: steps.create-pr.outputs.pull-request-url != ''
env:
PR_URL: ${{ steps.create-pr.outputs.pull-request-url }}
run: | run: |
echo "## Pull Request Created" >> $GITHUB_STEP_SUMMARY {
echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY echo "## Pull Request Created"
echo "🔗 [View Pull Request]($PR_URL)"
} >> "$GITHUB_STEP_SUMMARY"

View File

@ -44,4 +44,4 @@ jobs:
git add . git add .
git commit -m "bump version ${VERSION}" git commit -m "bump version ${VERSION}"
git push git push
gh pr create --dry-run=$DRY_RUN -l "type/ci" -l "no-changelog" -B "$REF_NAME" --title "Release: Bump version to ${VERSION}" --body "Updated version to ${VERSION}" gh pr create --dry-run="$DRY_RUN" -l "type/ci" -l "no-changelog" -B "$REF_NAME" --title "Release: Bump version to ${VERSION}" --body "Updated version to ${VERSION}"

View File

@ -142,12 +142,12 @@ jobs:
- name: "Commit changelog changes" - name: "Commit changelog changes"
run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md run: git add CHANGELOG.md && git commit --allow-empty -m "Update changelog" CHANGELOG.md
- name: "git push" - name: "git push"
if: ${{ inputs.dry_run }} != true if: inputs.dry_run != true
run: git push run: git push
- name: "Create changelog PR" - name: "Create changelog PR"
run: > run: >
gh pr create \ gh pr create \
--dry-run=${DRY_RUN} \ --dry-run="${DRY_RUN}" \
--label "no-backport" \ --label "no-backport" \
--label "no-changelog" \ --label "no-changelog" \
-B "${TARGET}" \ -B "${TARGET}" \

View File

@ -48,7 +48,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Verify inputs - name: Verify inputs
run: | run: |
if [ -z $PLUGIN_ID ]; then echo "Missing plugin ID"; exit 1; fi if [ -z "$PLUGIN_ID" ]; then echo "Missing plugin ID"; exit 1; fi
- id: get-secrets - id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main # zizmor: ignore[unpinned-uses] uses: grafana/shared-workflows/actions/get-vault-secrets@main # zizmor: ignore[unpinned-uses]
with: with:
@ -72,13 +72,13 @@ jobs:
shell: bash shell: bash
id: get_dir id: get_dir
run: | run: |
dir=$(dirname \ dir="$(dirname \
$(egrep -lir --include=plugin.json --exclude-dir=dist \ "$(grep -Elir --include=plugin.json --exclude-dir=dist \
'"id": "${PLUGIN_ID}"' \ '"id": "'"${PLUGIN_ID}"'"' \
public/app/plugins \ public/app/plugins \
) \ )" \
) )"
echo "dir=${dir}" >> $GITHUB_OUTPUT echo "dir=${dir}" >> "$GITHUB_OUTPUT"
- name: Install frontend dependencies - name: Install frontend dependencies
shell: bash shell: bash
working-directory: ${{ steps.get_dir.outputs.dir }} working-directory: ${{ steps.get_dir.outputs.dir }}
@ -88,17 +88,17 @@ jobs:
shell: sh shell: sh
working-directory: ${{ steps.get_dir.outputs.dir }} working-directory: ${{ steps.get_dir.outputs.dir }}
run: | run: |
[ ! -d ./bin ] && mkdir -pv ./bin || true mkdir -pv ./bin
curl -fL -o ./bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v$GRABPL_VERSION/grabpl curl -fL -o ./bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v"$GRABPL_VERSION"/grabpl
chmod 0755 ./bin/grabpl chmod 0755 ./bin/grabpl
- name: Check backend - name: Check backend
id: check_backend id: check_backend
shell: bash shell: bash
run: | run: |
if egrep -qr --include=main.go 'datasource.Manage\("$PLUGIN_ID"' pkg/tsdb; then if grep -Eqr --include=main.go 'datasource.Manage\('"$PLUGIN_ID" pkg/tsdb; then
echo "has_backend=true" >> $GITHUB_OUTPUT echo "has_backend=true" >> "$GITHUB_OUTPUT"
else else
echo "has_backend=false" >> $GITHUB_OUTPUT echo "has_backend=false" >> "$GITHUB_OUTPUT"
fi fi
- name: Setup golang environment - name: Setup golang environment
uses: actions/setup-go@19bb51245e9c80abacb2e91cc42b33fa478b8639 uses: actions/setup-go@19bb51245e9c80abacb2e91cc42b33fa478b8639
@ -149,6 +149,8 @@ jobs:
- name: build:frontend - name: build:frontend
shell: bash shell: bash
id: build_frontend id: build_frontend
env:
OUTPUT_DIR: ${{ steps.get_dir.outputs.dir }}
run: | run: |
command="plugin:build:commit" command="plugin:build:commit"
if [ "$GITHUB_REF" != "refs/heads/main" ]; then if [ "$GITHUB_REF" != "refs/heads/main" ]; then
@ -156,15 +158,15 @@ jobs:
command="plugin:build" command="plugin:build"
fi fi
yarn $command --scope="@grafana-plugins/$PLUGIN_ID" yarn $command --scope="@grafana-plugins/$PLUGIN_ID"
version=$(cat ${{ steps.get_dir.outputs.dir }}/dist/plugin.json | jq -r .info.version) version="$(jq -r .info.version "$OUTPUT_DIR"/dist/plugin.json)"
echo "version=${version}" >> $GITHUB_OUTPUT echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: build:backend - name: build:backend
if: steps.check_backend.outputs.has_backend == 'true' if: steps.check_backend.outputs.has_backend == 'true'
shell: bash shell: bash
env: env:
VERSION: ${{ steps.build_frontend.outputs.version }} VERSION: ${{ steps.build_frontend.outputs.version }}
run: | run: |
make build-plugin-go PLUGIN_ID=$PLUGIN_ID make build-plugin-go PLUGIN_ID="$PLUGIN_ID"
- name: package - name: package
working-directory: ${{ steps.get_dir.outputs.dir }} working-directory: ${{ steps.get_dir.outputs.dir }}
run: | run: |
@ -177,16 +179,17 @@ jobs:
env: env:
GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }} GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }}
VERSION: ${{ steps.build_frontend.outputs.version }} VERSION: ${{ steps.build_frontend.outputs.version }}
GCOM_API: ${{ env.GCOM_API }}
run: | run: |
api_res=$(curl -X 'GET' -H "Authorization: Bearer $GCOM_TOKEN" \ api_res="$(curl -X 'GET' -H "Authorization: Bearer $GCOM_TOKEN" \
'${{ env.GCOM_API}}/api/plugins/$PLUGIN_ID?version=$VERSION' \ "$GCOM_API/api/plugins/$PLUGIN_ID?version=$VERSION" \
-H 'accept: application/json') -H 'accept: application/json')"
api_res_code=$(echo $api_res | jq -r .code) api_res_code="$(echo "$api_res" | jq -r .code)"
if [ "$api_res_code" = "NotFound" ]; then if [ "$api_res_code" = "NotFound" ]; then
echo "No existing release found" echo "No existing release found"
else else
echo "Expecting a missing release, got:" echo "Expecting a missing release, got:"
echo $api_res echo "$api_res"
exit 1 exit 1
fi fi
- name: store build artifacts - name: store build artifacts
@ -197,55 +200,46 @@ jobs:
- name: Publish release to Google Cloud Storage - name: Publish release to Google Cloud Storage
working-directory: ${{ steps.get_dir.outputs.dir }} working-directory: ${{ steps.get_dir.outputs.dir }}
env: env:
VERSION: ${{ steps.build_frontend.outputs.version }} VERSION: ${{ steps.build_frontend.outputs.version }}
GCP_BUCKET: ${{ env.GCP_BUCKET }}
run: | run: |
echo "Publish release to Google Cloud Storage:" echo "Publish release to Google Cloud Storage:"
set -x
touch ci/packages/windows ci/packages/darwin ci/packages/linux ci/packages/any touch ci/packages/windows ci/packages/darwin ci/packages/linux ci/packages/any
gsutil -m cp -r ci/packages/*windows* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/windows gsutil -m cp -r ci/packages/*windows* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/windows"
gsutil -m cp -r ci/packages/*linux* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux gsutil -m cp -r ci/packages/*linux* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/linux"
gsutil -m cp -r ci/packages/*darwin* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/darwin gsutil -m cp -r ci/packages/*darwin* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/darwin"
gsutil -m cp -r ci/packages/*any* gs://${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/any gsutil -m cp -r ci/packages/*any* "gs://$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/any"
- name: Publish new plugin version on grafana.com - name: Publish new plugin version on grafana.com
if: steps.check_backend.outputs.has_backend == 'true' if: steps.check_backend.outputs.has_backend == 'true'
working-directory: ${{ steps.get_dir.outputs.dir }} working-directory: ${{ steps.get_dir.outputs.dir }}
env: env:
GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }} GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }}
VERSION: ${{ steps.build_frontend.outputs.version }} VERSION: ${{ steps.build_frontend.outputs.version }}
GCP_BUCKET: ${{ env.GCP_BUCKET }}
OUTPUT_DIR: ${{ steps.get_dir.outputs.dir }}
GCOM_API: ${{ env.GCOM_API }}
run: | run: |
echo "Publish new plugin version on grafana.com:" echo "Publish new plugin version on grafana.com:"
echo "Plugin version: ${VERSION}" echo "Plugin version: ${VERSION}"
result=`curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" ${{ env.GCOM_API}}/api/plugins -d "{
\"url\": \"https://github.com/grafana/grafana/tree/main/${{ steps.get_dir.outputs.dir }}\", OUTPUT_URL="https://github.com/grafana/grafana/tree/$OUTPUT_DIR" \
\"download\": { jq -n '{"url": env.OUTPUT_URL}' > body.json
\"linux-amd64\": { osarchs=(linux_amd64 linux_arm64 linux_arm windows_amd64 darwin_amd64 darwin_arm64)
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux/$PLUGIN_ID-${VERSION}.linux_amd64.zip\", for osarch in "${osarchs[@]}"; do
\"md5\": \"$(cat ci/packages/info-linux_amd64.json | jq -r .plugin.md5)\" echo "Processing $osarch"
}, KEY="${osarch//_/-}" \
\"linux-arm64\": { OSARCH="$osarch" \
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux/$PLUGIN_ID-${VERSION}.linux_arm64.zip\", jq -s '. as $i | .[0] | .download[env.KEY] = {
\"md5\": \"$(cat ci/packages/info-linux_arm64.json | jq -r .plugin.md5)\" "url": "https://storage.googleapis.com/\(env.GCP_BUCKET)/\(env.PLUGIN_ID)/release/\(env.VERSION)/linux/\(env.PLUGIN_ID)-\(env.VERSION).\(env.OSARCH).zip",
}, "md5": $i[1].plugin.md5
\"linux-arm\": { }' body.json ci/packages/info-"$osarch".json > tmp.json && mv tmp.json body.json
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/linux/$PLUGIN_ID-${VERSION}.linux_arm.zip\", done
\"md5\": \"$(cat ci/packages/info-linux_arm.json | jq -r .plugin.md5)\"
}, result="$(curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" "$GCOM_API"/api/plugins --data-binary '@body.json')"
\"windows-amd64\": { if [[ "$(echo "$result" | jq -r .version)" == "null" ]]; then
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/windows/$PLUGIN_ID-${VERSION}.windows_amd64.zip\",
\"md5\": \"$(cat ci/packages/info-windows_amd64.json | jq -r .plugin.md5)\"
},
\"darwin-amd64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/darwin/$PLUGIN_ID-${VERSION}.darwin_amd64.zip\",
\"md5\": \"$(cat ci/packages/info-darwin_amd64.json | jq -r .plugin.md5)\"
},
\"darwin-arm64\": {
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/darwin/$PLUGIN_ID-${VERSION}.darwin_arm64.zip\",
\"md5\": \"$(cat ci/packages/info-darwin_arm64.json | jq -r .plugin.md5)\"
}
}
}"`
if [[ "$(echo $result | jq -r .version)" == "null" ]]; then
echo "Failed to publish plugin version. Got:" echo "Failed to publish plugin version. Got:"
echo $result echo "$result"
exit 1 exit 1
fi fi
- name: Publish new plugin version on grafana.com (frontend only) - name: Publish new plugin version on grafana.com (frontend only)
@ -254,20 +248,29 @@ jobs:
env: env:
GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }} GCOM_TOKEN: ${{ env.PLUGINS_GCOM_TOKEN }}
VERSION: ${{ steps.build_frontend.outputs.version }} VERSION: ${{ steps.build_frontend.outputs.version }}
GCOM_API: ${{ env.GCOM_API }}
OUTPUT_DIR: ${{ steps.get_dir.outputs.dir }}
GCP_BUCKET: ${{ env.GCP_BUCKET }}
run: | run: |
echo "Publish new plugin version on grafana.com:" echo "Publish new plugin version on grafana.com:"
echo "Plugin version: ${VERSION}" echo "Plugin version: ${VERSION}"
result=`curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" ${{ env.GCOM_API}}/api/plugins -d "{
\"url\": \"https://github.com/grafana/grafana/tree/main/${{ steps.get_dir.outputs.dir }}\", OUTPUT_URL="https://github.com/grafana/grafana/tree/$OUTPUT_DIR" \
\"download\": { DOWNLOAD_URL="https://storage.googleapis.com/$GCP_BUCKET/$PLUGIN_ID/release/${VERSION}/any/$PLUGIN_ID-${VERSION}.any.zip" \
\"any\": { MD5_CHECKSUM="$(jq -r '.plugin.md5' ci/packages/info-any.json)" \
\"url\": \"https://storage.googleapis.com/${{ env.GCP_BUCKET }}/$PLUGIN_ID/release/${VERSION}/any/$PLUGIN_ID-${VERSION}.any.zip\", jq -rn '{
\"md5\": \"$(cat ci/packages/info-any.json | jq -r .plugin.md5)\" "url": env.OUTPUT_URL,
"download": {
"any": {
"url": env.DOWNLOAD_URL,
"md5": env.MD5_CHECKSUM
} }
} }
}"` }' > body.json
if [[ "$(echo $result | jq -r .version)" == "null" ]]; then
result="$(curl -H "Authorization: Bearer $GCOM_TOKEN" -H "Content-Type: application/json" "$GCOM_API"/api/plugins --data-binary '@body.json')"
if [[ "$(echo "$result" | jq -r .version)" == "null" ]]; then
echo "Failed to publish plugin version. Got:" echo "Failed to publish plugin version. Got:"
echo $result echo "$result"
exit 1 exit 1
fi fi

View File

@ -41,6 +41,7 @@ jobs:
ISSUE_NUMBER: ${{ github.event.issue.number }} ISSUE_NUMBER: ${{ github.event.issue.number }}
TARGET_PROJECT: ${{ env.TARGET_PROJECT }} TARGET_PROJECT: ${{ env.TARGET_PROJECT }}
run: | run: |
# shellcheck disable=SC2016 # we don't want the $s to be expanded
gh api graphql -f query=' gh api graphql -f query='
query($org: String!, $repo: String!) { query($org: String!, $repo: String!) {
repository(name: $repo, owner: $org) { repository(name: $repo, owner: $org) {
@ -55,15 +56,18 @@ jobs:
} }
} }
} }
}' -f org=$ORGANIZATION -f repo=$REPO > projects_data.json }' -f org="$ORGANIZATION" -f repo="$REPO" > projects_data.json
echo 'IN_TARGET_PROJ='$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number=='"$TARGET_PROJECT"') | .project != null' projects_data.json) >> $GITHUB_ENV {
echo 'ITEM_ID='$(jq '.data.repository.issue.id' projects_data.json) >> $GITHUB_ENV echo "IN_TARGET_PROJ=$(jq '.data.repository.issue.projectItems.nodes[] | select(.project.number=='"$TARGET_PROJECT"') | .project != null' projects_data.json)"
echo "ITEM_ID=$(jq '.data.repository.issue.id' projects_data.json)"
} >> "$GITHUB_ENV"
- name: Set up label array - name: Set up label array
if: env.IN_TARGET_PROJ if: env.IN_TARGET_PROJ
env: env:
LABEL_IDS: ${{ env.LABEL_IDS }} LABEL_IDS: ${{ env.LABEL_IDS }}
run: | run: |
# shellcheck disable=SC2153 # we define the variable on the line above in 'read'
IFS=',' read -ra LABEL_IDs <<< "$LABEL_IDS" IFS=',' read -ra LABEL_IDs <<< "$LABEL_IDS"
for item in "${LABEL_IDs[@]}"; do for item in "${LABEL_IDs[@]}"; do
echo "Item: $item" echo "Item: $item"
@ -74,6 +78,7 @@ jobs:
GH_TOKEN: ${{ steps.generate_token.outputs.token }} GH_TOKEN: ${{ steps.generate_token.outputs.token }}
LABEL_IDS: ${{ env.LABEL_IDS }} LABEL_IDS: ${{ env.LABEL_IDS }}
run: | run: |
# shellcheck disable=SC2016 # we don't want the $s to be expanded
gh api graphql -f query=' gh api graphql -f query='
mutation ($labelableId: ID!, $labelIds: [ID!]!) { mutation ($labelableId: ID!, $labelIds: [ID!]!) {
addLabelsToLabelable( addLabelsToLabelable(
@ -81,4 +86,4 @@ jobs:
) { ) {
clientMutationId clientMutationId
} }
}' -f labelableId=$ITEM_ID -f labelIds=$LABEL_IDS }' -f labelableId="$ITEM_ID" -f labelIds="$LABEL_IDS"

View File

@ -399,7 +399,7 @@ jobs:
echo "Breaking changes detected. Please check the levitate report in your pull request. This workflow won't block merging." echo "Breaking changes detected. Please check the levitate report in your pull request. This workflow won't block merging."
fi fi
exit ${LV_EXIT_CODE} exit "${LV_EXIT_CODE}"
shell: bash shell: bash
env: env:
LV_EXIT_CODE: ${{ steps.levitate-run.outputs.exit_code }} LV_EXIT_CODE: ${{ steps.levitate-run.outputs.exit_code }}

View File

@ -26,13 +26,14 @@ jobs:
cache-dependency-path: 'yarn.lock' cache-dependency-path: 'yarn.lock'
- run: yarn install --immutable --check-cache - run: yarn install --immutable --check-cache
- run: | - run: |
# shellcheck disable=SC2102,SC2016,SC2125 # this is just a string. we _want_ all the bash features to be disabled.
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.' 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) make i18n-extract || (echo "${extract_error_message}" && false)
- run: | - run: |
uncommited_error_message="::error::Translation extraction has not been committed. Please run 'make i18n-extract', commit the changes and push again." 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) file_diff=$(git diff --dirstat public/locales)
if [ -n "$file_diff" ]; then if [ -n "$file_diff" ]; then
echo $file_diff echo "$file_diff"
echo "${uncommited_error_message}" echo "${uncommited_error_message}"
exit 1 exit 1
fi fi

View File

@ -151,20 +151,21 @@ jobs:
# - the PR does not modify files other than json files under the public/locales/ directory # - the PR does not modify files other than json files under the public/locales/ directory
# - the PR does not modify the en-US locale # - the PR does not modify the en-US locale
run: | run: |
filesChanged=$(gh pr diff --name-only ${{ steps.crowdin-download.outputs.pull_request_url }}) filesChanged="$(gh pr diff --name-only "$PR_URL")"
if [[ $(echo $filesChanged | grep -v 'public/locales/[a-zA-Z\-]*/grafana.json' | wc -l) -ne 0 ]]; then if [[ $(echo "$filesChanged" | grep -cv 'public/locales/[a-zA-Z\-]*/grafana.json') -ne 0 ]]; then
echo "Non-i18n changes detected, not approving" echo "Non-i18n changes detected, not approving"
exit 1 exit 1
fi fi
if [[ $(echo $filesChanged | grep "public/locales/en-US" | wc -l) -ne 0 ]]; then if [[ $(echo "$filesChanged" | grep -c "public/locales/en-US") -ne 0 ]]; then
echo "public/locales/en-US changes detected, not approving" echo "public/locales/en-US changes detected, not approving"
exit 1 exit 1
fi fi
echo "Approving and enabling automerge" echo "Approving and enabling automerge"
gh pr review ${{ steps.crowdin-download.outputs.pull_request_url }} --approve gh pr review "$PR_URL" --approve
gh pr merge --auto --squash ${{ steps.crowdin-download.outputs.pull_request_url }} gh pr merge --auto --squash "$PR_URL"
env: env:
GITHUB_TOKEN: ${{ steps.generate_approver_token.outputs.token }} GITHUB_TOKEN: ${{ steps.generate_approver_token.outputs.token }}
PR_URL: ${{ steps.crowdin-download.outputs.pull_request_url }}

View File

@ -65,5 +65,5 @@ jobs:
if ! git diff --exit-code --quiet; then if ! git diff --exit-code --quiet; then
echo "Committing and pushing workspace changes" echo "Committing and pushing workspace changes"
git commit -a -m "update workspace" git commit -a -m "update workspace"
git push origin $BRANCH_NAME git push origin "$BRANCH_NAME"
fi fi

View File

@ -36,7 +36,7 @@ jobs:
with: with:
verb: run verb: run
args: go run ./cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir=grafana --go-version=${GRAFANA_GO_VERSION} > out.txt 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: mv "$(cat out.txt)" grafana.tar.gz
- run: echo "artifact=grafana-e2e-${{github.run_number}}" >> "$GITHUB_OUTPUT" - run: echo "artifact=grafana-e2e-${{github.run_number}}" >> "$GITHUB_OUTPUT"
id: artifact id: artifact
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4

View File

@ -30,8 +30,11 @@ jobs:
go-version-file: go.mod go-version-file: go.mod
cache: true cache: true
- run: | - run: |
go_packages="$(find ./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+' | grep -o '\(.*\)/' | sort -u)"
IFS=' ' read -ra packages <<< "$go_packages"
make gen-go 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) go test -tags=sqlite -timeout=5m -run '^TestIntegration' "${packages[@]}"
mysql: mysql:
name: MySQL name: MySQL
runs-on: ubuntu-latest-8-cores runs-on: ubuntu-latest-8-cores
@ -62,10 +65,13 @@ jobs:
go-version-file: go.mod go-version-file: go.mod
cache: true cache: true
- run: | - run: |
go_packages="$(find ./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+' | grep -o '\(.*\)/' | sort -u)"
IFS=' ' read -ra packages <<< "$go_packages"
sudo apt-get update -yq && sudo apt-get install mariadb-client 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 mariadb -h 127.0.0.1 -P 3306 -u root -prootpass --disable-ssl-verify-server-cert < devenv/docker/blocks/mysql_tests/setup.sql
make gen-go 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) go test -tags=mysql -p=1 -timeout=5m -run '^TestIntegration' "${packages[@]}"
postgres: postgres:
name: Postgres name: Postgres
runs-on: ubuntu-latest-8-cores runs-on: ubuntu-latest-8-cores
@ -95,7 +101,10 @@ jobs:
PGPASSWORD: grafanatest PGPASSWORD: grafanatest
POSTGRES_HOST: 127.0.0.1 POSTGRES_HOST: 127.0.0.1
run: | run: |
go_packages="$(find ./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+' | grep -o '\(.*\)/' | sort -u)"
IFS=' ' read -ra packages <<< "$go_packages"
sudo apt-get update -yq && sudo apt-get install postgresql-client 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 psql -p 5432 -h 127.0.0.1 -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql
make gen-go 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) go test -p=1 -tags=postgres -timeout=5m -run '^TestIntegration' "${packages[@]}"

View File

@ -44,19 +44,23 @@ jobs:
steps: steps:
- if: ${{ github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/') }} - if: ${{ github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/') }}
run: | run: |
echo "VERSION=$(echo ${HEAD_REF} | sed -e 's/release\/.*\//v/g')" >> $GITHUB_ENV {
echo "DRY_RUN=${{ contains(github.event.pull_request.labels.*.name, 'release/dry-run') }}" >> $GITHUB_ENV echo "VERSION=$(echo "${HEAD_REF}" | sed -e 's/release\/.*\//v/g')"
echo "LATEST=${{ contains(github.event.pull_request.labels.*.name, 'release/latest') && '1' || '0' }}" >> $GITHUB_ENV echo "DRY_RUN=${{ contains(github.event.pull_request.labels.*.name, 'release/dry-run') }}"
echo "LATEST=${{ contains(github.event.pull_request.labels.*.name, 'release/latest') && '1' || '0' }}"
} >> "$GITHUB_ENV"
- id: output - id: output
run: | run: |
echo "dry_run: $DRY_RUN" echo "dry_run: $DRY_RUN"
echo "latest: $LATEST" echo "latest: $LATEST"
echo "version: $VERSION" echo "version: $VERSION"
echo "release_branch=$(echo $VERSION | sed -s 's/^v/release-/g')" >> "$GITHUB_OUTPUT" {
echo "dry_run=$DRY_RUN" >> "$GITHUB_OUTPUT" echo "release_branch=$(echo "$VERSION" | sed -s 's/^v/release-/g')"
echo "latest=$LATEST" >> "$GITHUB_OUTPUT" echo "dry_run=$DRY_RUN"
echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "latest=$LATEST"
echo "version=$VERSION"
} >> "$GITHUB_OUTPUT"
create_next_release_branch_grafana: create_next_release_branch_grafana:
name: Create next release branch (Grafana) name: Create next release branch (Grafana)
needs: setup needs: setup
@ -113,5 +117,5 @@ jobs:
VERSION: ${{ needs.setup.outputs.version }} VERSION: ${{ needs.setup.outputs.version }}
steps: steps:
- run: | - run: |
echo announce on slack that $VERSION has been released echo announce on slack that "$VERSION" has been released
echo dry run: $DRY_RUN echo dry run: "$DRY_RUN"

View File

@ -166,7 +166,7 @@ jobs:
git commit -m "Update version to $VERSION" git commit -m "Update version to $VERSION"
- name: Git push - name: Git push
if: ${{ inputs.dry_run }} != true if: inputs.dry_run != true
run: git push --set-upstream origin "release/${{ github.run_id }}/$VERSION" run: git push --set-upstream origin "release/${{ github.run_id }}/$VERSION"
- name: Create PR without backports - name: Create PR without backports
@ -177,10 +177,10 @@ jobs:
run: | run: |
LATEST_FLAG="" LATEST_FLAG=""
if [ "$LATEST" = "true" ]; then if [ "$LATEST" = "true" ]; then
LATEST_FLAG='-l "release/latest"' LATEST_FLAG=(-l "release/latest")
fi fi
gh pr create \ gh pr create \
$LATEST_FLAG \ "${LATEST_FLAG[@]}" \
-l "no-changelog" \ -l "no-changelog" \
--dry-run="$DRY_RUN" \ --dry-run="$DRY_RUN" \
-B "$BRANCH" \ -B "$BRANCH" \
@ -195,10 +195,10 @@ jobs:
run: | run: |
LATEST_FLAG="" LATEST_FLAG=""
if [ "$LATEST" = "true" ]; then if [ "$LATEST" = "true" ]; then
LATEST_FLAG='-l "release/latest"' LATEST_FLAG=(-l "release/latest")
fi fi
gh pr create \ gh pr create \
$LATEST_FLAG \ "${LATEST_FLAG[@]}" \
-l "product-approved" \ -l "product-approved" \
-l "no-changelog" \ -l "no-changelog" \
--dry-run="$DRY_RUN" \ --dry-run="$DRY_RUN" \

View File

@ -40,7 +40,7 @@ jobs:
cache: 'yarn' cache: 'yarn'
- name: Cache Node Modules - name: Cache Node Modules
id: cache-node-modules id: cache-node-modules
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: | path: |
node_modules node_modules
@ -56,7 +56,7 @@ jobs:
runTests: false runTests: false
- name: Cache Grafana Build and Dependencies - name: Cache Grafana Build and Dependencies
id: cache-grafana id: cache-grafana
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: | path: |
bin/ bin/
@ -74,9 +74,11 @@ jobs:
- name: Get list of .ini files - name: Get list of .ini files
id: get_files id: get_files
env:
WORKSPACE: ${{ github.workspace }}
run: | run: |
INI_FILES=$(ls ${{ github.workspace }}/e2e/dashboards-search-suite/*.ini | jq -R -s -c 'split("\n")[:-1]') INI_FILES="$(find "$WORKSPACE"/e2e/dashboards-search-suite/ -type f -name '*.ini' | jq -R -s -c 'split("\n")[:-1]')"
echo "ini_files=$INI_FILES" >> $GITHUB_OUTPUT echo "ini_files=$INI_FILES" >> "$GITHUB_OUTPUT"
shell: bash shell: bash
run_tests: run_tests:
@ -98,7 +100,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Restore Cached Node Modules - name: Restore Cached Node Modules
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: | path: |
node_modules node_modules
@ -106,7 +108,7 @@ jobs:
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
- name: Restore Cached Grafana Build and Dependencies - name: Restore Cached Grafana Build and Dependencies
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: | path: |
bin/ bin/
@ -122,11 +124,12 @@ jobs:
env: env:
INI_NAME: ${{ matrix.ini_file }} INI_NAME: ${{ matrix.ini_file }}
run: | run: |
FILE_NAME=$(basename "$env.INI_NAME" .ini) FILE_NAME="$(basename "$INI_NAME" .ini)"
echo "FILE_NAME=$FILE_NAME" >> $GITHUB_OUTPUT echo "FILE_NAME=$FILE_NAME" >> "$GITHUB_OUTPUT"
- name: Run tests for ${{ steps.set_file_name.outputs.FILE_NAME }} - name: Run tests for ${{ steps.set_file_name.outputs.FILE_NAME }}
env: env:
INI_NAME: ${{ matrix.ini_file }} INI_NAME: ${{ matrix.ini_file }}
WORKSPACE: ${{ github.workspace }}
run: | run: |
cp -rf $INI_NAME ${{ github.workspace }}/scripts/grafana-server/custom.ini cp -rf "$INI_NAME" "$WORKSPACE"/scripts/grafana-server/custom.ini
yarn e2e:dashboards-search || echo "Test failed but marking as success since unified search is behind a feature flag and should not block PRs" yarn e2e:dashboards-search || echo "Test failed but marking as success since unified search is behind a feature flag and should not block PRs"

View File

@ -26,13 +26,13 @@ jobs:
args: go run ./pkg/build/e2e --package=grafana.tar.gz --suite=${{ inputs.suite }} args: go run ./pkg/build/e2e --package=grafana.tar.gz --suite=${{ inputs.suite }}
- name: Set suite name - name: Set suite name
id: set-suite-name id: set-suite-name
if: always() if: success() || failure()
env: env:
SUITE: ${{ inputs.suite }} SUITE: ${{ inputs.suite }}
run: | run: |
echo "suite=$(echo $SUITE | sed 's/\//-/g')" >> $GITHUB_OUTPUT echo "suite=$(echo "$SUITE" | sed 's/\//-/g')" >> "$GITHUB_OUTPUT"
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: always() if: success() || failure()
with: with:
name: e2e-${{ steps.set-suite-name.outputs.suite }}-${{github.run_number}} name: e2e-${{ steps.set-suite-name.outputs.suite }}-${{github.run_number}}
path: videos path: videos

View File

@ -60,11 +60,11 @@ jobs:
# Check if user is in the allowed list # Check if user is in the allowed list
for allowed_user in "${ALLOWED_USERS[@]}"; do for allowed_user in "${ALLOWED_USERS[@]}"; do
if [ "$allowed_user" = "$USERNAME" ]; then if [ "$allowed_user" = "$USERNAME" ]; then
echo "user_allowed=true" >> $GITHUB_OUTPUT echo "user_allowed=true" >> "$GITHUB_OUTPUT"
exit 0 exit 0
fi fi
done done
echo "user_allowed=false" >> $GITHUB_OUTPUT echo "user_allowed=false" >> "$GITHUB_OUTPUT"
# Convert the issue/PR number to a node ID for the GraphQL API # Convert the issue/PR number to a node ID for the GraphQL API
- name: Get node ID for item - name: Get node ID for item

View File

@ -30,3 +30,13 @@ The following directories and their subdirectories are licensed under their orig
``` ```
public/vendor/ public/vendor/
``` ```
## MIT license
The following files are licensed under MIT License:
```
.github/workflows/actionlint-format.txt
-> Vendored: https://github.com/rhysd/actionlint/blob/2ab3a12c7848f6c15faca9a92612ef4261d0e370/testdata/format/sarif_template.txt
-> The workflow that uses it is AGPL-3.0-only.
```